Skip to content

Commit ba801a4

Browse files
committed
make Miri work in rustc bootstrap stage 0
1 parent 4eaf05c commit ba801a4

File tree

3 files changed

+45
-17
lines changed

3 files changed

+45
-17
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,13 @@ Moreover, Miri recognizes some environment variables:
222222
* `MIRI_TEST_FLAGS` (recognized by the test suite) defines extra flags to be
223223
passed to Miri.
224224

225+
The following environment variables are internal, but used to communicate between
226+
different Miri binaries, and as such worht documenting:
227+
228+
* `MIRI_BE_RUSTC` when set to any value tells the Miri driver to actually not
229+
interpret the code but compile it like rustc would. This is useful to be sure
230+
that the compiled `rlib`s are compatible with Miri.
231+
225232
## Contributing and getting help
226233

227234
If you want to contribute to Miri, great! Please check out our

src/bin/cargo-miri.rs

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,15 @@ fn get_arg_flag_value(name: &str) -> Option<String> {
8686
}
8787
}
8888

89-
/// Returns a command for the right `miri` binary.
90-
fn miri() -> Command {
89+
/// Returns the path to the `miri` binary
90+
fn find_miri() -> PathBuf {
9191
let mut path = std::env::current_exe().expect("current executable path invalid");
9292
path.set_file_name("miri");
93-
Command::new(path)
93+
path
94+
}
95+
96+
fn miri() -> Command {
97+
Command::new(find_miri())
9498
}
9599

96100
fn cargo() -> Command {
@@ -322,7 +326,8 @@ fn setup(subcommand: MiriCommand) {
322326
show_error(format!("Given Rust source directory `{}` does not exist.", rust_src.display()));
323327
}
324328

325-
// Next, we need our own libstd. We will do this work in whatever is a good cache dir for this platform.
329+
// Next, we need our own libstd. Prepare a xargo project for that purpose.
330+
// We will do this work in whatever is a good cache dir for this platform.
326331
let dirs = directories::ProjectDirs::from("org", "rust-lang", "miri").unwrap();
327332
let dir = dirs.cache_dir();
328333
if !dir.exists() {
@@ -360,20 +365,31 @@ path = "lib.rs"
360365
)
361366
.unwrap();
362367
File::create(dir.join("lib.rs")).unwrap();
363-
// Prepare xargo invocation.
368+
369+
// Determine architectures.
370+
// We always need to set a target so rustc bootstrap can tell apart host from target crates.
371+
let host = rustc_version::version_meta().unwrap().host;
364372
let target = get_arg_flag_value("--target");
365-
let print_sysroot = subcommand == MiriCommand::Setup
366-
&& has_arg_flag("--print-sysroot"); // whether we just print the sysroot path
373+
let target = target.as_ref().unwrap_or(&host);
374+
// Now invoke xargo.
367375
let mut command = xargo_check();
368376
command.arg("build").arg("-q");
377+
command.arg("--target").arg(target);
369378
command.current_dir(&dir);
370-
command.env("RUSTFLAGS", miri::miri_default_args().join(" "));
371379
command.env("XARGO_HOME", &dir);
372380
command.env("XARGO_RUST_SRC", &rust_src);
373-
// Handle target flag.
374-
if let Some(target) = &target {
375-
command.arg("--target").arg(target);
381+
// Use Miri as rustc to build a libstd compatible with us (and use the right flags).
382+
// However, when we are running in bootstrap, we cannot just overwrite `RUSTC`,
383+
// because we still need bootstrap to distinguish between host and target crates.
384+
// In that case we overwrite `RUSTC_REAL` instead which determines the rustc used
385+
// for target crates.
386+
if env::var_os("RUSTC_STAGE").is_some() {
387+
command.env("RUSTC_REAL", find_miri());
388+
} else {
389+
command.env("RUSTC", find_miri());
376390
}
391+
command.env("MIRI_BE_RUSTC", "1");
392+
command.env("RUSTFLAGS", miri::miri_default_args().join(" "));
377393
// Finally run it!
378394
if command.status().expect("failed to run xargo").success().not() {
379395
show_error(format!("Failed to run xargo"));
@@ -382,12 +398,11 @@ path = "lib.rs"
382398
// That should be it! But we need to figure out where xargo built stuff.
383399
// Unfortunately, it puts things into a different directory when the
384400
// architecture matches the host.
385-
let is_host = match &target {
386-
None => true,
387-
Some(target) => target == &rustc_version::version_meta().unwrap().host,
388-
};
389-
let sysroot = if is_host { dir.join("HOST") } else { PathBuf::from(dir) };
401+
let sysroot = if target == &host { dir.join("HOST") } else { PathBuf::from(dir) };
390402
std::env::set_var("MIRI_SYSROOT", &sysroot); // pass the env var to the processes we spawn, which will turn it into "--sysroot" flags
403+
// Figure out what to print.
404+
let print_sysroot = subcommand == MiriCommand::Setup
405+
&& has_arg_flag("--print-sysroot"); // whether we just print the sysroot path
391406
if print_sysroot {
392407
// Print just the sysroot and nothing else; this way we do not need any escaping.
393408
println!("{}", sysroot.display());
@@ -476,7 +491,7 @@ fn in_cargo_miri() {
476491

477492
// Set `RUSTC_WRAPPER` to ourselves. Cargo will prepend that binary to its usual invocation,
478493
// i.e., the first argument is `rustc` -- which is what we use in `main` to distinguish
479-
// the two codepaths.
494+
// the two codepaths. (That extra argument is why we prefer this over setting `RUSTC`.)
480495
let path = std::env::current_exe().expect("current executable path invalid");
481496
cmd.env("RUSTC_WRAPPER", path);
482497
if verbose {

src/bin/miri.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,12 @@ fn compile_time_sysroot() -> Option<String> {
124124
}
125125

126126
fn main() {
127+
// If the environment asks us to actually be rustc, then do that.
128+
if env::var_os("MIRI_BE_RUSTC").is_some() {
129+
eprintln!("miri-as-rustc called with args: {:?}", env::args());
130+
return rustc_driver::main();
131+
}
132+
127133
init_early_loggers();
128134

129135
// Parse our arguments and split them across `rustc` and `miri`.

0 commit comments

Comments
 (0)