@@ -205,12 +205,6 @@ fn forward_patched_extern_arg(args: &mut impl Iterator<Item = String>, cmd: &mut
205
205
}
206
206
}
207
207
208
- fn forward_miri_sysroot ( cmd : & mut Command ) {
209
- let sysroot = env:: var_os ( "MIRI_SYSROOT" ) . expect ( "the wrapper should have set MIRI_SYSROOT" ) ;
210
- cmd. arg ( "--sysroot" ) ;
211
- cmd. arg ( sysroot) ;
212
- }
213
-
214
208
/// Escapes `s` in a way that is suitable for using it as a string literal in TOML syntax.
215
209
fn escape_for_toml ( s : & str ) -> String {
216
210
// We want to surround this string in quotes `"`. So we first escape all quotes,
@@ -237,8 +231,15 @@ fn miri() -> Command {
237
231
Command :: new ( find_miri ( ) )
238
232
}
239
233
234
+ fn miri_for_host ( ) -> Command {
235
+ let mut cmd = miri ( ) ;
236
+ cmd. env ( "MIRI_BE_RUSTC" , "host" ) ;
237
+ cmd
238
+ }
239
+
240
240
fn version_info ( ) -> VersionMeta {
241
- VersionMeta :: for_command ( miri ( ) ) . expect ( "failed to determine underlying rustc version of Miri" )
241
+ VersionMeta :: for_command ( miri_for_host ( ) )
242
+ . expect ( "failed to determine underlying rustc version of Miri" )
242
243
}
243
244
244
245
fn cargo ( ) -> Command {
@@ -336,7 +337,7 @@ fn ask_to_run(mut cmd: Command, ask: bool, text: &str) {
336
337
a => show_error ( format ! ( "invalid answer `{}`" , a) ) ,
337
338
} ;
338
339
} else {
339
- println ! ( "Running `{:?}` to {}." , cmd, text) ;
340
+ eprintln ! ( "Running `{:?}` to {}." , cmd, text) ;
340
341
}
341
342
342
343
if cmd. status ( ) . unwrap_or_else ( |_| panic ! ( "failed to execute {:?}" , cmd) ) . success ( ) . not ( ) {
@@ -364,7 +365,7 @@ fn write_to_file(filename: &Path, content: &str) {
364
365
/// Performs the setup required to make `cargo miri` work: Getting a custom-built libstd. Then sets
365
366
/// `MIRI_SYSROOT`. Skipped if `MIRI_SYSROOT` is already set, in which case we expect the user has
366
367
/// done all this already.
367
- fn setup ( subcommand : & MiriCommand ) {
368
+ fn setup ( subcommand : & MiriCommand , host : & str , target : & str ) {
368
369
let only_setup = matches ! ( subcommand, MiriCommand :: Setup ) ;
369
370
let ask_user = !only_setup;
370
371
let print_sysroot = only_setup && has_arg_flag ( "--print-sysroot" ) ; // whether we just print the sysroot path
@@ -398,8 +399,10 @@ fn setup(subcommand: &MiriCommand) {
398
399
}
399
400
None => {
400
401
// Check for `rust-src` rustup component.
401
- let output =
402
- miri ( ) . args ( & [ "--print" , "sysroot" ] ) . output ( ) . expect ( "failed to determine sysroot" ) ;
402
+ let output = miri_for_host ( )
403
+ . args ( & [ "--print" , "sysroot" ] )
404
+ . output ( )
405
+ . expect ( "failed to determine sysroot" ) ;
403
406
if !output. status . success ( ) {
404
407
show_error ( format ! (
405
408
"Failed to determine sysroot; Miri said:\n {}" ,
@@ -472,18 +475,21 @@ path = "lib.rs"
472
475
) ;
473
476
write_to_file ( & dir. join ( "lib.rs" ) , "#![no_std]" ) ;
474
477
475
- // Determine architectures.
476
- // We always need to set a target so rustc bootstrap can tell apart host from target crates.
477
- let host = version_info ( ) . host ;
478
- let target = get_arg_flag_value ( "--target" ) ;
479
- let target = target. as_ref ( ) . unwrap_or ( & host) ;
478
+ // Figure out where xargo will build its stuff.
479
+ // Unfortunately, it puts things into a different directory when the
480
+ // architecture matches the host.
481
+ let sysroot = if target == host { dir. join ( "HOST" ) } else { PathBuf :: from ( dir) } ;
482
+ // Make sure all target-level Miri invocations know their sysroot.
483
+ std:: env:: set_var ( "MIRI_SYSROOT" , & sysroot) ;
484
+
480
485
// Now invoke xargo.
481
486
let mut command = xargo_check ( ) ;
482
487
command. arg ( "check" ) . arg ( "-q" ) ;
483
- command. arg ( "--target" ) . arg ( target) ;
484
488
command. current_dir ( & dir) ;
485
489
command. env ( "XARGO_HOME" , & dir) ;
486
490
command. env ( "XARGO_RUST_SRC" , & rust_src) ;
491
+ // We always need to set a target so rustc bootstrap can tell apart host from target crates.
492
+ command. arg ( "--target" ) . arg ( target) ;
487
493
// Use Miri as rustc to build a libstd compatible with us (and use the right flags).
488
494
// However, when we are running in bootstrap, we cannot just overwrite `RUSTC`,
489
495
// because we still need bootstrap to distinguish between host and target crates.
@@ -523,6 +529,7 @@ path = "lib.rs"
523
529
command. stdout ( process:: Stdio :: null ( ) ) ;
524
530
command. stderr ( process:: Stdio :: null ( ) ) ;
525
531
}
532
+
526
533
// Finally run it!
527
534
if command. status ( ) . expect ( "failed to run xargo" ) . success ( ) . not ( ) {
528
535
if only_setup {
@@ -534,11 +541,6 @@ path = "lib.rs"
534
541
}
535
542
}
536
543
537
- // That should be it! But we need to figure out where xargo built stuff.
538
- // Unfortunately, it puts things into a different directory when the
539
- // architecture matches the host.
540
- let sysroot = if target == & host { dir. join ( "HOST" ) } else { PathBuf :: from ( dir) } ;
541
- std:: env:: set_var ( "MIRI_SYSROOT" , & sysroot) ; // pass the env var to the processes we spawn, which will turn it into "--sysroot" flags
542
544
// Figure out what to print.
543
545
if only_setup {
544
546
eprintln ! ( "A sysroot for Miri is now available in `{}`." , sysroot. display( ) ) ;
@@ -677,8 +679,13 @@ fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
677
679
} ;
678
680
let verbose = num_arg_flag ( "-v" ) ;
679
681
682
+ // Determine the involved architectures.
683
+ let host = version_info ( ) . host ;
684
+ let target = get_arg_flag_value ( "--target" ) ;
685
+ let target = target. as_ref ( ) . unwrap_or ( & host) ;
686
+
680
687
// We always setup.
681
- setup ( & subcommand) ;
688
+ setup ( & subcommand, & host , target ) ;
682
689
683
690
// Invoke actual cargo for the job, but with different flags.
684
691
// We re-use `cargo test` and `cargo run`, which makes target and binary handling very easy but
@@ -727,7 +734,7 @@ fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
727
734
if get_arg_flag_value ( "--target" ) . is_none ( ) {
728
735
// No target given. Explicitly pick the host.
729
736
cmd. arg ( "--target" ) ;
730
- cmd. arg ( version_info ( ) . host ) ;
737
+ cmd. arg ( & host) ;
731
738
}
732
739
733
740
// Set ourselves as runner for al binaries invoked by cargo.
@@ -754,16 +761,19 @@ fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
754
761
"WARNING: Ignoring `RUSTC` environment variable; set `MIRI` if you want to control the binary used as the driver."
755
762
) ;
756
763
}
757
- // We'd prefer to just clear this env var, but cargo does not always honor `RUSTC_WRAPPER`
758
- // (https://github.com/rust-lang/cargo/issues/10885). There is no good way to single out these invocations;
759
- // some build scripts use the RUSTC env var as well. So we set it directly to the `miri` driver and
760
- // hope that all they do is ask for the version number -- things could quickly go downhill from here.
764
+ // Build scripts (and also cargo: https://github.com/rust-lang/cargo/issues/10885) will invoke `rustc` even when `RUSTC_WRAPPER` is set.
765
+ // To make sure everything is coherent, we want that to be the Miri driver, but acting as rustc, on the target level.
766
+ // (Target, rather than host, is needed for cross-interpretation situations.) This is not a
767
+ // perfect emulation of real rustc (it might be unable to produce binaries since the sysroot is
768
+ // check-only), but it's as close as we can get, and it's good enough for autocfg.
769
+ //
761
770
// In `main`, we need the value of `RUSTC` to distinguish RUSTC_WRAPPER invocations from rustdoc
762
771
// or TARGET_RUNNER invocations, so we canonicalize it here to make it exceedingly unlikely that
763
772
// there would be a collision with other invocations of cargo-miri (as rustdoc or as runner).
764
773
// We explicitly do this even if RUSTC_STAGE is set, since for these builds we do *not* want the
765
774
// bootstrap `rustc` thing in our way! Instead, we have MIRI_HOST_SYSROOT to use for host builds.
766
775
cmd. env ( "RUSTC" , & fs:: canonicalize ( find_miri ( ) ) . unwrap ( ) ) ;
776
+ cmd. env ( "MIRI_BE_RUSTC" , "target" ) ; // we better remember to *unset* this in the other phases!
767
777
768
778
// Set rustdoc to us as well, so we can run doctests.
769
779
cmd. env ( "RUSTDOC" , & cargo_miri_path) ;
@@ -832,6 +842,11 @@ fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
832
842
}
833
843
}
834
844
845
+ // phase_cargo_miri set `MIRI_BE_RUSTC` for when build scripts directly invoke the driver;
846
+ // however, if we get called back by cargo here, we'll carefully compute the right flags
847
+ // ourselves, so we first un-do what the earlier phase did.
848
+ env:: remove_var ( "MIRI_BE_RUSTC" ) ;
849
+
835
850
let verbose = std:: env:: var ( "MIRI_VERBOSE" )
836
851
. map_or ( 0 , |verbose| verbose. parse ( ) . expect ( "verbosity flag must be an integer" ) ) ;
837
852
let target_crate = is_target_crate ( ) ;
@@ -946,11 +961,6 @@ fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
946
961
}
947
962
}
948
963
949
- // Use our custom sysroot (but not if that is what we are currently building).
950
- if phase != RustcPhase :: Setup {
951
- forward_miri_sysroot ( & mut cmd) ;
952
- }
953
-
954
964
// During setup, patch the panic runtime for `libpanic_abort` (mirroring what bootstrap usually does).
955
965
if phase == RustcPhase :: Setup
956
966
&& get_arg_flag_value ( "--crate-name" ) . as_deref ( ) == Some ( "panic_abort" )
@@ -1010,6 +1020,11 @@ enum RunnerPhase {
1010
1020
}
1011
1021
1012
1022
fn phase_runner ( mut binary_args : impl Iterator < Item = String > , phase : RunnerPhase ) {
1023
+ // phase_cargo_miri set `MIRI_BE_RUSTC` for when build scripts directly invoke the driver;
1024
+ // however, if we get called back by cargo here, we'll carefully compute the right flags
1025
+ // ourselves, so we first un-do what the earlier phase did.
1026
+ env:: remove_var ( "MIRI_BE_RUSTC" ) ;
1027
+
1013
1028
let verbose = std:: env:: var ( "MIRI_VERBOSE" )
1014
1029
. map_or ( 0 , |verbose| verbose. parse ( ) . expect ( "verbosity flag must be an integer" ) ) ;
1015
1030
@@ -1077,10 +1092,6 @@ fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: RunnerPhas
1077
1092
cmd. arg ( arg) ;
1078
1093
}
1079
1094
}
1080
- // Set sysroot (if we are inside rustdoc, we already did that in `phase_cargo_rustdoc`).
1081
- if phase != RunnerPhase :: Rustdoc {
1082
- forward_miri_sysroot ( & mut cmd) ;
1083
- }
1084
1095
// Respect `MIRIFLAGS`.
1085
1096
if let Ok ( a) = env:: var ( "MIRIFLAGS" ) {
1086
1097
// This code is taken from `RUSTFLAGS` handling in cargo.
@@ -1151,7 +1162,7 @@ fn phase_rustdoc(mut args: impl Iterator<Item = String>) {
1151
1162
cmd. arg ( "-Z" ) . arg ( "unstable-options" ) ;
1152
1163
1153
1164
// rustdoc needs to know the right sysroot.
1154
- forward_miri_sysroot ( & mut cmd) ;
1165
+ cmd. arg ( "--sysroot" ) . arg ( env :: var_os ( "MIRI_SYSROOT" ) . unwrap ( ) ) ;
1155
1166
// make sure the 'miri' flag is set for rustdoc
1156
1167
cmd. arg ( "--cfg" ) . arg ( "miri" ) ;
1157
1168
0 commit comments