Skip to content

Commit

Permalink
Allow test targets to be set via CLI args
Browse files Browse the repository at this point in the history
  • Loading branch information
RossSmyth committed May 8, 2024
1 parent 28ab963 commit 4fecb9d
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 29 deletions.
74 changes: 46 additions & 28 deletions miri-script/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand All @@ -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")?;
Expand Down Expand Up @@ -446,10 +449,28 @@ impl Command {
Ok(())
}

fn test(bless: bool, flags: Vec<OsString>) -> Result<()> {
fn test(bless: bool, mut flags: Vec<OsString>) -> Result<()> {
let mut e = MiriEnv::new()?;

// Extract the target from env vars or CLI args if it exists.
let target = get_target(&flags)?;
if let Some(target) = target.as_deref() {
// This must be set, it is what make it actually cross-interpret.
e.sh.set_var("MIRI_TEST_TARGET", target);

if has_flag(&flags, "target") {
// We must remove the flag if it came from the CLI because test driver has no idea
// what the target flag does.
let position = flags.iter().position(|flag| flag == "--target").unwrap();

// Remove both the key and the value
flags.remove(position);
flags.remove(position);
}
}

// 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.
Expand All @@ -470,29 +491,26 @@ impl Command {
// Scan for "--target" to overwrite the "MIRI_TEST_TARGET" env var so
// that we set the MIRI_SYSROOT up the right way. We must make sure that
// MIRI_TEST_TARGET and `--target` are in sync.
use itertools::Itertools;
let target = flags
.iter()
.take_while(|arg| *arg != "--")
.tuple_windows()
.find(|(first, _)| *first == "--target");
if let Some((_, target)) = target {
// Found it!
let target = get_target(&flags)?;

if let Some(target) = target.as_deref() {
// If cross-interpreting, we must set the flags accordingly.
e.sh.set_var("MIRI_TEST_TARGET", target);
} 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());

// Set target if not in the arguments
if !has_flag(&flags, "target") {
flags.push("--target".into());
flags.push(target.into());
}
}

// 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");
if !have_edition {
if !has_flag(&flags, "edition") {
flags.push("--edition=2021".into()); // keep in sync with `tests/ui.rs`.`
}

// 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.as_deref())?;
flags.push("--sysroot".into());
flags.push(miri_sysroot.into());

Expand Down
32 changes: 31 additions & 1 deletion miri-script/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,36 @@ pub fn flagsplit(flags: &str) -> Vec<String> {
flags.split(' ').map(str::trim).filter(|s| !s.is_empty()).map(str::to_string).collect()
}

/// Get the target the user wants from either their CLI arguments, or env vars.
pub fn get_target(args: &[OsString]) -> Result<Option<String>> {
use itertools::Itertools;

// Search for the target flag
let target = args
.iter()
.take_while(|arg| *arg != "--")
.tuple_windows()
.find(|(first, _)| *first == "--target");

if let Some((_, target)) = target {
match target.clone().into_string() {
Ok(target) => Ok(Some(target)),
Err(err) => Err(anyhow!("Failed to convert argument to target string: {:?}", err)),
}
} else if let Ok(target) = std::env::var("MIRI_TEST_TARGET") {
Ok(Some(target))
} else {
Ok(None)
}
}

/// Search for if a flag exists
pub fn has_flag(args: &[OsString], flag: &str) -> bool {
let flag = "--".to_owned() + flag;

args.iter().take_while(|arg| *arg != "--").any(|arg| *arg == flag[..])
}

/// Some extra state we track for building Miri, such as the right RUSTFLAGS.
pub struct MiriEnv {
/// miri_dir is the root of the miri repository checkout we are working in.
Expand Down Expand Up @@ -143,7 +173,7 @@ impl MiriEnv {
let MiriEnv { toolchain, cargo_extra_flags, .. } = self;
cmd!(
self.sh,
"cargo +{toolchain} test {cargo_extra_flags...} --manifest-path {manifest_path} {args...}"
"cargo +{toolchain} test {cargo_extra_flags...} --manifest-path {manifest_path} -- {args...}"
)
.run()?;
Ok(())
Expand Down

0 comments on commit 4fecb9d

Please sign in to comment.