add 'x.py miri', and make it work for 'library/{core,alloc,std}'

This commit is contained in:
Ralf Jung 2024-04-01 23:56:59 +02:00
parent b390f2f458
commit a6803b9de4
14 changed files with 423 additions and 31 deletions

View file

@ -5,6 +5,11 @@
const BENCH_N: usize = 1000;
fn main() {
if cfg!(miri) {
// Don't benchmark Miri...
// (Due to bootstrap quirks, this gets picked up by `x.py miri library/alloc --no-doc`.)
return;
}
let a: VecDeque<i32> = (0..VECDEQUE_LEN).collect();
let b: VecDeque<i32> = (0..VECDEQUE_LEN).collect();

View file

@ -0,0 +1,4 @@
//! Grep bootstrap for `MIRI_REPLACE_LIBRS_IF_NOT_TEST` to learn what this is about.
#![no_std]
extern crate alloc as realalloc;
pub use realalloc::*;

View file

@ -0,0 +1,4 @@
//! Grep bootstrap for `MIRI_REPLACE_LIBRS_IF_NOT_TEST` to learn what this is about.
#![no_std]
extern crate core as realcore;
pub use realcore::*;

View file

@ -0,0 +1,4 @@
//! Grep bootstrap for `MIRI_REPLACE_LIBRS_IF_NOT_TEST` to learn what this is about.
#![no_std]
extern crate std as realstd;
pub use realstd::*;

View file

@ -2536,9 +2536,14 @@ fn prepare_cargo_test(
//
// Note that to run the compiler we need to run with the *host* libraries,
// but our wrapper scripts arrange for that to be the case anyway.
let mut dylib_path = dylib_path();
dylib_path.insert(0, PathBuf::from(&*builder.sysroot_libdir(compiler, target)));
cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
//
// We skip everything on Miri as then this overwrites the libdir set up
// by `Cargo::new` and that actually makes things go wrong.
if builder.kind != Kind::Miri {
let mut dylib_path = dylib_path();
dylib_path.insert(0, PathBuf::from(&*builder.sysroot_libdir(compiler, target)));
cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
}
if builder.remote_tested(target) {
cargo.env(
@ -2594,28 +2599,62 @@ fn run(self, builder: &Builder<'_>) {
let target = self.target;
let mode = self.mode;
// Prepare sysroot
// See [field@compile::Std::force_recompile].
builder.ensure(compile::Std::force_recompile(compiler, compiler.host));
if builder.config.build != target {
builder.ensure(compile::Std::force_recompile(compiler, target));
builder.ensure(RemoteCopyLibs { compiler, target });
}
// If we're not doing a full bootstrap but we're testing a stage2
// version of libstd, then what we're actually testing is the libstd
// produced in stage1. Reflect that here by updating the compiler that
// we're working with automatically.
let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
let mut cargo = builder::Cargo::new(
builder,
compiler,
mode,
SourceType::InTree,
target,
builder.kind.as_str(),
);
let mut cargo = if builder.kind == Kind::Miri {
if builder.top_stage == 0 {
eprintln!("ERROR: `x.py miri` requires stage 1 or higher");
std::process::exit(1);
}
// Build `cargo miri test` command
// (Implicitly prepares target sysroot)
let mut cargo = builder::Cargo::new(
builder,
compiler,
mode,
SourceType::InTree,
target,
"miri-test",
);
// This hack helps bootstrap run standard library tests in Miri. The issue is as
// follows: when running `cargo miri test` on libcore, cargo builds a local copy of core
// and makes it a dependency of the integration test crate. This copy duplicates all the
// lang items, so the build fails. (Regular testing avoids this because the sysroot is a
// literal copy of what `cargo build` produces, but since Miri builds its own sysroot
// this does not work for us.) So we need to make it so that the locally built libcore
// contains all the items from `core`, but does not re-define them -- we want to replace
// the entire crate but a re-export of the sysroot crate. We do this by swapping out the
// source file: if `MIRI_REPLACE_LIBRS_IF_NOT_TEST` is set and we are building a
// `lib.rs` file, and a `lib.miri.rs` file exists in the same folder, we build that
// instead. But crucially we only do that for the library, not the test builds.
cargo.env("MIRI_REPLACE_LIBRS_IF_NOT_TEST", "1");
cargo
} else {
// Also prepare a sysroot for the target.
if builder.config.build != target {
builder.ensure(compile::Std::force_recompile(compiler, target));
builder.ensure(RemoteCopyLibs { compiler, target });
}
// Build `cargo test` command
builder::Cargo::new(
builder,
compiler,
mode,
SourceType::InTree,
target,
builder.kind.as_str(),
)
};
match mode {
Mode::Std => {

View file

@ -631,6 +631,7 @@ pub enum Kind {
Format,
#[value(alias = "t")]
Test,
Miri,
Bench,
#[value(alias = "d")]
Doc,
@ -673,6 +674,7 @@ pub fn as_str(&self) -> &'static str {
Kind::Fix => "fix",
Kind::Format => "fmt",
Kind::Test => "test",
Kind::Miri => "miri",
Kind::Bench => "bench",
Kind::Doc => "doc",
Kind::Clean => "clean",
@ -822,6 +824,7 @@ macro_rules! describe {
// Run run-make last, since these won't pass without make on Windows
test::RunMake,
),
Kind::Miri => describe!(test::Crate),
Kind::Bench => describe!(test::Crate, test::CrateLibrustc),
Kind::Doc => describe!(
doc::UnstableBook,
@ -970,6 +973,7 @@ pub fn new(build: &Build) -> Builder<'_> {
Subcommand::Fix => (Kind::Fix, &paths[..]),
Subcommand::Doc { .. } => (Kind::Doc, &paths[..]),
Subcommand::Test { .. } => (Kind::Test, &paths[..]),
Subcommand::Miri { .. } => (Kind::Miri, &paths[..]),
Subcommand::Bench { .. } => (Kind::Bench, &paths[..]),
Subcommand::Dist => (Kind::Dist, &paths[..]),
Subcommand::Install => (Kind::Install, &paths[..]),
@ -1309,7 +1313,11 @@ pub fn bare_cargo(
if cmd == "clippy" {
cargo = self.cargo_clippy_cmd(compiler);
cargo.arg(cmd);
} else if let Some(subcmd) = cmd.strip_prefix("miri-") {
} else if let Some(subcmd) = cmd.strip_prefix("miri") {
// Command must be "miri-X".
let subcmd = subcmd
.strip_prefix("-")
.unwrap_or_else(|| panic!("expected `miri-$subcommand`, but got {}", cmd));
cargo = self.cargo_miri_cmd(compiler);
cargo.arg("miri").arg(subcmd);
} else {

View file

@ -2022,7 +2022,7 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
Subcommand::Build { .. } => {
flags.stage.or(build_stage).unwrap_or(if download_rustc { 2 } else { 1 })
}
Subcommand::Test { .. } => {
Subcommand::Test { .. } | Subcommand::Miri { .. } => {
flags.stage.or(test_stage).unwrap_or(if download_rustc { 2 } else { 1 })
}
Subcommand::Bench { .. } => flags.stage.or(bench_stage).unwrap_or(2),
@ -2044,6 +2044,7 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
if flags.stage.is_none() && crate::CiEnv::current() != crate::CiEnv::None {
match config.cmd {
Subcommand::Test { .. }
| Subcommand::Miri { .. }
| Subcommand::Doc { .. }
| Subcommand::Build { .. }
| Subcommand::Bench { .. }
@ -2099,7 +2100,9 @@ pub(crate) fn git(&self) -> Command {
pub(crate) fn test_args(&self) -> Vec<&str> {
let mut test_args = match self.cmd {
Subcommand::Test { ref test_args, .. } | Subcommand::Bench { ref test_args, .. } => {
Subcommand::Test { ref test_args, .. }
| Subcommand::Bench { ref test_args, .. }
| Subcommand::Miri { ref test_args, .. } => {
test_args.iter().flat_map(|s| s.split_whitespace()).collect()
}
_ => vec![],

View file

@ -382,6 +382,25 @@ pub enum Subcommand {
/// `/<build_base>/rustfix_missing_coverage.txt`
rustfix_coverage: bool,
},
/// Build and run some test suites *in Miri*
Miri {
#[arg(long)]
/// run all tests regardless of failure
no_fail_fast: bool,
#[arg(long, value_name = "ARGS", allow_hyphen_values(true))]
/// extra arguments to be passed for the test tool being used
/// (e.g. libtest, compiletest or rustdoc)
test_args: Vec<String>,
/// extra options to pass the compiler when running tests
#[arg(long, value_name = "ARGS", allow_hyphen_values(true))]
rustc_args: Vec<String>,
#[arg(long)]
/// do not run doc tests
no_doc: bool,
#[arg(long)]
/// only run doc tests
doc: bool,
},
/// Build and run some benchmarks
Bench {
#[arg(long, allow_hyphen_values(true))]
@ -453,6 +472,7 @@ pub fn kind(&self) -> Kind {
Subcommand::Fix { .. } => Kind::Fix,
Subcommand::Format { .. } => Kind::Format,
Subcommand::Test { .. } => Kind::Test,
Subcommand::Miri { .. } => Kind::Miri,
Subcommand::Clean { .. } => Kind::Clean,
Subcommand::Dist { .. } => Kind::Dist,
Subcommand::Install { .. } => Kind::Install,
@ -464,7 +484,7 @@ pub fn kind(&self) -> Kind {
pub fn rustc_args(&self) -> Vec<&str> {
match *self {
Subcommand::Test { ref rustc_args, .. } => {
Subcommand::Test { ref rustc_args, .. } | Subcommand::Miri { ref rustc_args, .. } => {
rustc_args.iter().flat_map(|s| s.split_whitespace()).collect()
}
_ => vec![],
@ -473,14 +493,16 @@ pub fn rustc_args(&self) -> Vec<&str> {
pub fn fail_fast(&self) -> bool {
match *self {
Subcommand::Test { no_fail_fast, .. } => !no_fail_fast,
Subcommand::Test { no_fail_fast, .. } | Subcommand::Miri { no_fail_fast, .. } => {
!no_fail_fast
}
_ => false,
}
}
pub fn doc_tests(&self) -> DocTests {
match *self {
Subcommand::Test { doc, no_doc, .. } => {
Subcommand::Test { doc, no_doc, .. } | Subcommand::Miri { no_doc, doc, .. } => {
if doc {
DocTests::Only
} else if no_doc {

View file

@ -39,6 +39,7 @@ complete -c x.py -n "__fish_use_subcommand" -f -a "fix" -d 'Run cargo fix'
complete -c x.py -n "__fish_use_subcommand" -f -a "fmt" -d 'Run rustfmt'
complete -c x.py -n "__fish_use_subcommand" -f -a "doc" -d 'Build documentation'
complete -c x.py -n "__fish_use_subcommand" -f -a "test" -d 'Build and run some test suites'
complete -c x.py -n "__fish_use_subcommand" -f -a "miri" -d 'Build and run some test suites *in Miri*'
complete -c x.py -n "__fish_use_subcommand" -f -a "bench" -d 'Build and run some benchmarks'
complete -c x.py -n "__fish_use_subcommand" -f -a "clean" -d 'Clean out build directories'
complete -c x.py -n "__fish_use_subcommand" -f -a "dist" -d 'Build distribution artifacts'
@ -308,6 +309,45 @@ complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-profile-generate
complete -c x.py -n "__fish_seen_subcommand_from test" -l enable-bolt-settings -d 'Enable BOLT link flags'
complete -c x.py -n "__fish_seen_subcommand_from test" -l skip-stage0-validation -d 'Skip stage0 compiler validation'
complete -c x.py -n "__fish_seen_subcommand_from test" -s h -l help -d 'Print help (see more with \'--help\')'
complete -c x.py -n "__fish_seen_subcommand_from miri" -l test-args -d 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)' -r
complete -c x.py -n "__fish_seen_subcommand_from miri" -l rustc-args -d 'extra options to pass the compiler when running tests' -r
complete -c x.py -n "__fish_seen_subcommand_from miri" -l config -d 'TOML configuration file for build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from miri" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
complete -c x.py -n "__fish_seen_subcommand_from miri" -l build -d 'build target of the stage0 compiler' -r -f
complete -c x.py -n "__fish_seen_subcommand_from miri" -l host -d 'host targets to build' -r -f
complete -c x.py -n "__fish_seen_subcommand_from miri" -l target -d 'target targets to build' -r -f
complete -c x.py -n "__fish_seen_subcommand_from miri" -l exclude -d 'build paths to exclude' -r -F
complete -c x.py -n "__fish_seen_subcommand_from miri" -l skip -d 'build paths to skip' -r -F
complete -c x.py -n "__fish_seen_subcommand_from miri" -l rustc-error-format -r -f
complete -c x.py -n "__fish_seen_subcommand_from miri" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
complete -c x.py -n "__fish_seen_subcommand_from miri" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
complete -c x.py -n "__fish_seen_subcommand_from miri" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
complete -c x.py -n "__fish_seen_subcommand_from miri" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
complete -c x.py -n "__fish_seen_subcommand_from miri" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
complete -c x.py -n "__fish_seen_subcommand_from miri" -s j -l jobs -d 'number of jobs to run in parallel' -r -f
complete -c x.py -n "__fish_seen_subcommand_from miri" -l warnings -d 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour' -r -f -a "{deny '',warn '',default ''}"
complete -c x.py -n "__fish_seen_subcommand_from miri" -l error-format -d 'rustc error format' -r -f
complete -c x.py -n "__fish_seen_subcommand_from miri" -l color -d 'whether to use color in cargo and rustc output' -r -f -a "{always '',never '',auto ''}"
complete -c x.py -n "__fish_seen_subcommand_from miri" -l llvm-skip-rebuild -d 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml' -r -f -a "{true '',false ''}"
complete -c x.py -n "__fish_seen_subcommand_from miri" -l rust-profile-generate -d 'generate PGO profile with rustc build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from miri" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from miri" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from miri" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r
complete -c x.py -n "__fish_seen_subcommand_from miri" -l set -d 'override options in config.toml' -r -f
complete -c x.py -n "__fish_seen_subcommand_from miri" -l no-fail-fast -d 'run all tests regardless of failure'
complete -c x.py -n "__fish_seen_subcommand_from miri" -l no-doc -d 'do not run doc tests'
complete -c x.py -n "__fish_seen_subcommand_from miri" -l doc -d 'only run doc tests'
complete -c x.py -n "__fish_seen_subcommand_from miri" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
complete -c x.py -n "__fish_seen_subcommand_from miri" -s i -l incremental -d 'use incremental compilation'
complete -c x.py -n "__fish_seen_subcommand_from miri" -l include-default-paths -d 'include default paths in addition to the provided ones'
complete -c x.py -n "__fish_seen_subcommand_from miri" -l dry-run -d 'dry run; don\'t build anything'
complete -c x.py -n "__fish_seen_subcommand_from miri" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims'
complete -c x.py -n "__fish_seen_subcommand_from miri" -l json-output -d 'use message-format=json'
complete -c x.py -n "__fish_seen_subcommand_from miri" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)'
complete -c x.py -n "__fish_seen_subcommand_from miri" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
complete -c x.py -n "__fish_seen_subcommand_from miri" -l enable-bolt-settings -d 'Enable BOLT link flags'
complete -c x.py -n "__fish_seen_subcommand_from miri" -l skip-stage0-validation -d 'Skip stage0 compiler validation'
complete -c x.py -n "__fish_seen_subcommand_from miri" -s h -l help -d 'Print help (see more with \'--help\')'
complete -c x.py -n "__fish_seen_subcommand_from bench" -l test-args -r
complete -c x.py -n "__fish_seen_subcommand_from bench" -l config -d 'TOML configuration file for build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from bench" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"

View file

@ -66,6 +66,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
[CompletionResult]::new('fmt', 'fmt', [CompletionResultType]::ParameterValue, 'Run rustfmt')
[CompletionResult]::new('doc', 'doc', [CompletionResultType]::ParameterValue, 'Build documentation')
[CompletionResult]::new('test', 'test', [CompletionResultType]::ParameterValue, 'Build and run some test suites')
[CompletionResult]::new('miri', 'miri', [CompletionResultType]::ParameterValue, 'Build and run some test suites *in Miri*')
[CompletionResult]::new('bench', 'bench', [CompletionResultType]::ParameterValue, 'Build and run some benchmarks')
[CompletionResult]::new('clean', 'clean', [CompletionResultType]::ParameterValue, 'Clean out build directories')
[CompletionResult]::new('dist', 'dist', [CompletionResultType]::ParameterValue, 'Build distribution artifacts')
@ -386,6 +387,52 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
break
}
'x.py;miri' {
[CompletionResult]::new('--test-args', 'test-args', [CompletionResultType]::ParameterName, 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)')
[CompletionResult]::new('--rustc-args', 'rustc-args', [CompletionResultType]::ParameterName, 'extra options to pass the compiler when running tests')
[CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
[CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
[CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
[CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'host targets to build')
[CompletionResult]::new('--target', 'target', [CompletionResultType]::ParameterName, 'target targets to build')
[CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
[CompletionResult]::new('--skip', 'skip', [CompletionResultType]::ParameterName, 'build paths to skip')
[CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
[CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
[CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
[CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
[CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
[CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
[CompletionResult]::new('-j', 'j', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
[CompletionResult]::new('--jobs', 'jobs', [CompletionResultType]::ParameterName, 'number of jobs to run in parallel')
[CompletionResult]::new('--warnings', 'warnings', [CompletionResultType]::ParameterName, 'if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour')
[CompletionResult]::new('--error-format', 'error-format', [CompletionResultType]::ParameterName, 'rustc error format')
[CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'whether to use color in cargo and rustc output')
[CompletionResult]::new('--llvm-skip-rebuild', 'llvm-skip-rebuild', [CompletionResultType]::ParameterName, 'whether rebuilding llvm should be skipped, overriding `skip-rebuld` in config.toml')
[CompletionResult]::new('--rust-profile-generate', 'rust-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with rustc build')
[CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
[CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
[CompletionResult]::new('--reproducible-artifact', 'reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive')
[CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
[CompletionResult]::new('--no-fail-fast', 'no-fail-fast', [CompletionResultType]::ParameterName, 'run all tests regardless of failure')
[CompletionResult]::new('--no-doc', 'no-doc', [CompletionResultType]::ParameterName, 'do not run doc tests')
[CompletionResult]::new('--doc', 'doc', [CompletionResultType]::ParameterName, 'only run doc tests')
[CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
[CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
[CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
[CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
[CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
[CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims')
[CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
[CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)')
[CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
[CompletionResult]::new('--enable-bolt-settings', 'enable-bolt-settings', [CompletionResultType]::ParameterName, 'Enable BOLT link flags')
[CompletionResult]::new('--skip-stage0-validation', 'skip-stage0-validation', [CompletionResultType]::ParameterName, 'Skip stage0 compiler validation')
[CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
break
}
'x.py;bench' {
[CompletionResult]::new('--test-args', 'test-args', [CompletionResultType]::ParameterName, 'test-args')
[CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')

View file

@ -42,6 +42,9 @@ _x.py() {
bootstrap,install)
cmd="bootstrap__install"
;;
bootstrap,miri)
cmd="bootstrap__miri"
;;
bootstrap,run)
cmd="bootstrap__run"
;;
@ -61,7 +64,7 @@ _x.py() {
case "${cmd}" in
x.py)
opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]... build check clippy fix fmt doc test bench clean dist install run setup suggest"
opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]... build check clippy fix fmt doc test miri bench clean dist install run setup suggest"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@ -1290,6 +1293,124 @@ _x.py() {
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
x.py__miri)
opts="-v -i -j -h --no-fail-fast --test-args --rustc-args --no-doc --doc --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
--test-args)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--rustc-args)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--config)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--build-dir)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--build)
COMPREPLY=("${cur}")
return 0
;;
--host)
COMPREPLY=("${cur}")
return 0
;;
--target)
COMPREPLY=("${cur}")
return 0
;;
--exclude)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--skip)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--rustc-error-format)
COMPREPLY=("${cur}")
return 0
;;
--on-fail)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--stage)
COMPREPLY=("${cur}")
return 0
;;
--keep-stage)
COMPREPLY=("${cur}")
return 0
;;
--keep-stage-std)
COMPREPLY=("${cur}")
return 0
;;
--src)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--jobs)
COMPREPLY=("${cur}")
return 0
;;
-j)
COMPREPLY=("${cur}")
return 0
;;
--warnings)
COMPREPLY=($(compgen -W "deny warn default" -- "${cur}"))
return 0
;;
--error-format)
COMPREPLY=("${cur}")
return 0
;;
--color)
COMPREPLY=($(compgen -W "always never auto" -- "${cur}"))
return 0
;;
--llvm-skip-rebuild)
COMPREPLY=($(compgen -W "true false" -- "${cur}"))
return 0
;;
--rust-profile-generate)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--rust-profile-use)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--llvm-profile-use)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--reproducible-artifact)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--set)
COMPREPLY=("${cur}")
return 0
;;
*)
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
x.py__run)
opts="-v -i -j -h --args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then

View file

@ -389,6 +389,54 @@ _arguments "${_arguments_options[@]}" \
'*::paths -- paths for the subcommand:_files' \
&& ret=0
;;
(miri)
_arguments "${_arguments_options[@]}" \
'*--test-args=[extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)]:ARGS: ' \
'*--rustc-args=[extra options to pass the compiler when running tests]:ARGS: ' \
'--config=[TOML configuration file for build]:FILE:_files' \
'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \
'--build=[build target of the stage0 compiler]:BUILD:( )' \
'--host=[host targets to build]:HOST:( )' \
'--target=[target targets to build]:TARGET:( )' \
'*--exclude=[build paths to exclude]:PATH:_files' \
'*--skip=[build paths to skip]:PATH:_files' \
'--rustc-error-format=[]:RUSTC_ERROR_FORMAT:( )' \
'--on-fail=[command to run on failure]:CMD:_cmdstring' \
'--stage=[stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)]:N:( )' \
'*--keep-stage=[stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)]:N:( )' \
'*--keep-stage-std=[stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)]:N:( )' \
'--src=[path to the root of the rust checkout]:DIR:_files -/' \
'-j+[number of jobs to run in parallel]:JOBS:( )' \
'--jobs=[number of jobs to run in parallel]:JOBS:( )' \
'--warnings=[if value is deny, will deny warnings if value is warn, will emit warnings otherwise, use the default configured behaviour]:deny|warn:(deny warn default)' \
'--error-format=[rustc error format]:FORMAT:( )' \
'--color=[whether to use color in cargo and rustc output]:STYLE:(always never auto)' \
'--llvm-skip-rebuild=[whether rebuilding llvm should be skipped, overriding \`skip-rebuld\` in config.toml]:VALUE:(true false)' \
'--rust-profile-generate=[generate PGO profile with rustc build]:PROFILE:_files' \
'--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \
'--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \
'*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT: ' \
'*--set=[override options in config.toml]:section.option=value:( )' \
'--no-fail-fast[run all tests regardless of failure]' \
'--no-doc[do not run doc tests]' \
'--doc[only run doc tests]' \
'*-v[use verbose output (-vv for very verbose)]' \
'*--verbose[use verbose output (-vv for very verbose)]' \
'-i[use incremental compilation]' \
'--incremental[use incremental compilation]' \
'--include-default-paths[include default paths in addition to the provided ones]' \
'--dry-run[dry run; don'\''t build anything]' \
'--dump-bootstrap-shims[Indicates whether to dump the work done from bootstrap shims]' \
'--json-output[use message-format=json]' \
'--bypass-bootstrap-lock[Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)]' \
'--llvm-profile-generate[generate PGO profile with llvm built for rustc]' \
'--enable-bolt-settings[Enable BOLT link flags]' \
'--skip-stage0-validation[Skip stage0 compiler validation]' \
'-h[Print help (see more with '\''--help'\'')]' \
'--help[Print help (see more with '\''--help'\'')]' \
'*::paths -- paths for the subcommand:_files' \
&& ret=0
;;
(bench)
_arguments "${_arguments_options[@]}" \
'*--test-args=[]:TEST_ARGS: ' \
@ -710,6 +758,7 @@ _x.py_commands() {
'fmt:Run rustfmt' \
'doc:Build documentation' \
'test:Build and run some test suites' \
'miri:Build and run some test suites *in Miri*' \
'bench:Build and run some benchmarks' \
'clean:Clean out build directories' \
'dist:Build distribution artifacts' \
@ -770,6 +819,11 @@ _x.py__install_commands() {
local commands; commands=()
_describe -t commands 'x.py install commands' commands "$@"
}
(( $+functions[_x.py__miri_commands] )) ||
_x.py__miri_commands() {
local commands; commands=()
_describe -t commands 'x.py miri commands' commands "$@"
}
(( $+functions[_x.py__run_commands] )) ||
_x.py__run_commands() {
local commands; commands=()

View file

@ -507,6 +507,8 @@ binaries, and as such worth documenting:
crate currently being compiled.
* `MIRI_ORIG_RUSTDOC` is set and read by different phases of `cargo-miri` to remember the
value of `RUSTDOC` from before it was overwritten.
* `MIRI_REPLACE_LIBRS_IF_NOT_TEST` when set to any value enables a hack that helps bootstrap
run the standard library tests in Miri.
* `MIRI_VERBOSE` when set to any value tells the various `cargo-miri` phases to
perform verbose logging.
* `MIRI_HOST_SYSROOT` is set by bootstrap to tell `cargo-miri` which sysroot to use for *host*

View file

@ -3,7 +3,7 @@
use std::env;
use std::fs::{self, File};
use std::io::BufReader;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::process::Command;
use rustc_version::VersionMeta;
@ -412,9 +412,25 @@ fn out_filenames() -> Vec<PathBuf> {
// Arguments are treated very differently depending on whether this crate is
// for interpretation by Miri, or for use by a build script / proc macro.
if target_crate {
// Forward arguments, but remove "link" from "--emit" to make this a check-only build.
// Forward arguments, but patched.
let emit_flag = "--emit";
// This hack helps bootstrap run standard library tests in Miri. The issue is as follows:
// when running `cargo miri test` on libcore, cargo builds a local copy of core and makes it
// a dependency of the integration test crate. This copy duplicates all the lang items, so
// the build fails. (Regular testing avoids this because the sysroot is a literal copy of
// what `cargo build` produces, but since Miri builds its own sysroot this does not work for
// us.) So we need to make it so that the locally built libcore contains all the items from
// `core`, but does not re-define them -- we want to replace the entire crate but a
// re-export of the sysroot crate. We do this by swapping out the source file: if
// `MIRI_REPLACE_LIBRS_IF_NOT_TEST` is set and we are building a `lib.rs` file, and a
// `lib.miri.rs` file exists in the same folder, we build that instead. But crucially we
// only do that for the library, not the unit test crate (which would be runnable) or
// rustdoc (which would have a different `phase`).
let replace_librs = env::var_os("MIRI_REPLACE_LIBRS_IF_NOT_TEST").is_some()
&& !runnable_crate
&& phase == RustcPhase::Build;
while let Some(arg) = args.next() {
// Patch `--emit`: remove "link" from "--emit" to make this a check-only build.
if let Some(val) = arg.strip_prefix(emit_flag) {
// Patch this argument. First, extract its value.
let val =
@ -429,13 +445,36 @@ fn out_filenames() -> Vec<PathBuf> {
}
}
cmd.arg(format!("{emit_flag}={}", val.join(",")));
} else if arg == "--extern" {
// Patch `--extern` filenames, since Cargo sometimes passes stub `.rlib` files:
// https://github.com/rust-lang/miri/issues/1705
forward_patched_extern_arg(&mut args, &mut cmd);
} else {
cmd.arg(arg);
continue;
}
// Patch `--extern` filenames, since Cargo sometimes passes stub `.rlib` files:
// https://github.com/rust-lang/miri/issues/1705
if arg == "--extern" {
forward_patched_extern_arg(&mut args, &mut cmd);
continue;
}
// If the REPLACE_LIBRS hack is enabled and we are building a `lib.rs` file, and a
// `lib.miri.rs` file exists, then build that instead. We only consider relative paths
// as cargo uses those for files in the workspace; dependencies from crates.io get
// absolute paths.
if replace_librs {
let path = Path::new(&arg);
if path.is_relative()
&& path.file_name().is_some_and(|f| f == "lib.rs")
&& path.is_file()
{
let miri_rs = Path::new(&arg).with_extension("miri.rs");
if miri_rs.is_file() {
if verbose > 0 {
eprintln!("Performing REPLACE_LIBRS hack: {arg:?} -> {miri_rs:?}");
}
cmd.arg(miri_rs);
continue;
}
}
}
// Fallback: just propagate the argument.
cmd.arg(arg);
}
// During setup, patch the panic runtime for `libpanic_abort` (mirroring what bootstrap usually does).