diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-07 05:48:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-07 05:48:48 +0000 |
commit | ef24de24a82fe681581cc130f342363c47c0969a (patch) | |
tree | 0d494f7e1a38b95c92426f58fe6eaa877303a86c /compiler/rustc_codegen_gcc/build_system/src/build.rs | |
parent | Releasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip |
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_codegen_gcc/build_system/src/build.rs')
-rw-r--r-- | compiler/rustc_codegen_gcc/build_system/src/build.rs | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/compiler/rustc_codegen_gcc/build_system/src/build.rs b/compiler/rustc_codegen_gcc/build_system/src/build.rs new file mode 100644 index 000000000..eaca7a987 --- /dev/null +++ b/compiler/rustc_codegen_gcc/build_system/src/build.rs @@ -0,0 +1,248 @@ +use crate::config::{set_config, ConfigInfo}; +use crate::utils::{ + get_gcc_path, run_command, run_command_with_output_and_env, walk_dir, +}; +use std::collections::HashMap; +use std::ffi::OsStr; +use std::fs; +use std::path::Path; + +#[derive(Default)] +struct BuildArg { + codegen_release_channel: bool, + sysroot_release_channel: bool, + sysroot_panic_abort: bool, + flags: Vec<String>, + gcc_path: String, +} + +impl BuildArg { + fn new() -> Result<Option<Self>, String> { + let gcc_path = get_gcc_path()?; + let mut build_arg = Self { + gcc_path, + ..Default::default() + }; + // We skip binary name and the `build` command. + let mut args = std::env::args().skip(2); + + while let Some(arg) = args.next() { + match arg.as_str() { + "--release" => build_arg.codegen_release_channel = true, + "--release-sysroot" => build_arg.sysroot_release_channel = true, + "--no-default-features" => { + build_arg.flags.push("--no-default-features".to_string()); + } + "--sysroot-panic-abort" => { + build_arg.sysroot_panic_abort = true; + }, + "--features" => { + if let Some(arg) = args.next() { + build_arg.flags.push("--features".to_string()); + build_arg.flags.push(arg.as_str().into()); + } else { + return Err( + "Expected a value after `--features`, found nothing".to_string() + ); + } + } + "--help" => { + Self::usage(); + return Ok(None); + } + "--target-triple" => { + if args.next().is_some() { + // Handled in config.rs. + } else { + return Err( + "Expected a value after `--target-triple`, found nothing".to_string() + ); + } + } + "--target" => { + if args.next().is_some() { + // Handled in config.rs. + } else { + return Err( + "Expected a value after `--target`, found nothing".to_string() + ); + } + } + arg => return Err(format!("Unknown argument `{}`", arg)), + } + } + Ok(Some(build_arg)) + } + + fn usage() { + println!( + r#" +`build` command help: + + --release : Build codegen in release mode + --release-sysroot : Build sysroot in release mode + --sysroot-panic-abort : Build the sysroot without unwinding support. + --no-default-features : Add `--no-default-features` flag + --features [arg] : Add a new feature [arg] + --target-triple [arg] : Set the target triple to [arg] + --help : Show this help +"# + ) + } +} + +fn build_sysroot( + env: &mut HashMap<String, String>, + args: &BuildArg, + config: &ConfigInfo, +) -> Result<(), String> { + std::env::set_current_dir("build_sysroot") + .map_err(|error| format!("Failed to go to `build_sysroot` directory: {:?}", error))?; + // Cleanup for previous run + // Clean target dir except for build scripts and incremental cache + let _ = walk_dir( + "target", + |dir: &Path| { + for top in &["debug", "release"] { + let _ = fs::remove_dir_all(dir.join(top).join("build")); + let _ = fs::remove_dir_all(dir.join(top).join("deps")); + let _ = fs::remove_dir_all(dir.join(top).join("examples")); + let _ = fs::remove_dir_all(dir.join(top).join("native")); + + let _ = walk_dir( + dir.join(top), + |sub_dir: &Path| { + if sub_dir + .file_name() + .map(|filename| filename.to_str().unwrap().starts_with("libsysroot")) + .unwrap_or(false) + { + let _ = fs::remove_dir_all(sub_dir); + } + Ok(()) + }, + |file: &Path| { + if file + .file_name() + .map(|filename| filename.to_str().unwrap().starts_with("libsysroot")) + .unwrap_or(false) + { + let _ = fs::remove_file(file); + } + Ok(()) + }, + ); + } + Ok(()) + }, + |_| Ok(()), + ); + + let _ = fs::remove_file("Cargo.lock"); + let _ = fs::remove_file("test_target/Cargo.lock"); + let _ = fs::remove_dir_all("sysroot"); + + // Builds libs + let mut rustflags = env + .get("RUSTFLAGS") + .cloned() + .unwrap_or_default(); + if args.sysroot_panic_abort { + rustflags.push_str(" -Cpanic=abort -Zpanic-abort-tests"); + } + env.insert( + "RUSTFLAGS".to_string(), + format!("{} -Zmir-opt-level=3", rustflags), + ); + let channel = if args.sysroot_release_channel { + run_command_with_output_and_env( + &[ + &"cargo", + &"build", + &"--target", + &config.target, + &"--release", + ], + None, + Some(&env), + )?; + "release" + } else { + run_command_with_output_and_env( + &[ + &"cargo", + &"build", + &"--target", + &config.target, + ], + None, + Some(env), + )?; + "debug" + }; + + // Copy files to sysroot + let sysroot_path = format!("sysroot/lib/rustlib/{}/lib/", config.target_triple); + fs::create_dir_all(&sysroot_path) + .map_err(|error| format!("Failed to create directory `{}`: {:?}", sysroot_path, error))?; + let copier = |dir_to_copy: &Path| { + run_command(&[&"cp", &"-r", &dir_to_copy, &sysroot_path], None).map(|_| ()) + }; + walk_dir( + &format!("target/{}/{}/deps", config.target_triple, channel), + copier, + copier, + )?; + + Ok(()) +} + +fn build_codegen(args: &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()); + + let mut command: Vec<&dyn AsRef<OsStr>> = vec![&"cargo", &"rustc"]; + if args.codegen_release_channel { + command.push(&"--release"); + env.insert("CHANNEL".to_string(), "release".to_string()); + env.insert("CARGO_INCREMENTAL".to_string(), "1".to_string()); + } else { + env.insert("CHANNEL".to_string(), "debug".to_string()); + } + let flags = args.flags.iter().map(|s| s.as_str()).collect::<Vec<_>>(); + for flag in &flags { + command.push(flag); + } + run_command_with_output_and_env(&command, None, Some(&env))?; + + let config = set_config(&mut env, &[], Some(&args.gcc_path))?; + + // We voluntarily ignore the error. + let _ = fs::remove_dir_all("target/out"); + let gccjit_target = "target/out/gccjit"; + fs::create_dir_all(gccjit_target).map_err(|error| { + format!( + "Failed to create directory `{}`: {:?}", + gccjit_target, error + ) + })?; + + println!("[BUILD] sysroot"); + build_sysroot( + &mut env, + args, + &config, + )?; + Ok(()) +} + +pub fn run() -> Result<(), String> { + let args = match BuildArg::new()? { + Some(args) => args, + None => return Ok(()), + }; + build_codegen(&args)?; + Ok(()) +} |