about summary refs log tree commit diff
diff options
context:
space:
mode:
authorantoyo <antoyo@users.noreply.github.com>2023-12-30 07:37:45 -0500
committerGitHub <noreply@github.com>2023-12-30 07:37:45 -0500
commita91d9e1dcead0b1b17affffc6da5a31ef7f5a2fd (patch)
tree6cf80448ac4b2bac7be62f2d82210d18612fe1d0
parentb2e0cc5cec26881586a557ecd89487881597bbf8 (diff)
parentc122376493e40dd494dac45614205c340141f005 (diff)
downloadrust-a91d9e1dcead0b1b17affffc6da5a31ef7f5a2fd.tar.gz
rust-a91d9e1dcead0b1b17affffc6da5a31ef7f5a2fd.zip
Merge pull request #405 from GuillaumeGomez/rustify-cargo-sh
Rustify `cargo.sh`
-rw-r--r--.github/workflows/stdarch.yml4
-rw-r--r--Readme.md10
-rw-r--r--build_system/src/cargo.rs114
-rw-r--r--build_system/src/main.rs5
-rw-r--r--build_system/src/test.rs2
-rw-r--r--build_system/src/utils.rs52
-rwxr-xr-xcargo.sh23
-rwxr-xr-xy.sh6
8 files changed, 175 insertions, 41 deletions
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..67b301d9aa6
--- /dev/null
+++ b/build_system/src/cargo.rs
@@ -0,0 +1,114 @@
+use crate::config::ConfigInfo;
+use crate::utils::{
+    get_toolchain, run_command_with_output_and_env_no_err, rustc_toolchain_version_info,
+    rustc_version_info,
+};
+
+use std::collections::HashMap;
+use std::ffi::OsStr;
+use std::path::PathBuf;
+
+fn args() -> Result<Option<Vec<String>>, 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::<Vec<_>>();
+    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()
+        .and_then(|path| path.canonicalize())
+        .map_err(|error| format!("Failed to get current directory path: {:?}", error))?;
+    let current_exe = std::env::current_exe()
+        .and_then(|path| path.canonicalize())
+        .map_err(|error| format!("Failed to get current exe path: {:?}", error))?;
+    let mut parent_dir = current_exe
+        .components()
+        .map(|comp| comp.as_os_str())
+        .collect::<Vec<_>>();
+    // We run this script from "build_system/target/release/y", so we need to remove these elements.
+    for to_remove in &["y", "release", "target", "build_system"] {
+        if parent_dir
+            .last()
+            .map(|part| part == to_remove)
+            .unwrap_or(false)
+        {
+            parent_dir.pop();
+        } else {
+            return Err(format!(
+                "Build script not executed from `build_system/target/release/y` (in path {})",
+                current_exe.display(),
+            ));
+        }
+    }
+    let parent_dir = PathBuf::from(parent_dir.join(&OsStr::new("/")));
+    std::env::set_current_dir(&parent_dir).map_err(|error| {
+        format!(
+            "Failed to go to `{}` folder: {:?}",
+            parent_dir.display(),
+            error
+        )
+    })?;
+
+    let mut env: HashMap<String, String> = 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(&current_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<OsStr>> = vec![&"cargo", &toolchain];
+    for arg in &args {
+        command.push(arg);
+    }
+    if run_command_with_output_and_env_no_err(&command, None, Some(&env)).is_err() {
+        std::process::exit(1);
+    }
+
+    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::env;
 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 @@ Available commands for build_system:
 }
 
 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..f0a07b597a0 100644
--- a/build_system/src/utils.rs
+++ b/build_system/src/utils.rs
@@ -30,6 +30,7 @@ fn check_exit_status(
     cwd: Option<&Path>,
     exit_status: ExitStatus,
     output: Option<&Output>,
+    show_err: bool,
 ) -> Result<(), String> {
     if exit_status.success() {
         return Ok(());
@@ -46,7 +47,9 @@ fn check_exit_status(
         exit_status.code()
     );
     let input = input.iter().map(|i| i.as_ref()).collect::<Vec<&OsStr>>();
-    eprintln!("Command `{:?}` failed", input);
+    if show_err {
+        eprintln!("Command `{:?}` failed", input);
+    }
     if let Some(output) = output {
         let stdout = String::from_utf8_lossy(&output.stdout);
         if !stdout.is_empty() {
@@ -88,7 +91,7 @@ pub fn run_command_with_env(
     let output = get_command_inner(input, cwd, env)
         .output()
         .map_err(|e| command_error(input, &cwd, e))?;
-    check_exit_status(input, cwd, output.status, Some(&output))?;
+    check_exit_status(input, cwd, output.status, Some(&output), true)?;
     Ok(output)
 }
 
@@ -101,7 +104,7 @@ pub fn run_command_with_output(
         .map_err(|e| command_error(input, &cwd, e))?
         .wait()
         .map_err(|e| command_error(input, &cwd, e))?;
-    check_exit_status(input, cwd, exit_status, None)?;
+    check_exit_status(input, cwd, exit_status, None, true)?;
     Ok(())
 }
 
@@ -115,7 +118,21 @@ pub fn run_command_with_output_and_env(
         .map_err(|e| command_error(input, &cwd, e))?
         .wait()
         .map_err(|e| command_error(input, &cwd, e))?;
-    check_exit_status(input, cwd, exit_status, None)?;
+    check_exit_status(input, cwd, exit_status, None, true)?;
+    Ok(())
+}
+
+pub fn run_command_with_output_and_env_no_err(
+    input: &[&dyn AsRef<OsStr>],
+    cwd: Option<&Path>,
+    env: Option<&HashMap<String, String>>,
+) -> Result<(), String> {
+    let exit_status = get_command_inner(input, cwd, env)
+        .spawn()
+        .map_err(|e| command_error(input, &cwd, e))?
+        .wait()
+        .map_err(|e| command_error(input, &cwd, e))?;
+    check_exit_status(input, cwd, exit_status, None, false)?;
     Ok(())
 }
 
@@ -158,21 +175,42 @@ pub fn get_os_name() -> Result<String, String> {
     }
 }
 
-#[derive(Default)]
+#[derive(Default, PartialEq)]
 pub struct RustcVersionInfo {
+    pub short: String,
     pub version: String,
     pub host: Option<String>,
     pub commit_hash: Option<String>,
     pub commit_date: Option<String>,
 }
 
+pub fn rustc_toolchain_version_info(toolchain: &str) -> Result<RustcVersionInfo, String> {
+    rustc_version_info_inner(None, Some(toolchain))
+}
+
 pub fn rustc_version_info(rustc: Option<&str>) -> Result<RustcVersionInfo, String> {
-    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<RustcVersionInfo, String> {
+    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 $@
diff --git a/y.sh b/y.sh
index 188109743e3..69d7917dd77 100755
--- a/y.sh
+++ b/y.sh
@@ -2,7 +2,7 @@
 
 set -e
 echo "[BUILD] build system" 1>&2
-cd build_system
+pushd $(dirname "$0")/build_system > /dev/null
 cargo build --release
-cd ..
-./build_system/target/release/y $@
+popd > /dev/null
+$(dirname "$0")/build_system/target/release/y $@