make miri script smarter: auto-determine MIRI_SYSROOT, handle MIRI_TEST_TARGET

This commit is contained in:
Ralf Jung 2019-05-27 14:40:27 +02:00
parent eb85ced8c7
commit cf96396fcc
4 changed files with 78 additions and 39 deletions

View File

@ -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

83
miri
View File

@ -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

View File

@ -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());
}
}

View File

@ -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