Skip to content

Commit 6834944

Browse files
committed
fix MIRI_BE_RUSTC value during sysroot build
1 parent a86eab3 commit 6834944

File tree

2 files changed

+57
-43
lines changed

2 files changed

+57
-43
lines changed

README.md

+5-4
Original file line numberDiff line numberDiff line change
@@ -283,16 +283,17 @@ Moreover, Miri recognizes some environment variables:
283283
architecture to test against. `miri` and `cargo miri` accept the `--target`
284284
flag for the same purpose.
285285

286-
The following environment variables are internal, but used to communicate between
287-
different Miri binaries, and as such worth documenting:
286+
The following environment variables are *internal* and must not be used by
287+
anyone but Miri itself. They are used to communicate between different Miri
288+
binaries, and as such worth documenting:
288289

289290
* `MIRI_BE_RUSTC` can be set to `host` or `target`. It tells the Miri driver to
290291
actually not interpret the code but compile it like rustc would. With `target`, Miri sets
291292
some compiler flags to prepare the code for interpretation; with `host`, this is not done.
292293
This environment variable is useful to be sure that the compiled `rlib`s are compatible
293294
with Miri.
294-
When set while running `cargo-miri`, it indicates that we are part of a sysroot
295-
build (for which some crates need special treatment).
295+
* `MIRI_CALLED_FROM_XARGO` is set during the Miri-induced `xargo` sysroot build,
296+
which will re-invoke `cargo-miri` as the `rustc` to use for this build.
296297
* `MIRI_CALLED_FROM_RUSTDOC` when set to any value tells `cargo-miri` that it is
297298
running as a child process of `rustdoc`, which invokes it twice for each doc-test
298299
and requires special treatment, most notably a check-only build before interpretation.

cargo-miri/bin.rs

+52-39
Original file line numberDiff line numberDiff line change
@@ -413,14 +413,14 @@ path = "lib.rs"
413413
// for target crates.
414414
// We set ourselves (`cargo-miri`) instead of Miri directly to be able to patch the flags
415415
// for `libpanic_abort` (usually this is done by bootstrap but we have to do it ourselves).
416-
// The `MIRI_BE_RUSTC` will mean we dispatch to `phase_setup_rustc`.
416+
// The `MIRI_CALLED_FROM_XARGO` will mean we dispatch to `phase_setup_rustc`.
417417
let cargo_miri_path = std::env::current_exe().expect("current executable path invalid");
418418
if env::var_os("RUSTC_STAGE").is_some() {
419419
command.env("RUSTC_REAL", &cargo_miri_path);
420420
} else {
421421
command.env("RUSTC", &cargo_miri_path);
422422
}
423-
command.env("MIRI_BE_RUSTC", "target");
423+
command.env("MIRI_CALLED_FROM_XARGO", "1");
424424
// Make sure there are no other wrappers or flags getting in our way
425425
// (Cc https://github.com/rust-lang/miri/issues/1421).
426426
// This is consistent with normal `cargo build` that does not apply `RUSTFLAGS`
@@ -450,21 +450,6 @@ path = "lib.rs"
450450
}
451451
}
452452

453-
fn phase_setup_rustc(args: env::Args) {
454-
// Mostly we just forward everything.
455-
// `MIRI_BE_RUST` is already set.
456-
let mut cmd = miri();
457-
cmd.args(args);
458-
459-
// Patch the panic runtime for `libpanic_abort` (mirroring what bootstrap usually does).
460-
if get_arg_flag_value("--crate-name").as_deref() == Some("panic_abort") {
461-
cmd.arg("-C").arg("panic=abort");
462-
}
463-
464-
// Run it!
465-
exec(cmd);
466-
}
467-
468453
fn phase_cargo_miri(mut args: env::Args) {
469454
// Check for version and help flags even when invoked as `cargo-miri`.
470455
if has_arg_flag("--help") || has_arg_flag("-h") {
@@ -598,7 +583,17 @@ fn phase_cargo_miri(mut args: env::Args) {
598583
exec(cmd)
599584
}
600585

601-
fn phase_cargo_rustc(mut args: env::Args) {
586+
#[derive(Debug, Copy, Clone, PartialEq)]
587+
enum RustcPhase {
588+
/// `rustc` called via `xargo` for sysroot build.
589+
Setup,
590+
/// `rustc` called by `cargo` for regular build.
591+
Build,
592+
/// `rustc` called by `rustdoc` for doctest.
593+
Rustdoc,
594+
}
595+
596+
fn phase_rustc(mut args: env::Args, phase: RustcPhase) {
602597
/// Determines if we are being invoked (as rustc) to build a crate for
603598
/// the "target" architecture, in contrast to the "host" architecture.
604599
/// Host crates are for build scripts and proc macros and still need to
@@ -644,7 +639,7 @@ fn phase_cargo_rustc(mut args: env::Args) {
644639

645640
let verbose = std::env::var_os("MIRI_VERBOSE").is_some();
646641
let target_crate = is_target_crate();
647-
let print = get_arg_flag_value("--print").is_some(); // whether this is cargo passing `--print` to get some infos
642+
let print = get_arg_flag_value("--print").is_some() || has_arg_flag("-vV"); // whether this is cargo/xargo invoking rustc to get some infos
648643

649644
let store_json = |info: CrateRunInfo| {
650645
// Create a stub .d file to stop Cargo from "rebuilding" the crate:
@@ -669,7 +664,8 @@ fn phase_cargo_rustc(mut args: env::Args) {
669664
let runnable_crate = !print && is_runnable_crate();
670665

671666
if runnable_crate && target_crate {
672-
let inside_rustdoc = env::var_os("MIRI_CALLED_FROM_RUSTDOC").is_some();
667+
assert!(phase != RustcPhase::Setup, "there should be no interpretation during sysroot build");
668+
let inside_rustdoc = phase == RustcPhase::Rustdoc;
673669
// This is the binary or test crate that we want to interpret under Miri.
674670
// But we cannot run it here, as cargo invoked us as a compiler -- our stdin and stdout are not
675671
// like we want them.
@@ -749,8 +745,15 @@ fn phase_cargo_rustc(mut args: env::Args) {
749745
}
750746
}
751747

752-
// Use our custom sysroot.
753-
forward_miri_sysroot(&mut cmd);
748+
// Use our custom sysroot (but not if that is what we are currently building).
749+
if phase != RustcPhase::Setup {
750+
forward_miri_sysroot(&mut cmd);
751+
}
752+
753+
// During setup, patch the panic runtime for `libpanic_abort` (mirroring what bootstrap usually does).
754+
if phase == RustcPhase::Setup && get_arg_flag_value("--crate-name").as_deref() == Some("panic_abort") {
755+
cmd.arg("-C").arg("panic=abort");
756+
}
754757
} else {
755758
// For host crates or when we are printing, just forward everything.
756759
cmd.args(args);
@@ -783,7 +786,15 @@ fn phase_cargo_rustc(mut args: env::Args) {
783786
}
784787
}
785788

786-
fn phase_cargo_runner(binary: &Path, binary_args: env::Args) {
789+
#[derive(Debug, Copy, Clone, PartialEq)]
790+
enum RunnerPhase {
791+
/// `cargo` is running a binary
792+
Cargo,
793+
/// `rustdoc` is running a binary
794+
Rustdoc,
795+
}
796+
797+
fn phase_runner(binary: &Path, binary_args: env::Args, phase: RunnerPhase) {
787798
let verbose = std::env::var_os("MIRI_VERBOSE").is_some();
788799

789800
let file = File::open(&binary)
@@ -840,8 +851,8 @@ fn phase_cargo_runner(binary: &Path, binary_args: env::Args) {
840851
cmd.arg(arg);
841852
}
842853
}
843-
if env::var_os("MIRI_CALLED_FROM_RUSTDOC").is_none() {
844-
// Set sysroot (if we are inside rustdoc, we already did that in `phase_cargo_rustdoc`).
854+
// Set sysroot (if we are inside rustdoc, we already did that in `phase_cargo_rustdoc`).
855+
if phase != RunnerPhase::Rustdoc {
845856
forward_miri_sysroot(&mut cmd);
846857
}
847858
// Respect `MIRIFLAGS`.
@@ -869,14 +880,17 @@ fn phase_cargo_runner(binary: &Path, binary_args: env::Args) {
869880
eprintln!("[cargo-miri runner] {:?}", cmd);
870881
}
871882

872-
if std::env::var_os("MIRI_CALLED_FROM_RUSTDOC").is_some() {
873-
exec_with_pipe(cmd, &info.stdin)
874-
} else {
875-
exec(cmd)
883+
match phase {
884+
RunnerPhase::Rustdoc => {
885+
exec_with_pipe(cmd, &info.stdin)
886+
}
887+
RunnerPhase::Cargo => {
888+
exec(cmd)
889+
}
876890
}
877891
}
878892

879-
fn phase_cargo_rustdoc(fst_arg: &str, mut args: env::Args) {
893+
fn phase_rustdoc(fst_arg: &str, mut args: env::Args) {
880894
let verbose = std::env::var_os("MIRI_VERBOSE").is_some();
881895

882896
// phase_cargo_miri sets the RUSTDOC env var to ourselves, so we can't use that here;
@@ -950,15 +964,14 @@ fn main() {
950964
args.next().unwrap();
951965

952966
// Dispatch running as part of sysroot compilation.
953-
if env::var_os("MIRI_BE_RUSTC").is_some() {
954-
phase_setup_rustc(args);
967+
if env::var_os("MIRI_CALLED_FROM_XARGO").is_some() {
968+
phase_rustc(args, RustcPhase::Setup);
955969
return;
956970
}
957971

958972
// The way rustdoc invokes rustc is indistuingishable from the way cargo invokes rustdoc by the
959973
// arguments alone. `phase_cargo_rustdoc` sets this environment variable to let us disambiguate.
960-
let invoked_by_rustdoc = env::var_os("MIRI_CALLED_FROM_RUSTDOC").is_some();
961-
if invoked_by_rustdoc {
974+
if env::var_os("MIRI_CALLED_FROM_RUSTDOC").is_some() {
962975
// ...however, we then also see this variable when rustdoc invokes us as the testrunner!
963976
// The runner is invoked as `$runtool ($runtool-arg)* output_file`;
964977
// since we don't specify any runtool-args, and rustdoc supplies multiple arguments to
@@ -967,12 +980,12 @@ fn main() {
967980
let arg = args.next().unwrap();
968981
let binary = Path::new(&arg);
969982
if binary.exists() {
970-
phase_cargo_runner(binary, args);
983+
phase_runner(binary, args, RunnerPhase::Rustdoc);
971984
} else {
972985
show_error(format!("`cargo-miri` called with non-existing path argument `{}` in rustdoc mode; please invoke this binary through `cargo miri`", arg));
973986
}
974987
} else {
975-
phase_cargo_rustc(args);
988+
phase_rustc(args, RustcPhase::Rustdoc);
976989
}
977990

978991
return;
@@ -988,17 +1001,17 @@ fn main() {
9881001
// On top of that, we are also called as RUSTDOC, but that is just a stub currently.
9891002
match args.next().as_deref() {
9901003
Some("miri") => phase_cargo_miri(args),
991-
Some("rustc") => phase_cargo_rustc(args),
1004+
Some("rustc") => phase_rustc(args, RustcPhase::Build),
9921005
Some(arg) => {
9931006
// We have to distinguish the "runner" and "rustdoc" cases.
9941007
// As runner, the first argument is the binary (a file that should exist, with an absolute path);
9951008
// as rustdoc, the first argument is a flag (`--something`).
9961009
let binary = Path::new(arg);
9971010
if binary.exists() {
9981011
assert!(!arg.starts_with("--")); // not a flag
999-
phase_cargo_runner(binary, args);
1012+
phase_runner(binary, args, RunnerPhase::Cargo);
10001013
} else if arg.starts_with("--") {
1001-
phase_cargo_rustdoc(arg, args);
1014+
phase_rustdoc(arg, args);
10021015
} else {
10031016
show_error(format!("`cargo-miri` called with unexpected first argument `{}`; please only invoke this binary through `cargo miri`", arg));
10041017
}

0 commit comments

Comments
 (0)