Skip to content

Commit c199a39

Browse files
committed
bootstrap: add support for running Miri on a file
1 parent 452cf4f commit c199a39

File tree

4 files changed

+132
-54
lines changed

4 files changed

+132
-54
lines changed

src/bootstrap/builder.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,7 @@ impl<'a> Builder<'a> {
755755
run::BuildManifest,
756756
run::BumpStage0,
757757
run::ReplaceVersionPlaceholder,
758+
run::Miri,
758759
),
759760
// These commands either don't use paths, or they're special-cased in Build::build()
760761
Kind::Clean | Kind::Format | Kind::Setup => vec![],
@@ -818,7 +819,7 @@ impl<'a> Builder<'a> {
818819
Subcommand::Bench { ref paths, .. } => (Kind::Bench, &paths[..]),
819820
Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]),
820821
Subcommand::Install { ref paths } => (Kind::Install, &paths[..]),
821-
Subcommand::Run { ref paths } => (Kind::Run, &paths[..]),
822+
Subcommand::Run { ref paths, .. } => (Kind::Run, &paths[..]),
822823
Subcommand::Format { .. } => (Kind::Format, &[][..]),
823824
Subcommand::Clean { .. } | Subcommand::Setup { .. } => {
824825
panic!()

src/bootstrap/flags.rs

+17-8
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ pub enum Subcommand {
140140
},
141141
Run {
142142
paths: Vec<PathBuf>,
143+
args: Vec<String>,
143144
},
144145
Setup {
145146
profile: Profile,
@@ -342,6 +343,9 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
342343
Kind::Format => {
343344
opts.optflag("", "check", "check formatting instead of applying.");
344345
}
346+
Kind::Run => {
347+
opts.optmulti("", "args", "arguments for the tool", "ARGS");
348+
}
345349
_ => {}
346350
};
347351

@@ -613,7 +617,7 @@ Arguments:
613617
println!("\nrun requires at least a path!\n");
614618
usage(1, &opts, verbose, &subcommand_help);
615619
}
616-
Subcommand::Run { paths }
620+
Subcommand::Run { paths, args: matches.opt_strs("args") }
617621
}
618622
Kind::Setup => {
619623
let profile = if paths.len() > 1 {
@@ -721,24 +725,29 @@ impl Subcommand {
721725
}
722726

723727
pub fn test_args(&self) -> Vec<&str> {
724-
let mut args = vec![];
725-
726728
match *self {
727729
Subcommand::Test { ref test_args, .. } | Subcommand::Bench { ref test_args, .. } => {
728-
args.extend(test_args.iter().flat_map(|s| s.split_whitespace()))
730+
test_args.iter().flat_map(|s| s.split_whitespace()).collect()
729731
}
730-
_ => (),
732+
_ => vec![],
731733
}
732-
733-
args
734734
}
735735

736736
pub fn rustc_args(&self) -> Vec<&str> {
737737
match *self {
738738
Subcommand::Test { ref rustc_args, .. } => {
739739
rustc_args.iter().flat_map(|s| s.split_whitespace()).collect()
740740
}
741-
_ => Vec::new(),
741+
_ => vec![],
742+
}
743+
}
744+
745+
pub fn args(&self) -> Vec<&str> {
746+
match *self {
747+
Subcommand::Run { ref args, .. } => {
748+
args.iter().flat_map(|s| s.split_whitespace()).collect()
749+
}
750+
_ => vec![],
742751
}
743752
}
744753

src/bootstrap/run.rs

+66-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
use std::process::Command;
2+
13
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
4+
use crate::config::TargetSelection;
25
use crate::dist::distdir;
3-
use crate::tool::Tool;
6+
use crate::test;
7+
use crate::tool::{self, SourceType, Tool};
48
use crate::util::output;
5-
use std::process::Command;
9+
use crate::Mode;
610

711
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
812
pub struct ExpandYamlAnchors;
@@ -125,3 +129,63 @@ impl Step for ReplaceVersionPlaceholder {
125129
builder.run(&mut cmd);
126130
}
127131
}
132+
133+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
134+
pub struct Miri {
135+
stage: u32,
136+
host: TargetSelection,
137+
target: TargetSelection,
138+
}
139+
140+
impl Step for Miri {
141+
type Output = ();
142+
const ONLY_HOSTS: bool = false;
143+
144+
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
145+
run.path("src/tools/miri")
146+
}
147+
148+
fn make_run(run: RunConfig<'_>) {
149+
run.builder.ensure(Miri {
150+
stage: run.builder.top_stage,
151+
host: run.build_triple(),
152+
target: run.target,
153+
});
154+
}
155+
156+
fn run(self, builder: &Builder<'_>) {
157+
let stage = self.stage;
158+
let host = self.host;
159+
let target = self.target;
160+
let compiler = builder.compiler(stage, host);
161+
162+
let miri = builder
163+
.ensure(tool::Miri { compiler, target: self.host, extra_features: Vec::new() })
164+
.expect("in-tree tool");
165+
let miri_sysroot = test::Miri::build_miri_sysroot(builder, compiler, &miri, target);
166+
167+
// # Run miri.
168+
// Running it via `cargo run` as that figures out the right dylib path.
169+
// add_rustc_lib_path does not add the path that contains librustc_driver-<...>.so.
170+
let mut miri = tool::prepare_tool_cargo(
171+
builder,
172+
compiler,
173+
Mode::ToolRustc,
174+
host,
175+
"run",
176+
"src/tools/miri",
177+
SourceType::InTree,
178+
&[],
179+
);
180+
miri.add_rustc_lib_path(builder, compiler);
181+
// Forward arguments.
182+
miri.arg("--").arg("--target").arg(target.rustc_target_arg());
183+
miri.args(builder.config.cmd.args());
184+
185+
// miri tests need to know about the stage sysroot
186+
miri.env("MIRI_SYSROOT", &miri_sysroot);
187+
188+
let mut miri = Command::from(miri);
189+
builder.run(&mut miri);
190+
}
191+
}

src/bootstrap/test.rs

+47-43
Original file line numberDiff line numberDiff line change
@@ -464,49 +464,14 @@ pub struct Miri {
464464
target: TargetSelection,
465465
}
466466

467-
impl Step for Miri {
468-
type Output = ();
469-
const ONLY_HOSTS: bool = false;
470-
471-
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
472-
run.path("src/tools/miri")
473-
}
474-
475-
fn make_run(run: RunConfig<'_>) {
476-
run.builder.ensure(Miri {
477-
stage: run.builder.top_stage,
478-
host: run.build_triple(),
479-
target: run.target,
480-
});
481-
}
482-
483-
/// Runs `cargo test` for miri.
484-
fn run(self, builder: &Builder<'_>) {
485-
let stage = self.stage;
486-
let host = self.host;
487-
let target = self.target;
488-
let compiler = builder.compiler(stage, host);
489-
// We need the stdlib for the *next* stage, as it was built with this compiler that also built Miri.
490-
// Except if we are at stage 2, the bootstrap loop is complete and we can stick with our current stage.
491-
let compiler_std = builder.compiler(if stage < 2 { stage + 1 } else { stage }, host);
492-
493-
let miri = builder
494-
.ensure(tool::Miri { compiler, target: self.host, extra_features: Vec::new() })
495-
.expect("in-tree tool");
496-
let _cargo_miri = builder
497-
.ensure(tool::CargoMiri { compiler, target: self.host, extra_features: Vec::new() })
498-
.expect("in-tree tool");
499-
// The stdlib we need might be at a different stage. And just asking for the
500-
// sysroot does not seem to populate it, so we do that first.
501-
builder.ensure(compile::Std::new(compiler_std, host));
502-
let sysroot = builder.sysroot(compiler_std);
503-
504-
// # Run `cargo miri setup` for the given target.
467+
impl Miri {
468+
/// Run `cargo miri setup` for the given target, return where the Miri sysroot was put.
469+
pub fn build_miri_sysroot(builder: &Builder<'_>, compiler: Compiler, miri: &Path, target: TargetSelection) -> String {
505470
let mut cargo = tool::prepare_tool_cargo(
506471
builder,
507472
compiler,
508473
Mode::ToolRustc,
509-
host,
474+
compiler.host,
510475
"run",
511476
"src/tools/miri/cargo-miri",
512477
SourceType::InTree,
@@ -534,7 +499,7 @@ impl Step for Miri {
534499
cargo.arg("--print-sysroot");
535500

536501
// FIXME: Is there a way in which we can re-use the usual `run` helpers?
537-
let miri_sysroot = if builder.config.dry_run {
502+
if builder.config.dry_run {
538503
String::new()
539504
} else {
540505
builder.verbose(&format!("running: {:?}", cargo));
@@ -547,7 +512,48 @@ impl Step for Miri {
547512
let sysroot = stdout.trim_end();
548513
builder.verbose(&format!("`cargo miri setup --print-sysroot` said: {:?}", sysroot));
549514
sysroot.to_owned()
550-
};
515+
}
516+
}
517+
}
518+
519+
impl Step for Miri {
520+
type Output = ();
521+
const ONLY_HOSTS: bool = false;
522+
523+
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
524+
run.path("src/tools/miri")
525+
}
526+
527+
fn make_run(run: RunConfig<'_>) {
528+
run.builder.ensure(Miri {
529+
stage: run.builder.top_stage,
530+
host: run.build_triple(),
531+
target: run.target,
532+
});
533+
}
534+
535+
/// Runs `cargo test` for miri.
536+
fn run(self, builder: &Builder<'_>) {
537+
let stage = self.stage;
538+
let host = self.host;
539+
let target = self.target;
540+
let compiler = builder.compiler(stage, host);
541+
// We need the stdlib for the *next* stage, as it was built with this compiler that also built Miri.
542+
// Except if we are at stage 2, the bootstrap loop is complete and we can stick with our current stage.
543+
let compiler_std = builder.compiler(if stage < 2 { stage + 1 } else { stage }, host);
544+
545+
let miri = builder
546+
.ensure(tool::Miri { compiler, target: self.host, extra_features: Vec::new() })
547+
.expect("in-tree tool");
548+
let _cargo_miri = builder
549+
.ensure(tool::CargoMiri { compiler, target: self.host, extra_features: Vec::new() })
550+
.expect("in-tree tool");
551+
// The stdlib we need might be at a different stage. And just asking for the
552+
// sysroot does not seem to populate it, so we do that first.
553+
builder.ensure(compile::Std::new(compiler_std, host));
554+
let sysroot = builder.sysroot(compiler_std);
555+
// We also need a Miri sysroot.
556+
let miri_sysroot = Miri::build_miri_sysroot(builder, compiler, &miri, target);
551557

552558
// # Run `cargo test`.
553559
let mut cargo = tool::prepare_tool_cargo(
@@ -565,7 +571,6 @@ impl Step for Miri {
565571
// miri tests need to know about the stage sysroot
566572
cargo.env("MIRI_SYSROOT", &miri_sysroot);
567573
cargo.env("MIRI_HOST_SYSROOT", sysroot);
568-
cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
569574
cargo.env("MIRI", &miri);
570575
// propagate --bless
571576
if builder.config.cmd.bless() {
@@ -606,7 +611,6 @@ impl Step for Miri {
606611
// Tell `cargo miri` where to find things.
607612
cargo.env("MIRI_SYSROOT", &miri_sysroot);
608613
cargo.env("MIRI_HOST_SYSROOT", sysroot);
609-
cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
610614
cargo.env("MIRI", &miri);
611615
// Debug things.
612616
cargo.env("RUST_BACKTRACE", "1");

0 commit comments

Comments
 (0)