diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs index 6d07455c0de..968dc62cd98 100644 --- a/src/tools/miri/miri-script/src/commands.rs +++ b/src/tools/miri/miri-script/src/commands.rs @@ -23,7 +23,9 @@ const JOSH_PORT: &str = "42042"; impl MiriEnv { /// Returns the location of the sysroot. - fn build_miri_sysroot(&mut self, quiet: bool) -> Result { + /// + /// If the target is None the sysroot will be built for the host machine. + fn build_miri_sysroot(&mut self, quiet: bool, target: Option<&str>) -> Result { if let Some(miri_sysroot) = self.sh.var_os("MIRI_SYSROOT") { // Sysroot already set, use that. return Ok(miri_sysroot.into()); @@ -35,26 +37,27 @@ impl MiriEnv { self.build(path!(self.miri_dir / "Cargo.toml"), &[], quiet)?; self.build(&manifest_path, &[], quiet)?; - let target = &match self.sh.var("MIRI_TEST_TARGET") { - Ok(target) => vec!["--target".into(), target], - Err(_) => vec![], - }; + let target_flag = + &if let Some(target) = target { vec!["--target", target] } else { vec![] }; + if !quiet { - match self.sh.var("MIRI_TEST_TARGET") { - Ok(target) => eprintln!("$ (building Miri sysroot for {target})"), - Err(_) => eprintln!("$ (building Miri sysroot)"), + if let Some(target) = target { + eprintln!("$ (building Miri sysroot for {target})"); + } else { + eprintln!("$ (building Miri sysroot)"); } } + let output = cmd!(self.sh, "cargo +{toolchain} --quiet run {cargo_extra_flags...} --manifest-path {manifest_path} -- - miri setup --print-sysroot {target...}" + miri setup --print-sysroot {target_flag...}" ).read(); let Ok(output) = output else { // Run it again (without `--print-sysroot` or `--quiet`) so the user can see the error. cmd!( self.sh, "cargo +{toolchain} run {cargo_extra_flags...} --manifest-path {manifest_path} -- - miri setup {target...}" + miri setup {target_flag...}" ) .run() .with_context(|| "`cargo miri setup` failed")?; @@ -161,7 +164,7 @@ impl Command { Command::Install { flags } => Self::install(flags), Command::Build { flags } => Self::build(flags), Command::Check { flags } => Self::check(flags), - Command::Test { bless, flags } => Self::test(bless, flags), + Command::Test { bless, flags, target } => Self::test(bless, flags, target), Command::Run { dep, verbose, many_seeds, flags } => Self::run(dep, verbose, many_seeds, flags), Command::Fmt { flags } => Self::fmt(flags), @@ -446,16 +449,23 @@ impl Command { Ok(()) } - fn test(bless: bool, flags: Vec) -> Result<()> { + fn test(bless: bool, flags: Vec, target: Option) -> Result<()> { let mut e = MiriEnv::new()?; + + if let Some(target) = target.as_deref() { + // Tell the sysroot which target to test. + e.sh.set_var("MIRI_TEST_TARGET", target); + } + // Prepare a sysroot. - e.build_miri_sysroot(/* quiet */ false)?; + e.build_miri_sysroot(/* quiet */ false, target.as_deref())?; // Then test, and let caller control flags. // Only in root project as `cargo-miri` has no tests. if bless { e.sh.set_var("RUSTC_BLESS", "Gesundheit"); } + e.test(path!(e.miri_dir / "Cargo.toml"), &flags)?; Ok(()) } @@ -476,14 +486,26 @@ impl Command { .take_while(|arg| *arg != "--") .tuple_windows() .find(|(first, _)| *first == "--target"); - if let Some((_, target)) = target { + + let target_triple = if let Some((_, target)) = target { // Found it! e.sh.set_var("MIRI_TEST_TARGET", target); + + let triple = target + .clone() + .into_string() + .map_err(|_| anyhow!("invalid target triple encoding"))?; + Some(triple) } else if let Ok(target) = std::env::var("MIRI_TEST_TARGET") { // Convert `MIRI_TEST_TARGET` into `--target`. flags.push("--target".into()); - flags.push(target.into()); - } + flags.push(target.clone().into()); + + Some(target) + } else { + None + }; + // Scan for "--edition", set one ourselves if that flag is not present. let have_edition = flags.iter().take_while(|arg| *arg != "--").any(|arg| *arg == "--edition"); @@ -492,7 +514,8 @@ impl Command { } // Prepare a sysroot, and add it to the flags. - let miri_sysroot = e.build_miri_sysroot(/* quiet */ !verbose)?; + let miri_sysroot = + e.build_miri_sysroot(/* quiet */ !verbose, target_triple.as_deref())?; flags.push("--sysroot".into()); flags.push(miri_sysroot.into()); diff --git a/src/tools/miri/miri-script/src/main.rs b/src/tools/miri/miri-script/src/main.rs index f0ebbc84690..c92513a0fa7 100644 --- a/src/tools/miri/miri-script/src/main.rs +++ b/src/tools/miri/miri-script/src/main.rs @@ -33,6 +33,9 @@ pub enum Command { bless: bool, /// Flags that are passed through to `cargo test`. flags: Vec, + /// The cross-interpretation target. + /// If none then the host is the target. + target: Option, }, /// Build miri, set up a sysroot and then run the driver with the given . /// (Also respects MIRIFLAGS environment variable.) @@ -84,9 +87,9 @@ Just build miri. are passed to `cargo build`. ./miri check : Just check miri. are passed to `cargo check`. -./miri test [--bless] : +./miri test [--bless] [--target] : Build miri, set up a sysroot and then run the test suite. are passed -to the final `cargo test` invocation. +to the test harness. ./miri run [--dep] [-v|--verbose] [--many-seeds|--many-seeds=..to|--many-seeds=from..to] : Build miri, set up a sysroot and then run the driver with the given . @@ -147,12 +150,38 @@ fn main() -> Result<()> { Some("build") => Command::Build { flags: args.collect() }, Some("check") => Command::Check { flags: args.collect() }, Some("test") => { - let bless = args.peek().is_some_and(|a| a.to_str() == Some("--bless")); - if bless { - // Consume the flag. + let mut target = std::env::var("MIRI_TEST_TARGET").ok(); + let mut bless = false; + + while let Some(arg) = args.peek().and_then(|s| s.to_str()) { + match arg { + "--bless" => bless = true, + "--target" => { + // Skip "--target" + args.next().unwrap(); + + // Check that there is a target triple, and that it is unicode. + target = if let Some(value) = args.peek() { + let target_str = value + .clone() + .into_string() + .map_err(|_| anyhow!("invalid target triple encoding"))?; + Some(target_str) + } else { + bail!("no target triple found") + } + } + // Only parse the leading flags. + _ => break, + } + + // Consume the flag, look at the next one. args.next().unwrap(); } - Command::Test { bless, flags: args.collect() } + + // Prepend a "--" so that the rest of the arguments are passed to the test driver. + let args = std::iter::once(OsString::from("--")).chain(args); + Command::Test { bless, flags: args.collect(), target } } Some("run") => { let mut dep = false;