diff --git a/Cargo.lock b/Cargo.lock index 470b38d5a91cb..96bb4c9a30a55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3376,6 +3376,7 @@ dependencies = [ "rustdoc-json-types", "serde_json", "similar", + "tempfile", "wasmparser 0.236.1", ] diff --git a/compiler/rustc_target/src/spec/targets/i586_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_redox.rs index 935666630daec..56e1c8a9705d0 100644 --- a/compiler/rustc_target/src/spec/targets/i586_unknown_redox.rs +++ b/compiler/rustc_target/src/spec/targets/i586_unknown_redox.rs @@ -11,7 +11,7 @@ pub(crate) fn target() -> Target { Target { llvm_target: "i586-unknown-redox".into(), - metadata: TargetMetadata { description: None, tier: None, host_tools: None, std: None }, + metadata: TargetMetadata { description: None, tier: Some(3), host_tools: None, std: None }, pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128" diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs index ecf232f1ab2fa..768b1a1ba1128 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_none.rs @@ -15,7 +15,7 @@ pub(crate) fn target() -> Target { llvm_target: "x86_64-unknown-linux-none".into(), metadata: TargetMetadata { description: None, - tier: None, + tier: Some(3), host_tools: None, std: Some(false), }, diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs index 83835705f3daa..0fb4d186087bc 100644 --- a/compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs +++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs @@ -9,7 +9,7 @@ pub(crate) fn target() -> Target { pointer_width: 32, data_layout: "e-m:e-p:32:32-v1:8:8-i64:64-i128:128-n32".into(), arch: Arch::Xtensa, - metadata: TargetMetadata { description: None, tier: None, host_tools: None, std: None }, + metadata: TargetMetadata { description: None, tier: Some(3), host_tools: None, std: None }, options: TargetOptions { endian: Endian::Little, diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs index 42e4c7bf8bec2..81eab657db712 100644 --- a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs +++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs @@ -9,7 +9,7 @@ pub(crate) fn target() -> Target { pointer_width: 32, data_layout: "e-m:e-p:32:32-v1:8:8-i64:64-i128:128-n32".into(), arch: Arch::Xtensa, - metadata: TargetMetadata { description: None, tier: None, host_tools: None, std: None }, + metadata: TargetMetadata { description: None, tier: Some(3), host_tools: None, std: None }, options: TargetOptions { endian: Endian::Little, diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs index 498daf4e60639..fb1f4f4719794 100644 --- a/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs +++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs @@ -9,7 +9,7 @@ pub(crate) fn target() -> Target { pointer_width: 32, data_layout: "e-m:e-p:32:32-v1:8:8-i64:64-i128:128-n32".into(), arch: Arch::Xtensa, - metadata: TargetMetadata { description: None, tier: None, host_tools: None, std: None }, + metadata: TargetMetadata { description: None, tier: Some(3), host_tools: None, std: None }, options: TargetOptions { endian: Endian::Little, diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index b26df1586e715..11ae98e9b6c3a 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1625,6 +1625,12 @@ test!(RunMakeCargo { suite: "run-make-cargo", default: true }); +test!(BuildStd { + path: "tests/build-std", + mode: CompiletestMode::RunMake, + suite: "build-std", + default: true +}); test!(AssemblyLlvm { path: "tests/assembly-llvm", @@ -1948,7 +1954,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the let stage0_rustc_path = builder.compiler(0, test_compiler.host); cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path)); - if suite == "run-make-cargo" { + if matches!(suite, "run-make-cargo" | "build-std") { let cargo_path = if test_compiler.stage == 0 { // If we're using `--stage 0`, we should provide the bootstrap cargo. builder.initial_cargo.clone() diff --git a/src/bootstrap/src/core/builder/cli_paths.rs b/src/bootstrap/src/core/builder/cli_paths.rs index 5ff2b380e4b93..1b0caa980e1de 100644 --- a/src/bootstrap/src/core/builder/cli_paths.rs +++ b/src/bootstrap/src/core/builder/cli_paths.rs @@ -20,6 +20,7 @@ pub(crate) const PATH_REMAP: &[(&str, &[&str])] = &[ &[ // tidy-alphabetical-start "tests/assembly-llvm", + "tests/build-std", "tests/codegen-llvm", "tests/codegen-units", "tests/coverage", diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap index 4ab84c3cabc1a..583f4691bcc19 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap @@ -213,3 +213,6 @@ expression: test [Test] test::RunMakeCargo targets: [aarch64-unknown-linux-gnu] - Suite(test::tests/run-make-cargo) +[Test] test::BuildStd + targets: [aarch64-unknown-linux-gnu] + - Suite(test::tests/build-std) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap index 2a4805e4fd687..56f41778b0b11 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap @@ -212,3 +212,6 @@ expression: test --skip=coverage [Test] test::RunMakeCargo targets: [aarch64-unknown-linux-gnu] - Suite(test::tests/run-make-cargo) +[Test] test::BuildStd + targets: [aarch64-unknown-linux-gnu] + - Suite(test::tests/build-std) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests.snap index ad9660ef5c918..65349a59a1e80 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests.snap @@ -5,6 +5,9 @@ expression: test tests [Test] test::AssemblyLlvm targets: [aarch64-unknown-linux-gnu] - Suite(test::tests/assembly-llvm) +[Test] test::BuildStd + targets: [aarch64-unknown-linux-gnu] + - Suite(test::tests/build-std) [Test] test::CodegenLlvm targets: [aarch64-unknown-linux-gnu] - Suite(test::tests/codegen-llvm) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_skip_coverage.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_skip_coverage.snap index 4572f089b0ae3..694bb0672ee42 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_skip_coverage.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_skip_coverage.snap @@ -5,6 +5,9 @@ expression: test tests --skip=coverage [Test] test::AssemblyLlvm targets: [aarch64-unknown-linux-gnu] - Suite(test::tests/assembly-llvm) +[Test] test::BuildStd + targets: [aarch64-unknown-linux-gnu] + - Suite(test::tests/build-std) [Test] test::CodegenLlvm targets: [aarch64-unknown-linux-gnu] - Suite(test::tests/codegen-llvm) diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 9e1a65bca79d8..69ddf98f88d9b 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -927,6 +927,7 @@ impl<'a> Builder<'a> { test::CollectLicenseMetadata, test::RunMake, test::RunMakeCargo, + test::BuildStd, ), Kind::Miri => describe!(test::Crate), Kind::Bench => describe!(test::Crate, test::CrateLibrustc, test::CrateRustdoc), diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 66614cc6cced8..0ab8925c99f0d 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -2077,7 +2077,7 @@ mod snapshot { let ctx = TestCtx::new(); insta::assert_snapshot!( prepare_test_config(&ctx) - .render_steps(), @r" + .render_steps(), @" [build] rustc 0 -> Tidy 1 [test] tidy <> [build] rustdoc 0 @@ -2150,6 +2150,7 @@ mod snapshot { [test] compiletest-run-make 1 [build] rustc 0 -> cargo 1 [test] compiletest-run-make-cargo 1 + [test] compiletest-build-std 1 "); } @@ -2255,7 +2256,7 @@ mod snapshot { insta::assert_snapshot!( prepare_test_config(&ctx) .stage(2) - .render_steps(), @r" + .render_steps(), @" [build] rustc 0 -> Tidy 1 [test] tidy <> [build] rustdoc 0 @@ -2333,6 +2334,7 @@ mod snapshot { [test] compiletest-run-make 2 [build] rustc 1 -> cargo 2 [test] compiletest-run-make-cargo 2 + [test] compiletest-build-std 2 "); } diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 450fde3bbc38e..0865aba36a5eb 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -77,6 +77,7 @@ string_enum! { RustdocUi => "rustdoc-ui", Ui => "ui", UiFullDeps => "ui-fulldeps", + BuildStd => "build-std", } } diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs index ba3a123473671..2fe179716ba1e 100644 --- a/src/tools/compiletest/src/runtest/run_make.rs +++ b/src/tools/compiletest/src/runtest/run_make.rs @@ -191,7 +191,7 @@ impl TestCx<'_> { .env("LLVM_COMPONENTS", &self.config.llvm_components); // Only `run-make-cargo` test suite gets an in-tree `cargo`, not `run-make`. - if self.config.suite == TestSuite::RunMakeCargo { + if matches!(self.config.suite, TestSuite::RunMakeCargo | TestSuite::BuildStd) { cmd.env( "CARGO", self.config.cargo_path.as_ref().expect("cargo must be built and made available"), diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml index 9d9cd656f5700..918f5ef0d5069 100644 --- a/src/tools/run-make-support/Cargo.toml +++ b/src/tools/run-make-support/Cargo.toml @@ -17,6 +17,7 @@ object = "0.37" regex = "1.11" serde_json = "1.0" similar = "2.7" +tempfile = "3" wasmparser = { version = "0.236", default-features = false, features = ["std", "features", "validate"] } # tidy-alphabetical-end diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs index 0aeb189bb6a5b..f4a09f9faae8f 100644 --- a/src/tools/run-make-support/src/command.rs +++ b/src/tools/run-make-support/src/command.rs @@ -46,6 +46,8 @@ pub struct Command { // Emulate linear type semantics. drop_bomb: DropBomb, already_executed: bool, + + context: String, } impl Command { @@ -60,6 +62,7 @@ impl Command { stdout: None, stderr: None, already_executed: false, + context: String::new(), } } @@ -69,6 +72,16 @@ impl Command { self.cmd } + pub(crate) fn get_context(&self) -> &str { + &self.context + } + + /// Appends context to the command, to provide a better error message if the command fails. + pub fn context(&mut self, ctx: &str) -> &mut Self { + self.context.push_str(&format!("{ctx}\n")); + self + } + /// Specify a stdin input buffer. This is a convenience helper, pub fn stdin_buf>(&mut self, input: I) -> &mut Self { self.stdin_buf = Some(input.as_ref().to_vec().into_boxed_slice()); diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 5253dc04a93e2..b19d73b78a942 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -34,7 +34,9 @@ pub mod rfs { } // Re-exports of third-party library crates. -pub use {bstr, gimli, libc, object, regex, rustdoc_json_types, serde_json, similar, wasmparser}; +pub use { + bstr, gimli, libc, object, regex, rustdoc_json_types, serde_json, similar, tempfile, wasmparser, +}; // Helpers for building names of output artifacts that are potentially target-specific. pub use crate::artifact_names::{ diff --git a/src/tools/run-make-support/src/util.rs b/src/tools/run-make-support/src/util.rs index af01758447b93..7908dc1f7b3d9 100644 --- a/src/tools/run-make-support/src/util.rs +++ b/src/tools/run-make-support/src/util.rs @@ -21,6 +21,9 @@ pub(crate) fn handle_failed_output( eprintln!("output status: `{}`", output.status()); eprintln!("=== STDOUT ===\n{}\n\n", output.stdout_utf8()); eprintln!("=== STDERR ===\n{}\n\n", output.stderr_utf8()); + if !cmd.get_context().is_empty() { + eprintln!("Context:\n{}", cmd.get_context()); + } std::process::exit(1) } diff --git a/tests/build-std/configurations/rmake.rs b/tests/build-std/configurations/rmake.rs new file mode 100644 index 0000000000000..24e5e2d615c30 --- /dev/null +++ b/tests/build-std/configurations/rmake.rs @@ -0,0 +1,132 @@ +// This test ensures we are able to compile -Zbuild-std=core under a variety of profiles. + +#![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 = 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 a tier!", 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. + let num_threads = std::env::var("RUST_TEST_THREADS") + .map(|threads| threads.parse::().unwrap()) + .unwrap_or_else(|_| std::thread::available_parallelism().unwrap().get()); + + for _ in 0..num_threads { + 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(); +}