mirror of
https://github.com/rust-lang/rust.git
synced 2026-01-25 07:48:44 +00:00
Rollup merge of #150524 - test-build-std, r=jieyouxu,kobzol
Test that -Zbuild-std=core works on a variety of profiles See [#t-infra > Non-blocking testing for -Zbuild-std?](https://rust-lang.zulipchat.com/#narrow/channel/242791-t-infra/topic/Non-blocking.20testing.20for.20-Zbuild-std.3F/with/565837190) for some background. This is an incredibly CPU-hungry run-make-cargo test, but at least on my desktop the entire suite only takes a minute.
This commit is contained in:
@@ -3337,6 +3337,7 @@ dependencies = [
|
||||
"rustdoc-json-types",
|
||||
"serde_json",
|
||||
"similar",
|
||||
"tempfile",
|
||||
"wasmparser 0.236.1",
|
||||
]
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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),
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -53,6 +53,11 @@ check-aux:
|
||||
src/tools/cargotest \
|
||||
src/tools/test-float-parse \
|
||||
$(BOOTSTRAP_ARGS)
|
||||
# The build-std suite is off by default because it is uncommonly slow
|
||||
# and memory-hungry.
|
||||
$(Q)$(BOOTSTRAP) test --stage 2 \
|
||||
build-std \
|
||||
$(BOOTSTRAP_ARGS)
|
||||
# Run standard library tests in Miri.
|
||||
$(Q)MIRIFLAGS="-Zmiri-strict-provenance" \
|
||||
$(BOOTSTRAP) miri --stage 2 \
|
||||
|
||||
@@ -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: false
|
||||
});
|
||||
|
||||
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()
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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 <host> -> Tidy 1 <host>
|
||||
[test] tidy <>
|
||||
[build] rustdoc 0 <host>
|
||||
@@ -2255,7 +2255,7 @@ mod snapshot {
|
||||
insta::assert_snapshot!(
|
||||
prepare_test_config(&ctx)
|
||||
.stage(2)
|
||||
.render_steps(), @r"
|
||||
.render_steps(), @"
|
||||
[build] rustc 0 <host> -> Tidy 1 <host>
|
||||
[test] tidy <>
|
||||
[build] rustdoc 0 <host>
|
||||
|
||||
@@ -78,6 +78,10 @@ The following test suites are available, with links for more information:
|
||||
|
||||
[`run-make`](#run-make-tests) are general purpose tests using Rust programs.
|
||||
|
||||
### The build-std test suite
|
||||
|
||||
[`build-std`](#build-std-tests) test that -Zbuild-std works.
|
||||
|
||||
### Rustdoc test suites
|
||||
|
||||
| Test suite | Purpose |
|
||||
@@ -429,6 +433,12 @@ use cases that require testing in-tree `cargo` in conjunction with in-tree `rust
|
||||
The `run-make` test suite does not have access to in-tree `cargo` (so it can be the
|
||||
faster-to-iterate test suite).
|
||||
|
||||
### `build-std` tests
|
||||
|
||||
The tests in [`tests/build-std`] check that `-Zbuild-std` works. This is currently
|
||||
just a run-make test suite with a single recipe. The recipe generates test cases
|
||||
and runs them in parallel.
|
||||
|
||||
#### Using Rust recipes
|
||||
|
||||
Each test should be in a separate directory with a `rmake.rs` Rust program,
|
||||
|
||||
@@ -77,6 +77,7 @@ string_enum! {
|
||||
RustdocUi => "rustdoc-ui",
|
||||
Ui => "ui",
|
||||
UiFullDeps => "ui-fulldeps",
|
||||
BuildStd => "build-std",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -190,8 +190,8 @@ impl TestCx<'_> {
|
||||
// through a specific CI runner).
|
||||
.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 {
|
||||
// The `run-make-cargo` and `build-std` suites need an in-tree `cargo`, `run-make` does not.
|
||||
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"),
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
|
||||
self.stdin_buf = Some(input.as_ref().to_vec().into_boxed_slice());
|
||||
|
||||
@@ -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::{
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
131
tests/build-std/configurations/rmake.rs
Normal file
131
tests/build-std/configurations/rmake.rs
Normal file
@@ -0,0 +1,131 @@
|
||||
// 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();
|
||||
}
|
||||
Reference in New Issue
Block a user