| // This test ensures we are able to compile -Zbuild-std=core under a variety of profiles. |
| // Currently, it tests that we can compile to all Tier 1 targets, and it does this by checking what |
| // the tier metadata in target-spec JSON. This means that all in-tree targets must have a tier set. |
| |
| #![deny(warnings)] |
| |
| use std::collections::HashMap; |
| use std::sync::{Arc, Mutex}; |
| use std::thread; |
| |
| use run_make_support::serde_json::{self, Value}; |
| use run_make_support::tempfile::TempDir; |
| use run_make_support::{cargo, rfs, rustc}; |
| |
| #[derive(Clone)] |
| struct Task { |
| target: String, |
| opt_level: u8, |
| debug: u8, |
| panic: &'static str, |
| } |
| |
| fn manifest(task: &Task) -> String { |
| let Task { opt_level, debug, panic, target: _ } = task; |
| format!( |
| r#"[package] |
| name = "scratch" |
| version = "0.1.0" |
| edition = "2024" |
| |
| [lib] |
| path = "lib.rs" |
| |
| [profile.release] |
| opt-level = {opt_level} |
| debug = {debug} |
| panic = "{panic}" |
| "# |
| ) |
| } |
| |
| fn main() { |
| let mut targets = Vec::new(); |
| let all_targets = |
| rustc().args(&["--print=all-target-specs-json", "-Zunstable-options"]).run().stdout_utf8(); |
| let all_targets: HashMap<String, Value> = serde_json::from_str(&all_targets).unwrap(); |
| for (target, spec) in all_targets { |
| let metadata = spec.as_object().unwrap()["metadata"].as_object().unwrap(); |
| let tier = metadata["tier"] |
| .as_u64() |
| .expect(&format!("Target {} is missing tier metadata", target)); |
| if tier == 1 { |
| targets.push(target); |
| } |
| } |
| |
| let mut tasks = Vec::new(); |
| |
| // Testing every combination of compiler flags is infeasible. So we are making some attempt to |
| // choose combinations that will tend to run into problems. |
| // |
| // The particular combination of settings below is tuned to look for problems generating the |
| // code for compiler-builtins. |
| // We only exercise opt-level 0 and 3 to exercise mir-opt-level 1 and 2. |
| // We only exercise debug 0 and 2 because level 2 turns off some MIR optimizations. |
| // We only test abort and immediate-abort because abort vs unwind doesn't change MIR much at |
| // all. but immediate-abort does. |
| // |
| // Currently this only tests that we can compile the tier 1 targets. But since we are using |
| // -Zbuild-std=core, we could have any list of targets. |
| |
| for opt_level in [0, 3] { |
| for debug in [0, 2] { |
| for panic in ["abort", "immediate-abort"] { |
| for target in &targets { |
| tasks.push(Task { target: target.clone(), opt_level, debug, panic }); |
| } |
| } |
| } |
| } |
| |
| let tasks = Arc::new(Mutex::new(tasks)); |
| let mut threads = Vec::new(); |
| |
| // Try to obey the -j argument passed to bootstrap, otherwise fall back to using all the system |
| // resouces. This test can be rather memory-hungry (~1 GB/thread); if it causes trouble in |
| // practice do not hesitate to limit its parallelism. |
| for _ in 0..run_make_support::env::jobs() { |
| let tasks = Arc::clone(&tasks); |
| let handle = thread::spawn(move || { |
| loop { |
| let maybe_task = tasks.lock().unwrap().pop(); |
| if let Some(task) = maybe_task { |
| test(task); |
| } else { |
| break; |
| } |
| } |
| }); |
| threads.push(handle); |
| } |
| |
| for t in threads { |
| t.join().unwrap(); |
| } |
| } |
| |
| fn test(task: Task) { |
| let dir = TempDir::new().unwrap(); |
| |
| let manifest = manifest(&task); |
| rfs::write(dir.path().join("Cargo.toml"), &manifest); |
| rfs::write(dir.path().join("lib.rs"), "#![no_std]"); |
| |
| let mut args = vec!["build", "--release", "-Zbuild-std=core", "--target", &task.target, "-j1"]; |
| if task.panic == "immediate-abort" { |
| args.push("-Zpanic-immediate-abort"); |
| } |
| cargo() |
| .current_dir(dir.path()) |
| .args(&args) |
| .env("RUSTC_BOOTSTRAP", "1") |
| // Visual Studio 2022 requires that the LIB env var be set so it can |
| // find the Windows SDK. |
| .env("LIB", std::env::var("LIB").unwrap_or_default()) |
| .context(&format!( |
| "build-std for target `{}` failed with the following Cargo.toml:\n\n{manifest}", |
| task.target |
| )) |
| .run(); |
| } |