Skip to content

Commit 93b8c23

Browse files
committed
Merge remote-tracking branch 'origin/master' into cargo-miri-test
2 parents ce5089c + 3a93831 commit 93b8c23

13 files changed

+129
-125
lines changed

.travis.yml

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -12,49 +12,22 @@ os:
1212
dist: xenial
1313

1414
before_script:
15-
# install extra stuff for cross-compilation
15+
# Linux: install extra stuff for cross-compilation
1616
- if [[ "$TRAVIS_OS_NAME" == linux ]]; then sudo apt update && sudo apt install gcc-multilib; fi
17-
# macOS weirdness (https://github.com/travis-ci/travis-ci/issues/6307, https://github.com/travis-ci/travis-ci/issues/10165)
18-
- if [[ "$TRAVIS_OS_NAME" == osx ]]; then rvm get stable; fi
1917
# Compute the rust version we use. We do not use "language: rust" to have more control here.
2018
- |
2119
if [[ "$TRAVIS_EVENT_TYPE" == cron ]]; then
2220
RUST_TOOLCHAIN=nightly
2321
else
2422
RUST_TOOLCHAIN=$(cat rust-version)
2523
fi
26-
- |
27-
if [ "$TRAVIS_OS_NAME" == osx ]; then
28-
export MIRI_SYSROOT_BASE=~/Library/Caches/miri.miri.miri/
29-
else
30-
export MIRI_SYSROOT_BASE=~/.cache/miri/
31-
fi
3224
# install Rust
3325
- curl https://build.travis-ci.org/files/rustup-init.sh -sSf | sh -s -- -y --default-toolchain "$RUST_TOOLCHAIN"
3426
- export PATH=$HOME/.cargo/bin:$PATH
3527
- rustc --version
3628

3729
script:
38-
- set -e
39-
- |
40-
# Build and install miri
41-
cargo build --release --all-features --all-targets &&
42-
cargo install --all-features --force --path .
43-
- |
44-
# Get ourselves a MIR-full libstd for the host and a foreign architecture
45-
cargo miri setup &&
46-
if [[ "$TRAVIS_OS_NAME" == osx ]]; then
47-
cargo miri setup --target i686-apple-darwin
48-
else
49-
cargo miri setup --target i686-unknown-linux-gnu
50-
fi
51-
- |
52-
# Test miri with full MIR, on the host and other architectures
53-
MIRI_SYSROOT=$MIRI_SYSROOT_BASE/HOST cargo test --release --all-features &&
54-
MIRI_SYSROOT=$MIRI_SYSROOT_BASE cargo test --release --all-features
55-
- |
56-
# Test cargo integration
57-
(cd test-cargo-miri && MIRI_SYSROOT=$MIRI_SYSROOT_BASE/HOST ./run-test.py)
30+
- ./travis.sh
5831

5932
notifications:
6033
email:

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ directories = { version = "1.0", optional = true }
3939
rustc_version = { version = "0.2.3", optional = true }
4040
env_logger = "0.5"
4141
log = "0.4"
42+
# A noop dependency that changes in the Rust repository, it's a bit of a hack.
43+
# See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust`
44+
# for more information.
45+
rustc-workspace-hack = "1.0.0"
4246

4347
[build-dependencies]
4448
vergen = "3"

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,9 @@ MIRI_LOG=rustc_mir::interpret=debug,miri::stacked_borrows cargo run tests/run-pa
154154
In addition, you can set `MIRI_BACKTRACE=1` to get a backtrace of where an
155155
evaluation error was originally created.
156156

157-
### Miri `-Z` flags
157+
### Miri `-Z` flags and environment variables
158158

159-
Several `-Z` flags are relevant for miri:
159+
Several `-Z` flags are relevant for Miri:
160160

161161
* `-Zmir-opt-level` controls how many MIR optimizations are performed. miri
162162
overrides the default to be `0`; be advised that using any higher level can
@@ -168,6 +168,14 @@ Several `-Z` flags are relevant for miri:
168168
enforcing the validity invariant, which is enforced by default. This is
169169
mostly useful for debugging; it means miri will miss bugs in your program.
170170

171+
Moreover, Miri recognizes some environment variables:
172+
173+
* `MIRI_SYSROOT` (recognized by `miri`, `cargo miri` and the test suite)
174+
indicates the sysroot to use.
175+
* `MIRI_TARGET` (recognized by the test suite) indicates which target
176+
architecture to test against. `miri` and `cargo miri` accept the `--target`
177+
flag for the same purpose.
178+
171179
## Contributing and getting help
172180

173181
Check out the issues on this GitHub repository for some ideas. There's lots that

rust-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
nightly-2018-12-08
1+
nightly-2018-12-14

src/bin/cargo-miri.rs

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
extern crate cargo_metadata;
44

55
use std::path::{PathBuf, Path};
6-
use std::io::{self, Write};
6+
use std::io::{self, Write, BufRead};
77
use std::process::Command;
88
use std::fs::{self, File};
99

@@ -114,6 +114,36 @@ fn list_targets() -> impl Iterator<Item=cargo_metadata::Target> {
114114
package.targets.into_iter()
115115
}
116116

117+
fn xargo_version() -> Option<(u32, u32, u32)> {
118+
let out = Command::new("xargo").arg("--version").output().ok()?;
119+
if !out.status.success() {
120+
return None;
121+
}
122+
// Parse output. The first line looks like "xargo 0.3.12 (b004f1c 2018-12-13)".
123+
let line = out.stderr.lines().nth(0)
124+
.expect("malformed `xargo --version` output: not at least one line")
125+
.expect("malformed `xargo --version` output: error reading first line");
126+
let version = line.split(' ').nth(1)
127+
.expect("malformed `xargo --version` output: not at least two words");
128+
let mut version_pieces = version.split('.');
129+
let major = version_pieces.next()
130+
.expect("malformed `xargo --version` output: not a major version piece")
131+
.parse()
132+
.expect("malformed `xargo --version` output: major version is not an integer");
133+
let minor = version_pieces.next()
134+
.expect("malformed `xargo --version` output: not a minor version piece")
135+
.parse()
136+
.expect("malformed `xargo --version` output: minor version is not an integer");
137+
let patch = version_pieces.next()
138+
.expect("malformed `xargo --version` output: not a patch version piece")
139+
.parse()
140+
.expect("malformed `xargo --version` output: patch version is not an integer");
141+
if !version_pieces.next().is_none() {
142+
panic!("malformed `xargo --version` output: more than three pieces in version");
143+
}
144+
Some((major, minor, patch))
145+
}
146+
117147
fn ask(question: &str) {
118148
let mut buf = String::new();
119149
print!("{} [Y/n] ", question);
@@ -134,14 +164,15 @@ fn setup(ask_user: bool) {
134164
}
135165

136166
// First, we need xargo
137-
if Command::new("xargo").arg("--version").output().is_err()
138-
{
167+
let xargo = xargo_version();
168+
if xargo.map_or(true, |v| v < (0, 3, 13)) {
139169
if ask_user {
140-
ask("It seems you do not have xargo installed. I will run `cargo install xargo`. Proceed?");
170+
ask("It seems you do not have a recent enough xargo installed. I will run `cargo install xargo -f`. Proceed?");
141171
} else {
142-
println!("Installing xargo: `cargo install xargo`");
172+
println!("Installing xargo: `cargo install xargo -f`");
143173
}
144-
if !Command::new("cargo").args(&["install", "xargo"]).status().unwrap().success() {
174+
// FIXME: Go back to using releases, once a 0.3.13 got released.
175+
if !Command::new("cargo").args(&["install", "xargo", "-f", "--git", "https://github.com/japaric/xargo"]).status().unwrap().success() {
145176
show_error(format!("Failed to install xargo"));
146177
}
147178
}
@@ -304,8 +335,8 @@ fn main() {
304335
_ => {}
305336
}
306337
}
307-
} else {
308-
// This arm is executed when cargo-miri runs `cargo rustc` with the `RUSTC` env var set to itself:
338+
} else if let Some("rustc") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) {
339+
// This arm is executed when cargo-miri runs `cargo rustc` with the `RUSTC_WRAPPER` env var set to itself:
309340
// Dependencies get dispatched to rustc, the final test/binary to miri.
310341

311342
let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
@@ -331,11 +362,11 @@ fn main() {
331362

332363
// this conditional check for the --sysroot flag is there so users can call `cargo-miri` directly
333364
// without having to pass --sysroot or anything
365+
let rustc_args = std::env::args().skip(2);
334366
let mut args: Vec<String> = if std::env::args().any(|s| s == "--sysroot") {
335-
std::env::args().skip(1).collect()
367+
rustc_args.collect()
336368
} else {
337-
std::env::args()
338-
.skip(1)
369+
rustc_args
339370
.chain(Some("--sysroot".to_owned()))
340371
.chain(Some(sys_root))
341372
.collect()
@@ -364,6 +395,8 @@ fn main() {
364395
Err(ref e) if miri_enabled => panic!("error during miri run: {:?}", e),
365396
Err(ref e) => panic!("error during rustc call: {:?}", e),
366397
}
398+
} else {
399+
show_error(format!("Must be called with either `miri` or `rustc` as first argument."))
367400
}
368401
}
369402

@@ -388,7 +421,7 @@ where
388421
let path = std::env::current_exe().expect("current executable path invalid");
389422
let exit_status = Command::new("cargo")
390423
.args(&args)
391-
.env("RUSTC", path)
424+
.env("RUSTC_WRAPPER", path)
392425
.spawn()
393426
.expect("could not run cargo")
394427
.wait()

tests/compiletest.rs

Lines changed: 25 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#![test_runner(test_runner)]
44

55
use std::slice::SliceConcatExt;
6-
use std::path::{PathBuf, Path};
6+
use std::path::PathBuf;
77
use std::env;
88

99
use compiletest_rs as compiletest;
@@ -34,10 +34,11 @@ fn mk_config(mode: &str) -> compiletest::common::ConfigWithTemp {
3434
config.compile_lib_path = rustc_lib_path();
3535
}
3636
config.filter = env::args().nth(1);
37+
config.host = get_host();
3738
config
3839
}
3940

40-
fn compile_fail(sysroot: &Path, path: &str, target: &str, host: &str, opt: bool) {
41+
fn compile_fail(path: &str, target: &str, opt: bool) {
4142
let opt_str = if opt { " with optimizations" } else { "" };
4243
eprintln!("{}", format!(
4344
"## Running compile-fail tests in {} against miri for target {}{}",
@@ -47,7 +48,6 @@ fn compile_fail(sysroot: &Path, path: &str, target: &str, host: &str, opt: bool)
4748
).green().bold());
4849

4950
let mut flags = Vec::new();
50-
flags.push(format!("--sysroot {}", sysroot.display()));
5151
flags.push("-Dwarnings -Dunused".to_owned()); // overwrite the -Aunused in compiletest-rs
5252
flags.push("--edition 2018".to_owned());
5353
if opt {
@@ -60,12 +60,11 @@ fn compile_fail(sysroot: &Path, path: &str, target: &str, host: &str, opt: bool)
6060
let mut config = mk_config("compile-fail");
6161
config.src_base = PathBuf::from(path);
6262
config.target = target.to_owned();
63-
config.host = host.to_owned();
6463
config.target_rustcflags = Some(flags.join(" "));
6564
compiletest::run_tests(&config);
6665
}
6766

68-
fn miri_pass(sysroot: &Path, path: &str, target: &str, host: &str, opt: bool) {
67+
fn miri_pass(path: &str, target: &str, opt: bool) {
6968
let opt_str = if opt { " with optimizations" } else { "" };
7069
eprintln!("{}", format!(
7170
"## Running run-pass tests in {} against miri for target {}{}",
@@ -75,69 +74,33 @@ fn miri_pass(sysroot: &Path, path: &str, target: &str, host: &str, opt: bool) {
7574
).green().bold());
7675

7776
let mut flags = Vec::new();
78-
flags.push(format!("--sysroot {}", sysroot.display()));
7977
flags.push("-Dwarnings -Dunused".to_owned()); // overwrite the -Aunused in compiletest-rs
8078
flags.push("--edition 2018".to_owned());
8179
if opt {
82-
// FIXME: We use opt level 1 because MIR inlining defeats the validation
83-
// whitelist.
84-
flags.push("-Zmir-opt-level=1".to_owned());
80+
flags.push("-Zmir-opt-level=3".to_owned());
8581
}
8682

8783
let mut config = mk_config("ui");
8884
config.src_base = PathBuf::from(path);
8985
config.target = target.to_owned();
90-
config.host = host.to_owned();
9186
config.target_rustcflags = Some(flags.join(" "));
9287
compiletest::run_tests(&config);
9388
}
9489

95-
fn is_target_dir<P: Into<PathBuf>>(path: P) -> bool {
96-
let mut path = path.into();
97-
path.push("lib");
98-
path.metadata().map(|m| m.is_dir()).unwrap_or(false)
99-
}
100-
101-
fn target_has_std<P: Into<PathBuf>>(path: P) -> bool {
102-
let mut path = path.into();
103-
path.push("lib");
104-
std::fs::read_dir(path)
105-
.expect("invalid target")
106-
.map(|entry| entry.unwrap())
107-
.filter(|entry| entry.file_type().unwrap().is_file())
108-
.filter_map(|entry| entry.file_name().into_string().ok())
109-
.any(|file_name| file_name == "libstd.rlib")
110-
}
111-
112-
113-
fn for_all_targets<F: FnMut(String)>(sysroot: &Path, f: F) {
114-
let target_dir = sysroot.join("lib").join("rustlib");
115-
let mut targets = std::fs::read_dir(target_dir)
116-
.expect("invalid sysroot")
117-
.map(|entry| entry.unwrap())
118-
.filter(|entry| is_target_dir(entry.path()))
119-
.filter(|entry| target_has_std(entry.path()))
120-
.map(|entry| entry.file_name().into_string().unwrap())
121-
.peekable();
122-
123-
if targets.peek().is_none() {
124-
panic!("No valid targets found");
90+
/// Make sure the MIRI_SYSROOT env var is set
91+
fn set_sysroot() {
92+
if std::env::var("MIRI_SYSROOT").is_ok() {
93+
// Nothing to do
94+
return;
12595
}
126-
127-
targets.for_each(f);
128-
}
129-
130-
fn get_sysroot() -> PathBuf {
131-
let sysroot = std::env::var("MIRI_SYSROOT").unwrap_or_else(|_| {
132-
let sysroot = std::process::Command::new("rustc")
133-
.arg("--print")
134-
.arg("sysroot")
135-
.output()
136-
.expect("rustc not found")
137-
.stdout;
138-
String::from_utf8(sysroot).expect("sysroot is not utf8")
139-
});
140-
PathBuf::from(sysroot.trim())
96+
let sysroot = std::process::Command::new("rustc")
97+
.arg("--print")
98+
.arg("sysroot")
99+
.output()
100+
.expect("rustc not found")
101+
.stdout;
102+
let sysroot = String::from_utf8(sysroot).expect("sysroot is not utf8");
103+
std::env::set_var("MIRI_SYSROOT", sysroot.trim());
141104
}
142105

143106
fn get_host() -> String {
@@ -153,28 +116,20 @@ fn get_host() -> String {
153116
version_meta.host
154117
}
155118

156-
fn run_pass_miri(opt: bool) {
157-
let sysroot = get_sysroot();
158-
let host = get_host();
119+
fn get_target() -> String {
120+
std::env::var("MIRI_TARGET").unwrap_or_else(|_| get_host())
121+
}
159122

160-
for_all_targets(&sysroot, |target| {
161-
miri_pass(&sysroot, "tests/run-pass", &target, &host, opt);
162-
});
123+
fn run_pass_miri(opt: bool) {
124+
miri_pass("tests/run-pass", &get_target(), opt);
163125
}
164126

165127
fn compile_fail_miri(opt: bool) {
166-
let sysroot = get_sysroot();
167-
let host = get_host();
168-
169-
for_all_targets(&sysroot, |target| {
170-
compile_fail(&sysroot, "tests/compile-fail", &target, &host, opt);
171-
});
128+
compile_fail("tests/compile-fail", &get_target(), opt);
172129
}
173130

174131
fn test_runner(_tests: &[&()]) {
175-
// We put everything into a single test to avoid the parallelism `cargo test`
176-
// introduces. We still get parallelism within our tests because `compiletest`
177-
// uses `libtest` which runs jobs in parallel.
132+
set_sysroot();
178133

179134
run_pass_miri(false);
180135
run_pass_miri(true);

tests/run-pass/foreign-fn-linkname.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
//ignore-windows: Uses POSIX APIs
1212

13-
#![feature(libc)]
13+
#![feature(rustc_private)]
1414
#![allow(unused_extern_crates)] // rustc bug https://github.com/rust-lang/rust/issues/56098
1515

1616
extern crate libc;

0 commit comments

Comments
 (0)