diff options
| author | Ralf Jung <post@ralfj.de> | 2024-04-01 23:56:59 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2024-04-03 20:27:20 +0200 |
| commit | a6803b9de4e7ab146b442162316b340f887a7796 (patch) | |
| tree | 8404dc9f930f4d08b53067d69c5a1d48af732893 /src/bootstrap | |
| parent | b390f2f458da288b1be2955bd310a0d45f3bf3ec (diff) | |
add 'x.py miri', and make it work for 'library/{core,alloc,std}'
Diffstat (limited to 'src/bootstrap')
| -rw-r--r-- | src/bootstrap/src/core/build_steps/test.rs | 71 | ||||
| -rw-r--r-- | src/bootstrap/src/core/builder.rs | 10 | ||||
| -rw-r--r-- | src/bootstrap/src/core/config/config.rs | 7 | ||||
| -rw-r--r-- | src/bootstrap/src/core/config/flags.rs | 28 |
4 files changed, 94 insertions, 22 deletions
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index b1ae0724e62..bacf5f0d33c 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2536,9 +2536,14 @@ fn prepare_cargo_test( // // Note that to run the compiler we need to run with the *host* libraries, // but our wrapper scripts arrange for that to be the case anyway. - let mut dylib_path = dylib_path(); - dylib_path.insert(0, PathBuf::from(&*builder.sysroot_libdir(compiler, target))); - cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); + // + // We skip everything on Miri as then this overwrites the libdir set up + // by `Cargo::new` and that actually makes things go wrong. + if builder.kind != Kind::Miri { + let mut dylib_path = dylib_path(); + dylib_path.insert(0, PathBuf::from(&*builder.sysroot_libdir(compiler, target))); + cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); + } if builder.remote_tested(target) { cargo.env( @@ -2594,28 +2599,62 @@ impl Step for Crate { let target = self.target; let mode = self.mode; + // Prepare sysroot // See [field@compile::Std::force_recompile]. builder.ensure(compile::Std::force_recompile(compiler, compiler.host)); - if builder.config.build != target { - builder.ensure(compile::Std::force_recompile(compiler, target)); - builder.ensure(RemoteCopyLibs { compiler, target }); - } - // If we're not doing a full bootstrap but we're testing a stage2 // version of libstd, then what we're actually testing is the libstd // produced in stage1. Reflect that here by updating the compiler that // we're working with automatically. let compiler = builder.compiler_for(compiler.stage, compiler.host, target); - let mut cargo = builder::Cargo::new( - builder, - compiler, - mode, - SourceType::InTree, - target, - builder.kind.as_str(), - ); + let mut cargo = if builder.kind == Kind::Miri { + if builder.top_stage == 0 { + eprintln!("ERROR: `x.py miri` requires stage 1 or higher"); + std::process::exit(1); + } + + // Build `cargo miri test` command + // (Implicitly prepares target sysroot) + let mut cargo = builder::Cargo::new( + builder, + compiler, + mode, + SourceType::InTree, + target, + "miri-test", + ); + // This hack helps bootstrap run standard library tests in Miri. The issue is as + // follows: when running `cargo miri test` on libcore, cargo builds a local copy of core + // and makes it a dependency of the integration test crate. This copy duplicates all the + // lang items, so the build fails. (Regular testing avoids this because the sysroot is a + // literal copy of what `cargo build` produces, but since Miri builds its own sysroot + // this does not work for us.) So we need to make it so that the locally built libcore + // contains all the items from `core`, but does not re-define them -- we want to replace + // the entire crate but a re-export of the sysroot crate. We do this by swapping out the + // source file: if `MIRI_REPLACE_LIBRS_IF_NOT_TEST` is set and we are building a + // `lib.rs` file, and a `lib.miri.rs` file exists in the same folder, we build that + // instead. But crucially we only do that for the library, not the test builds. + cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1"); + cargo + } else { + // Also prepare a sysroot for the target. + if builder.config.build != target { + builder.ensure(compile::Std::force_recompile(compiler, target)); + builder.ensure(RemoteCopyLibs { compiler, target }); + } + + // Build `cargo test` command + builder::Cargo::new( + builder, + compiler, + mode, + SourceType::InTree, + target, + builder.kind.as_str(), + ) + }; match mode { Mode::Std => { diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 0d72cc380e6..e110a489cc0 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -631,6 +631,7 @@ pub enum Kind { Format, #[value(alias = "t")] Test, + Miri, Bench, #[value(alias = "d")] Doc, @@ -673,6 +674,7 @@ impl Kind { Kind::Fix => "fix", Kind::Format => "fmt", Kind::Test => "test", + Kind::Miri => "miri", Kind::Bench => "bench", Kind::Doc => "doc", Kind::Clean => "clean", @@ -822,6 +824,7 @@ impl<'a> Builder<'a> { // Run run-make last, since these won't pass without make on Windows test::RunMake, ), + Kind::Miri => describe!(test::Crate), Kind::Bench => describe!(test::Crate, test::CrateLibrustc), Kind::Doc => describe!( doc::UnstableBook, @@ -970,6 +973,7 @@ impl<'a> Builder<'a> { Subcommand::Fix => (Kind::Fix, &paths[..]), Subcommand::Doc { .. } => (Kind::Doc, &paths[..]), Subcommand::Test { .. } => (Kind::Test, &paths[..]), + Subcommand::Miri { .. } => (Kind::Miri, &paths[..]), Subcommand::Bench { .. } => (Kind::Bench, &paths[..]), Subcommand::Dist => (Kind::Dist, &paths[..]), Subcommand::Install => (Kind::Install, &paths[..]), @@ -1309,7 +1313,11 @@ impl<'a> Builder<'a> { if cmd == "clippy" { cargo = self.cargo_clippy_cmd(compiler); cargo.arg(cmd); - } else if let Some(subcmd) = cmd.strip_prefix("miri-") { + } else if let Some(subcmd) = cmd.strip_prefix("miri") { + // Command must be "miri-X". + let subcmd = subcmd + .strip_prefix("-") + .unwrap_or_else(|| panic!("expected `miri-$subcommand`, but got {}", cmd)); cargo = self.cargo_miri_cmd(compiler); cargo.arg("miri").arg(subcmd); } else { diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 67cde01ccdb..96dec975250 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2022,7 +2022,7 @@ impl Config { Subcommand::Build { .. } => { flags.stage.or(build_stage).unwrap_or(if download_rustc { 2 } else { 1 }) } - Subcommand::Test { .. } => { + Subcommand::Test { .. } | Subcommand::Miri { .. } => { flags.stage.or(test_stage).unwrap_or(if download_rustc { 2 } else { 1 }) } Subcommand::Bench { .. } => flags.stage.or(bench_stage).unwrap_or(2), @@ -2044,6 +2044,7 @@ impl Config { if flags.stage.is_none() && crate::CiEnv::current() != crate::CiEnv::None { match config.cmd { Subcommand::Test { .. } + | Subcommand::Miri { .. } | Subcommand::Doc { .. } | Subcommand::Build { .. } | Subcommand::Bench { .. } @@ -2099,7 +2100,9 @@ impl Config { pub(crate) fn test_args(&self) -> Vec<&str> { let mut test_args = match self.cmd { - Subcommand::Test { ref test_args, .. } | Subcommand::Bench { ref test_args, .. } => { + Subcommand::Test { ref test_args, .. } + | Subcommand::Bench { ref test_args, .. } + | Subcommand::Miri { ref test_args, .. } => { test_args.iter().flat_map(|s| s.split_whitespace()).collect() } _ => vec![], diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index 7262b785ee0..7782f7e61c9 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -382,6 +382,25 @@ pub enum Subcommand { /// `/<build_base>/rustfix_missing_coverage.txt` rustfix_coverage: bool, }, + /// Build and run some test suites *in Miri* + Miri { + #[arg(long)] + /// run all tests regardless of failure + no_fail_fast: bool, + #[arg(long, value_name = "ARGS", allow_hyphen_values(true))] + /// extra arguments to be passed for the test tool being used + /// (e.g. libtest, compiletest or rustdoc) + test_args: Vec<String>, + /// extra options to pass the compiler when running tests + #[arg(long, value_name = "ARGS", allow_hyphen_values(true))] + rustc_args: Vec<String>, + #[arg(long)] + /// do not run doc tests + no_doc: bool, + #[arg(long)] + /// only run doc tests + doc: bool, + }, /// Build and run some benchmarks Bench { #[arg(long, allow_hyphen_values(true))] @@ -453,6 +472,7 @@ impl Subcommand { Subcommand::Fix { .. } => Kind::Fix, Subcommand::Format { .. } => Kind::Format, Subcommand::Test { .. } => Kind::Test, + Subcommand::Miri { .. } => Kind::Miri, Subcommand::Clean { .. } => Kind::Clean, Subcommand::Dist { .. } => Kind::Dist, Subcommand::Install { .. } => Kind::Install, @@ -464,7 +484,7 @@ impl Subcommand { pub fn rustc_args(&self) -> Vec<&str> { match *self { - Subcommand::Test { ref rustc_args, .. } => { + Subcommand::Test { ref rustc_args, .. } | Subcommand::Miri { ref rustc_args, .. } => { rustc_args.iter().flat_map(|s| s.split_whitespace()).collect() } _ => vec![], @@ -473,14 +493,16 @@ impl Subcommand { pub fn fail_fast(&self) -> bool { match *self { - Subcommand::Test { no_fail_fast, .. } => !no_fail_fast, + Subcommand::Test { no_fail_fast, .. } | Subcommand::Miri { no_fail_fast, .. } => { + !no_fail_fast + } _ => false, } } pub fn doc_tests(&self) -> DocTests { match *self { - Subcommand::Test { doc, no_doc, .. } => { + Subcommand::Test { doc, no_doc, .. } | Subcommand::Miri { no_doc, doc, .. } => { if doc { DocTests::Only } else if no_doc { |
