about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2024-02-09 15:26:44 +0100
committerGuillaume Gomez <guillaume1.gomez@gmail.com>2024-02-11 21:53:56 +0100
commit2640b316e2e64dd1c4a79ba81bd2da809ad47d41 (patch)
tree660cff2a02b0abb53719c7a274a8109ed9b078e9
parent357cae82ad36cd40a34050132adf28171a28539d (diff)
downloadrust-2640b316e2e64dd1c4a79ba81bd2da809ad47d41.tar.gz
rust-2640b316e2e64dd1c4a79ba81bd2da809ad47d41.zip
Switch to `config.toml` instead of `gcc-path`
-rw-r--r--.gitignore1
-rw-r--r--Readme.md22
-rw-r--r--build_system/Cargo.lock9
-rw-r--r--build_system/Cargo.toml3
-rw-r--r--build_system/src/build.rs25
-rw-r--r--build_system/src/config.rs112
-rw-r--r--build_system/src/test.rs35
-rw-r--r--build_system/src/utils.rs32
-rw-r--r--config.example.toml2
9 files changed, 173 insertions, 68 deletions
diff --git a/.gitignore b/.gitignore
index c865386dad3..687c3a6797a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,3 +28,4 @@ tools/llvmint-2
 # The `llvm` folder is generated by the `tools/generate_intrinsics.py` script to update intrinsics.
 llvm
 build_system/target
+config.toml
diff --git a/Readme.md b/Readme.md
index 39ff41acf84..a380d0d5be6 100644
--- a/Readme.md
+++ b/Readme.md
@@ -49,17 +49,27 @@ $ make check-jit
 $ make check-jit RUNTESTFLAGS="-v -v -v jit.exp=jit.dg/test-asm.cc"
 ```
 
-**Put the path to your custom build of libgccjit in the file `gcc_path`.**
+**Put the path to your custom build of libgccjit in the file `config.toml`.**
+
+If you followed the instructions exactly as written (ie, you have created a `gcc-build` folder
+where gcc is built), the only thing you need to do is:
+
+```bash
+$ cp config.example.toml config.toml
+```
+
+But if you did something different, you also need to set the `gcc-path` value in `config.toml` with
+the result of this command:
 
 ```bash
-$ dirname $(readlink -f `find . -name libgccjit.so`) > gcc_path
+$ dirname $(readlink -f `find . -name libgccjit.so`)
 ```
 
 Then you can run commands like this:
 
 ```bash
 $ ./y.sh prepare # download and patch sysroot src and install hyperfine for benchmarking
-$ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) ./y.sh build --release --features master
+$ ./y.sh build --release --features master
 ```
 
 To run the tests:
@@ -100,7 +110,7 @@ error: failed to copy bitcode to object file: No such file or directory (os erro
 > You should prefer using the Cargo method.
 
 ```bash
-$ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) rustc +$(cat $CG_GCCJIT_DIR/rust-toolchain | grep 'channel' | cut -d '=' -f 2 | sed 's/"//g' | sed 's/ //g') -Cpanic=abort -Zcodegen-backend=$CG_GCCJIT_DIR/target/release/librustc_codegen_gcc.so --sysroot $CG_GCCJIT_DIR/build_sysroot/sysroot my_crate.rs
+$ LIBRARY_PATH="[gcc-path value]" LD_LIBRARY_PATH="[gcc-path value]" rustc +$(cat $CG_GCCJIT_DIR/rust-toolchain | grep 'channel' | cut -d '=' -f 2 | sed 's/"//g' | sed 's/ //g') -Cpanic=abort -Zcodegen-backend=$CG_GCCJIT_DIR/target/release/librustc_codegen_gcc.so --sysroot $CG_GCCJIT_DIR/build_sysroot/sysroot my_crate.rs
 ```
 
 ## Env vars
@@ -322,7 +332,7 @@ generate it in [gimple.md](./doc/gimple.md).
 #### Configuring rustc_codegen_gcc
 
  * 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`.
+ * Set the path to the cross-compiling libgccjit in `gcc-path` (in `config.toml`).
  * 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 ../y.sh cargo build --target m68k-unknown-linux-gnu`.
 
@@ -338,4 +348,4 @@ If you get the following error:
 /usr/bin/ld: unrecognised emulation mode: m68kelf
 ```
 
-Make sure you set `gcc_path` to the install directory.
+Make sure you set `gcc-path` (in `config.toml`) to the install directory.
diff --git a/build_system/Cargo.lock b/build_system/Cargo.lock
index 86268e19160..e727561a2bf 100644
--- a/build_system/Cargo.lock
+++ b/build_system/Cargo.lock
@@ -3,5 +3,14 @@
 version = 3
 
 [[package]]
+name = "boml"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85fdb93f04c73bff54305fa437ffea5449c41edcaadfe882f35836206b166ac5"
+
+[[package]]
 name = "y"
 version = "0.1.0"
+dependencies = [
+ "boml",
+]
diff --git a/build_system/Cargo.toml b/build_system/Cargo.toml
index f36709ea036..d2600ed5a03 100644
--- a/build_system/Cargo.toml
+++ b/build_system/Cargo.toml
@@ -3,6 +3,9 @@ name = "y"
 version = "0.1.0"
 edition = "2021"
 
+[dependencies]
+boml = "0.3.1"
+
 [[bin]]
 name = "y"
 path = "src/main.rs"
diff --git a/build_system/src/build.rs b/build_system/src/build.rs
index 3149560b458..efae5a46b04 100644
--- a/build_system/src/build.rs
+++ b/build_system/src/build.rs
@@ -1,5 +1,5 @@
 use crate::config::{Channel, ConfigInfo};
-use crate::utils::{get_gcc_path, run_command, run_command_with_output_and_env, walk_dir};
+use crate::utils::{run_command, run_command_with_output_and_env, walk_dir};
 use std::collections::HashMap;
 use std::ffi::OsStr;
 use std::fs;
@@ -8,17 +8,12 @@ use std::path::Path;
 #[derive(Default)]
 struct BuildArg {
     flags: Vec<String>,
-    gcc_path: String,
     config_info: ConfigInfo,
 }
 
 impl BuildArg {
     fn new() -> Result<Option<Self>, String> {
-        let gcc_path = get_gcc_path()?;
-        let mut build_arg = Self {
-            gcc_path,
-            ..Default::default()
-        };
+        let mut build_arg = Self::default();
         // We skip binary name and the `build` command.
         let mut args = std::env::args().skip(2);
 
@@ -169,7 +164,8 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
     fs::create_dir_all(&sysroot_src_path).map_err(|error| {
         format!(
             "Failed to create directory `{}`: {:?}",
-            sysroot_src_path.display(), error
+            sysroot_src_path.display(),
+            error
         )
     })?;
     run_command(
@@ -188,8 +184,14 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
 fn build_codegen(args: &mut BuildArg) -> Result<(), String> {
     let mut env = HashMap::new();
 
-    env.insert("LD_LIBRARY_PATH".to_string(), args.gcc_path.clone());
-    env.insert("LIBRARY_PATH".to_string(), args.gcc_path.clone());
+    env.insert(
+        "LD_LIBRARY_PATH".to_string(),
+        args.config_info.gcc_path.clone(),
+    );
+    env.insert(
+        "LIBRARY_PATH".to_string(),
+        args.config_info.gcc_path.clone(),
+    );
 
     let mut command: Vec<&dyn AsRef<OsStr>> = vec![&"cargo", &"rustc"];
     if args.config_info.channel == Channel::Release {
@@ -205,7 +207,7 @@ fn build_codegen(args: &mut BuildArg) -> Result<(), String> {
     }
     run_command_with_output_and_env(&command, None, Some(&env))?;
 
-    args.config_info.setup(&mut env, Some(&args.gcc_path))?;
+    args.config_info.setup(&mut env, None)?;
 
     // We voluntarily ignore the error.
     let _ = fs::remove_dir_all("target/out");
@@ -227,6 +229,7 @@ pub fn run() -> Result<(), String> {
         Some(args) => args,
         None => return Ok(()),
     };
+    args.config_info.setup_gcc_path(None)?;
     build_codegen(&mut args)?;
     Ok(())
 }
diff --git a/build_system/src/config.rs b/build_system/src/config.rs
index 1824bdd292f..09fa3ee9d3b 100644
--- a/build_system/src/config.rs
+++ b/build_system/src/config.rs
@@ -1,7 +1,11 @@
-use crate::utils::{get_gcc_path, get_os_name, rustc_version_info, split_args};
+use crate::utils::{get_os_name, rustc_version_info, split_args};
 use std::collections::HashMap;
 use std::env as std_env;
 use std::ffi::OsStr;
+use std::fs;
+use std::path::Path;
+
+use boml::{types::TomlValue, Toml};
 
 #[derive(Default, PartialEq, Eq, Clone, Copy, Debug)]
 pub enum Channel {
@@ -19,6 +23,72 @@ impl Channel {
     }
 }
 
+fn failed_config_parsing(err: &str) -> Result<ConfigFile, String> {
+    Err(format!(
+        "Failed to parse `{}`: {}",
+        ConfigFile::CONFIG_FILE,
+        err
+    ))
+}
+
+#[derive(Default)]
+pub struct ConfigFile {
+    gcc_path: Option<String>,
+    download_gccjit: Option<bool>,
+}
+
+impl ConfigFile {
+    pub const CONFIG_FILE: &'static str = "config.toml";
+
+    pub fn new() -> Result<Self, String> {
+        let content = fs::read_to_string(Self::CONFIG_FILE).map_err(|_| {
+            format!(
+                "Failed to read `{}`. Take a look at `Readme.md` to see how to set up the project",
+                Self::CONFIG_FILE,
+            )
+        })?;
+        let toml = Toml::parse(&content).map_err(|err| {
+            format!(
+                "Error occurred around `{}`: {:?}",
+                &content[err.start..=err.end],
+                err.kind
+            )
+        })?;
+        let mut config = Self::default();
+        for (key, value) in toml.iter() {
+            match (key, value) {
+                ("gcc-path", TomlValue::String(value)) => {
+                    config.gcc_path = Some(value.as_str().to_string())
+                }
+                ("gcc-path", _) => {
+                    return failed_config_parsing("Expected a string for `gcc-path`")
+                }
+                ("download-gccjit", TomlValue::Boolean(value)) => {
+                    config.download_gccjit = Some(*value)
+                }
+                ("download-gccjit", _) => {
+                    return failed_config_parsing("Expected a boolean for `download-gccjit`")
+                }
+                _ => return failed_config_parsing(&format!("Unknown key `{}`", key)),
+            }
+        }
+        if config.gcc_path.is_none() && config.download_gccjit.is_none() {
+            return failed_config_parsing(
+                "At least one of `gcc-path` or `download-gccjit` value must be set",
+            );
+        }
+        if let Some(gcc_path) = config.gcc_path.as_mut() {
+            let path = Path::new(gcc_path);
+            *gcc_path = path
+                .canonicalize()
+                .map_err(|err| format!("Failed to get absolute path of `{}`: {:?}", gcc_path, err))?
+                .display()
+                .to_string();
+        }
+        Ok(config)
+    }
+}
+
 #[derive(Default, Debug)]
 pub struct ConfigInfo {
     pub target: String,
@@ -33,6 +103,7 @@ pub struct ConfigInfo {
     pub sysroot_panic_abort: bool,
     pub cg_backend_path: String,
     pub sysroot_path: String,
+    pub gcc_path: String,
 }
 
 impl ConfigInfo {
@@ -80,18 +151,43 @@ impl ConfigInfo {
         command
     }
 
+    pub fn setup_gcc_path(&mut self, override_gcc_path: Option<&str>) -> Result<(), String> {
+        let ConfigFile { gcc_path, .. } = ConfigFile::new()?;
+
+        self.gcc_path = match override_gcc_path {
+            Some(path) => {
+                if gcc_path.is_some() {
+                    println!("overriding setting from `{}`", ConfigFile::CONFIG_FILE);
+                }
+                path.to_string()
+            }
+            None => {
+                match gcc_path {
+                    Some(path) => path,
+                    // FIXME: Once we support "download", rewrite this.
+                    None => {
+                        return Err(format!(
+                            "missing `gcc-path` value from `{}`",
+                            ConfigFile::CONFIG_FILE
+                        ))
+                    }
+                }
+            }
+        };
+        Ok(())
+    }
+
     pub fn setup(
         &mut self,
         env: &mut HashMap<String, String>,
-        gcc_path: Option<&str>,
+        override_gcc_path: Option<&str>,
     ) -> Result<(), String> {
         env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string());
 
-        let gcc_path = match gcc_path {
-            Some(path) => path.to_string(),
-            None => get_gcc_path()?,
-        };
-        env.insert("GCC_PATH".to_string(), gcc_path.clone());
+        if self.gcc_path.is_empty() || override_gcc_path.is_some() {
+            self.setup_gcc_path(override_gcc_path)?;
+        }
+        env.insert("GCC_PATH".to_string(), self.gcc_path.clone());
 
         if self.cargo_target_dir.is_empty() {
             match env.get("CARGO_TARGET_DIR").filter(|dir| !dir.is_empty()) {
@@ -225,7 +321,9 @@ impl ConfigInfo {
             // line option to change it.
             target = current_dir.join("target/out").display(),
             sysroot = sysroot.display(),
+            gcc_path = self.gcc_path,
         );
+        env.insert("LIBRARY_PATH".to_string(), ld_library_path.clone());
         env.insert("LD_LIBRARY_PATH".to_string(), ld_library_path.clone());
         env.insert("DYLD_LIBRARY_PATH".to_string(), ld_library_path);
 
diff --git a/build_system/src/test.rs b/build_system/src/test.rs
index 65643229243..1cacd6efc7f 100644
--- a/build_system/src/test.rs
+++ b/build_system/src/test.rs
@@ -1,7 +1,7 @@
 use crate::build;
 use crate::config::{Channel, ConfigInfo};
 use crate::utils::{
-    get_gcc_path, get_toolchain, git_clone, remove_file, run_command, run_command_with_env,
+    get_toolchain, git_clone, remove_file, run_command, run_command_with_env,
     run_command_with_output_and_env, rustc_version_info, split_args, walk_dir,
 };
 
@@ -109,7 +109,7 @@ fn show_usage() {
 struct TestArg {
     no_default_features: bool,
     build_only: bool,
-    gcc_path: String,
+    gcc_path: Option<String>,
     runners: BTreeSet<String>,
     flags: Vec<String>,
     backend: Option<String>,
@@ -181,12 +181,10 @@ impl TestArg {
                 }
             }
 
-            test_arg.gcc_path = if use_system_gcc {
+            if use_system_gcc {
                 println!("Using system GCC");
-                "gcc".to_string()
-            } else {
-                get_gcc_path()?
-            };
+                test_arg.gcc_path = Some("gcc".to_string());
+            }
         }
         match (test_arg.current_part, test_arg.nb_parts) {
             (Some(_), Some(_)) | (None, None) => {}
@@ -488,7 +486,8 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> {
 }
 
 fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<(), String> {
-    let toolchain = format!("+{channel}-{host}",
+    let toolchain = format!(
+        "+{channel}-{host}",
         channel = get_toolchain()?, // May also include date
         host = args.config_info.host_triple
     );
@@ -527,7 +526,12 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<(), String> {
         }
     })?;
     let rustc = String::from_utf8(
-        run_command_with_env(&[&"rustup", &toolchain, &"which", &"rustc"], rust_dir, Some(env))?.stdout,
+        run_command_with_env(
+            &[&"rustup", &toolchain, &"which", &"rustc"],
+            rust_dir,
+            Some(env),
+        )?
+        .stdout,
     )
     .map_err(|error| format!("Failed to retrieve rustc path: {:?}", error))
     .and_then(|rustc| {
@@ -1162,8 +1166,15 @@ pub fn run() -> Result<(), String> {
     };
     let mut env: HashMap<String, String> = std::env::vars().collect();
 
-    env.insert("LD_LIBRARY_PATH".to_string(), args.gcc_path.clone());
-    env.insert("LIBRARY_PATH".to_string(), args.gcc_path.clone());
+    args.config_info.setup_gcc_path(None)?;
+    env.insert(
+        "LIBRARY_PATH".to_string(),
+        args.config_info.gcc_path.clone(),
+    );
+    env.insert(
+        "LD_LIBRARY_PATH".to_string(),
+        args.config_info.gcc_path.clone(),
+    );
 
     build_if_no_backend(&env, &args)?;
     if args.build_only {
@@ -1171,7 +1182,7 @@ pub fn run() -> Result<(), String> {
         return Ok(());
     }
 
-    args.config_info.setup(&mut env, Some(&args.gcc_path))?;
+    args.config_info.setup(&mut env, args.gcc_path.as_deref())?;
 
     if args.runners.is_empty() {
         run_all(&env, &args)?;
diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs
index 85f1e18006c..b288eff94a5 100644
--- a/build_system/src/utils.rs
+++ b/build_system/src/utils.rs
@@ -248,38 +248,6 @@ pub fn get_toolchain() -> Result<String, String> {
     }
 }
 
-pub fn get_gcc_path() -> Result<String, String> {
-    let content = match fs::read_to_string("gcc_path") {
-        Ok(content) => content,
-        Err(_) => {
-            return Err(
-                "Please put the path to your custom build of libgccjit in the file \
-                   `gcc_path`, see Readme.md for details"
-                    .into(),
-            )
-        }
-    };
-    match content
-        .split('\n')
-        .map(|line| line.trim())
-        .filter(|line| !line.is_empty())
-        .next()
-    {
-        Some(gcc_path) => {
-            let path = Path::new(gcc_path);
-            if !path.exists() {
-                Err(format!(
-                    "Path `{}` contained in the `gcc_path` file doesn't exist",
-                    gcc_path,
-                ))
-            } else {
-                Ok(gcc_path.into())
-            }
-        }
-        None => Err("No path found in `gcc_path` file".into()),
-    }
-}
-
 pub struct CloneResult {
     pub ran_clone: bool,
     pub repo_name: String,
diff --git a/config.example.toml b/config.example.toml
new file mode 100644
index 00000000000..dcc414b7310
--- /dev/null
+++ b/config.example.toml
@@ -0,0 +1,2 @@
+gcc-path = "gcc-build/gcc"
+# download-gccjit = true