6 ./miri install <flags>:
7 Installs the miri driver and cargo-miri. <flags> are passed to `cargo
8 install`. Sets up the rpath such that the installed binary should work in any
9 working directory. However, the rustup toolchain when invoking `cargo miri`
10 needs to be the same one used for `./miri install`.
13 Just build miri. <flags> are passed to `cargo build`.
16 Just check miri. <flags> are passed to `cargo check`.
19 Build miri, set up a sysroot and then run the test suite. <flags> are passed
20 to the final `cargo test` invocation.
23 Build miri, set up a sysroot and then run the driver with the given <flags>.
24 (Also respects MIRIFLAGS environment variable.)
27 Format all sources and tests. <flags> are passed to `rustfmt`.
29 ./miri clippy <flags>:
30 Runs clippy on all sources. <flags> are passed to `cargo clippy`.
33 Runs just `cargo <flags>` with the Miri-specific environment variables.
34 Mainly meant to be invoked by rust-analyzer.
36 ./miri many-seeds <command>:
37 Runs <command> over and over again with different seeds for Miri. The MIRIFLAGS
38 variable is set to its original value appended with ` -Zmiri-seed=$SEED` for
41 ./miri bench <benches>:
42 Runs the benchmarks from bench-cargo-miri in hyperfine. hyperfine needs to be installed.
43 <benches> can explicitly list the benchmarks to run; by default, all of them are run.
45 ./miri toolchain <flags>:
46 Update and activate the rustup toolchain 'miri' to the commit given in the
48 `rustup-toolchain-install-master` must be installed for this to work. Any extra
49 flags are passed to `rustup-toolchain-install-master`.
51 ./miri rustc-pull <commit>:
52 Pull and merge Miri changes from the rustc repo. Defaults to fetching the latest
53 rustc commit. The fetched commit is stored in the `rust-version` file, so the
54 next `./miri toolchain` will install the rustc that just got pulled.
56 ./miri rustc-push <github user> <branch>:
57 Push Miri changes back to the rustc repo. This will pull a copy of the rustc
58 history into the Miri repo, unless you set the RUSTC_GIT env var to an existing
59 clone of the rustc repo.
64 If already set, the "sysroot setup" step is skipped.
67 Pass extra flags to all cargo invocations. (Ignored by `./miri cargo`.)
71 ## We need to know which command to run and some global constants.
73 if [ -z "$COMMAND" ]; then
78 # macOS does not have a useful readlink/realpath so we have to use Python instead...
79 MIRIDIR=$(python3 -c 'import os, sys; print(os.path.dirname(os.path.realpath(sys.argv[1])))' "$0")
80 # Used for rustc syncs.
81 JOSH_FILTER=":rev(75dd959a3a40eb5b4574f8d2e23aa6efbeb33573:prefix=src/tools/miri):/src/tools/miri"
82 # Needed for `./miri bench`.
83 TOOLCHAIN=$(cd "$MIRIDIR"; rustup show active-toolchain | head -n 1 | cut -d ' ' -f 1)
85 ## Early commands, that don't do auto-things and don't want the environment-altering things happening below.
89 NEW_COMMIT=$(cat rust-version)
90 # Make sure rustup-toolchain-install-master is installed.
91 if ! which rustup-toolchain-install-master >/dev/null; then
92 echo "Please install rustup-toolchain-install-master by running 'cargo install rustup-toolchain-install-master'"
95 # Check if we already are at that commit.
96 CUR_COMMIT=$(rustc +miri --version -v 2>/dev/null | grep "^commit-hash: " | cut -d " " -f 2)
97 if [[ "$CUR_COMMIT" == "$NEW_COMMIT" ]]; then
98 echo "miri toolchain is already at commit $CUR_COMMIT."
99 rustup override set miri
102 # Install and setup new toolchain.
103 rustup toolchain uninstall miri
104 rustup-toolchain-install-master -n miri -c cargo -c rust-src -c rustc-dev -c llvm-tools -c rustfmt -c clippy "$@" -- "$NEW_COMMIT"
105 rustup override set miri
108 # Call 'cargo metadata' on the sources in case that changes the lockfile
109 # (which fails under some setups when it is done from inside vscode).
110 cargo metadata --format-version 1 --manifest-path "$(rustc --print sysroot)/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml" >/dev/null
117 if [ -z "$FETCH_COMMIT" ]; then
118 FETCH_COMMIT=$(git ls-remote https://github.com/rust-lang/rust/ HEAD | cut -f 1)
120 # Update rust-version file. As a separate commit, since making it part of
121 # the merge has confused the heck out of josh in the past.
122 echo "$FETCH_COMMIT" > rust-version
123 git commit rust-version -m "Preparing for merge from rustc"
124 # Fetch given rustc commit and note down which one that was
125 git fetch http://localhost:8000/rust-lang/rust.git@$FETCH_COMMIT$JOSH_FILTER.git
126 git merge FETCH_HEAD --no-ff -m "Merge from rustc"
132 if [ -z "$USER" ] || [ -z "$BRANCH" ]; then
133 echo "Usage: $0 rustc-push <github user> <branch>"
136 if [ -n "$RUSTC_GIT" ]; then
137 # Use an existing fork for the branch updates.
140 # Do this in the local Miri repo.
141 echo "This will pull a copy of the rust-lang/rust history into this Miri checkout, growing it by about 1GB."
142 read -r -p "To avoid that, abort now and set the RUSTC_GIT environment variable to an existing rustc checkout. Proceed? [y/N] "
143 if [[ ! $REPLY =~ ^[Yy]$ ]]; then
148 # Prepare the branch. Pushing works much better if we use as base exactly
149 # the commit that we pulled from last time, so we use the `rust-version`
150 # file as a good approximation of that.
151 BASE=$(cat "$MIRIDIR/rust-version")
152 echo "Preparing $USER/rust (base: $BASE)..."
153 if git fetch "https://github.com/$USER/rust" "$BRANCH" &>/dev/null; then
154 echo "The branch '$BRANCH' seems to already exist in 'https://github.com/$USER/rust'. Please delete it and try again."
157 git fetch https://github.com/rust-lang/rust $BASE
158 git push https://github.com/$USER/rust $BASE:refs/heads/$BRANCH -f
160 # Do the actual push.
162 echo "Pushing Miri changes..."
163 git push http://localhost:8000/$USER/rust.git$JOSH_FILTER.git HEAD:$BRANCH
164 # Do a round-trip check to make sure the push worked as expected.
166 git fetch http://localhost:8000/$USER/rust.git@$JOSH_FILTER.git $BRANCH &>/dev/null
167 if [[ $(git rev-parse HEAD) != $(git rev-parse FETCH_HEAD) ]]; then
168 echo "ERROR: Josh created a non-roundtrip push! Do NOT merge this into rustc!"
171 echo "Confirmed that the push round-trips back to Miri properly. Please create a rustc PR:"
172 echo " https://github.com/$USER/rust/pull/new/$BRANCH"
177 for SEED in $(seq 0 255); do
178 echo "Trying seed: $SEED"
179 MIRIFLAGS="$MIRIFLAGS -Zlayout-seed=$SEED -Zmiri-seed=$SEED" $@ || { echo "Failing seed: $SEED"; break; }
184 # Make sure we have an up-to-date Miri installed
186 # Run the requested benchmarks
187 if [ -z "${1+exists}" ]; then
188 BENCHES=( $(ls "$MIRIDIR/bench-cargo-miri" ) )
192 for BENCH in "${BENCHES[@]}"; do
193 hyperfine -w 1 -m 5 --shell=none "cargo +$TOOLCHAIN miri run --manifest-path $MIRIDIR/bench-cargo-miri/$BENCH/Cargo.toml"
199 ## Run the auto-things.
200 if [ -z "$MIRI_AUTO_OPS" ]; then
201 export MIRI_AUTO_OPS=42
203 # Run this first, so that the toolchain doesn't change after
204 # other code has run.
205 if [ -f "$MIRIDIR/.auto-everything" ] || [ -f "$MIRIDIR/.auto-toolchain" ] ; then
207 # Let's make sure to actually use that toolchain, too.
211 if [ -f "$MIRIDIR/.auto-everything" ] || [ -f "$MIRIDIR/.auto-fmt" ] ; then
215 if [ -f "$MIRIDIR/.auto-everything" ] || [ -f "$MIRIDIR/.auto-clippy" ] ; then
216 $0 clippy -- -D warnings
220 ## Prepare the environment
221 # Determine some toolchain properties
222 TARGET=$(rustc +$TOOLCHAIN --version --verbose | grep "^host:" | cut -d ' ' -f 2)
223 SYSROOT=$(rustc +$TOOLCHAIN --print sysroot)
224 LIBDIR=$SYSROOT/lib/rustlib/$TARGET/lib
225 if ! test -d "$LIBDIR"; then
226 echo "Something went wrong determining the library dir."
227 echo "I got $LIBDIR but that does not exist."
228 echo "Please report a bug at https://github.com/rust-lang/miri/issues."
232 # Prepare flags for cargo and rustc.
233 CARGO="cargo +$TOOLCHAIN"
234 # Share target dir between `miri` and `cargo-miri`.
235 if [ -z "$CARGO_TARGET_DIR" ]; then
236 export CARGO_TARGET_DIR="$MIRIDIR/target"
238 # We configure dev builds to not be unusably slow.
239 if [ -z "$CARGO_PROFILE_DEV_OPT_LEVEL" ]; then
240 export CARGO_PROFILE_DEV_OPT_LEVEL=2
242 # Enable rustc-specific lints (ignored without `-Zunstable-options`).
243 export RUSTFLAGS="-Zunstable-options -Wrustc::internal $RUSTFLAGS"
244 # We set the rpath so that Miri finds the private rustc libraries it needs.
245 export RUSTFLAGS="-C link-args=-Wl,-rpath,$LIBDIR $RUSTFLAGS"
249 # Build a sysroot and set MIRI_SYSROOT to use it. Arguments are passed to `cargo miri setup`.
251 if ! MIRI_SYSROOT="$($CARGO run $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/cargo-miri/Cargo.toml -- miri setup --print-sysroot "$@")"; then
252 echo "'cargo miri setup' failed"
258 # Prepare and set MIRI_SYSROOT. Respects `MIRI_TEST_TARGET` and takes into account
259 # locally built vs. distributed rustc.
261 if [ -n "$MIRI_SYSROOT" ]; then
262 # Sysroot already set, use that.
265 # We need to build a sysroot.
266 if [ -n "$MIRI_TEST_TARGET" ]; then
267 build_sysroot --target "$MIRI_TEST_TARGET"
278 # "--locked" to respect the Cargo.lock file if it exists.
279 $CARGO install $CARGO_EXTRA_FLAGS --path "$MIRIDIR" --force --locked "$@"
280 $CARGO install $CARGO_EXTRA_FLAGS --path "$MIRIDIR"/cargo-miri --force --locked "$@"
283 # Check, and let caller control flags.
284 $CARGO check $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml --all-targets "$@"
285 $CARGO check $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/cargo-miri/Cargo.toml "$@"
288 # Build, and let caller control flags.
289 $CARGO build $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml "$@"
290 $CARGO build $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/cargo-miri/Cargo.toml "$@"
293 # First build and get a sysroot.
294 $CARGO build $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml
296 if [ "$COMMAND" = "bless" ]; then
297 export MIRI_BLESS="Gesundheit"
299 # Then test, and let caller control flags.
300 # Only in root project as `cargo-miri` has no tests.
301 $CARGO test $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml "$@"
304 # Scan for "--target" to overwrite the "MIRI_TEST_TARGET" env var so
305 # that we set the MIRI_SYSROOT up the right way.
308 if [ "$LAST_ARG" = "--target" ]; then
310 export MIRI_TEST_TARGET="$ARG"
316 if [ "$FOUND_TARGET_OPT" = "0" ] && [ -n "$MIRI_TEST_TARGET" ]; then
317 # Make sure Miri actually uses this target.
318 MIRIFLAGS="$MIRIFLAGS --target $MIRI_TEST_TARGET"
320 # First build and get a sysroot.
321 $CARGO build $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml
323 # Then run the actual command.
324 exec $CARGO run $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml -- $MIRIFLAGS "$@"
327 find "$MIRIDIR" -not \( -name target -prune \) -name '*.rs' \
328 | xargs rustfmt +$TOOLCHAIN --edition=2021 --config-path "$MIRIDIR/rustfmt.toml" "$@"
331 $CARGO clippy $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml --all-targets "$@"
332 $CARGO clippy $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/cargo-miri/Cargo.toml "$@"
335 # We carefully kept the working dir intact, so this will run cargo *on the workspace in the
336 # current working dir*, not on the main Miri workspace. That is exactly what RA needs.
340 echo "Unknown command: $COMMAND"