make Miri work in rustc bootstrap stage 0

This commit is contained in:
Ralf Jung 2020-05-09 12:24:30 +02:00
parent 4eaf05c4ec
commit ba801a45db
3 changed files with 45 additions and 17 deletions

View file

@ -222,6 +222,13 @@ Moreover, Miri recognizes some environment variables:
* `MIRI_TEST_FLAGS` (recognized by the test suite) defines extra flags to be
passed to Miri.
The following environment variables are internal, but used to communicate between
different Miri binaries, and as such worht documenting:
* `MIRI_BE_RUSTC` when set to any value tells the Miri driver to actually not
interpret the code but compile it like rustc would. This is useful to be sure
that the compiled `rlib`s are compatible with Miri.
## Contributing and getting help
If you want to contribute to Miri, great! Please check out our

View file

@ -86,11 +86,15 @@ fn get_arg_flag_value(name: &str) -> Option<String> {
}
}
/// Returns a command for the right `miri` binary.
fn miri() -> Command {
/// Returns the path to the `miri` binary
fn find_miri() -> PathBuf {
let mut path = std::env::current_exe().expect("current executable path invalid");
path.set_file_name("miri");
Command::new(path)
path
}
fn miri() -> Command {
Command::new(find_miri())
}
fn cargo() -> Command {
@ -322,7 +326,8 @@ fn setup(subcommand: MiriCommand) {
show_error(format!("Given Rust source directory `{}` does not exist.", rust_src.display()));
}
// Next, we need our own libstd. We will do this work in whatever is a good cache dir for this platform.
// Next, we need our own libstd. Prepare a xargo project for that purpose.
// We will do this work in whatever is a good cache dir for this platform.
let dirs = directories::ProjectDirs::from("org", "rust-lang", "miri").unwrap();
let dir = dirs.cache_dir();
if !dir.exists() {
@ -360,20 +365,31 @@ path = "lib.rs"
)
.unwrap();
File::create(dir.join("lib.rs")).unwrap();
// Prepare xargo invocation.
// Determine architectures.
// We always need to set a target so rustc bootstrap can tell apart host from target crates.
let host = rustc_version::version_meta().unwrap().host;
let target = get_arg_flag_value("--target");
let print_sysroot = subcommand == MiriCommand::Setup
&& has_arg_flag("--print-sysroot"); // whether we just print the sysroot path
let target = target.as_ref().unwrap_or(&host);
// Now invoke xargo.
let mut command = xargo_check();
command.arg("build").arg("-q");
command.arg("--target").arg(target);
command.current_dir(&dir);
command.env("RUSTFLAGS", miri::miri_default_args().join(" "));
command.env("XARGO_HOME", &dir);
command.env("XARGO_RUST_SRC", &rust_src);
// Handle target flag.
if let Some(target) = &target {
command.arg("--target").arg(target);
// Use Miri as rustc to build a libstd compatible with us (and use the right flags).
// However, when we are running in bootstrap, we cannot just overwrite `RUSTC`,
// because we still need bootstrap to distinguish between host and target crates.
// In that case we overwrite `RUSTC_REAL` instead which determines the rustc used
// for target crates.
if env::var_os("RUSTC_STAGE").is_some() {
command.env("RUSTC_REAL", find_miri());
} else {
command.env("RUSTC", find_miri());
}
command.env("MIRI_BE_RUSTC", "1");
command.env("RUSTFLAGS", miri::miri_default_args().join(" "));
// Finally run it!
if command.status().expect("failed to run xargo").success().not() {
show_error(format!("Failed to run xargo"));
@ -382,12 +398,11 @@ path = "lib.rs"
// That should be it! But we need to figure out where xargo built stuff.
// Unfortunately, it puts things into a different directory when the
// architecture matches the host.
let is_host = match &target {
None => true,
Some(target) => target == &rustc_version::version_meta().unwrap().host,
};
let sysroot = if is_host { dir.join("HOST") } else { PathBuf::from(dir) };
let sysroot = if target == &host { dir.join("HOST") } else { PathBuf::from(dir) };
std::env::set_var("MIRI_SYSROOT", &sysroot); // pass the env var to the processes we spawn, which will turn it into "--sysroot" flags
// Figure out what to print.
let print_sysroot = subcommand == MiriCommand::Setup
&& has_arg_flag("--print-sysroot"); // whether we just print the sysroot path
if print_sysroot {
// Print just the sysroot and nothing else; this way we do not need any escaping.
println!("{}", sysroot.display());
@ -476,7 +491,7 @@ fn in_cargo_miri() {
// Set `RUSTC_WRAPPER` to ourselves. Cargo will prepend that binary to its usual invocation,
// i.e., the first argument is `rustc` -- which is what we use in `main` to distinguish
// the two codepaths.
// the two codepaths. (That extra argument is why we prefer this over setting `RUSTC`.)
let path = std::env::current_exe().expect("current executable path invalid");
cmd.env("RUSTC_WRAPPER", path);
if verbose {

View file

@ -124,6 +124,12 @@ fn compile_time_sysroot() -> Option<String> {
}
fn main() {
// If the environment asks us to actually be rustc, then do that.
if env::var_os("MIRI_BE_RUSTC").is_some() {
eprintln!("miri-as-rustc called with args: {:?}", env::args());
return rustc_driver::main();
}
init_early_loggers();
// Parse our arguments and split them across `rustc` and `miri`.