@@ -6,7 +6,7 @@ use std::ops::Not;
6
6
use std:: path:: { Path , PathBuf } ;
7
7
use std:: process:: Command ;
8
8
9
- const XARGO_MIN_VERSION : ( u32 , u32 , u32 ) = ( 0 , 3 , 17 ) ;
9
+ const XARGO_MIN_VERSION : ( u32 , u32 , u32 ) = ( 0 , 3 , 19 ) ;
10
10
11
11
const CARGO_MIRI_HELP : & str = r#"Interprets bin crates and tests in Miri
12
12
@@ -84,7 +84,37 @@ fn get_arg_flag_value(name: &str) -> Option<String> {
84
84
}
85
85
}
86
86
87
- fn list_targets ( ) -> impl Iterator < Item = cargo_metadata:: Target > {
87
+ fn is_build_dep ( mut args : impl Iterator < Item = String > ) -> bool {
88
+ args. any ( |arg| arg. starts_with ( "--emit=" ) && arg. contains ( "link" ) )
89
+ }
90
+
91
+ // Returns whether or not Cargo invoked the wrapper (this binary) to compile
92
+ // the final, target crate (either a test for 'cargo test', or a binary for 'cargo run')
93
+ // Right now, this is an awful hack that checks several different pieces of information
94
+ // to try to figure out if the crate being compiled is the right one.
95
+ // Ideally, Cargo would set en environment variable indicating whether or
96
+ // not the wrapper is being invoked on the target crate.
97
+ // For now, this is the best we can do
98
+ fn is_target_crate ( is_build_script : bool ) -> bool {
99
+ // Cargo sets this to the directory containing the manifest of the crate
100
+ // the wrapper is being invoekd to compile. This should be unique
101
+ // across the entire build (except for build scripts, which we handle below).
102
+ // We cannot check the crate name, since this may not be unique
103
+ // (e.g. if the build contains multiple versions of the same crate,
104
+ // or the same crate from multiple sources)
105
+ let manifest_dir = std:: env:: var ( "CARGO_MANIFEST_DIR" ) . ok ( ) ;
106
+
107
+ // The manifest directory for our target crate. This is set by `cargo-miri`
108
+ // (the original invoation by the user) by using `cargo_metadata` to locate
109
+ // the manifest.
110
+ let expected_dir = std:: env:: var ( "MIRI_MAGIC_DIR" ) . expect ( "MIRI_MAGIC_DIR not set!" ) ;
111
+
112
+ manifest_dir == Some ( expected_dir) && !is_build_script
113
+
114
+ }
115
+
116
+
117
+ fn read_cargo_metadata ( ) -> ( impl Iterator < Item = cargo_metadata:: Target > , String ) {
88
118
// We need to get the manifest, and then the metadata, to enumerate targets.
89
119
let manifest_path =
90
120
get_arg_flag_value ( "--manifest-path" ) . map ( |m| Path :: new ( & m) . canonicalize ( ) . unwrap ( ) ) ;
@@ -124,7 +154,7 @@ fn list_targets() -> impl Iterator<Item = cargo_metadata::Target> {
124
154
let package = metadata. packages . remove ( package_index) ;
125
155
126
156
// Finally we got the list of targets to build
127
- package. targets . into_iter ( )
157
+ ( package. targets . into_iter ( ) , metadata . workspace_root . to_string_lossy ( ) . to_string ( ) )
128
158
}
129
159
130
160
/// Returns the path to the `miri` binary
@@ -197,7 +227,7 @@ fn xargo() -> Command {
197
227
// Bootstrap tells us where to find xargo
198
228
Command :: new ( val)
199
229
} else {
200
- Command :: new ( "xargo" )
230
+ Command :: new ( "xargo-check " )
201
231
}
202
232
}
203
233
@@ -458,8 +488,10 @@ fn in_cargo_miri() {
458
488
return ;
459
489
}
460
490
491
+ let ( targets, root_dir) = read_cargo_metadata ( ) ;
492
+
461
493
// Now run the command.
462
- for target in list_targets ( ) {
494
+ for target in targets {
463
495
let mut args = std:: env:: args ( ) . skip ( skip) ;
464
496
let kind = target
465
497
. kind
@@ -469,7 +501,8 @@ fn in_cargo_miri() {
469
501
// change to add additional arguments. `FLAGS` is set to identify
470
502
// this target. The user gets to control what gets actually passed to Miri.
471
503
let mut cmd = cargo ( ) ;
472
- cmd. arg ( "rustc" ) ;
504
+ cmd. arg ( "check" ) ;
505
+ cmd. arg ( "--target" ) . arg ( "x86_64-unknown-linux-gnu" ) ;
473
506
match ( subcommand, kind. as_str ( ) ) {
474
507
( MiriCommand :: Run , "bin" ) => {
475
508
// FIXME: we just run all the binaries here.
@@ -496,10 +529,15 @@ fn in_cargo_miri() {
496
529
}
497
530
cmd. arg ( arg) ;
498
531
}
532
+
533
+ let args_vec: Vec < String > = args. collect ( ) ;
534
+ cmd. env ( "MIRI_MAGIC_DIR" , root_dir. clone ( ) ) ;
535
+ cmd. env ( "MIRI_MAGIC_ARGS" , serde_json:: to_string ( & args_vec) . expect ( "failed to serialize args" ) ) ;
536
+
499
537
// Add `--` (to end the `cargo` flags), and then the user flags. We add markers around the
500
538
// user flags to be able to identify them later. "cargo rustc" adds more stuff after this,
501
539
// so we have to mark both the beginning and the end.
502
- cmd. arg ( "--" ) . arg ( "cargo-miri-marker-begin" ) . args ( args) . arg ( "cargo-miri-marker-end" ) ;
540
+ // cmd.arg("--").arg("cargo-miri-marker-begin").args(args).arg("cargo-miri-marker-end");
503
541
let path = std:: env:: current_exe ( ) . expect ( "current executable path invalid" ) ;
504
542
cmd. env ( "RUSTC_WRAPPER" , path) ;
505
543
if verbose {
@@ -519,25 +557,27 @@ fn inside_cargo_rustc() {
519
557
let sysroot = std:: env:: var ( "MIRI_SYSROOT" ) . expect ( "The wrapper should have set MIRI_SYSROOT" ) ;
520
558
521
559
let rustc_args = std:: env:: args ( ) . skip ( 2 ) ; // skip `cargo rustc`
522
- let mut args: Vec < String > =
523
- rustc_args. chain ( Some ( "--sysroot" . to_owned ( ) ) ) . chain ( Some ( sysroot) ) . collect ( ) ;
524
- args. splice ( 0 ..0 , miri:: miri_default_args ( ) . iter ( ) . map ( ToString :: to_string) ) ;
560
+
561
+ let in_build_script = is_build_dep ( std:: env:: args ( ) . skip ( 2 ) ) ;
562
+
563
+ let mut args = if in_build_script {
564
+ rustc_args. collect ( )
565
+ } else {
566
+ let mut args: Vec < String > = rustc_args
567
+ . chain ( Some ( "--sysroot" . to_owned ( ) ) )
568
+ . chain ( Some ( sysroot) )
569
+ . collect ( ) ;
570
+ args. splice ( 0 ..0 , miri:: miri_default_args ( ) . iter ( ) . map ( ToString :: to_string) ) ;
571
+ args
572
+ } ;
525
573
526
574
// See if we can find the `cargo-miri` markers. Those only get added to the binary we want to
527
575
// run. They also serve to mark the user-defined arguments, which we have to move all the way
528
576
// to the end (they get added somewhere in the middle).
529
577
let needs_miri =
530
- if let Some ( begin) = args. iter ( ) . position ( |arg| arg == "cargo-miri-marker-begin" ) {
531
- let end = args
532
- . iter ( )
533
- . position ( |arg| arg == "cargo-miri-marker-end" )
534
- . expect ( "cannot find end marker" ) ;
535
- // These mark the user arguments. We remove the first and last as they are the markers.
536
- let mut user_args = args. drain ( begin..=end) ;
537
- assert_eq ! ( user_args. next( ) . unwrap( ) , "cargo-miri-marker-begin" ) ;
538
- assert_eq ! ( user_args. next_back( ) . unwrap( ) , "cargo-miri-marker-end" ) ;
539
- // Collect the rest and add it back at the end.
540
- let mut user_args = user_args. collect :: < Vec < String > > ( ) ;
578
+ if is_target_crate ( in_build_script) {
579
+ let magic = std:: env:: var ( "MIRI_MAGIC_ARGS" ) . expect ( "missing MIRI_MAGIC_ARGS" ) ;
580
+ let mut user_args: Vec < String > = serde_json:: from_str ( & magic) . expect ( "failed to deserialize args" ) ;
541
581
args. append ( & mut user_args) ;
542
582
// Run this in Miri.
543
583
true
0 commit comments