Skip to content

Commit fb8abe5

Browse files
committed
shift Miri's stage so that it matches other rustc-based tools
1 parent b5fe655 commit fb8abe5

File tree

3 files changed

+74
-57
lines changed

3 files changed

+74
-57
lines changed

src/bootstrap/src/core/build_steps/run.rs

+19-9
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ impl Step for ReplaceVersionPlaceholder {
121121

122122
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
123123
pub struct Miri {
124-
host: TargetSelection,
125124
target: TargetSelection,
126125
}
127126

@@ -134,24 +133,35 @@ impl Step for Miri {
134133
}
135134

136135
fn make_run(run: RunConfig<'_>) {
137-
run.builder.ensure(Miri { host: run.build_triple(), target: run.target });
136+
run.builder.ensure(Miri { target: run.target });
138137
}
139138

140139
fn run(self, builder: &Builder<'_>) {
141-
let stage = builder.top_stage;
142-
let host = self.host;
140+
let host = builder.build.build;
143141
let target = self.target;
144-
let compiler = builder.compiler(stage, host);
145-
146-
let compiler_std = builder.compiler(if stage < 2 { stage + 1 } else { stage }, host);
147-
let miri_sysroot = test::Miri::build_miri_sysroot(builder, compiler_std, target);
142+
let stage = builder.top_stage;
143+
if stage == 0 {
144+
eprintln!("miri cannot be run at stage 0");
145+
std::process::exit(1);
146+
}
147+
148+
// This compiler runs on the host, we'll just use it for the target.
149+
let target_compiler = builder.compiler(stage, host);
150+
// Similar to `compile::Assemble`, build with the previous stage's compiler. Otherwise
151+
// we'd have stageN/bin/rustc and stageN/bin/rustdoc be effectively different stage
152+
// compilers, which isn't what we want. Rustdoc should be linked in the same way as the
153+
// rustc compiler it's paired with, so it must be built with the previous stage compiler.
154+
let host_compiler = builder.compiler(stage - 1, host);
155+
156+
// Get a target sysroot for Miri.
157+
let miri_sysroot = test::Miri::build_miri_sysroot(builder, target_compiler, target);
148158

149159
// # Run miri.
150160
// Running it via `cargo run` as that figures out the right dylib path.
151161
// add_rustc_lib_path does not add the path that contains librustc_driver-<...>.so.
152162
let mut miri = tool::prepare_tool_cargo(
153163
builder,
154-
compiler,
164+
host_compiler,
155165
Mode::ToolRustc,
156166
host,
157167
"run",

src/bootstrap/src/core/build_steps/test.rs

+49-43
Original file line numberDiff line numberDiff line change
@@ -493,21 +493,20 @@ impl Step for RustDemangler {
493493

494494
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
495495
pub struct Miri {
496-
host: TargetSelection,
497496
target: TargetSelection,
498497
}
499498

500499
impl Miri {
501500
/// Run `cargo miri setup` for the given target, return where the Miri sysroot was put.
502501
pub fn build_miri_sysroot(
503502
builder: &Builder<'_>,
504-
compiler_std: Compiler,
503+
compiler: Compiler,
505504
target: TargetSelection,
506505
) -> String {
507-
let miri_sysroot = builder.out.join(compiler_std.host.triple).join("miri-sysroot");
506+
let miri_sysroot = builder.out.join(compiler.host.triple).join("miri-sysroot");
508507
let mut cargo = builder::Cargo::new(
509508
builder,
510-
compiler_std, // this is compiler+1; cargo_miri_cmd will do -1 again
509+
compiler,
511510
Mode::Std,
512511
SourceType::Submodule,
513512
target,
@@ -520,13 +519,8 @@ impl Miri {
520519
cargo.env("MIRI_SYSROOT", &miri_sysroot);
521520

522521
let mut cargo = Command::from(cargo);
523-
let _guard = builder.msg(
524-
Kind::Build,
525-
compiler_std.stage,
526-
"miri sysroot",
527-
compiler_std.host,
528-
compiler_std.host,
529-
);
522+
let _guard =
523+
builder.msg(Kind::Build, compiler.stage, "miri sysroot", compiler.host, target);
530524
builder.run(&mut cargo);
531525

532526
// # Determine where Miri put its sysroot.
@@ -563,34 +557,51 @@ impl Step for Miri {
563557
}
564558

565559
fn make_run(run: RunConfig<'_>) {
566-
run.builder.ensure(Miri { host: run.build_triple(), target: run.target });
560+
run.builder.ensure(Miri { target: run.target });
567561
}
568562

569563
/// Runs `cargo test` for miri.
570564
fn run(self, builder: &Builder<'_>) {
571-
let stage = builder.top_stage;
572-
let host = self.host;
565+
let host = builder.build.build;
573566
let target = self.target;
574-
let compiler = builder.compiler(stage, host);
575-
// We need the stdlib for the *next* stage, as it was built with this compiler that also built Miri.
576-
// Except if we are at stage 2, the bootstrap loop is complete and we can stick with our current stage.
577-
let compiler_std = builder.compiler(if stage < 2 { stage + 1 } else { stage }, host);
578-
579-
let miri =
580-
builder.ensure(tool::Miri { compiler, target: host, extra_features: Vec::new() });
567+
let stage = builder.top_stage;
568+
if stage == 0 {
569+
eprintln!("miri cannot be tested at stage 0");
570+
std::process::exit(1);
571+
}
572+
573+
// This compiler runs on the host, we'll just use it for the target.
574+
let target_compiler = builder.compiler(stage, host);
575+
// Similar to `compile::Assemble`, build with the previous stage's compiler. Otherwise
576+
// we'd have stageN/bin/rustc and stageN/bin/rustdoc be effectively different stage
577+
// compilers, which isn't what we want. Rustdoc should be linked in the same way as the
578+
// rustc compiler it's paired with, so it must be built with the previous stage compiler.
579+
let host_compiler = builder.compiler(stage - 1, host);
580+
581+
// Build our tools.
582+
let miri = builder.ensure(tool::Miri {
583+
compiler: host_compiler,
584+
target: host,
585+
extra_features: Vec::new(),
586+
});
581587
// the ui tests also assume cargo-miri has been built
582-
builder.ensure(tool::CargoMiri { compiler, target: host, extra_features: Vec::new() });
583-
// The stdlib we need might be at a different stage. And just asking for the
584-
// sysroot does not seem to populate it, so we do that first.
585-
builder.ensure(compile::Std::new(compiler_std, host));
586-
let sysroot = builder.sysroot(compiler_std);
587-
// We also need a Miri sysroot.
588-
let miri_sysroot = Miri::build_miri_sysroot(builder, compiler_std, target);
588+
builder.ensure(tool::CargoMiri {
589+
compiler: host_compiler,
590+
target: host,
591+
extra_features: Vec::new(),
592+
});
593+
594+
// We also need sysroots, for Miri and for the host (the latter for build scripts).
595+
// This is for the tests so everything is done with the target compiler.
596+
let miri_sysroot = Miri::build_miri_sysroot(builder, target_compiler, target);
597+
builder.ensure(compile::Std::new(target_compiler, host));
598+
let sysroot = builder.sysroot(target_compiler);
589599

590600
// # Run `cargo test`.
601+
// This is with the Miri crate, so it uses the host compiler.
591602
let mut cargo = tool::prepare_tool_cargo(
592603
builder,
593-
compiler,
604+
host_compiler,
594605
Mode::ToolRustc,
595606
host,
596607
"test",
@@ -603,7 +614,7 @@ impl Step for Miri {
603614

604615
// We can NOT use `run_cargo_test` since Miri's integration tests do not use the usual test
605616
// harness and therefore do not understand the flags added by `add_flags_and_try_run_test`.
606-
let mut cargo = prepare_cargo_test(cargo, &[], &[], "miri", compiler, target, builder);
617+
let mut cargo = prepare_cargo_test(cargo, &[], &[], "miri", host_compiler, host, builder);
607618

608619
// miri tests need to know about the stage sysroot
609620
cargo.env("MIRI_SYSROOT", &miri_sysroot);
@@ -618,7 +629,7 @@ impl Step for Miri {
618629
cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
619630

620631
{
621-
let _guard = builder.msg_sysroot_tool(Kind::Test, compiler.stage, "miri", host, target);
632+
let _guard = builder.msg_sysroot_tool(Kind::Test, stage, "miri", host, target);
622633
let _time = helpers::timeit(builder);
623634
builder.run(&mut cargo);
624635
}
@@ -636,7 +647,7 @@ impl Step for Miri {
636647
{
637648
let _guard = builder.msg_sysroot_tool(
638649
Kind::Test,
639-
compiler.stage,
650+
stage,
640651
"miri (mir-opt-level 4)",
641652
host,
642653
target,
@@ -650,10 +661,10 @@ impl Step for Miri {
650661
// This is just a smoke test (Miri's own CI invokes this in a bunch of different ways and ensures
651662
// that we get the desired output), but that is sufficient to make sure that the libtest harness
652663
// itself executes properly under Miri, and that all the logic in `cargo-miri` does not explode.
653-
// Everything here needs `compiler_std` to be actually testing the Miri in the current stage.
664+
// This is running the build `cargo-miri` for the given target, so we need the target compiler.
654665
let mut cargo = tool::prepare_tool_cargo(
655666
builder,
656-
compiler_std, // this is compiler+1; cargo_miri_cmd will do -1 again
667+
target_compiler,
657668
Mode::ToolStd, // it's unclear what to use here, we're not building anything just doing a smoke test!
658669
target,
659670
"miri-test",
@@ -662,16 +673,12 @@ impl Step for Miri {
662673
&[],
663674
);
664675

665-
// `prepare_tool_cargo` sets RUSTDOC to the bootstrap wrapper and RUSTDOC_REAL to a dummy path as this is a "miri", not a "test".
666-
// Also, we want the rustdoc from the "next" stage for the same reason that we build a std from the next stage.
667-
// So let's just set that here, and bypass bootstrap's RUSTDOC (just like cargo-miri already ignores bootstrap's RUSTC_WRAPPER).
668-
if builder.doc_tests != DocTests::No {
669-
cargo.env("RUSTDOC", builder.rustdoc(compiler_std));
670-
}
676+
// We're not using `prepare_cargo_test` so we have to do this ourselves.
677+
// (We're not using that as the test-cargo-miri crate is not known to bootstrap.)
671678
match builder.doc_tests {
672679
DocTests::Yes => {}
673680
DocTests::No => {
674-
cargo.arg("--tests");
681+
cargo.args(["--lib", "--bins", "--examples", "--tests", "--benches"]);
675682
}
676683
DocTests::Only => {
677684
cargo.arg("--doc");
@@ -686,8 +693,7 @@ impl Step for Miri {
686693
cargo.arg("--").args(builder.config.test_args());
687694
let mut cargo = Command::from(cargo);
688695
{
689-
let _guard =
690-
builder.msg_sysroot_tool(Kind::Test, compiler.stage, "cargo-miri", host, target);
696+
let _guard = builder.msg_sysroot_tool(Kind::Test, stage, "cargo-miri", host, target);
691697
let _time = helpers::timeit(builder);
692698
builder.run(&mut cargo);
693699
}

src/bootstrap/src/core/builder.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -1031,10 +1031,10 @@ impl<'a> Builder<'a> {
10311031
StepDescription::run(v, self, paths);
10321032
}
10331033

1034-
/// Obtain a compiler at a given stage and for a given host. Explicitly does
1035-
/// not take `Compiler` since all `Compiler` instances are meant to be
1036-
/// obtained through this function, since it ensures that they are valid
1037-
/// (i.e., built and assembled).
1034+
/// Obtain a compiler at a given stage and for a given host (i.e., this is the target that the
1035+
/// compiler will run on, *not* the target it will build code for). Explicitly does not take
1036+
/// `Compiler` since all `Compiler` instances are meant to be obtained through this function,
1037+
/// since it ensures that they are valid (i.e., built and assembled).
10381038
pub fn compiler(&self, stage: u32, host: TargetSelection) -> Compiler {
10391039
self.ensure(compile::Assemble { target_compiler: Compiler { stage, host } })
10401040
}
@@ -1703,7 +1703,8 @@ impl<'a> Builder<'a> {
17031703
.env("RUSTDOC", self.bootstrap_out.join("rustdoc"))
17041704
.env(
17051705
"RUSTDOC_REAL",
1706-
if cmd == "doc" || cmd == "rustdoc" || (cmd == "test" && want_rustdoc) {
1706+
// Make sure to handle both `test` and `miri-test` commands.
1707+
if cmd == "doc" || cmd == "rustdoc" || (cmd.ends_with("test") && want_rustdoc) {
17071708
self.rustdoc(compiler)
17081709
} else {
17091710
PathBuf::from("/path/to/nowhere/rustdoc/not/required")

0 commit comments

Comments
 (0)