From 2640b316e2e64dd1c4a79ba81bd2da809ad47d41 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 9 Feb 2024 15:26:44 +0100 Subject: [PATCH] Switch to `config.toml` instead of `gcc-path` --- .gitignore | 1 + Readme.md | 22 ++++++-- build_system/Cargo.lock | 9 +++ build_system/Cargo.toml | 3 + build_system/src/build.rs | 25 +++++---- build_system/src/config.rs | 112 ++++++++++++++++++++++++++++++++++--- build_system/src/test.rs | 35 ++++++++---- build_system/src/utils.rs | 32 ----------- config.example.toml | 2 + 9 files changed, 173 insertions(+), 68 deletions(-) create mode 100644 config.example.toml 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 -$ dirname $(readlink -f `find . -name libgccjit.so`) > gcc_path +$ 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`) ``` 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 @@ -2,6 +2,15 @@ # It is not intended for manual editing. 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 @@ #[derive(Default)] struct BuildArg { flags: Vec, - gcc_path: String, config_info: ConfigInfo, } impl BuildArg { fn new() -> Result, 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, 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, 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> = 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 @@ pub fn as_str(self) -> &'static str { } } +fn failed_config_parsing(err: &str) -> Result { + Err(format!( + "Failed to parse `{}`: {}", + ConfigFile::CONFIG_FILE, + err + )) +} + +#[derive(Default)] +pub struct ConfigFile { + gcc_path: Option, + download_gccjit: Option, +} + +impl ConfigFile { + pub const CONFIG_FILE: &'static str = "config.toml"; + + pub fn new() -> Result { + 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 @@ pub fn rustc_command_vec(&self) -> Vec<&dyn AsRef> { 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, - 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 @@ pub fn setup( // 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, runners: BTreeSet, flags: Vec, backend: Option, @@ -181,12 +181,10 @@ fn new() -> Result, String> { } } - 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 = 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 { } } -pub fn get_gcc_path() -> Result { - 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