Support --test/--bin/--lib in cargo-miri
This commit is contained in:
parent
9f3e7cf2c2
commit
3bc8302a54
@ -378,6 +378,69 @@ path = "lib.rs"
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum CargoTargets {
|
||||||
|
All,
|
||||||
|
Filtered { lib: bool, bin: Vec<String>, test: Vec<String> },
|
||||||
|
}
|
||||||
|
|
||||||
|
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<Item = String>,
|
||||||
|
) -> (CargoTargets, Vec<String>, Vec<String>) {
|
||||||
|
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() {
|
fn in_cargo_miri() {
|
||||||
let (subcommand, skip) = match std::env::args().nth(2).as_deref() {
|
let (subcommand, skip) = match std::env::args().nth(2).as_deref() {
|
||||||
Some("test") => (MiriCommand::Test, 3),
|
Some("test") => (MiriCommand::Test, 3),
|
||||||
@ -398,13 +461,18 @@ fn in_cargo_miri() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let (target_filters, cargo_args, miri_args) =
|
||||||
|
parse_cargo_miri_args(std::env::args().skip(skip));
|
||||||
|
|
||||||
// Now run the command.
|
// Now run the command.
|
||||||
for target in list_targets() {
|
for target in list_targets() {
|
||||||
let mut args = std::env::args().skip(skip);
|
|
||||||
let kind = target
|
let kind = target
|
||||||
.kind
|
.kind
|
||||||
.get(0)
|
.get(0)
|
||||||
.expect("badly formatted cargo metadata: target::kind is an empty array");
|
.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
|
// Now we run `cargo check $FLAGS $ARGS`, giving the user the
|
||||||
// change to add additional arguments. `FLAGS` is set to identify
|
// change to add additional arguments. `FLAGS` is set to identify
|
||||||
// this target. The user gets to control what gets actually passed to Miri.
|
// this target. The user gets to control what gets actually passed to Miri.
|
||||||
@ -412,8 +480,6 @@ fn in_cargo_miri() {
|
|||||||
cmd.arg("check");
|
cmd.arg("check");
|
||||||
match (subcommand, kind.as_str()) {
|
match (subcommand, kind.as_str()) {
|
||||||
(MiriCommand::Run, "bin") => {
|
(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);
|
cmd.arg("--bin").arg(target.name);
|
||||||
}
|
}
|
||||||
(MiriCommand::Test, "test") => {
|
(MiriCommand::Test, "test") => {
|
||||||
@ -430,10 +496,7 @@ fn in_cargo_miri() {
|
|||||||
_ => continue,
|
_ => continue,
|
||||||
}
|
}
|
||||||
// Forward user-defined `cargo` args until first `--`.
|
// Forward user-defined `cargo` args until first `--`.
|
||||||
while let Some(arg) = args.next() {
|
for arg in cargo_args.iter() {
|
||||||
if arg == "--" {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cmd.arg(arg);
|
cmd.arg(arg);
|
||||||
}
|
}
|
||||||
// We want to always run `cargo` with `--target`. This later helps us detect
|
// 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).
|
// 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
|
// Since we're using "cargo check", we have no other way of passing
|
||||||
// these arguments.
|
// these arguments.
|
||||||
let args_vec: Vec<String> = args.collect();
|
cmd.env("MIRI_ARGS", serde_json::to_string(&miri_args).expect("failed to serialize args"));
|
||||||
cmd.env("MIRI_ARGS", serde_json::to_string(&args_vec).expect("failed to serialize args"));
|
|
||||||
|
|
||||||
// Set `RUSTC_WRAPPER` to ourselves. Cargo will prepend that binary to its usual invocation,
|
// 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
|
// i.e., the first argument is `rustc` -- which is what we use in `main` to distinguish
|
||||||
|
Loading…
x
Reference in New Issue
Block a user