From: David Cook Date: Wed, 26 Aug 2020 00:00:46 +0000 (-0500) Subject: Support --test/--bin/--lib in cargo-miri X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=3bc8302a54653f3f92b015106a5322f7ce8e29a0;hp=9f3e7cf2c2f0d9be32011bd4d9cd5d934b69dc7a;p=rust.git Support --test/--bin/--lib in cargo-miri --- diff --git a/cargo-miri/bin.rs b/cargo-miri/bin.rs index a2d6c3fc5b7..029c5e5610c 100644 --- a/cargo-miri/bin.rs +++ b/cargo-miri/bin.rs @@ -378,6 +378,69 @@ fn setup(subcommand: MiriCommand) { } } +enum CargoTargets { + All, + Filtered { lib: bool, bin: Vec, test: Vec }, +} + +impl CargoTargets { + fn matches(&self, kind: &str, name: &str) -> bool { + match self { + CargoTargets::All => true, + CargoTargets::Filtered { lib, bin, test } => match kind { + "lib" => *lib, + "bin" => bin.iter().any(|n| n == name), + "test" => test.iter().any(|n| n == name), + _ => false, + }, + } + } +} + +fn parse_cargo_miri_args( + mut args: impl Iterator, +) -> (CargoTargets, Vec, Vec) { + let mut lib_present = false; + let mut bin_targets = Vec::new(); + let mut test_targets = Vec::new(); + let mut additional_args = Vec::new(); + while let Some(arg) = args.next() { + match arg { + arg if arg == "--" => break, + arg if arg == "--lib" => lib_present = true, + arg if arg == "--bin" => { + if let Some(binary) = args.next() { + if binary == "--" { + show_error(format!("\"--bin\" takes one argument.")); + } else { + bin_targets.push(binary) + } + } else { + show_error(format!("\"--bin\" takes one argument.")); + } + } + arg if arg == "--test" => { + if let Some(test) = args.next() { + if test == "--" { + show_error(format!("\"--test\" takes one argument.")); + } else { + test_targets.push(test) + } + } else { + show_error(format!("\"--test\" takes one argument.")); + } + } + other => additional_args.push(other), + } + } + let targets = if !lib_present && bin_targets.len() == 0 && test_targets.len() == 0 { + CargoTargets::All + } else { + CargoTargets::Filtered { lib: lib_present, bin: bin_targets, test: test_targets } + }; + (targets, additional_args, args.collect()) +} + fn in_cargo_miri() { let (subcommand, skip) = match std::env::args().nth(2).as_deref() { Some("test") => (MiriCommand::Test, 3), @@ -398,13 +461,18 @@ fn in_cargo_miri() { return; } + let (target_filters, cargo_args, miri_args) = + parse_cargo_miri_args(std::env::args().skip(skip)); + // Now run the command. for target in list_targets() { - let mut args = std::env::args().skip(skip); let kind = target .kind .get(0) .expect("badly formatted cargo metadata: target::kind is an empty array"); + if !target_filters.matches(kind, &target.name) { + continue; + } // Now we run `cargo check $FLAGS $ARGS`, giving the user the // change to add additional arguments. `FLAGS` is set to identify // this target. The user gets to control what gets actually passed to Miri. @@ -412,8 +480,6 @@ fn in_cargo_miri() { cmd.arg("check"); match (subcommand, kind.as_str()) { (MiriCommand::Run, "bin") => { - // FIXME: we just run all the binaries here. - // We should instead support `cargo miri --bin foo`. cmd.arg("--bin").arg(target.name); } (MiriCommand::Test, "test") => { @@ -430,10 +496,7 @@ fn in_cargo_miri() { _ => continue, } // Forward user-defined `cargo` args until first `--`. - while let Some(arg) = args.next() { - if arg == "--" { - break; - } + for arg in cargo_args.iter() { cmd.arg(arg); } // We want to always run `cargo` with `--target`. This later helps us detect @@ -450,8 +513,7 @@ fn in_cargo_miri() { // our actual target crate (the binary or the test we are running). // Since we're using "cargo check", we have no other way of passing // these arguments. - let args_vec: Vec = args.collect(); - cmd.env("MIRI_ARGS", serde_json::to_string(&args_vec).expect("failed to serialize args")); + cmd.env("MIRI_ARGS", serde_json::to_string(&miri_args).expect("failed to serialize args")); // Set `RUSTC_WRAPPER` to ourselves. Cargo will prepend that binary to its usual invocation, // i.e., the first argument is `rustc` -- which is what we use in `main` to distinguish