Skip to content

Commit ecab8a4

Browse files
author
hyd-dev
committed
Skip unit tests of proc-macro crates
1 parent eae9569 commit ecab8a4

File tree

1 file changed

+59
-19
lines changed

1 file changed

+59
-19
lines changed

cargo-miri/bin.rs

Lines changed: 59 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ enum MiriCommand {
3737
Setup,
3838
}
3939

40-
/// The inforamtion Miri needs to run a crate. Stored as JSON when the crate is "compiled".
40+
/// The information to run a crate with the given environment.
4141
#[derive(Serialize, Deserialize)]
42-
struct CrateRunInfo {
42+
struct CrateRunEnv {
4343
/// The command-line arguments.
4444
args: Vec<String>,
4545
/// The environment.
@@ -48,13 +48,22 @@ struct CrateRunInfo {
4848
current_dir: OsString,
4949
}
5050

51+
/// The information Miri needs to run a crate. Stored as JSON when the crate is "compiled".
52+
#[derive(Serialize, Deserialize)]
53+
enum CrateRunInfo {
54+
/// Run it with the given environment.
55+
RunWith(CrateRunEnv),
56+
/// Skip it as Miri does not support interpreting such kind of crates.
57+
SkipProcMacroTest,
58+
}
59+
5160
impl CrateRunInfo {
5261
/// Gather all the information we need.
5362
fn collect(args: env::Args) -> Self {
5463
let args = args.collect();
5564
let env = env::vars_os().collect();
5665
let current_dir = env::current_dir().unwrap().into_os_string();
57-
CrateRunInfo { args, env, current_dir }
66+
Self::RunWith(CrateRunEnv { args, env, current_dir })
5867
}
5968

6069
fn store(&self, filename: &Path) {
@@ -90,6 +99,7 @@ fn has_arg_flag(name: &str) -> bool {
9099
args.any(|val| val == name)
91100
}
92101

102+
/// Yields all values of command line flag `name`.
93103
struct ArgFlagValueIter<'a> {
94104
args: TakeWhile<env::Args, fn(&String) -> bool>,
95105
name: &'a str,
@@ -455,14 +465,15 @@ fn phase_cargo_miri(mut args: env::Args) {
455465
// This is needed to make the `CARGO_TARGET_*_RUNNER` env var do something,
456466
// and it later helps us detect which crates are proc-macro/build-script
457467
// (host crates) and which crates are needed for the program itself.
458-
let target = if let Some(target) = get_arg_flag_value("--target") {
468+
let host = version_info().host;
469+
let target = get_arg_flag_value("--target");
470+
let target = if let Some(ref target) = target {
459471
target
460472
} else {
461473
// No target given. Pick default and tell cargo about it.
462-
let host = version_info().host;
463474
cmd.arg("--target");
464475
cmd.arg(&host);
465-
host
476+
&host
466477
};
467478

468479
// Forward all further arguments. We do some processing here because we want to
@@ -514,17 +525,27 @@ fn phase_cargo_miri(mut args: env::Args) {
514525
}
515526
cmd.env("RUSTC_WRAPPER", &cargo_miri_path);
516527

517-
// Set the runner for the current target to us as well, so we can interpret the binaries.
518-
let runner_env_name = format!("CARGO_TARGET_{}_RUNNER", target.to_uppercase().replace('-', "_"));
519-
cmd.env(&runner_env_name, &cargo_miri_path);
528+
let runner_env_name = |triple: &str| {
529+
format!("CARGO_TARGET_{}_RUNNER", triple.to_uppercase().replace('-', "_"))
530+
};
531+
let host_runner_env_name = runner_env_name(&host);
532+
let target_runner_env_name = runner_env_name(target);
533+
// Set the target runner to us, so we can interpret the binaries.
534+
cmd.env(&target_runner_env_name, &cargo_miri_path);
535+
// Unit tests of `proc-macro` crates are run on the host, so we set the host runner to
536+
// us in order to skip them.
537+
cmd.env(&host_runner_env_name, &cargo_miri_path);
520538

521539
// Set rustdoc to us as well, so we can make it do nothing (see issue #584).
522540
cmd.env("RUSTDOC", &cargo_miri_path);
523541

524542
// Run cargo.
525543
if verbose {
526544
eprintln!("[cargo-miri miri] RUSTC_WRAPPER={:?}", cargo_miri_path);
527-
eprintln!("[cargo-miri miri] {}={:?}", runner_env_name, cargo_miri_path);
545+
eprintln!("[cargo-miri miri] {}={:?}", target_runner_env_name, cargo_miri_path);
546+
if *target != host {
547+
eprintln!("[cargo-miri miri] {}={:?}", host_runner_env_name, cargo_miri_path);
548+
}
528549
eprintln!("[cargo-miri miri] RUSTDOC={:?}", cargo_miri_path);
529550
eprintln!("[cargo-miri miri] {:?}", cmd);
530551
cmd.env("MIRI_VERBOSE", ""); // This makes the other phases verbose.
@@ -587,23 +608,34 @@ fn phase_cargo_rustc(args: env::Args) {
587608
_ => {},
588609
}
589610

590-
if !print && target_crate && is_runnable_crate() {
591-
// This is the binary or test crate that we want to interpret under Miri.
592-
// But we cannot run it here, as cargo invoked us as a compiler -- our stdin and stdout are not
593-
// like we want them.
594-
// Instead of compiling, we write JSON into the output file with all the relevant command-line flags
595-
// and environment variables; this is used when cargo calls us again in the CARGO_TARGET_RUNNER phase.
596-
let info = CrateRunInfo::collect(args);
611+
let store_json = |info: CrateRunInfo| {
597612
let filename = out_filename("", "");
598613
if verbose {
599614
eprintln!("[cargo-miri rustc] writing run info to `{}`", filename.display());
600615
}
601-
602616
info.store(&filename);
603617
// For Windows, do the same thing again with `.exe` appended to the filename.
604618
// (Need to do this here as cargo moves that "binary" to a different place before running it.)
605619
info.store(&out_filename("", ".exe"));
620+
};
606621

622+
let runnable_crate = !print && is_runnable_crate();
623+
624+
if runnable_crate && target_crate {
625+
// This is the binary or test crate that we want to interpret under Miri.
626+
// But we cannot run it here, as cargo invoked us as a compiler -- our stdin and stdout are not
627+
// like we want them.
628+
// Instead of compiling, we write JSON into the output file with all the relevant command-line flags
629+
// and environment variables; this is used when cargo calls us again in the CARGO_TARGET_RUNNER phase.
630+
store_json(CrateRunInfo::collect(args));
631+
return;
632+
}
633+
634+
if runnable_crate && ArgFlagValueIter::new("--extern").any(|krate| krate == "proc_macro") {
635+
// This is a "runnable" `proc-macro` crate (unit tests). We do not support
636+
// interpreting that under Miri now, so we write a JSON file to (display a
637+
// helpful message and) skip it in the runner phase.
638+
store_json(CrateRunInfo::SkipProcMacroTest);
607639
return;
608640
}
609641

@@ -671,8 +703,16 @@ fn phase_cargo_runner(binary: &Path, binary_args: env::Args) {
671703
let file = File::open(&binary)
672704
.unwrap_or_else(|_| show_error(format!("file {:?} not found or `cargo-miri` invoked incorrectly; please only invoke this binary through `cargo miri`", binary)));
673705
let file = BufReader::new(file);
674-
let info: CrateRunInfo = serde_json::from_reader(file)
706+
707+
let info = serde_json::from_reader(file)
675708
.unwrap_or_else(|_| show_error(format!("file {:?} contains outdated or invalid JSON; try `cargo clean`", binary)));
709+
let info = match info {
710+
CrateRunInfo::RunWith(info) => info,
711+
CrateRunInfo::SkipProcMacroTest => {
712+
eprintln!("Running unit tests of `proc-macro` crates is not currently supported by Miri.");
713+
return;
714+
}
715+
};
676716

677717
// Set missing env vars. Looks like `build.rs` vars are still set at run-time, but
678718
// `CARGO_BIN_EXE_*` are not. This means we can give the run-time environment precedence,

0 commit comments

Comments
 (0)