@@ -119,6 +119,41 @@ fn list_targets() -> impl Iterator<Item=cargo_metadata::Target> {
119
119
package. targets . into_iter ( )
120
120
}
121
121
122
+ /// Returns the path to the `miri` binary
123
+ fn find_miri ( ) -> PathBuf {
124
+ let mut path = std:: env:: current_exe ( ) . expect ( "current executable path invalid" ) ;
125
+ path. set_file_name ( "miri" ) ;
126
+ path
127
+ }
128
+
129
+ /// Make sure that the `miri` and `rustc` binary are from the same sysroot.
130
+ /// This can be violated e.g. when miri is locally built and installed with a different
131
+ /// toolchain than what is used when `cargo miri` is run.
132
+ fn test_sysroot_consistency ( ) {
133
+ fn get_sysroot ( mut cmd : Command ) -> PathBuf {
134
+ let out = cmd. arg ( "--print" ) . arg ( "sysroot" )
135
+ . output ( ) . expect ( "Failed to run rustc to get sysroot info" ) ;
136
+ assert ! ( out. status. success( ) , "Bad status code when getting sysroot info" ) ;
137
+ let sysroot = out. stdout . lines ( ) . nth ( 0 )
138
+ . expect ( "didn't get at least one line for the sysroot" ) . unwrap ( ) ;
139
+ PathBuf :: from ( sysroot) . canonicalize ( )
140
+ . expect ( "Failed to canonicalize sysroot" )
141
+ }
142
+
143
+ let rustc_sysroot = get_sysroot ( Command :: new ( "rustc" ) ) ;
144
+ let miri_sysroot = get_sysroot ( Command :: new ( find_miri ( ) ) ) ;
145
+
146
+ if rustc_sysroot != miri_sysroot {
147
+ show_error ( format ! (
148
+ "miri was built for a different sysroot than the rustc in your current toolchain.\n \
149
+ Make sure you use the same toolchain to run miri that you used to build it!\n \
150
+ rustc sysroot: `{}`\n \
151
+ miri sysroot: `{}`",
152
+ rustc_sysroot. display( ) , miri_sysroot. display( )
153
+ ) ) ;
154
+ }
155
+ }
156
+
122
157
fn xargo_version ( ) -> Option < ( u32 , u32 , u32 ) > {
123
158
let out = Command :: new ( "xargo" ) . arg ( "--version" ) . output ( ) . ok ( ) ?;
124
159
if !out. status . success ( ) {
@@ -265,11 +300,11 @@ path = "lib.rs"
265
300
Some ( target) => target == rustc_version:: version_meta ( ) . unwrap ( ) . host ,
266
301
} ;
267
302
let sysroot = if is_host { dir. join ( "HOST" ) } else { PathBuf :: from ( dir) } ;
268
- std:: env:: set_var ( "MIRI_SYSROOT" , & sysroot) ;
303
+ std:: env:: set_var ( "MIRI_SYSROOT" , & sysroot) ; // pass the env var to the processes we spawn, which will turn it into "--sysroot" flags
269
304
if print_env {
270
305
println ! ( "MIRI_SYSROOT={}" , sysroot. display( ) ) ;
271
306
} else if !ask_user {
272
- println ! ( "A libstd for Miri is now available in `{}`" , sysroot. display( ) ) ;
307
+ println ! ( "A libstd for Miri is now available in `{}`. " , sysroot. display( ) ) ;
273
308
}
274
309
}
275
310
@@ -313,6 +348,9 @@ fn in_cargo_miri() {
313
348
} ;
314
349
let verbose = has_arg_flag ( "-v" ) ;
315
350
351
+ // Some basic sanity checks
352
+ test_sysroot_consistency ( ) ;
353
+
316
354
// We always setup.
317
355
let ask = subcommand != MiriCommand :: Setup ;
318
356
setup ( ask) ;
@@ -385,38 +423,13 @@ fn in_cargo_miri() {
385
423
}
386
424
387
425
fn inside_cargo_rustc ( ) {
388
- let home = option_env ! ( "RUSTUP_HOME" ) . or ( option_env ! ( "MULTIRUST_HOME" ) ) ;
389
- let toolchain = option_env ! ( "RUSTUP_TOOLCHAIN" ) . or ( option_env ! ( "MULTIRUST_TOOLCHAIN" ) ) ;
390
- let sys_root = if let Ok ( sysroot) = :: std:: env:: var ( "MIRI_SYSROOT" ) {
391
- sysroot
392
- } else if let ( Some ( home) , Some ( toolchain) ) = ( home, toolchain) {
393
- format ! ( "{}/toolchains/{}" , home, toolchain)
394
- } else {
395
- option_env ! ( "RUST_SYSROOT" )
396
- . map ( |s| s. to_owned ( ) )
397
- . or_else ( || {
398
- Command :: new ( "rustc" )
399
- . arg ( "--print" )
400
- . arg ( "sysroot" )
401
- . output ( )
402
- . ok ( )
403
- . and_then ( |out| String :: from_utf8 ( out. stdout ) . ok ( ) )
404
- . map ( |s| s. trim ( ) . to_owned ( ) )
405
- } )
406
- . expect ( "need to specify `RUST_SYSROOT` env var during miri compilation, or use rustup or multirust" )
407
- } ;
426
+ let sysroot = std:: env:: var ( "MIRI_SYSROOT" ) . expect ( "The wrapper should have set MIRI_SYSROOT" ) ;
408
427
409
- // This conditional check for the `--sysroot` flag is there so that users can call `cargo-miri`
410
- // directly without having to pass `--sysroot` or anything.
411
- let rustc_args = std:: env:: args ( ) . skip ( 2 ) ;
412
- let mut args: Vec < String > = if std:: env:: args ( ) . any ( |s| s == "--sysroot" ) {
413
- rustc_args. collect ( )
414
- } else {
415
- rustc_args
416
- . chain ( Some ( "--sysroot" . to_owned ( ) ) )
417
- . chain ( Some ( sys_root) )
418
- . collect ( )
419
- } ;
428
+ let rustc_args = std:: env:: args ( ) . skip ( 2 ) ; // skip `cargo rustc`
429
+ let mut args: Vec < String > = rustc_args
430
+ . chain ( Some ( "--sysroot" . to_owned ( ) ) )
431
+ . chain ( Some ( sysroot) )
432
+ . collect ( ) ;
420
433
args. splice ( 0 ..0 , miri:: miri_default_args ( ) . iter ( ) . map ( ToString :: to_string) ) ;
421
434
422
435
// See if we can find the `cargo-miri` markers. Those only get added to the binary we want to
@@ -441,9 +454,7 @@ fn inside_cargo_rustc() {
441
454
} ;
442
455
443
456
let mut command = if needs_miri {
444
- let mut path = std:: env:: current_exe ( ) . expect ( "current executable path invalid" ) ;
445
- path. set_file_name ( "miri" ) ;
446
- Command :: new ( path)
457
+ Command :: new ( find_miri ( ) )
447
458
} else {
448
459
Command :: new ( "rustc" )
449
460
} ;
0 commit comments