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`.
52 Pull and merge Miri changes from the rustc repo. The fetched commit is stored in
53 the `rust-version` file, so the next `./miri toolchain` will install the rustc
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
116 FETCH_COMMIT=$(git ls-remote https://github.com/rust-lang/rust/ HEAD | cut -f 1)
117 # We can't pull from a commit with josh
118 # (https://github.com/josh-project/josh/issues/1034), so we just hope that
119 # nothing gets merged into rustc *during* this pull.
120 git fetch http://localhost:8000/rust-lang/rust.git$JOSH_FILTER.git master
121 # Just verify that `master` didn't move.
122 if [[ $FETCH_COMMIT != $(git ls-remote https://github.com/rust-lang/rust/ HEAD | cut -f 1) ]]; then
123 echo "Looks like something got merged into Rust *while we were pulling*. Aborting. Please try again."
125 echo "$FETCH_COMMIT" > rust-version # do this *before* merging as merging will fail in case of conflicts
126 git merge FETCH_HEAD --no-ff -m "Merge from rustc"
127 git commit rust-version --amend -m "Merge from rustc"
133 if [ -z "$USER" ] || [ -z "$BRANCH" ]; then
134 echo "Usage: $0 rustc-push <github user> <branch>"
137 if [ -n "$RUSTC_GIT" ]; then
138 # Use an existing fork for the branch updates.
141 # Do this in the local Miri repo.
142 echo "This will pull a copy of the rust-lang/rust history into this Miri checkout, growing it by about 1GB."
143 read -r -p "To avoid that, abort now and set the RUSTC_GIT environment variable to an existing rustc checkout. Proceed? [y/N] "
144 if [[ ! $REPLY =~ ^[Yy]$ ]]; then
149 # Prepare the branch. Pushing works much better if we use as base exactly
150 # the commit that we pulled from last time, so we use the `rust-version`
151 # file as a good approximation of that.
152 BASE=$(cat "$MIRIDIR/rust-version")
153 echo "Preparing $USER/rust (base: $BASE)..."
154 if git fetch "https://github.com/$USER/rust" "$BRANCH" &>/dev/null; then
155 echo "The branch '$BRANCH' seems to already exist in 'https://github.com/$USER/rust'. Please delete it and try again."
158 git fetch https://github.com/rust-lang/rust $BASE
159 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
167 for SEED in $({ echo obase=16; seq 0 255; } | bc); do
168 echo "Trying seed: $SEED"
169 MIRIFLAGS="$MIRIFLAGS -Zmiri-seed=$SEED" $@ || { echo "Failing seed: $SEED"; break; }
174 # Make sure we have an up-to-date Miri installed
176 # Run the requested benchmarks
177 if [ -z "${1+exists}" ]; then
178 BENCHES=( $(ls "$MIRIDIR/bench-cargo-miri" ) )
182 for BENCH in "${BENCHES[@]}"; do
183 hyperfine -w 1 -m 5 --shell=none "cargo +$TOOLCHAIN miri run --manifest-path $MIRIDIR/bench-cargo-miri/$BENCH/Cargo.toml"
189 ## Run the auto-things.
190 if [ -z "$MIRI_AUTO_OPS" ]; then
191 export MIRI_AUTO_OPS=42
193 # Run this first, so that the toolchain doesn't change after
194 # other code has run.
195 if [ -f "$MIRIDIR/.auto-everything" ] || [ -f "$MIRIDIR/.auto-toolchain" ] ; then
197 # Let's make sure to actually use that toolchain, too.
201 if [ -f "$MIRIDIR/.auto-everything" ] || [ -f "$MIRIDIR/.auto-fmt" ] ; then
205 if [ -f "$MIRIDIR/.auto-everything" ] || [ -f "$MIRIDIR/.auto-clippy" ] ; then
206 $0 clippy -- -D warnings
210 ## Prepare the environment
211 # Determine some toolchain properties
212 TARGET=$(rustc +$TOOLCHAIN --version --verbose | grep "^host:" | cut -d ' ' -f 2)
213 SYSROOT=$(rustc +$TOOLCHAIN --print sysroot)
214 LIBDIR=$SYSROOT/lib/rustlib/$TARGET/lib
215 if ! test -d "$LIBDIR"; then
216 echo "Something went wrong determining the library dir."
217 echo "I got $LIBDIR but that does not exist."
218 echo "Please report a bug at https://github.com/rust-lang/miri/issues."
222 # Prepare flags for cargo and rustc.
223 CARGO="cargo +$TOOLCHAIN"
224 # Share target dir between `miri` and `cargo-miri`.
225 if [ -z "$CARGO_TARGET_DIR" ]; then
226 export CARGO_TARGET_DIR="$MIRIDIR/target"
228 # We configure dev builds to not be unusably slow.
229 if [ -z "$CARGO_PROFILE_DEV_OPT_LEVEL" ]; then
230 export CARGO_PROFILE_DEV_OPT_LEVEL=2
232 # Enable rustc-specific lints (ignored without `-Zunstable-options`).
233 export RUSTFLAGS="-Zunstable-options -Wrustc::internal $RUSTFLAGS"
234 # We set the rpath so that Miri finds the private rustc libraries it needs.
235 export RUSTFLAGS="-C link-args=-Wl,-rpath,$LIBDIR $RUSTFLAGS"
239 # Build a sysroot and set MIRI_SYSROOT to use it. Arguments are passed to `cargo miri setup`.
241 if ! MIRI_SYSROOT="$($CARGO run $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/cargo-miri/Cargo.toml -- miri setup --print-sysroot "$@")"; then
242 echo "'cargo miri setup' failed"
248 # Prepare and set MIRI_SYSROOT. Respects `MIRI_TEST_TARGET` and takes into account
249 # locally built vs. distributed rustc.
251 if [ -n "$MIRI_SYSROOT" ]; then
252 # Sysroot already set, use that.
255 # We need to build a sysroot.
256 if [ -n "$MIRI_TEST_TARGET" ]; then
257 build_sysroot --target "$MIRI_TEST_TARGET"
268 # "--locked" to respect the Cargo.lock file if it exists.
269 $CARGO install $CARGO_EXTRA_FLAGS --path "$MIRIDIR" --force --locked "$@"
270 $CARGO install $CARGO_EXTRA_FLAGS --path "$MIRIDIR"/cargo-miri --force --locked "$@"
273 # Check, and let caller control flags.
274 $CARGO check $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml --all-targets "$@"
275 $CARGO check $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/cargo-miri/Cargo.toml "$@"
278 # Build, and let caller control flags.
279 $CARGO build $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml "$@"
280 $CARGO build $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/cargo-miri/Cargo.toml "$@"
283 # First build and get a sysroot.
284 $CARGO build $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml
286 if [ "$COMMAND" = "bless" ]; then
287 export MIRI_BLESS="Gesundheit"
289 # Then test, and let caller control flags.
290 # Only in root project as `cargo-miri` has no tests.
291 $CARGO test $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml "$@"
294 # Scan for "--target" to overwrite the "MIRI_TEST_TARGET" env var so
295 # that we set the MIRI_SYSROOT up the right way.
298 if [ "$LAST_ARG" = "--target" ]; then
300 export MIRI_TEST_TARGET="$ARG"
306 if [ "$FOUND_TARGET_OPT" = "0" ] && [ -n "$MIRI_TEST_TARGET" ]; then
307 # Make sure Miri actually uses this target.
308 MIRIFLAGS="$MIRIFLAGS --target $MIRI_TEST_TARGET"
310 # First build and get a sysroot.
311 $CARGO build $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml
313 # Then run the actual command.
314 exec $CARGO run $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml -- $MIRIFLAGS "$@"
317 find "$MIRIDIR" -not \( -name target -prune \) -name '*.rs' \
318 | xargs rustfmt +$TOOLCHAIN --edition=2021 --config-path "$MIRIDIR/rustfmt.toml" "$@"
321 $CARGO clippy $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml --all-targets "$@"
322 $CARGO clippy $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/cargo-miri/Cargo.toml "$@"
325 # We carefully kept the working dir intact, so this will run cargo *on the workspace in the
326 # current working dir*, not on the main Miri workspace. That is exactly what RA needs.
330 echo "Unknown command: $COMMAND"