Skip to content

Commit a66ca27

Browse files
committed
prepare_tool_cargo: add support for a miri-test mode, and use it in the cargo-miri smoke test and Miri sysroot build
1 parent fd7909a commit a66ca27

File tree

3 files changed

+69
-70
lines changed

3 files changed

+69
-70
lines changed

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

+4-10
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-
stage: u32,
125124
host: TargetSelection,
126125
target: TargetSelection,
127126
}
@@ -135,22 +134,17 @@ impl Step for Miri {
135134
}
136135

137136
fn make_run(run: RunConfig<'_>) {
138-
run.builder.ensure(Miri {
139-
stage: run.builder.top_stage,
140-
host: run.build_triple(),
141-
target: run.target,
142-
});
137+
run.builder.ensure(Miri { host: run.build_triple(), target: run.target });
143138
}
144139

145140
fn run(self, builder: &Builder<'_>) {
146-
let stage = self.stage;
141+
let stage = builder.top_stage;
147142
let host = self.host;
148143
let target = self.target;
149144
let compiler = builder.compiler(stage, host);
150145

151-
let miri =
152-
builder.ensure(tool::Miri { compiler, target: self.host, extra_features: Vec::new() });
153-
let miri_sysroot = test::Miri::build_miri_sysroot(builder, compiler, &miri, target);
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);
154148

155149
// # Run miri.
156150
// Running it via `cargo run` as that figures out the right dylib path.

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

+28-53
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,6 @@ impl Step for RustDemangler {
493493

494494
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
495495
pub struct Miri {
496-
stage: u32,
497496
host: TargetSelection,
498497
target: TargetSelection,
499498
}
@@ -502,29 +501,21 @@ impl Miri {
502501
/// Run `cargo miri setup` for the given target, return where the Miri sysroot was put.
503502
pub fn build_miri_sysroot(
504503
builder: &Builder<'_>,
505-
compiler: Compiler,
506-
miri: &Path,
504+
compiler_std: Compiler,
507505
target: TargetSelection,
508506
) -> String {
509-
let miri_sysroot = builder.out.join(compiler.host.triple).join("miri-sysroot");
510-
let mut cargo = tool::prepare_tool_cargo(
507+
let miri_sysroot = builder.out.join(compiler_std.host.triple).join("miri-sysroot");
508+
let mut cargo = builder::Cargo::new(
511509
builder,
512-
compiler,
513-
Mode::ToolRustc,
514-
compiler.host,
515-
"run",
516-
"src/tools/miri/cargo-miri",
517-
SourceType::InTree,
518-
&[],
510+
compiler_std, // this is compiler+1; cargo_miri_cmd will do -1 again
511+
Mode::Std,
512+
SourceType::Submodule,
513+
target,
514+
"miri-setup",
519515
);
520-
cargo.add_rustc_lib_path(builder);
521-
cargo.arg("--").arg("miri").arg("setup");
522-
cargo.arg("--target").arg(target.rustc_target_arg());
523516

524517
// Tell `cargo miri setup` where to find the sources.
525518
cargo.env("MIRI_LIB_SRC", builder.src.join("library"));
526-
// Tell it where to find Miri.
527-
cargo.env("MIRI", miri);
528519
// Tell it where to put the sysroot.
529520
cargo.env("MIRI_SYSROOT", &miri_sysroot);
530521
// Debug things.
@@ -533,10 +524,10 @@ impl Miri {
533524
let mut cargo = Command::from(cargo);
534525
let _guard = builder.msg(
535526
Kind::Build,
536-
compiler.stage + 1,
527+
compiler_std.stage,
537528
"miri sysroot",
538-
compiler.host,
539-
compiler.host,
529+
compiler_std.host,
530+
compiler_std.host,
540531
);
541532
builder.run(&mut cargo);
542533

@@ -574,16 +565,12 @@ impl Step for Miri {
574565
}
575566

576567
fn make_run(run: RunConfig<'_>) {
577-
run.builder.ensure(Miri {
578-
stage: run.builder.top_stage,
579-
host: run.build_triple(),
580-
target: run.target,
581-
});
568+
run.builder.ensure(Miri { host: run.build_triple(), target: run.target });
582569
}
583570

584571
/// Runs `cargo test` for miri.
585572
fn run(self, builder: &Builder<'_>) {
586-
let stage = self.stage;
573+
let stage = builder.top_stage;
587574
let host = self.host;
588575
let target = self.target;
589576
let compiler = builder.compiler(stage, host);
@@ -592,18 +579,15 @@ impl Step for Miri {
592579
let compiler_std = builder.compiler(if stage < 2 { stage + 1 } else { stage }, host);
593580

594581
let miri =
595-
builder.ensure(tool::Miri { compiler, target: self.host, extra_features: Vec::new() });
596-
let _cargo_miri = builder.ensure(tool::CargoMiri {
597-
compiler,
598-
target: self.host,
599-
extra_features: Vec::new(),
600-
});
582+
builder.ensure(tool::Miri { compiler, target: host, extra_features: Vec::new() });
583+
// the ui tests also assume cargo-miri has been built
584+
builder.ensure(tool::CargoMiri { compiler, target: host, extra_features: Vec::new() });
601585
// The stdlib we need might be at a different stage. And just asking for the
602586
// sysroot does not seem to populate it, so we do that first.
603587
builder.ensure(compile::Std::new(compiler_std, host));
604588
let sysroot = builder.sysroot(compiler_std);
605589
// We also need a Miri sysroot.
606-
let miri_sysroot = Miri::build_miri_sysroot(builder, compiler, &miri, target);
590+
let miri_sysroot = Miri::build_miri_sysroot(builder, compiler_std, target);
607591

608592
// # Run `cargo test`.
609593
let mut cargo = tool::prepare_tool_cargo(
@@ -632,8 +616,8 @@ impl Step for Miri {
632616
// Set the target.
633617
cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
634618

635-
// This can NOT be `run_cargo_test` since the Miri test runner
636-
// does not understand the flags added by `add_flags_and_try_run_test`.
619+
// This can NOT be `run_cargo_test` since Miri's integration tests do not use the usual test
620+
// harness and therefore do not understand the flags added by `add_flags_and_try_run_test`.
637621
let mut cargo = prepare_cargo_test(cargo, &[], &[], "miri", compiler, target, builder);
638622
{
639623
let _time = helpers::timeit(builder);
@@ -660,28 +644,20 @@ impl Step for Miri {
660644
// # Run `cargo miri test`.
661645
// This is just a smoke test (Miri's own CI invokes this in a bunch of different ways and ensures
662646
// that we get the desired output), but that is sufficient to make sure that the libtest harness
663-
// itself executes properly under Miri.
647+
// itself executes properly under Miri, and that all the logic in `cargo-miri` does not explode.
648+
// Everything here needs `compiler_std` to be actually testing the Miri in the current stage.
664649
let mut cargo = tool::prepare_tool_cargo(
665650
builder,
666-
compiler,
667-
Mode::ToolRustc,
668-
host,
669-
"run",
670-
"src/tools/miri/cargo-miri",
651+
compiler_std, // this is compiler+1; cargo_miri_cmd will do -1 again
652+
Mode::ToolStd, // it's unclear what to use here, we're not building anything just doing a smoke test!
653+
target,
654+
"miri-test",
655+
"src/tools/miri/test-cargo-miri",
671656
SourceType::Submodule,
672657
&[],
673658
);
674-
cargo.add_rustc_lib_path(builder);
675-
cargo.arg("--").arg("miri").arg("test");
676-
if builder.config.locked_deps {
677-
cargo.arg("--locked");
678-
}
679-
cargo
680-
.arg("--manifest-path")
681-
.arg(builder.src.join("src/tools/miri/test-cargo-miri/Cargo.toml"));
682-
cargo.arg("--target").arg(target.rustc_target_arg());
683659

684-
// `prepare_tool_cargo` sets RUSTDOC to the bootstrap wrapper and RUSTDOC_REAL to a dummy path as this is a "run", not a "test".
660+
// `prepare_tool_cargo` sets RUSTDOC to the bootstrap wrapper and RUSTDOC_REAL to a dummy path as this is a "miri", not a "test".
685661
// Also, we want the rustdoc from the "next" stage for the same reason that we build a std from the next stage.
686662
// So let's just set that here, and bypass bootstrap's RUSTDOC (just like cargo-miri already ignores bootstrap's RUSTC_WRAPPER).
687663
if builder.doc_tests != DocTests::No {
@@ -697,10 +673,9 @@ impl Step for Miri {
697673
}
698674
}
699675

700-
// Tell `cargo miri` where to find things.
676+
// Tell `cargo miri` where to find the sysroots.
701677
cargo.env("MIRI_SYSROOT", &miri_sysroot);
702678
cargo.env("MIRI_HOST_SYSROOT", sysroot);
703-
cargo.env("MIRI", &miri);
704679
// Debug things.
705680
cargo.env("RUST_BACKTRACE", "1");
706681

src/bootstrap/src/core/builder.rs

+37-7
Original file line numberDiff line numberDiff line change
@@ -1253,6 +1253,28 @@ impl<'a> Builder<'a> {
12531253
cmd
12541254
}
12551255

1256+
pub fn cargo_miri_cmd(&self, run_compiler: Compiler) -> Command {
1257+
assert!(run_compiler.stage > 0);
1258+
let build_compiler = self.compiler(run_compiler.stage - 1, self.build.build);
1259+
// Make sure Miri itself is also built
1260+
let miri = self.ensure(tool::Miri {
1261+
compiler: build_compiler,
1262+
target: self.build.build,
1263+
extra_features: Vec::new(),
1264+
});
1265+
1266+
let cargo_miri = self.ensure(tool::CargoMiri {
1267+
compiler: build_compiler,
1268+
target: self.build.build,
1269+
extra_features: Vec::new(),
1270+
});
1271+
let mut cmd = Command::new(cargo_miri);
1272+
cmd.env("MIRI", &miri);
1273+
cmd.env("CARGO", &self.initial_cargo);
1274+
self.add_rustc_lib_path(run_compiler, &mut cmd);
1275+
cmd
1276+
}
1277+
12561278
pub fn rustdoc_cmd(&self, compiler: Compiler) -> Command {
12571279
let mut cmd = Command::new(self.bootstrap_out.join("rustdoc"));
12581280
cmd.env("RUSTC_STAGE", compiler.stage.to_string())
@@ -1296,18 +1318,24 @@ impl<'a> Builder<'a> {
12961318
target: TargetSelection,
12971319
cmd: &str,
12981320
) -> Command {
1299-
let mut cargo = if cmd == "clippy" {
1300-
self.cargo_clippy_cmd(compiler)
1321+
let mut cargo;
1322+
if cmd == "clippy" {
1323+
cargo = self.cargo_clippy_cmd(compiler);
1324+
cargo.arg(cmd);
1325+
} else if let Some(subcmd) = cmd.strip_prefix("miri-") {
1326+
cargo = self.cargo_miri_cmd(compiler);
1327+
cargo.arg("miri").arg(subcmd);
13011328
} else {
1302-
Command::new(&self.initial_cargo)
1303-
};
1329+
cargo = Command::new(&self.initial_cargo);
1330+
cargo.arg(cmd);
1331+
}
13041332

13051333
// Run cargo from the source root so it can find .cargo/config.
13061334
// This matters when using vendoring and the working directory is outside the repository.
13071335
cargo.current_dir(&self.src);
13081336

13091337
let out_dir = self.stage_out(compiler, mode);
1310-
cargo.env("CARGO_TARGET_DIR", &out_dir).arg(cmd);
1338+
cargo.env("CARGO_TARGET_DIR", &out_dir);
13111339

13121340
// Found with `rg "init_env_logger\("`. If anyone uses `init_env_logger`
13131341
// from out of tree it shouldn't matter, since x.py is only used for
@@ -1337,7 +1365,8 @@ impl<'a> Builder<'a> {
13371365

13381366
if self.config.rust_optimize.is_release() {
13391367
// FIXME: cargo bench/install do not accept `--release`
1340-
if cmd != "bench" && cmd != "install" {
1368+
// and miri doesn't want it
1369+
if cmd != "bench" && cmd != "install" && !cmd.starts_with("miri-") {
13411370
cargo.arg("--release");
13421371
}
13431372
}
@@ -1353,7 +1382,8 @@ impl<'a> Builder<'a> {
13531382
/// Cargo. This cargo will be configured to use `compiler` as the actual
13541383
/// rustc compiler, its output will be scoped by `mode`'s output directory,
13551384
/// it will pass the `--target` flag for the specified `target`, and will be
1356-
/// executing the Cargo command `cmd`.
1385+
/// executing the Cargo command `cmd`. `cmd` can be `miri-cmd` for commands
1386+
/// to be run with Miri.
13571387
fn cargo(
13581388
&self,
13591389
compiler: Compiler,

0 commit comments

Comments
 (0)