Skip to content

Commit 3c930e4

Browse files
authored
add Miri build script (#745)
add Miri build script
2 parents 4e329eb + 543e579 commit 3c930e4

File tree

6 files changed

+113
-55
lines changed

6 files changed

+113
-55
lines changed

.travis.yml

-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ env:
1616
global:
1717
- RUST_TEST_NOCAPTURE=1
1818
- RUST_BACKTRACE=1
19-
- RUSTFLAGS="-C debug-assertions"
2019

2120
before_script:
2221
# Linux: install extra stuff for cross-compilation

Cargo.toml

+5-2
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,15 @@ rustc_version = { version = "0.2.3", optional = true }
4040
env_logger = "0.6"
4141
log = "0.4"
4242
shell-escape = "0.1.4"
43+
hex = "0.3.2"
44+
rand = "0.6"
4345
# A noop dependency that changes in the Rust repository, it's a bit of a hack.
4446
# See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust`
4547
# for more information.
4648
rustc-workspace-hack = "1.0.0"
47-
hex = "0.3.2"
48-
rand = "0.6"
49+
# Depend on num-traits with default features to avoid having to rebuild
50+
# between "cargo build" and "cargo intall".
51+
num-traits = "*"
4952

5053
[build-dependencies]
5154
vergen = "3"

README.md

+14-37
Original file line numberDiff line numberDiff line change
@@ -141,42 +141,30 @@ version of `rustc` that, instead of compiling your code, runs it. It accepts
141141
all the same flags as `rustc` (though the ones only affecting code generation
142142
and linking obviously will have no effect) [and more][miri-flags].
143143

144-
To run the Miri driver, you need to have the `MIRI_SYSROOT` environment variable
145-
set to an appropriate sysroot. You can generate such a sysroot with the
146-
following incantation:
147-
148-
```
149-
cargo run --bin cargo-miri -- miri setup
150-
```
151-
152-
This basically runs the `cargo-miri` binary (which backs the `cargo miri`
153-
subcommand) with `cargo`, and asks it to `setup`. It should in the end print
154-
the directory where the libstd was built. In the following, we will assume it
155-
is `~/.cache/miri/HOST`; you may have to adjust that if you are not using Linux.
156-
157-
Now you can run the driver directly using
144+
Running the Miri driver requires some fiddling with environment variables, so
145+
the `miri` script helps you do that. For example, you can run the driver on a
146+
particular file by doing
158147

159148
```sh
160-
MIRI_SYSROOT=~/.cache/miri/HOST cargo run tests/run-pass/format.rs # or whatever test you like
149+
./miri run tests/run-pass/format.rs
150+
./miri run tests/run-pass/hello.rs --target i686-unknown-linux-gnu
161151
```
162152

163-
and you can run the test suite using
153+
and you can run the test suite using:
164154

165155
```
166-
cargo test
156+
./miri test
167157
```
168158

169-
We recommend adding the `--release` flag to make tests run faster.
170-
171-
`cargo test --release FILTER` only runs those tests that contain `FILTER` in
172-
their filename (including the base directory, e.g. `cargo test --release fail`
173-
will run all compile-fail tests).
159+
`./miri test FILTER` only runs those tests that contain `FILTER` in their
160+
filename (including the base directory, e.g. `./miri test fail` will run all
161+
compile-fail tests).
174162

175163
You can get a trace of which MIR statements are being executed by setting the
176164
`MIRI_LOG` environment variable. For example:
177165

178166
```sh
179-
MIRI_LOG=info cargo run tests/run-pass/vecs.rs
167+
MIRI_LOG=info ./miri run tests/run-pass/vecs.rs
180168
```
181169

182170
Setting `MIRI_LOG` like this will configure logging for Miri itself as well as
@@ -185,7 +173,7 @@ can also do more targeted configuration, e.g. the following helps debug the
185173
stacked borrows implementation:
186174

187175
```sh
188-
MIRI_LOG=rustc_mir::interpret=info,miri::stacked_borrows cargo run tests/run-pass/vecs.rs
176+
MIRI_LOG=rustc_mir::interpret=info,miri::stacked_borrows ./miri run tests/run-pass/vecs.rs
189177
```
190178

191179
In addition, you can set `MIRI_BACKTRACE=1` to get a backtrace of where an
@@ -199,7 +187,7 @@ is probably easier to test it with the cargo wrapper. You can install your
199187
development version of Miri using
200188

201189
```
202-
cargo install --path . --force
190+
./miri install
203191
```
204192

205193
and then you can use it as if it was installed by `rustup`. Make sure you use
@@ -235,18 +223,7 @@ rustup override set custom
235223
```
236224

237225
With this, you should now have a working development setup! See
238-
[above][testing-miri] for how to proceed working with the Miri driver. Notice
239-
that rustc's sysroot is already built for Miri in this case, so you can set
240-
`MIRI_SYSROOT=$(rustc --print sysroot)`.
241-
242-
Running `cargo miri` in this setup is a bit more complicated, because the Miri
243-
binary you just created needs help to find the libraries it links against. On
244-
Linux, you can set the rpath to make this "just work":
245-
246-
```sh
247-
export RUSTFLAGS="-C link-args=-Wl,-rpath,$(rustc --print sysroot)/lib/rustlib/x86_64-unknown-linux-gnu/lib"
248-
cargo install --path . --force
249-
```
226+
[above][testing-miri] for how to proceed working with the Miri driver.
250227

251228
### Miri `-Z` flags and environment variables
252229
[miri-flags]: #miri--z-flags-and-environment-variables

miri

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#!/bin/sh
2+
set -e
3+
# I'd love to use `jq` for parsing the JSON properly, but macOS is totally underequipped for this kind of work.
4+
TARGET=$(rustc --print target-spec-json -Z unstable-options | grep llvm-target | cut -d '"' -f 4)
5+
SYSROOT=$(rustc --print sysroot)
6+
# We set the rpath so that Miri finds the private rustc libraries it needs.
7+
# We enable debug-assertions to get tracing.
8+
# We enable line-only debuginfo for backtraces.
9+
export RUSTFLAGS="-C link-args=-Wl,-rpath,$SYSROOT/lib/rustlib/$TARGET/lib -C debug-assertions -C debuginfo=1"
10+
11+
## Helper functions
12+
13+
# Build a sysroot and set MIRI_SYSROOT to use it. Arguments are passed to `cargo miri setup`.
14+
build_sysroot() {
15+
# Build once, for the user to see.
16+
cargo run --release --bin cargo-miri -- miri setup "$@"
17+
# Call again, to just set env var.
18+
eval $(cargo run --release -q --bin cargo-miri -- miri setup --env "$@")
19+
export MIRI_SYSROOT
20+
}
21+
22+
# Prepare and set MIRI_SYSROOT. Respects `MIRI_TEST_TARGET` and takes into account
23+
# locally built vs. distributed rustc.
24+
find_sysroot() {
25+
# Get ourselves a sysroot
26+
if [ -n "$MIRI_SYSROOT" ]; then
27+
# Sysroot already set, use that.
28+
true
29+
elif echo "$SYSROOT" | egrep -q 'build/[^/]+/stage'; then
30+
# A local rustc build.
31+
if [ -n "$MIRI_TEST_TARGET" ]; then
32+
# Foreign targets still need a build. Use the rustc sources.
33+
export XARGO_RUST_SRC="$SYSROOT/../../../src"
34+
build_sysroot --target "$MIRI_TEST_TARGET"
35+
else
36+
# Assume we have a proper host libstd in $SYSROOT.
37+
true
38+
fi
39+
else
40+
# A normal toolchain. We have to build a sysroot either way.
41+
if [ -n "$MIRI_TEST_TARGET" ]; then
42+
build_sysroot --target "$MIRI_TEST_TARGET"
43+
else
44+
build_sysroot
45+
fi
46+
fi
47+
}
48+
49+
## Main
50+
51+
COMMAND="$1"
52+
shift
53+
54+
case "$COMMAND" in
55+
install)
56+
# "--locked" to respect the Cargo.lock file if it exists,
57+
# "--offline" to avoid querying the registry (for yanked packages).
58+
exec cargo "$COMMAND" --path "$(dirname "$0")" --force --locked --offline "$@"
59+
;;
60+
build)
61+
# Build, and let caller control flags.
62+
exec cargo "$COMMAND" --release "$@"
63+
;;
64+
test|run)
65+
# In "run" mode, scan for "--target" to set the "MIRI_TEST_TARGET" env var so
66+
# that we set the MIRI_SYSROOT up the right way.
67+
if [ "$COMMAND" = "run" ] && [ -z "$MIRI_TEST_TARGET" ]; then
68+
for ARG in "$@"; do
69+
if [ "$LAST_ARG" = "--target" ]; then
70+
# Found it!
71+
export MIRI_TEST_TARGET="$ARG"
72+
break
73+
fi
74+
LAST_ARG="$ARG"
75+
done
76+
fi
77+
# First build and get a sysroot.
78+
cargo build --release
79+
find_sysroot
80+
# Then run the actual command.
81+
exec cargo "$COMMAND" --release "$@"
82+
;;
83+
esac

src/bin/cargo-miri.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ path = "lib.rs"
243243
File::create(dir.join("lib.rs")).unwrap();
244244
// Run xargo.
245245
let target = get_arg_flag_value("--target");
246+
let print_env = !ask_user && has_arg_flag("--env"); // whether we just print the necessary environment variable
246247
let mut command = Command::new("xargo");
247248
command.arg("build").arg("-q")
248249
.current_dir(&dir)
@@ -265,7 +266,9 @@ path = "lib.rs"
265266
};
266267
let sysroot = if is_host { dir.join("HOST") } else { PathBuf::from(dir) };
267268
std::env::set_var("MIRI_SYSROOT", &sysroot);
268-
if !ask_user {
269+
if print_env {
270+
println!("MIRI_SYSROOT={}", sysroot.display());
271+
} else if !ask_user {
269272
println!("A libstd for Miri is now available in `{}`", sysroot.display());
270273
}
271274
}

travis.sh

+7-14
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,29 @@ set -euo pipefail
33

44
# Determine configuration
55
if [ "$TRAVIS_OS_NAME" == osx ]; then
6-
MIRI_SYSROOT_BASE=~/Library/Caches/miri.miri.miri/
76
FOREIGN_TARGET=i686-apple-darwin
87
else
9-
MIRI_SYSROOT_BASE=~/.cache/miri/
108
FOREIGN_TARGET=i686-unknown-linux-gnu
119
fi
1210

1311
# Prepare
1412
echo "Build and install miri"
15-
cargo build --release --all-features --all-targets
16-
cargo install --all-features --force --path .
17-
echo
18-
19-
echo "Get ourselves a MIR-full libstd for the host and a foreign architecture"
20-
cargo miri setup
21-
cargo miri setup --target "$FOREIGN_TARGET"
13+
./miri build --all-features --all-targets
14+
./miri install
2215
echo
2316

2417
# Test
2518
function run_tests {
26-
cargo test --release --all-features
27-
test-cargo-miri/run-test.py
19+
./miri test
20+
# "miri test" has built the sysroot for us, now this should pass without
21+
# any interactive questions.
22+
test-cargo-miri/run-test.py
2823
}
2924

3025
echo "Test host architecture"
31-
export MIRI_SYSROOT="$MIRI_SYSROOT_BASE"/HOST
3226
run_tests
3327
echo
3428

3529
echo "Test foreign architecture ($FOREIGN_TARGET)"
36-
export MIRI_SYSROOT="$MIRI_SYSROOT_BASE" MIRI_TEST_TARGET="$FOREIGN_TARGET"
37-
run_tests
30+
MIRI_TEST_TARGET="$FOREIGN_TARGET" run_tests
3831
echo

0 commit comments

Comments
 (0)