#!/bin/bash set -e USAGE=$(cat <<"EOF" COMMANDS ./miri install : Installs the miri driver and cargo-miri. are passed to `cargo install`. Sets up the rpath such that the installed binary should work in any working directory. ./miri build : Just build miri. are passed to `cargo build`. ./miri check : Just check miri. are passed to `cargo check`. ./miri test : Build miri, set up a sysroot and then run the test suite. are passed to the final `cargo test` invocation. ./miri run : Build miri, set up a sysroot and then run the driver with the given . All commands also exist in a "-debug" variant (e.g. "./miri run-debug ") which uses debug builds instead of release builds, for faster build times and slower execution times. ENVIRONMENT VARIABLES MIRI_SYSROOT: If already set, the "sysroot setup" step is skipped. CARGO_EXTRA_FLAGS: Pass extra flags to all cargo invocations. EOF ) ## Preparation TARGET=$(rustc --version --verbose | grep "^host:" | cut -d ' ' -f 2) SYSROOT=$(rustc --print sysroot) LIBDIR=$SYSROOT/lib/rustlib/$TARGET/lib MIRIDIR=$(dirname "$0") if readlink -e . &>/dev/null; then # This platform supports `readlink -e`. MIRIDIR=$(readlink -e "$MIRIDIR") fi if ! test -d "$LIBDIR"; then echo "Something went wrong determining the library dir." echo "I got $LIBDIR but that does not exist." echo "Please report a bug at https://github.com/rust-lang/miri/issues." exit 2 fi if [ -z "$CARGO_INCREMENTAL" ]; then # Default CARGO_INCREMENTAL to 1. export CARGO_INCREMENTAL=1 fi if [ -z "$CARGO_TARGET_DIR" ]; then # Share target dir between `miri` and `cargo-miri`. export CARGO_TARGET_DIR="$MIRIDIR/target" fi # We set the rpath so that Miri finds the private rustc libraries it needs. # We enable debug-assertions to get tracing. # We enable line-only debuginfo for backtraces. export RUSTFLAGS="-C link-args=-Wl,-rpath,$LIBDIR -C debug-assertions -C debuginfo=1 $RUSTFLAGS" ## Helper functions # Build a sysroot and set MIRI_SYSROOT to use it. Arguments are passed to `cargo miri setup`. build_sysroot() { # Build once, for the user to see. cargo run $CARGO_BUILD_FLAGS --manifest-path "$MIRIDIR"/cargo-miri/Cargo.toml -- miri setup "$@" # Call again, to just set env var. export MIRI_SYSROOT="$(cargo run $CARGO_BUILD_FLAGS --manifest-path "$MIRIDIR"/cargo-miri/Cargo.toml -q -- miri setup --print-sysroot "$@")" } # Prepare and set MIRI_SYSROOT. Respects `MIRI_TEST_TARGET` and takes into account # locally built vs. distributed rustc. find_sysroot() { if [ -n "$MIRI_SYSROOT" ]; then # Sysroot already set, use that. return 0 fi # We need to build a sysroot. if [ -n "$MIRI_TEST_TARGET" ]; then build_sysroot --target "$MIRI_TEST_TARGET" else build_sysroot fi } ## Main # Determine command. COMMAND="$1" [ $# -gt 0 ] && shift # Determine flags passed to all cargo invocations. # This is a bit more annoying that one would hope due to # . case "$COMMAND" in *-debug) CARGO_INSTALL_FLAGS="--target $TARGET --debug $CARGO_EXTRA_FLAGS" CARGO_BUILD_FLAGS="--target $TARGET $CARGO_EXTRA_FLAGS" ;; *) CARGO_INSTALL_FLAGS="--target $TARGET $CARGO_EXTRA_FLAGS" CARGO_BUILD_FLAGS="--target $TARGET --release $CARGO_EXTRA_FLAGS" ;; esac # Run command. case "$COMMAND" in install|install-debug) # "--locked" to respect the Cargo.lock file if it exists, # "--offline" to avoid querying the registry (for yanked packages). cargo install $CARGO_INSTALL_FLAGS --path "$MIRIDIR" --force --locked --offline "$@" cargo install $CARGO_INSTALL_FLAGS --path "$MIRIDIR"/cargo-miri --force --locked --offline "$@" ;; check|check-debug) # Check, and let caller control flags. cargo check $CARGO_BUILD_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml "$@" cargo check $CARGO_BUILD_FLAGS --manifest-path "$MIRIDIR"/cargo-miri/Cargo.toml "$@" ;; build|build-debug) # Build, and let caller control flags. cargo build $CARGO_BUILD_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml "$@" cargo build $CARGO_BUILD_FLAGS --manifest-path "$MIRIDIR"/cargo-miri/Cargo.toml "$@" ;; test|test-debug) # First build and get a sysroot. cargo build $CARGO_BUILD_FLAGS find_sysroot # Then test, and let caller control flags. # Only in root project as `cargo-miri` has no tests. exec cargo test $CARGO_BUILD_FLAGS "$@" ;; run|run-debug) # Scan for "--target" to set the "MIRI_TEST_TARGET" env var so # that we set the MIRI_SYSROOT up the right way. if [ -z "$MIRI_TEST_TARGET" ]; then for ARG in "$@"; do if [ "$LAST_ARG" = "--target" ]; then # Found it! export MIRI_TEST_TARGET="$ARG" break fi LAST_ARG="$ARG" done fi # First build and get a sysroot. cargo build $CARGO_BUILD_FLAGS find_sysroot # Then run the actual command. exec cargo run $CARGO_BUILD_FLAGS -- --sysroot "$MIRI_SYSROOT" "$@" ;; *) if [ -n "$COMMAND" ]; then echo "Unknown command: $COMMAND" echo fi echo "$USAGE" exit 1 esac