From 2e52b08800d5213e6cc7d75559f62584e8e0eede Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 21 Dec 2023 23:46:41 +0100 Subject: [PATCH] Rustify `cargo.sh` --- .github/workflows/stdarch.yml | 4 +- Readme.md | 10 ++-- build_system/src/cargo.rs | 98 +++++++++++++++++++++++++++++++++++ build_system/src/main.rs | 5 ++ build_system/src/test.rs | 2 +- build_system/src/utils.rs | 27 ++++++++-- cargo.sh | 23 -------- 7 files changed, 135 insertions(+), 34 deletions(-) create mode 100644 build_system/src/cargo.rs delete mode 100755 cargo.sh diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index dc670c5701c..d8336fe991b 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -126,11 +126,11 @@ jobs: if: ${{ !matrix.cargo_runner }} run: | cd build_sysroot/sysroot_src/library/stdarch/ - CHANNEL=release TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ../../../../cargo.sh test + CHANNEL=release TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ../../../../y.sh cargo test - name: Run stdarch tests if: ${{ matrix.cargo_runner }} run: | cd build_sysroot/sysroot_src/library/stdarch/ # FIXME: these tests fail when the sysroot is compiled with LTO because of a missing symbol in proc-macro. - STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ../../../../cargo.sh test -- --skip rtm --skip tbm --skip sse4a + STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ../../../../y.sh cargo test -- --skip rtm --skip tbm --skip sse4a diff --git a/Readme.md b/Readme.md index 68effb2bf78..f31b5c17969 100644 --- a/Readme.md +++ b/Readme.md @@ -79,7 +79,7 @@ export CG_GCCJIT_DIR=[the full path to rustc_codegen_gcc] ### Cargo ```bash -$ CHANNEL="release" $CG_GCCJIT_DIR/cargo.sh run +$ CHANNEL="release" $CG_GCCJIT_DIR/y.sh cargo run ``` If you compiled cg_gccjit in debug mode (aka you didn't pass `--release` to `./y.sh test`) you should use `CHANNEL="debug"` instead or omit `CHANNEL="release"` completely. @@ -230,13 +230,13 @@ Run do the command with `-v -save-temps` and then extract the `lto1` line from t ### How to send arguments to the GCC linker ``` -CG_RUSTFLAGS="-Clink-args=-save-temps -v" ../cargo.sh build +CG_RUSTFLAGS="-Clink-args=-save-temps -v" ../y.sh cargo build ``` ### How to see the personality functions in the asm dump ``` -CG_RUSTFLAGS="-Clink-arg=-save-temps -v -Clink-arg=-dA" ../cargo.sh build +CG_RUSTFLAGS="-Clink-arg=-save-temps -v -Clink-arg=-dA" ../y.sh cargo build ``` ### How to see the LLVM IR for a sysroot crate @@ -324,13 +324,13 @@ generate it in [gimple.md](./doc/gimple.md). * Run `./y.sh prepare --cross` so that the sysroot is patched for the cross-compiling case. * Set the path to the cross-compiling libgccjit in `gcc_path`. * Make sure you have the linker for your target (for instance `m68k-unknown-linux-gnu-gcc`) in your `$PATH`. Currently, the linker name is hardcoded as being `$TARGET-gcc`. Specify the target when building the sysroot: `./y.sh build --target-triple m68k-unknown-linux-gnu`. - * Build your project by specifying the target: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../cargo.sh build --target m68k-unknown-linux-gnu`. + * Build your project by specifying the target: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../y.sh cargo build --target m68k-unknown-linux-gnu`. If the target is not yet supported by the Rust compiler, create a [target specification file](https://docs.rust-embedded.org/embedonomicon/custom-target.html) (note that the `arch` specified in this file must be supported by the rust compiler). Then, you can use it the following way: * Add the target specification file using `--target` as an **absolute** path to build the sysroot: `./y.sh build --target-triple m68k-unknown-linux-gnu --target $(pwd)/m68k-unknown-linux-gnu.json` - * Build your project by specifying the target specification file: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../cargo.sh build --target path/to/m68k-unknown-linux-gnu.json`. + * Build your project by specifying the target specification file: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../y.sh cargo build --target path/to/m68k-unknown-linux-gnu.json`. If you get the following error: diff --git a/build_system/src/cargo.rs b/build_system/src/cargo.rs new file mode 100644 index 00000000000..06b543a6cad --- /dev/null +++ b/build_system/src/cargo.rs @@ -0,0 +1,98 @@ +use crate::config::ConfigInfo; +use crate::utils::{ + get_toolchain, run_command_with_output_and_env, rustc_toolchain_version_info, + rustc_version_info, +}; + +use std::collections::HashMap; +use std::ffi::OsStr; + +fn args() -> Result>, String> { + // We skip the binary and the "cargo" option. + if let Some("--help") = std::env::args().skip(2).next().as_deref() { + usage(); + return Ok(None); + } + let args = std::env::args().skip(2).collect::>(); + if args.is_empty() { + return Err( + "Expected at least one argument for `cargo` subcommand, found none".to_string(), + ); + } + Ok(Some(args)) +} + +fn usage() { + println!( + r#" +`cargo` command help: + + [args] : Arguments to be passed to the cargo command + --help : Show this help +"# + ) +} + +pub fn run() -> Result<(), String> { + let args = match args()? { + Some(a) => a, + None => return Ok(()), + }; + + // We first need to go to the original location to ensure that the config setup will go as + // expected. + let current_dir = std::env::current_dir() + .map_err(|error| format!("Failed to get current directory path: {:?}", error))?; + let current_exe = std::env::current_exe() + .map_err(|error| format!("Failed to get current exe path: {:?}", error))?; + let parent_dir = match current_exe.parent() { + Some(parent) => parent, + None => { + return Err(format!( + "Cannot get parent of current executable path `{}`", + current_exe.display() + )); + } + }; + std::env::set_current_dir(&parent_dir).map_err(|error| { + format!( + "Failed to go to `{}` folder: {:?}", + parent_dir.display(), + error + ) + })?; + + let mut env: HashMap = std::env::vars().collect(); + ConfigInfo::default().setup(&mut env, None)?; + let toolchain = get_toolchain()?; + + let toolchain_version = rustc_toolchain_version_info(&toolchain)?; + let default_version = rustc_version_info(None)?; + if toolchain_version != default_version { + println!( + "rustc_codegen_gcc is built for {} but the default rustc version is {}.", + toolchain_version.short, default_version.short, + ); + println!("Using {}.", toolchain_version.short); + } + + // We go back to the original folder since we now have set up everything we needed. + std::env::set_current_dir(¤t_dir).map_err(|error| { + format!( + "Failed to go back to `{}` folder: {:?}", + current_dir.display(), + error + ) + })?; + + let rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default(); + env.insert("RUSTDOCFLAGS".to_string(), rustflags); + let toolchain = format!("+{}", toolchain); + let mut command: Vec<&dyn AsRef> = vec![&"cargo", &toolchain]; + for arg in &args { + command.push(arg); + } + run_command_with_output_and_env(&command, None, Some(&env))?; + + Ok(()) +} diff --git a/build_system/src/main.rs b/build_system/src/main.rs index 1ed44b22a95..102c5486a75 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -2,6 +2,7 @@ use std::process; mod build; +mod cargo; mod clean; mod config; mod prepare; @@ -23,6 +24,7 @@ fn usage() { "\ Available commands for build_system: + cargo : Run cargo command clean : Run clean command prepare : Run prepare command build : Run build command @@ -32,6 +34,7 @@ fn usage() { } pub enum Command { + Cargo, Clean, Prepare, Build, @@ -44,6 +47,7 @@ fn main() { } let command = match env::args().nth(1).as_deref() { + Some("cargo") => Command::Cargo, Some("clean") => Command::Clean, Some("prepare") => Command::Prepare, Some("build") => Command::Build, @@ -61,6 +65,7 @@ fn main() { }; if let Err(e) = match command { + Command::Cargo => cargo::run(), Command::Clean => clean::run(), Command::Prepare => prepare::run(), Command::Build => build::run(), diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 1a9bb4ea94e..1577cbf2b53 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -796,7 +796,7 @@ fn extended_sysroot_tests(env: &Env, args: &TestArg) -> Result<(), String> { // echo "[BENCH COMPILE] ebobby/simple-raytracer" // hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "cargo clean" \ // "RUSTC=rustc RUSTFLAGS='' cargo build" \ - // "../cargo.sh build" + // "../y.sh cargo build" // echo "[BENCH RUN] ebobby/simple-raytracer" // cp ./target/debug/main ./raytracer_cg_gcc diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 276f4f2d989..fdd8bd8f4c4 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -158,21 +158,42 @@ pub fn get_os_name() -> Result { } } -#[derive(Default)] +#[derive(Default, PartialEq)] pub struct RustcVersionInfo { + pub short: String, pub version: String, pub host: Option, pub commit_hash: Option, pub commit_date: Option, } +pub fn rustc_toolchain_version_info(toolchain: &str) -> Result { + rustc_version_info_inner(None, Some(toolchain)) +} + pub fn rustc_version_info(rustc: Option<&str>) -> Result { - let output = run_command(&[&rustc.unwrap_or("rustc"), &"-vV"], None)?; + rustc_version_info_inner(rustc, None) +} + +fn rustc_version_info_inner( + rustc: Option<&str>, + toolchain: Option<&str>, +) -> Result { + let output = if let Some(toolchain) = toolchain { + run_command(&[&rustc.unwrap_or("rustc"), &toolchain, &"-vV"], None) + } else { + run_command(&[&rustc.unwrap_or("rustc"), &"-vV"], None) + }?; let content = std::str::from_utf8(&output.stdout).unwrap_or(""); let mut info = RustcVersionInfo::default(); + let mut lines = content.split('\n'); + info.short = match lines.next() { + Some(s) => s.to_string(), + None => return Err("failed to retrieve rustc version".to_string()), + }; - for line in content.split('\n').map(|line| line.trim()) { + for line in lines.map(|line| line.trim()) { match line.split_once(':') { Some(("host", data)) => info.host = Some(data.trim().to_string()), Some(("release", data)) => info.version = data.trim().to_string(), diff --git a/cargo.sh b/cargo.sh deleted file mode 100755 index b68a08ee88f..00000000000 --- a/cargo.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash - -if [ -z $CHANNEL ]; then -export CHANNEL='debug' -fi - -pushd $(dirname "$0") >/dev/null -source config.sh - -# read nightly compiler from rust-toolchain file -TOOLCHAIN=$(cat rust-toolchain | grep channel | sed 's/channel = "\(.*\)"/\1/') - -popd >/dev/null - -if [[ $(${RUSTC} -V) != $(${RUSTC} +${TOOLCHAIN} -V) ]]; then - echo "rustc_codegen_gcc is build for $(rustc +${TOOLCHAIN} -V) but the default rustc version is $(rustc -V)." - echo "Using $(rustc +${TOOLCHAIN} -V)." -fi - -cmd=$1 -shift - -RUSTDOCFLAGS="$RUSTFLAGS" cargo +${TOOLCHAIN} $cmd $@