diff --git a/README.md b/README.md index 09b23b0db12f..130072825e1c 100644 --- a/README.md +++ b/README.md @@ -141,14 +141,16 @@ version of `rustc` that, instead of compiling your code, runs it. It accepts all the same flags as `rustc` (though the ones only affecting code generation and linking obviously will have no effect) [and more][miri-flags]. -Running the Miri driver requires some fiddling with environment variables, so the `miri` script helps you do that. -For example, you can run the driver on a particular file by doing +Running the Miri driver requires some fiddling with environment variables, so +the `miri` script helps you do that. For example, you can run the driver on a +particular file by doing ```sh -./miri run tests/run-pass/format.rs # or whatever test you like +./miri run tests/run-pass/format.rs +./miri run tests/run-pass/hello.rs --target i686-unknown-linux-gnu ``` -and you can run the test suite using +and you can run the test suite using: ``` ./miri test diff --git a/miri b/miri index 99ae7c5811ee..1d090c8827fd 100755 --- a/miri +++ b/miri @@ -7,33 +7,76 @@ SYSROOT=$(rustc --print sysroot) # We enable line-only debuginfo for backtraces. export RUSTFLAGS="-C link-args=-Wl,-rpath,$SYSROOT/lib/rustlib/$TARGET/lib -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 --release --bin cargo-miri -- miri setup "$@" + # Call again, to just set env var. + eval $(cargo run --release -q --bin cargo-miri -- miri setup --env "$@") + export MIRI_SYSROOT +} + +# 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. + true + fi + else + # 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 +} + +## Main + COMMAND="$1" shift case "$COMMAND" in install) - exec cargo install --path "$(dirname "$0")" --force --locked --offline + # "--locked" to respect the Cargo.lock file if it exists, + # "--offline" to avoid querying the registry (for yanked packages). + exec cargo "$COMMAND" --path "$(dirname "$0")" --force --locked --offline "$@" ;; -build|test|run) - # Basic build - cargo build --release - - # We we want to just build, we are done. - if [ "$COMMAND" = "build" ]; then exit 0; fi - - # Get ourselves a sysroot - if [ -n "$MIRI_SYSROOT" ]; then - # sysroot already set - true - elif echo "$SYSROOT" | egrep -q 'build/[^/]+/stage'; then - # a local rustc build, assume we have a proper libstd in $SYSROOT - true - else - # we have to build a sysroot - cargo run --release --bin cargo-miri -- miri setup - export MIRI_SYSROOT=$HOME/.cache/miri/HOST +build) + # Build, and let caller control flags. + exec cargo "$COMMAND" --release "$@" + ;; +test|run) + # In "run" mode, scan for "--target" to set the "MIRI_TEST_TARGET" env var so + # that we set the MIRI_SYSROOT up the right way. + if [ "$COMMAND" = "run" ] && [ -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 --release + find_sysroot + # Then run the actual command. exec cargo "$COMMAND" --release "$@" ;; esac diff --git a/src/bin/cargo-miri.rs b/src/bin/cargo-miri.rs index 5dc7a75fc764..55c53e7361a5 100644 --- a/src/bin/cargo-miri.rs +++ b/src/bin/cargo-miri.rs @@ -243,6 +243,7 @@ path = "lib.rs" File::create(dir.join("lib.rs")).unwrap(); // Run xargo. let target = get_arg_flag_value("--target"); + let print_env = !ask_user && has_arg_flag("--env"); // whether we just print the necessary environment variable let mut command = Command::new("xargo"); command.arg("build").arg("-q") .current_dir(&dir) @@ -265,7 +266,9 @@ path = "lib.rs" }; let sysroot = if is_host { dir.join("HOST") } else { PathBuf::from(dir) }; std::env::set_var("MIRI_SYSROOT", &sysroot); - if !ask_user { + if print_env { + println!("MIRI_SYSROOT={}", sysroot.display()); + } else if !ask_user { println!("A libstd for Miri is now available in `{}`", sysroot.display()); } } diff --git a/travis.sh b/travis.sh index 84f9c408dcba..dc98ca44ae58 100755 --- a/travis.sh +++ b/travis.sh @@ -3,36 +3,27 @@ set -euo pipefail # Determine configuration if [ "$TRAVIS_OS_NAME" == osx ]; then - MIRI_SYSROOT_BASE=~/Library/Caches/miri.miri.miri/ FOREIGN_TARGET=i686-apple-darwin else - MIRI_SYSROOT_BASE=~/.cache/miri/ FOREIGN_TARGET=i686-unknown-linux-gnu fi # Prepare echo "Build and install miri" -cargo build --release --all-features --all-targets -cargo install --all-features --force --path . -echo - -echo "Get ourselves a MIR-full libstd for the host and a foreign architecture" -cargo miri setup -cargo miri setup --target "$FOREIGN_TARGET" +./miri build --all-features --all-targets +./miri install echo # Test function run_tests { - cargo test --release --all-features - test-cargo-miri/run-test.py + ./miri test + test-cargo-miri/run-test.py } echo "Test host architecture" -export MIRI_SYSROOT="$MIRI_SYSROOT_BASE"/HOST run_tests echo echo "Test foreign architecture ($FOREIGN_TARGET)" -export MIRI_SYSROOT="$MIRI_SYSROOT_BASE" MIRI_TEST_TARGET="$FOREIGN_TARGET" -run_tests +MIRI_TEST_TARGET="$FOREIGN_TARGET" run_tests echo