diff --git a/Readme.md b/Readme.md index da6e91587fd..92916079959 100644 --- a/Readme.md +++ b/Readme.md @@ -118,7 +118,13 @@ error: failed to copy bitcode to object file: No such file or directory (os erro ### Rustc -> You should prefer using the Cargo method. +If you want to run `rustc` directly, you can do so with: + +```bash +$ ./y.sh rustc my_crate.rs +``` + +You can do the same manually (although we don't recommend it): ```bash $ 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 diff --git a/build_system/src/cargo.rs b/build_system/src/cargo.rs deleted file mode 100644 index e4ea79b06f2..00000000000 --- a/build_system/src/cargo.rs +++ /dev/null @@ -1,97 +0,0 @@ -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>, 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() - .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::>(); - // 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 = std::env::vars().collect(); - ConfigInfo::default().setup(&mut env, false)?; - 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); - } - 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 48ffbc7a907..1bfba0f9828 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -2,12 +2,12 @@ use std::process; mod build; -mod cargo; mod clean; mod clone_gcc; mod config; mod info; mod prepare; +mod rust_tools; mod rustc_info; mod test; mod utils; @@ -29,6 +29,7 @@ fn usage() { Available commands for build_system: cargo : Run cargo command + rustc : Run rustc command clean : Run clean command prepare : Run prepare command build : Run build command @@ -45,6 +46,7 @@ pub enum Command { CloneGcc, Prepare, Build, + Rustc, Test, Info, } @@ -56,6 +58,7 @@ fn main() { let command = match env::args().nth(1).as_deref() { Some("cargo") => Command::Cargo, + Some("rustc") => Command::Rustc, Some("clean") => Command::Clean, Some("prepare") => Command::Prepare, Some("build") => Command::Build, @@ -75,7 +78,8 @@ fn main() { }; if let Err(e) = match command { - Command::Cargo => cargo::run(), + Command::Cargo => rust_tools::run_cargo(), + Command::Rustc => rust_tools::run_rustc(), Command::Clean => clean::run(), Command::Prepare => prepare::run(), Command::Build => build::run(), diff --git a/build_system/src/rust_tools.rs b/build_system/src/rust_tools.rs new file mode 100644 index 00000000000..242fa7ef949 --- /dev/null +++ b/build_system/src/rust_tools.rs @@ -0,0 +1,125 @@ +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(command: &str) -> Result>, String> { + // We skip the binary and the "cargo"/"rustc" option. + if let Some("--help") = std::env::args().skip(2).next().as_deref() { + usage(command); + return Ok(None); + } + let args = std::env::args().skip(2).collect::>(); + if args.is_empty() { + return Err(format!( + "Expected at least one argument for `{}` subcommand, found none", + command + )); + } + Ok(Some(args)) +} + +fn usage(command: &str) { + println!( + r#" +`{}` command help: + + [args] : Arguments to be passed to the cargo command + --help : Show this help +"#, + command, + ) +} + +struct RustcTools { + env: HashMap, + args: Vec, + toolchain: String, + config: ConfigInfo, +} + +impl RustcTools { + fn new(command: &str) -> Result, String> { + let Some(args) = args(command)? else { return Ok(None) }; + + // 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::>(); + // 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 = std::env::vars().collect(); + let mut config = ConfigInfo::default(); + config.setup(&mut env, false)?; + 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 toolchain = format!("+{}", toolchain); + Ok(Some(Self { toolchain, args, env, config })) + } +} + +pub fn run_cargo() -> Result<(), String> { + let Some(mut tools) = RustcTools::new("cargo")? else { return Ok(()) }; + let rustflags = tools.env.get("RUSTFLAGS").cloned().unwrap_or_default(); + tools.env.insert("RUSTDOCFLAGS".to_string(), rustflags); + let mut command: Vec<&dyn AsRef> = vec![&"cargo", &tools.toolchain]; + for arg in &tools.args { + command.push(arg); + } + if run_command_with_output_and_env_no_err(&command, None, Some(&tools.env)).is_err() { + std::process::exit(1); + } + + Ok(()) +} + +pub fn run_rustc() -> Result<(), String> { + let Some(tools) = RustcTools::new("rustc")? else { return Ok(()) }; + let mut command = tools.config.rustc_command_vec(); + for arg in &tools.args { + command.push(arg); + } + if run_command_with_output_and_env_no_err(&command, None, Some(&tools.env)).is_err() { + std::process::exit(1); + } + Ok(()) +}