@@ -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,21 @@ 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
765
+ // `rustc` even when `RUSTC_WRAPPER` is set. To make sure everything is coherent, we want that
766
+ // to be the Miri driver, but acting as rustc, on the target level. (Target, rather than host,
767
+ // is needed for cross-interpretation situations.) This is not a perfect emulation of real rustc
768
+ // (it might be unable to produce binaries since the sysroot is check-only), but it's as close
769
+ // as we can get, and it's good enough for autocfg.
770
+ //
761
771
// In `main`, we need the value of `RUSTC` to distinguish RUSTC_WRAPPER invocations from rustdoc
762
772
// or TARGET_RUNNER invocations, so we canonicalize it here to make it exceedingly unlikely that
763
- // there would be a collision with other invocations of cargo-miri (as rustdoc or as runner).
764
- // We explicitly do this even if RUSTC_STAGE is set, since for these builds we do *not* want the
765
- // bootstrap `rustc` thing in our way! Instead, we have MIRI_HOST_SYSROOT to use for host builds.
773
+ // there would be a collision with other invocations of cargo-miri (as rustdoc or as runner). We
774
+ // explicitly do this even if RUSTC_STAGE is set, since for these builds we do *not* want the
775
+ // bootstrap `rustc` thing in our way! Instead, we have MIRI_HOST_SYSROOT to use for host
776
+ // builds.
766
777
cmd. env ( "RUSTC" , & fs:: canonicalize ( find_miri ( ) ) . unwrap ( ) ) ;
778
+ cmd. env ( "MIRI_BE_RUSTC" , "target" ) ; // we better remember to *unset* this in the other phases!
767
779
768
780
// Set rustdoc to us as well, so we can run doctests.
769
781
cmd. env ( "RUSTDOC" , & cargo_miri_path) ;
@@ -832,10 +844,16 @@ fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
832
844
}
833
845
}
834
846
847
+ // phase_cargo_miri set `MIRI_BE_RUSTC` for when build scripts directly invoke the driver;
848
+ // however, if we get called back by cargo here, we'll carefully compute the right flags
849
+ // ourselves, so we first un-do what the earlier phase did.
850
+ env:: remove_var ( "MIRI_BE_RUSTC" ) ;
851
+
835
852
let verbose = std:: env:: var ( "MIRI_VERBOSE" )
836
853
. map_or ( 0 , |verbose| verbose. parse ( ) . expect ( "verbosity flag must be an integer" ) ) ;
837
854
let target_crate = is_target_crate ( ) ;
838
- let print = get_arg_flag_value ( "--print" ) . is_some ( ) || has_arg_flag ( "-vV" ) ; // whether this is cargo/xargo invoking rustc to get some infos
855
+ // Determine whether this is cargo/xargo invoking rustc to get some infos.
856
+ let info_query = get_arg_flag_value ( "--print" ) . is_some ( ) || has_arg_flag ( "-vV" ) ;
839
857
840
858
let store_json = |info : CrateRunInfo | {
841
859
// Create a stub .d file to stop Cargo from "rebuilding" the crate:
@@ -857,7 +875,7 @@ fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
857
875
info. store ( & out_filename ( "" , ".exe" ) ) ;
858
876
} ;
859
877
860
- let runnable_crate = !print && is_runnable_crate ( ) ;
878
+ let runnable_crate = !info_query && is_runnable_crate ( ) ;
861
879
862
880
if runnable_crate && target_crate {
863
881
assert ! (
@@ -919,7 +937,7 @@ fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
919
937
let mut emit_link_hack = false ;
920
938
// Arguments are treated very differently depending on whether this crate is
921
939
// for interpretation by Miri, or for use by a build script / proc macro.
922
- if !print && target_crate {
940
+ if !info_query && target_crate {
923
941
// Forward arguments, but remove "link" from "--emit" to make this a check-only build.
924
942
let emit_flag = "--emit" ;
925
943
while let Some ( arg) = args. next ( ) {
@@ -946,20 +964,16 @@ fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
946
964
}
947
965
}
948
966
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
967
// During setup, patch the panic runtime for `libpanic_abort` (mirroring what bootstrap usually does).
955
968
if phase == RustcPhase :: Setup
956
969
&& get_arg_flag_value ( "--crate-name" ) . as_deref ( ) == Some ( "panic_abort" )
957
970
{
958
971
cmd. arg ( "-C" ) . arg ( "panic=abort" ) ;
959
972
}
960
973
} else {
961
- // For host crates (but not when we are printing), we might still have to set the sysroot.
962
- if !print {
974
+ // For host crates (but not when we are just printing some info),
975
+ // we might still have to set the sysroot.
976
+ if !info_query {
963
977
// When we're running `cargo-miri` from `x.py` we need to pass the sysroot explicitly
964
978
// due to bootstrap complications.
965
979
if let Some ( sysroot) = std:: env:: var_os ( "MIRI_HOST_SYSROOT" ) {
@@ -980,7 +994,7 @@ fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
980
994
// Run it.
981
995
if verbose > 0 {
982
996
eprintln ! (
983
- "[cargo-miri rustc] target_crate={target_crate} runnable_crate={runnable_crate} print={print }"
997
+ "[cargo-miri rustc] target_crate={target_crate} runnable_crate={runnable_crate} info_query={info_query }"
984
998
) ;
985
999
}
986
1000
debug_cmd ( "[cargo-miri rustc]" , verbose, & cmd) ;
@@ -1010,12 +1024,19 @@ enum RunnerPhase {
1010
1024
}
1011
1025
1012
1026
fn phase_runner ( mut binary_args : impl Iterator < Item = String > , phase : RunnerPhase ) {
1027
+ // phase_cargo_miri set `MIRI_BE_RUSTC` for when build scripts directly invoke the driver;
1028
+ // however, if we get called back by cargo here, we'll carefully compute the right flags
1029
+ // ourselves, so we first un-do what the earlier phase did.
1030
+ env:: remove_var ( "MIRI_BE_RUSTC" ) ;
1031
+
1013
1032
let verbose = std:: env:: var ( "MIRI_VERBOSE" )
1014
1033
. map_or ( 0 , |verbose| verbose. parse ( ) . expect ( "verbosity flag must be an integer" ) ) ;
1015
1034
1016
1035
let binary = binary_args. next ( ) . unwrap ( ) ;
1017
1036
let file = File :: open ( & binary)
1018
- . unwrap_or_else ( |_| show_error ( format ! ( "file {:?} not found or `cargo-miri` invoked incorrectly; please only invoke this binary through `cargo miri`" , binary) ) ) ;
1037
+ . unwrap_or_else ( |_| show_error ( format ! (
1038
+ "file {:?} not found or `cargo-miri` invoked incorrectly; please only invoke this binary through `cargo miri`" , binary
1039
+ ) ) ) ;
1019
1040
let file = BufReader :: new ( file) ;
1020
1041
1021
1042
let info = serde_json:: from_reader ( file) . unwrap_or_else ( |_| {
@@ -1077,10 +1098,6 @@ fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: RunnerPhas
1077
1098
cmd. arg ( arg) ;
1078
1099
}
1079
1100
}
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
1101
// Respect `MIRIFLAGS`.
1085
1102
if let Ok ( a) = env:: var ( "MIRIFLAGS" ) {
1086
1103
// This code is taken from `RUSTFLAGS` handling in cargo.
@@ -1151,7 +1168,7 @@ fn phase_rustdoc(mut args: impl Iterator<Item = String>) {
1151
1168
cmd. arg ( "-Z" ) . arg ( "unstable-options" ) ;
1152
1169
1153
1170
// rustdoc needs to know the right sysroot.
1154
- forward_miri_sysroot ( & mut cmd) ;
1171
+ cmd. arg ( "--sysroot" ) . arg ( env :: var_os ( "MIRI_SYSROOT" ) . unwrap ( ) ) ;
1155
1172
// make sure the 'miri' flag is set for rustdoc
1156
1173
cmd. arg ( "--cfg" ) . arg ( "miri" ) ;
1157
1174
0 commit comments