#!/bin/sh 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 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 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 # 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" ## 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 --bin cargo-miri -- miri setup "$@" # Call again, to just set env var. eval $(cargo run $CARGO_BUILD_FLAGS -q --bin cargo-miri -- miri setup --env "$@") } # Prepare and set MIRI_SYSROOT. Respects `MIRI_TEST_TARGET` and takes into account # locally built vs. distributed rustc. find_sysroot() { # Get ourselves a sysroot if [ -n "$MIRI_SYSROOT" ]; then # Sysroot already set, use that. true elif echo "$SYSROOT" | egrep -q 'build/[^/]+/stage'; then # A local rustc build. if [ -n "$MIRI_TEST_TARGET" ]; then # Foreign targets still need a build. Use the rustc sources. export XARGO_RUST_SRC="$SYSROOT/../../../src" build_sysroot --target "$MIRI_TEST_TARGET" else # Assume we have a proper host libstd in $SYSROOT. MIRI_SYSROOT="$SYSROOT" fi else # A normal toolchain. We have to build a sysroot either way. if [ -n "$MIRI_TEST_TARGET" ]; then build_sysroot --target "$MIRI_TEST_TARGET" else build_sysroot fi fi export MIRI_SYSROOT } ## Main # Determine command. COMMAND="$1" 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="--debug $CARGO_EXTRA_FLAGS" CARGO_BUILD_FLAGS="$CARGO_EXTRA_FLAGS" ;; *) CARGO_INSTALL_FLAGS="$CARGO_EXTRA_FLAGS" CARGO_BUILD_FLAGS="--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). exec cargo install $CARGO_INSTALL_FLAGS --path "$(dirname "$0")" --force --locked --offline "$@" ;; build|build-debug) # Build, and let caller control flags. exec cargo build $CARGO_BUILD_FLAGS "$@" ;; test|test-debug) # First build and get a sysroot. cargo build $CARGO_BUILD_FLAGS find_sysroot # Then test, and let caller control flags. 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" "$@" ;; *) echo "Unknown command: $COMMAND" echo echo "$USAGE" exit 1 esac