@@ -37,9 +37,9 @@ enum MiriCommand {
37
37
Setup ,
38
38
}
39
39
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 .
41
41
#[ derive( Serialize , Deserialize ) ]
42
- struct CrateRunInfo {
42
+ struct CrateRunEnv {
43
43
/// The command-line arguments.
44
44
args : Vec < String > ,
45
45
/// The environment.
@@ -48,13 +48,22 @@ struct CrateRunInfo {
48
48
current_dir : OsString ,
49
49
}
50
50
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
+
51
60
impl CrateRunInfo {
52
61
/// Gather all the information we need.
53
62
fn collect ( args : env:: Args ) -> Self {
54
63
let args = args. collect ( ) ;
55
64
let env = env:: vars_os ( ) . collect ( ) ;
56
65
let current_dir = env:: current_dir ( ) . unwrap ( ) . into_os_string ( ) ;
57
- CrateRunInfo { args, env, current_dir }
66
+ Self :: RunWith ( CrateRunEnv { args, env, current_dir } )
58
67
}
59
68
60
69
fn store ( & self , filename : & Path ) {
@@ -90,6 +99,7 @@ fn has_arg_flag(name: &str) -> bool {
90
99
args. any ( |val| val == name)
91
100
}
92
101
102
+ /// Yields all values of command line flag `name`.
93
103
struct ArgFlagValueIter < ' a > {
94
104
args : TakeWhile < env:: Args , fn ( & String ) -> bool > ,
95
105
name : & ' a str ,
@@ -455,14 +465,15 @@ fn phase_cargo_miri(mut args: env::Args) {
455
465
// This is needed to make the `CARGO_TARGET_*_RUNNER` env var do something,
456
466
// and it later helps us detect which crates are proc-macro/build-script
457
467
// (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 {
459
471
target
460
472
} else {
461
473
// No target given. Pick default and tell cargo about it.
462
- let host = version_info ( ) . host ;
463
474
cmd. arg ( "--target" ) ;
464
475
cmd. arg ( & host) ;
465
- host
476
+ & host
466
477
} ;
467
478
468
479
// 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) {
514
525
}
515
526
cmd. env ( "RUSTC_WRAPPER" , & cargo_miri_path) ;
516
527
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) ;
520
538
521
539
// Set rustdoc to us as well, so we can make it do nothing (see issue #584).
522
540
cmd. env ( "RUSTDOC" , & cargo_miri_path) ;
523
541
524
542
// Run cargo.
525
543
if verbose {
526
544
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
+ }
528
549
eprintln ! ( "[cargo-miri miri] RUSTDOC={:?}" , cargo_miri_path) ;
529
550
eprintln ! ( "[cargo-miri miri] {:?}" , cmd) ;
530
551
cmd. env ( "MIRI_VERBOSE" , "" ) ; // This makes the other phases verbose.
@@ -587,23 +608,34 @@ fn phase_cargo_rustc(args: env::Args) {
587
608
_ => { } ,
588
609
}
589
610
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 | {
597
612
let filename = out_filename ( "" , "" ) ;
598
613
if verbose {
599
614
eprintln ! ( "[cargo-miri rustc] writing run info to `{}`" , filename. display( ) ) ;
600
615
}
601
-
602
616
info. store ( & filename) ;
603
617
// For Windows, do the same thing again with `.exe` appended to the filename.
604
618
// (Need to do this here as cargo moves that "binary" to a different place before running it.)
605
619
info. store ( & out_filename ( "" , ".exe" ) ) ;
620
+ } ;
606
621
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 ) ;
607
639
return ;
608
640
}
609
641
@@ -671,8 +703,16 @@ fn phase_cargo_runner(binary: &Path, binary_args: env::Args) {
671
703
let file = File :: open ( & binary)
672
704
. unwrap_or_else ( |_| show_error ( format ! ( "file {:?} not found or `cargo-miri` invoked incorrectly; please only invoke this binary through `cargo miri`" , binary) ) ) ;
673
705
let file = BufReader :: new ( file) ;
674
- let info: CrateRunInfo = serde_json:: from_reader ( file)
706
+
707
+ let info = serde_json:: from_reader ( file)
675
708
. 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
+ } ;
676
716
677
717
// Set missing env vars. Looks like `build.rs` vars are still set at run-time, but
678
718
// `CARGO_BIN_EXE_*` are not. This means we can give the run-time environment precedence,
0 commit comments