Skip to content

Commit c73f658

Browse files
committed
Auto merge of #3798 - RalfJung:miri-script-remap-path-prefix, r=saethlin
miri-script: use --remap-path-prefix to print errors relative to the right root Inspired by rust-lang/rust-clippy#13232, this makes it so that when cargo-miri fails to build, `./miri check` will print errors with paths like `cargo-miri/src/setup.rs`. That means we can get rid of the miri-symlink-hacks and instead tell RA to just always invoke the `./miri clippy` script just once, in the root. This means that we can no longer share a target dir between cargo-miri and miri as the RUSTFLAGS are different to crates that are shared in the dependency tree need to be built twice with two different flags. `miri-script` hence now has to set the MIRI environment variable to tell the `cargo miri setup` invocation where to find Miri. I also made it so that errors in miri-script itself are properly shown in RA, for which the `./miri` shell wrapper needs to set the right flags.
2 parents 693fcf6 + b9ebd52 commit c73f658

File tree

12 files changed

+135
-115
lines changed

12 files changed

+135
-115
lines changed

.cargo/config.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[unstable]
2+
profile-rustflags = true
3+
4+
# Add back the containing directory of the packages we have to refer to using --manifest-path.
5+
# Per-package profiles avoid adding this to build dependencies.
6+
[profile.dev.package."cargo-miri"]
7+
rustflags = ["--remap-path-prefix", "=cargo-miri"]
8+
[profile.dev.package."miri-script"]
9+
rustflags = ["--remap-path-prefix", "=miri-script"]

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ jobs:
6060
- name: clippy (all features)
6161
run: ./miri clippy --all-features -- -D warnings
6262
- name: rustdoc
63-
run: RUSTDOCFLAGS="-Dwarnings" ./miri cargo doc --document-private-items
63+
run: RUSTDOCFLAGS="-Dwarnings" ./miri doc --document-private-items
6464

6565
# These jobs doesn't actually test anything, but they're only used to tell
6666
# bors the build completed, as there is no practical way to detect when a

.github/workflows/setup/action.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ runs:
3535
run: cargo install -f rustup-toolchain-install-master hyperfine
3636
shell: bash
3737

38+
- name: Install nightly toolchain
39+
run: rustup toolchain install nightly --profile minimal
40+
shell: bash
41+
3842
- name: Install "master" toolchain
3943
run: |
4044
if [[ ${{ github.event_name }} == 'schedule' ]]; then

CONTRIBUTING.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,24 +173,24 @@ to `.vscode/settings.json` in your local Miri clone:
173173
"cargo-miri/Cargo.toml",
174174
"miri-script/Cargo.toml",
175175
],
176+
"rust-analyzer.check.invocationLocation": "root",
177+
"rust-analyzer.check.invocationStrategy": "once",
176178
"rust-analyzer.check.overrideCommand": [
177179
"env",
178180
"MIRI_AUTO_OPS=no",
179181
"./miri",
180-
"cargo",
181182
"clippy", // make this `check` when working with a locally built rustc
182183
"--message-format=json",
183-
"--all-targets",
184184
],
185185
// Contrary to what the name suggests, this also affects proc macros.
186+
"rust-analyzer.cargo.buildScripts.invocationLocation": "root",
187+
"rust-analyzer.cargo.buildScripts.invocationStrategy": "once",
186188
"rust-analyzer.cargo.buildScripts.overrideCommand": [
187189
"env",
188190
"MIRI_AUTO_OPS=no",
189191
"./miri",
190-
"cargo",
191192
"check",
192193
"--message-format=json",
193-
"--all-targets",
194194
],
195195
}
196196
```
@@ -309,6 +309,7 @@ anyone but Miri itself. They are used to communicate between different Miri
309309
binaries, and as such worth documenting:
310310

311311
* `CARGO_EXTRA_FLAGS` is understood by `./miri` and passed to all host cargo invocations.
312+
It is reserved for CI usage; setting the wrong flags this way can easily confuse the script.
312313
* `MIRI_BE_RUSTC` can be set to `host` or `target`. It tells the Miri driver to
313314
actually not interpret the code but compile it like rustc would. With `target`, Miri sets
314315
some compiler flags to prepare the code for interpretation; with `host`, this is not done.

cargo-miri/miri

Lines changed: 0 additions & 4 deletions
This file was deleted.

cargo-miri/src/util.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,9 @@ pub fn find_miri() -> PathBuf {
9393
if let Some(path) = env::var_os("MIRI") {
9494
return path.into();
9595
}
96+
// Assume it is in the same directory as ourselves.
9697
let mut path = std::env::current_exe().expect("current executable path invalid");
97-
if cfg!(windows) {
98-
path.set_file_name("miri.exe");
99-
} else {
100-
path.set_file_name("miri");
101-
}
98+
path.set_file_name(format!("miri{}", env::consts::EXE_SUFFIX));
10299
path
103100
}
104101

miri

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
#!/usr/bin/env bash
22
set -e
3+
# We want to call the binary directly, so we need to know where it ends up.
4+
MIRI_SCRIPT_TARGET_DIR="$(dirname "$0")"/miri-script/target
5+
# If stdout is not a terminal and we are not on CI, assume that we are being invoked by RA, and use JSON output.
6+
if ! [ -t 1 ] && [ -z "$CI" ]; then
7+
MESSAGE_FORMAT="--message-format=json"
8+
fi
9+
# We need a nightly toolchain, for the `profile-rustflags` cargo feature.
10+
cargo +nightly build $CARGO_EXTRA_FLAGS --manifest-path "$(dirname "$0")"/miri-script/Cargo.toml \
11+
-q --target-dir "$MIRI_SCRIPT_TARGET_DIR" $MESSAGE_FORMAT || \
12+
( echo "Failed to build miri-script. Is the 'nightly' toolchain installed?"; exit 1 )
313
# Instead of doing just `cargo run --manifest-path .. $@`, we invoke miri-script binary directly. Invoking `cargo run` goes through
414
# rustup (that sets it's own environmental variables), which is undesirable.
5-
MIRI_SCRIPT_TARGET_DIR="$(dirname "$0")"/miri-script/target
6-
cargo +stable build $CARGO_EXTRA_FLAGS -q --target-dir "$MIRI_SCRIPT_TARGET_DIR" --manifest-path "$(dirname "$0")"/miri-script/Cargo.toml || \
7-
( echo "Failed to build miri-script. Is the 'stable' toolchain installed?"; exit 1 )
815
"$MIRI_SCRIPT_TARGET_DIR"/debug/miri-script "$@"

miri-script/miri

Lines changed: 0 additions & 4 deletions
This file was deleted.

miri-script/src/commands.rs

Lines changed: 37 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const JOSH_FILTER: &str =
2222
const JOSH_PORT: u16 = 42042;
2323

2424
impl MiriEnv {
25+
/// Prepares the environment: builds miri and cargo-miri and a sysroot.
2526
/// Returns the location of the sysroot.
2627
///
2728
/// If the target is None the sysroot will be built for the host machine.
@@ -34,12 +35,10 @@ impl MiriEnv {
3435
// Sysroot already set, use that.
3536
return Ok(miri_sysroot.into());
3637
}
37-
let manifest_path = path!(self.miri_dir / "cargo-miri" / "Cargo.toml");
38-
let Self { toolchain, cargo_extra_flags, .. } = &self;
3938

4039
// Make sure everything is built. Also Miri itself.
41-
self.build(path!(self.miri_dir / "Cargo.toml"), &[], quiet)?;
42-
self.build(&manifest_path, &[], quiet)?;
40+
self.build(".", &[], quiet)?;
41+
self.build("cargo-miri", &[], quiet)?;
4342

4443
let target_flag = if let Some(target) = &target {
4544
vec![OsStr::new("--target"), target.as_ref()]
@@ -56,10 +55,12 @@ impl MiriEnv {
5655
eprintln!();
5756
}
5857

59-
let mut cmd = cmd!(self.sh,
60-
"cargo +{toolchain} --quiet run {cargo_extra_flags...} --manifest-path {manifest_path} --
61-
miri setup --print-sysroot {target_flag...}"
62-
);
58+
let mut cmd = self
59+
.cargo_cmd("cargo-miri", "run")
60+
.arg("--quiet")
61+
.arg("--")
62+
.args(&["miri", "setup", "--print-sysroot"])
63+
.args(target_flag);
6364
cmd.set_quiet(quiet);
6465
let output = cmd.read()?;
6566
self.sh.set_var("MIRI_SYSROOT", &output);
@@ -162,8 +163,8 @@ impl Command {
162163
| Command::Test { .. }
163164
| Command::Run { .. }
164165
| Command::Fmt { .. }
165-
| Command::Clippy { .. }
166-
| Command::Cargo { .. } => Self::auto_actions()?,
166+
| Command::Doc { .. }
167+
| Command::Clippy { .. } => Self::auto_actions()?,
167168
| Command::Toolchain { .. }
168169
| Command::Bench { .. }
169170
| Command::RustcPull { .. }
@@ -177,9 +178,9 @@ impl Command {
177178
Command::Test { bless, flags, target } => Self::test(bless, flags, target),
178179
Command::Run { dep, verbose, many_seeds, target, edition, flags } =>
179180
Self::run(dep, verbose, many_seeds, target, edition, flags),
181+
Command::Doc { flags } => Self::doc(flags),
180182
Command::Fmt { flags } => Self::fmt(flags),
181183
Command::Clippy { flags } => Self::clippy(flags),
182-
Command::Cargo { flags } => Self::cargo(flags),
183184
Command::Bench { target, benches } => Self::bench(target, benches),
184185
Command::Toolchain { flags } => Self::toolchain(flags),
185186
Command::RustcPull { commit } => Self::rustc_pull(commit.clone()),
@@ -433,39 +434,37 @@ impl Command {
433434

434435
fn build(flags: Vec<String>) -> Result<()> {
435436
let e = MiriEnv::new()?;
436-
e.build(path!(e.miri_dir / "Cargo.toml"), &flags, /* quiet */ false)?;
437-
e.build(path!(e.miri_dir / "cargo-miri" / "Cargo.toml"), &flags, /* quiet */ false)?;
437+
e.build(".", &flags, /* quiet */ false)?;
438+
e.build("cargo-miri", &flags, /* quiet */ false)?;
438439
Ok(())
439440
}
440441

441442
fn check(flags: Vec<String>) -> Result<()> {
442443
let e = MiriEnv::new()?;
443-
e.check(path!(e.miri_dir / "Cargo.toml"), &flags)?;
444-
e.check(path!(e.miri_dir / "cargo-miri" / "Cargo.toml"), &flags)?;
444+
e.check(".", &flags)?;
445+
e.check("cargo-miri", &flags)?;
445446
Ok(())
446447
}
447448

448-
fn clippy(flags: Vec<String>) -> Result<()> {
449+
fn doc(flags: Vec<String>) -> Result<()> {
449450
let e = MiriEnv::new()?;
450-
e.clippy(path!(e.miri_dir / "Cargo.toml"), &flags)?;
451-
e.clippy(path!(e.miri_dir / "cargo-miri" / "Cargo.toml"), &flags)?;
452-
e.clippy(path!(e.miri_dir / "miri-script" / "Cargo.toml"), &flags)?;
451+
e.doc(".", &flags)?;
452+
e.doc("cargo-miri", &flags)?;
453453
Ok(())
454454
}
455455

456-
fn cargo(flags: Vec<String>) -> Result<()> {
456+
fn clippy(flags: Vec<String>) -> Result<()> {
457457
let e = MiriEnv::new()?;
458-
let toolchain = &e.toolchain;
459-
// We carefully kept the working dir intact, so this will run cargo *on the workspace in the
460-
// current working dir*, not on the main Miri workspace. That is exactly what RA needs.
461-
cmd!(e.sh, "cargo +{toolchain} {flags...}").run()?;
458+
e.clippy(".", &flags)?;
459+
e.clippy("cargo-miri", &flags)?;
460+
e.clippy("miri-script", &flags)?;
462461
Ok(())
463462
}
464463

465464
fn test(bless: bool, mut flags: Vec<String>, target: Option<String>) -> Result<()> {
466465
let mut e = MiriEnv::new()?;
467466

468-
// Prepare a sysroot.
467+
// Prepare a sysroot. (Also builds cargo-miri, which we need.)
469468
e.build_miri_sysroot(/* quiet */ false, target.as_deref())?;
470469

471470
// Forward information to test harness.
@@ -482,7 +481,7 @@ impl Command {
482481

483482
// Then test, and let caller control flags.
484483
// Only in root project as `cargo-miri` has no tests.
485-
e.test(path!(e.miri_dir / "Cargo.toml"), &flags)?;
484+
e.test(".", &flags)?;
486485
Ok(())
487486
}
488487

@@ -510,32 +509,27 @@ impl Command {
510509
early_flags.push("--edition".into());
511510
early_flags.push(edition.as_deref().unwrap_or("2021").into());
512511

513-
// Prepare a sysroot, add it to the flags.
512+
// Prepare a sysroot, add it to the flags. (Also builds cargo-miri, which we need.)
514513
let miri_sysroot = e.build_miri_sysroot(/* quiet */ !verbose, target.as_deref())?;
515514
early_flags.push("--sysroot".into());
516515
early_flags.push(miri_sysroot.into());
517516

518517
// Compute everything needed to run the actual command. Also add MIRIFLAGS.
519-
let miri_manifest = path!(e.miri_dir / "Cargo.toml");
520518
let miri_flags = e.sh.var("MIRIFLAGS").unwrap_or_default();
521519
let miri_flags = flagsplit(&miri_flags);
522-
let toolchain = &e.toolchain;
523-
let extra_flags = &e.cargo_extra_flags;
524520
let quiet_flag = if verbose { None } else { Some("--quiet") };
525521
// This closure runs the command with the given `seed_flag` added between the MIRIFLAGS and
526522
// the `flags` given on the command-line.
527-
let run_miri = |sh: &Shell, seed_flag: Option<String>| -> Result<()> {
523+
let run_miri = |e: &MiriEnv, seed_flag: Option<String>| -> Result<()> {
528524
// The basic command that executes the Miri driver.
529525
let mut cmd = if dep {
530-
cmd!(
531-
sh,
532-
"cargo +{toolchain} {quiet_flag...} test {extra_flags...} --manifest-path {miri_manifest} --test ui -- --miri-run-dep-mode"
533-
)
526+
e.cargo_cmd(".", "test")
527+
.args(&["--test", "ui"])
528+
.args(quiet_flag)
529+
.arg("--")
530+
.args(&["--miri-run-dep-mode"])
534531
} else {
535-
cmd!(
536-
sh,
537-
"cargo +{toolchain} {quiet_flag...} run {extra_flags...} --manifest-path {miri_manifest} --"
538-
)
532+
e.cargo_cmd(".", "run").args(quiet_flag).arg("--")
539533
};
540534
cmd.set_quiet(!verbose);
541535
// Add Miri flags
@@ -551,14 +545,14 @@ impl Command {
551545
};
552546
// Run the closure once or many times.
553547
if let Some(seed_range) = many_seeds {
554-
e.run_many_times(seed_range, |sh, seed| {
548+
e.run_many_times(seed_range, |e, seed| {
555549
eprintln!("Trying seed: {seed}");
556-
run_miri(sh, Some(format!("-Zmiri-seed={seed}"))).inspect_err(|_| {
550+
run_miri(e, Some(format!("-Zmiri-seed={seed}"))).inspect_err(|_| {
557551
eprintln!("FAILING SEED: {seed}");
558552
})
559553
})?;
560554
} else {
561-
run_miri(&e.sh, None)?;
555+
run_miri(&e, None)?;
562556
}
563557
Ok(())
564558
}
@@ -585,6 +579,6 @@ impl Command {
585579
.filter_ok(|item| item.file_type().is_file())
586580
.map_ok(|item| item.into_path());
587581

588-
e.format_files(files, &e.toolchain[..], &config_path, &flags)
582+
e.format_files(files, &config_path, &flags)
589583
}
590584
}

miri-script/src/main.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ pub enum Command {
4848
/// Flags that are passed through to `miri`.
4949
flags: Vec<String>,
5050
},
51+
/// Build documentation
52+
Doc {
53+
/// Flags that are passed through to `cargo doc`.
54+
flags: Vec<String>,
55+
},
5156
/// Format all sources and tests.
5257
Fmt {
5358
/// Flags that are passed through to `rustfmt`.
@@ -58,9 +63,6 @@ pub enum Command {
5863
/// Flags that are passed through to `cargo clippy`.
5964
flags: Vec<String>,
6065
},
61-
/// Runs just `cargo <flags>` with the Miri-specific environment variables.
62-
/// Mainly meant to be invoked by rust-analyzer.
63-
Cargo { flags: Vec<String> },
6466
/// Runs the benchmarks from bench-cargo-miri in hyperfine. hyperfine needs to be installed.
6567
Bench {
6668
target: Option<String>,
@@ -151,6 +153,7 @@ fn main() -> Result<()> {
151153
let command = match args.next_raw().as_deref() {
152154
Some("build") => Command::Build { flags: args.remainder() },
153155
Some("check") => Command::Check { flags: args.remainder() },
156+
Some("doc") => Command::Doc { flags: args.remainder() },
154157
Some("test") => {
155158
let mut target = None;
156159
let mut bless = false;
@@ -205,7 +208,6 @@ fn main() -> Result<()> {
205208
}
206209
Some("fmt") => Command::Fmt { flags: args.remainder() },
207210
Some("clippy") => Command::Clippy { flags: args.remainder() },
208-
Some("cargo") => Command::Cargo { flags: args.remainder() },
209211
Some("install") => Command::Install { flags: args.remainder() },
210212
Some("bench") => {
211213
let mut target = None;

0 commit comments

Comments
 (0)