about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRoss Smyth <18294397+RossSmyth@users.noreply.github.com>2024-05-08 14:43:33 -0400
committerRoss Smyth <18294397+RossSmyth@users.noreply.github.com>2024-05-08 18:05:26 -0400
commit6580a22726abf9544c0752a3cd26860643b8aa5d (patch)
tree279c198601420a9057181e0491bde9c932f32bc7
parent720ff0d683d0a40b09abcb123ec90e104fd0a7c7 (diff)
downloadrust-6580a22726abf9544c0752a3cd26860643b8aa5d.tar.gz
rust-6580a22726abf9544c0752a3cd26860643b8aa5d.zip
Allow test targets to be set via CLI args
-rw-r--r--src/tools/miri/miri-script/src/commands.rs57
-rw-r--r--src/tools/miri/miri-script/src/main.rs41
2 files changed, 75 insertions, 23 deletions
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<PathBuf> {
+    ///
+    /// 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<PathBuf> {
         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<OsString>) -> Result<()> {
+    fn test(bless: bool, flags: Vec<OsString>, target: Option<String>) -> 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<OsString>,
+        /// The cross-interpretation target.
+        /// If none then the host is the target.
+        target: Option<String>,
     },
     /// Build miri, set up a sysroot and then run the driver with the given <flags>.
     /// (Also respects MIRIFLAGS environment variable.)
@@ -84,9 +87,9 @@ Just build miri. <flags> are passed to `cargo build`.
 ./miri check <flags>:
 Just check miri. <flags> are passed to `cargo check`.
 
-./miri test [--bless] <flags>:
+./miri test [--bless] [--target] <flags>:
 Build miri, set up a sysroot and then run the test suite. <flags> 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] <flags>:
 Build miri, set up a sysroot and then run the driver with the given <flags>.
@@ -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;