Switch to config.toml instead of gcc-path

This commit is contained in:
Guillaume Gomez 2024-02-09 15:26:44 +01:00
parent 357cae82ad
commit 2640b316e2
9 changed files with 173 additions and 68 deletions

1
.gitignore vendored
View File

@ -28,3 +28,4 @@ tools/llvmint-2
# The `llvm` folder is generated by the `tools/generate_intrinsics.py` script to update intrinsics. # The `llvm` folder is generated by the `tools/generate_intrinsics.py` script to update intrinsics.
llvm llvm
build_system/target build_system/target
config.toml

View File

@ -49,17 +49,27 @@ $ make check-jit
$ make check-jit RUNTESTFLAGS="-v -v -v jit.exp=jit.dg/test-asm.cc" $ 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 ```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: Then you can run commands like this:
```bash ```bash
$ ./y.sh prepare # download and patch sysroot src and install hyperfine for benchmarking $ ./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: 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. > You should prefer using the Cargo method.
```bash ```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 ## Env vars
@ -322,7 +332,7 @@ generate it in [gimple.md](./doc/gimple.md).
#### Configuring rustc_codegen_gcc #### Configuring rustc_codegen_gcc
* Run `./y.sh prepare --cross` so that the sysroot is patched for the cross-compiling case. * 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`. * 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`. * 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 /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.

View File

@ -2,6 +2,15 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "boml"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85fdb93f04c73bff54305fa437ffea5449c41edcaadfe882f35836206b166ac5"
[[package]] [[package]]
name = "y" name = "y"
version = "0.1.0" version = "0.1.0"
dependencies = [
"boml",
]

View File

@ -3,6 +3,9 @@ name = "y"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies]
boml = "0.3.1"
[[bin]] [[bin]]
name = "y" name = "y"
path = "src/main.rs" path = "src/main.rs"

View File

@ -1,5 +1,5 @@
use crate::config::{Channel, ConfigInfo}; 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::collections::HashMap;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::fs; use std::fs;
@ -8,17 +8,12 @@
#[derive(Default)] #[derive(Default)]
struct BuildArg { struct BuildArg {
flags: Vec<String>, flags: Vec<String>,
gcc_path: String,
config_info: ConfigInfo, config_info: ConfigInfo,
} }
impl BuildArg { impl BuildArg {
fn new() -> Result<Option<Self>, String> { fn new() -> Result<Option<Self>, String> {
let gcc_path = get_gcc_path()?; let mut build_arg = Self::default();
let mut build_arg = Self {
gcc_path,
..Default::default()
};
// We skip binary name and the `build` command. // We skip binary name and the `build` command.
let mut args = std::env::args().skip(2); 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| { fs::create_dir_all(&sysroot_src_path).map_err(|error| {
format!( format!(
"Failed to create directory `{}`: {:?}", "Failed to create directory `{}`: {:?}",
sysroot_src_path.display(), error sysroot_src_path.display(),
error
) )
})?; })?;
run_command( 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> { fn build_codegen(args: &mut BuildArg) -> Result<(), String> {
let mut env = HashMap::new(); let mut env = HashMap::new();
env.insert("LD_LIBRARY_PATH".to_string(), args.gcc_path.clone()); env.insert(
env.insert("LIBRARY_PATH".to_string(), args.gcc_path.clone()); "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"]; let mut command: Vec<&dyn AsRef<OsStr>> = vec![&"cargo", &"rustc"];
if args.config_info.channel == Channel::Release { 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))?; 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. // We voluntarily ignore the error.
let _ = fs::remove_dir_all("target/out"); let _ = fs::remove_dir_all("target/out");
@ -227,6 +229,7 @@ pub fn run() -> Result<(), String> {
Some(args) => args, Some(args) => args,
None => return Ok(()), None => return Ok(()),
}; };
args.config_info.setup_gcc_path(None)?;
build_codegen(&mut args)?; build_codegen(&mut args)?;
Ok(()) Ok(())
} }

View File

@ -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::collections::HashMap;
use std::env as std_env; use std::env as std_env;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::fs;
use std::path::Path;
use boml::{types::TomlValue, Toml};
#[derive(Default, PartialEq, Eq, Clone, Copy, Debug)] #[derive(Default, PartialEq, Eq, Clone, Copy, Debug)]
pub enum Channel { pub enum Channel {
@ -19,6 +23,72 @@ pub fn as_str(self) -> &'static str {
} }
} }
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)] #[derive(Default, Debug)]
pub struct ConfigInfo { pub struct ConfigInfo {
pub target: String, pub target: String,
@ -33,6 +103,7 @@ pub struct ConfigInfo {
pub sysroot_panic_abort: bool, pub sysroot_panic_abort: bool,
pub cg_backend_path: String, pub cg_backend_path: String,
pub sysroot_path: String, pub sysroot_path: String,
pub gcc_path: String,
} }
impl ConfigInfo { impl ConfigInfo {
@ -80,18 +151,43 @@ pub fn rustc_command_vec(&self) -> Vec<&dyn AsRef<OsStr>> {
command 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( pub fn setup(
&mut self, &mut self,
env: &mut HashMap<String, String>, env: &mut HashMap<String, String>,
gcc_path: Option<&str>, override_gcc_path: Option<&str>,
) -> Result<(), String> { ) -> Result<(), String> {
env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string()); env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string());
let gcc_path = match gcc_path { if self.gcc_path.is_empty() || override_gcc_path.is_some() {
Some(path) => path.to_string(), self.setup_gcc_path(override_gcc_path)?;
None => get_gcc_path()?, }
}; env.insert("GCC_PATH".to_string(), self.gcc_path.clone());
env.insert("GCC_PATH".to_string(), gcc_path.clone());
if self.cargo_target_dir.is_empty() { if self.cargo_target_dir.is_empty() {
match env.get("CARGO_TARGET_DIR").filter(|dir| !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. // line option to change it.
target = current_dir.join("target/out").display(), target = current_dir.join("target/out").display(),
sysroot = sysroot.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("LD_LIBRARY_PATH".to_string(), ld_library_path.clone());
env.insert("DYLD_LIBRARY_PATH".to_string(), ld_library_path); env.insert("DYLD_LIBRARY_PATH".to_string(), ld_library_path);

View File

@ -1,7 +1,7 @@
use crate::build; use crate::build;
use crate::config::{Channel, ConfigInfo}; use crate::config::{Channel, ConfigInfo};
use crate::utils::{ 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, run_command_with_output_and_env, rustc_version_info, split_args, walk_dir,
}; };
@ -109,7 +109,7 @@ fn show_usage() {
struct TestArg { struct TestArg {
no_default_features: bool, no_default_features: bool,
build_only: bool, build_only: bool,
gcc_path: String, gcc_path: Option<String>,
runners: BTreeSet<String>, runners: BTreeSet<String>,
flags: Vec<String>, flags: Vec<String>,
backend: Option<String>, backend: Option<String>,
@ -181,12 +181,10 @@ fn new() -> Result<Option<Self>, String> {
} }
} }
test_arg.gcc_path = if use_system_gcc { if use_system_gcc {
println!("Using system GCC"); println!("Using system GCC");
"gcc".to_string() test_arg.gcc_path = Some("gcc".to_string());
} else { }
get_gcc_path()?
};
} }
match (test_arg.current_part, test_arg.nb_parts) { match (test_arg.current_part, test_arg.nb_parts) {
(Some(_), Some(_)) | (None, None) => {} (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> { 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 channel = get_toolchain()?, // May also include date
host = args.config_info.host_triple 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( 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)) .map_err(|error| format!("Failed to retrieve rustc path: {:?}", error))
.and_then(|rustc| { .and_then(|rustc| {
@ -1162,8 +1166,15 @@ pub fn run() -> Result<(), String> {
}; };
let mut env: HashMap<String, String> = std::env::vars().collect(); let mut env: HashMap<String, String> = std::env::vars().collect();
env.insert("LD_LIBRARY_PATH".to_string(), args.gcc_path.clone()); args.config_info.setup_gcc_path(None)?;
env.insert("LIBRARY_PATH".to_string(), args.gcc_path.clone()); 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)?; build_if_no_backend(&env, &args)?;
if args.build_only { if args.build_only {
@ -1171,7 +1182,7 @@ pub fn run() -> Result<(), String> {
return Ok(()); 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() { if args.runners.is_empty() {
run_all(&env, &args)?; run_all(&env, &args)?;

View File

@ -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 struct CloneResult {
pub ran_clone: bool, pub ran_clone: bool,
pub repo_name: String, pub repo_name: String,

2
config.example.toml Normal file
View File

@ -0,0 +1,2 @@
gcc-path = "gcc-build/gcc"
# download-gccjit = true