diff --git a/build_system/src/main.rs b/build_system/src/main.rs index 99d466f2b86..1bfba0f9828 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -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, @@ -76,6 +79,7 @@ fn main() { if let Err(e) = match command { 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 index 80885d0c6c7..242fa7ef949 100644 --- a/build_system/src/rust_tools.rs +++ b/build_system/src/rust_tools.rs @@ -9,7 +9,7 @@ use std::path::PathBuf; fn args(command: &str) -> Result>, String> { - // We skip the binary and the "cargo" option. + // 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); @@ -36,66 +36,90 @@ fn usage(command: &str) { ) } -pub fn run_cargo() -> Result<(), String> { - let args = match args("cargo")? { - Some(a) => a, - None => return Ok(()), - }; +struct RustcTools { + env: HashMap, + args: Vec, + toolchain: String, + config: ConfigInfo, +} - // 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(), - )); +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 })) } - 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 { +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(&env)).is_err() { + 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(()) +}