Skip to content

Commit c2a2e25

Browse files
committed
Auto merge of #1525 - divergentdave:cargo-miri-targets, r=RalfJung
Support --test/--bin/--lib in cargo-miri This PR addresses a FIXME in cargo-miri, and filters the targets to be checked when any of the `--bin`, '--test`, or `--lib` flags are passed.
2 parents 13ea745 + 64e2d3e commit c2a2e25

File tree

1 file changed

+79
-10
lines changed

1 file changed

+79
-10
lines changed

cargo-miri/bin.rs

Lines changed: 79 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,74 @@ path = "lib.rs"
378378
}
379379
}
380380

381+
enum CargoTargets {
382+
All,
383+
Filtered { lib: bool, bin: Vec<String>, test: Vec<String> },
384+
}
385+
386+
impl CargoTargets {
387+
fn matches(&self, kind: &str, name: &str) -> bool {
388+
match self {
389+
CargoTargets::All => true,
390+
CargoTargets::Filtered { lib, bin, test } => match kind {
391+
"lib" => *lib,
392+
"bin" => bin.iter().any(|n| n == name),
393+
"test" => test.iter().any(|n| n == name),
394+
_ => false,
395+
},
396+
}
397+
}
398+
}
399+
400+
fn parse_cargo_miri_args(
401+
mut args: impl Iterator<Item = String>,
402+
) -> (CargoTargets, Vec<String>, Vec<String>) {
403+
let mut lib_present = false;
404+
let mut bin_targets = Vec::new();
405+
let mut test_targets = Vec::new();
406+
let mut additional_args = Vec::new();
407+
while let Some(arg) = args.next() {
408+
match arg {
409+
arg if arg == "--" => {
410+
// Miri arguments begin after the first "--".
411+
break;
412+
}
413+
arg if arg == "--lib" => lib_present = true,
414+
arg if arg == "--bin" => {
415+
if let Some(binary) = args.next() {
416+
if binary == "--" {
417+
show_error(format!("\"--bin\" takes one argument."));
418+
} else {
419+
bin_targets.push(binary)
420+
}
421+
} else {
422+
show_error(format!("\"--bin\" takes one argument."));
423+
}
424+
}
425+
arg if arg.starts_with("--bin=") => bin_targets.push((&arg["--bin=".len()..]).to_string()),
426+
arg if arg == "--test" => {
427+
if let Some(test) = args.next() {
428+
if test == "--" {
429+
show_error(format!("\"--test\" takes one argument."));
430+
} else {
431+
test_targets.push(test)
432+
}
433+
} else {
434+
show_error(format!("\"--test\" takes one argument."));
435+
}
436+
}
437+
arg if arg.starts_with("--test=") => test_targets.push((&arg["--test=".len()..]).to_string()),
438+
other => additional_args.push(other),
439+
}
440+
}
441+
let targets = if !lib_present && bin_targets.len() == 0 && test_targets.len() == 0 {
442+
CargoTargets::All
443+
} else {
444+
CargoTargets::Filtered { lib: lib_present, bin: bin_targets, test: test_targets }
445+
};
446+
(targets, additional_args, args.collect())
447+
}
448+
381449
fn in_cargo_miri() {
382450
let (subcommand, skip) = match std::env::args().nth(2).as_deref() {
383451
Some("test") => (MiriCommand::Test, 3),
@@ -398,22 +466,27 @@ fn in_cargo_miri() {
398466
return;
399467
}
400468

469+
// FIXME: this accepts --test, --lib, and multiple --bin for `cargo miri run`.
470+
let (target_filters, cargo_args, miri_args) =
471+
parse_cargo_miri_args(std::env::args().skip(skip));
472+
401473
// Now run the command.
402474
for target in list_targets() {
403-
let mut args = std::env::args().skip(skip);
404475
let kind = target
405476
.kind
406477
.get(0)
407478
.expect("badly formatted cargo metadata: target::kind is an empty array");
479+
if !target_filters.matches(kind, &target.name) {
480+
continue;
481+
}
408482
// Now we run `cargo check $FLAGS $ARGS`, giving the user the
409483
// change to add additional arguments. `FLAGS` is set to identify
410484
// this target. The user gets to control what gets actually passed to Miri.
411485
let mut cmd = cargo();
412486
cmd.arg("check");
413487
match (subcommand, kind.as_str()) {
414488
(MiriCommand::Run, "bin") => {
415-
// FIXME: we just run all the binaries here.
416-
// We should instead support `cargo miri --bin foo`.
489+
// FIXME: we default to running all binaries here.
417490
cmd.arg("--bin").arg(target.name);
418491
}
419492
(MiriCommand::Test, "test") => {
@@ -429,11 +502,8 @@ fn in_cargo_miri() {
429502
// The remaining targets we do not even want to build.
430503
_ => continue,
431504
}
432-
// Forward user-defined `cargo` args until first `--`.
433-
while let Some(arg) = args.next() {
434-
if arg == "--" {
435-
break;
436-
}
505+
// Forward further `cargo` args.
506+
for arg in cargo_args.iter() {
437507
cmd.arg(arg);
438508
}
439509
// We want to always run `cargo` with `--target`. This later helps us detect
@@ -450,8 +520,7 @@ fn in_cargo_miri() {
450520
// our actual target crate (the binary or the test we are running).
451521
// Since we're using "cargo check", we have no other way of passing
452522
// these arguments.
453-
let args_vec: Vec<String> = args.collect();
454-
cmd.env("MIRI_ARGS", serde_json::to_string(&args_vec).expect("failed to serialize args"));
523+
cmd.env("MIRI_ARGS", serde_json::to_string(&miri_args).expect("failed to serialize args"));
455524

456525
// Set `RUSTC_WRAPPER` to ourselves. Cargo will prepend that binary to its usual invocation,
457526
// i.e., the first argument is `rustc` -- which is what we use in `main` to distinguish

0 commit comments

Comments
 (0)