Auto merge of #43628 - oli-obk:orbital_standard_library, r=alexcrichton

Run the miri test suite on the aux builder and travis

Reopen of #38350

see https://github.com/rust-lang/rust/pull/43340#issuecomment-316940762 for earlier discussion

Rationale for running miri's test suite in rustc's CI is that miri currently contains many features that we want in const eval in the future, and these features would break if the test suite is not run.

fixes #44077

r? @nikomatsakis

cc @eddyb
This commit is contained in:
bors 2017-09-18 01:50:29 +00:00
commit caad2560bf
20 changed files with 336 additions and 47 deletions

3
.gitmodules vendored
View File

@ -39,3 +39,6 @@
[submodule "src/tools/rustfmt"] [submodule "src/tools/rustfmt"]
path = src/tools/rustfmt path = src/tools/rustfmt
url = https://github.com/rust-lang-nursery/rustfmt.git url = https://github.com/rust-lang-nursery/rustfmt.git
[submodule "src/tools/miri"]
path = src/tools/miri
url = https://github.com/solson/miri.git

View File

@ -291,6 +291,10 @@
# When creating source tarballs whether or not to create a source tarball. # When creating source tarballs whether or not to create a source tarball.
#dist-src = false #dist-src = false
# Whether to also run the Miri tests suite when running tests.
# As a side-effect also generates MIR for all libraries.
#test-miri = false
# ============================================================================= # =============================================================================
# Options for specific targets # Options for specific targets
# #

View File

@ -246,6 +246,12 @@ fn main() {
} }
} }
// When running miri tests, we need to generate MIR for all libraries
if env::var("TEST_MIRI").ok().map_or(false, |val| val == "true") {
cmd.arg("-Zalways-encode-mir");
cmd.arg("-Zmir-emit-validate=1");
}
// Force all crates compiled by this compiler to (a) be unstable and (b) // Force all crates compiled by this compiler to (a) be unstable and (b)
// allow the `rustc_private` feature to link to other unstable crates // allow the `rustc_private` feature to link to other unstable crates
// also in the sysroot. // also in the sysroot.

View File

@ -250,18 +250,18 @@ impl<'a> Builder<'a> {
tool::UnstableBookGen, tool::Tidy, tool::Linkchecker, tool::CargoTest, tool::UnstableBookGen, tool::Tidy, tool::Linkchecker, tool::CargoTest,
tool::Compiletest, tool::RemoteTestServer, tool::RemoteTestClient, tool::Compiletest, tool::RemoteTestServer, tool::RemoteTestClient,
tool::RustInstaller, tool::Cargo, tool::Rls, tool::Rustdoc, tool::Clippy, tool::RustInstaller, tool::Cargo, tool::Rls, tool::Rustdoc, tool::Clippy,
native::Llvm, tool::Rustfmt), native::Llvm, tool::Rustfmt, tool::Miri),
Kind::Test => describe!(check::Tidy, check::Bootstrap, check::DefaultCompiletest, Kind::Test => describe!(check::Tidy, check::Bootstrap, check::DefaultCompiletest,
check::HostCompiletest, check::Crate, check::CrateLibrustc, check::Rustdoc, check::HostCompiletest, check::Crate, check::CrateLibrustc, check::Rustdoc,
check::Linkcheck, check::Cargotest, check::Cargo, check::Rls, check::Docs, check::Linkcheck, check::Cargotest, check::Cargo, check::Rls, check::Docs,
check::ErrorIndex, check::Distcheck, check::Rustfmt), check::ErrorIndex, check::Distcheck, check::Rustfmt, check::Miri),
Kind::Bench => describe!(check::Crate, check::CrateLibrustc), Kind::Bench => describe!(check::Crate, check::CrateLibrustc),
Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook, Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook,
doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon, doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon,
doc::Reference, doc::Rustdoc, doc::CargoBook), doc::Reference, doc::Rustdoc, doc::CargoBook),
Kind::Dist => describe!(dist::Docs, dist::Mingw, dist::Rustc, dist::DebuggerScripts, Kind::Dist => describe!(dist::Docs, dist::Mingw, dist::Rustc, dist::DebuggerScripts,
dist::Std, dist::Analysis, dist::Src, dist::PlainSourceTarball, dist::Cargo, dist::Std, dist::Analysis, dist::Src, dist::PlainSourceTarball, dist::Cargo,
dist::Rls, dist::Extended, dist::HashSign), dist::Rls, dist::Extended, dist::HashSign, dist::DontDistWithMiriEnabled),
Kind::Install => describe!(install::Docs, install::Std, install::Cargo, install::Rls, Kind::Install => describe!(install::Docs, install::Std, install::Cargo, install::Rls,
install::Analysis, install::Src, install::Rustc), install::Analysis, install::Src, install::Rustc),
} }
@ -481,6 +481,7 @@ impl<'a> Builder<'a> {
} else { } else {
PathBuf::from("/path/to/nowhere/rustdoc/not/required") PathBuf::from("/path/to/nowhere/rustdoc/not/required")
}) })
.env("TEST_MIRI", self.config.test_miri.to_string())
.env("RUSTC_FLAGS", self.rustc_flags(target).join(" ")); .env("RUSTC_FLAGS", self.rustc_flags(target).join(" "));
if mode != Mode::Tool { if mode != Mode::Tool {

View File

@ -23,7 +23,7 @@ use std::path::{PathBuf, Path};
use std::process::Command; use std::process::Command;
use std::io::Read; use std::io::Read;
use build_helper::{self, output}; use build_helper::{self, output, BuildExpectation};
use builder::{Kind, RunConfig, ShouldRun, Builder, Compiler, Step}; use builder::{Kind, RunConfig, ShouldRun, Builder, Compiler, Step};
use cache::{INTERNER, Interned}; use cache::{INTERNER, Interned};
@ -33,6 +33,7 @@ use native;
use tool::{self, Tool}; use tool::{self, Tool};
use util::{self, dylib_path, dylib_path_var}; use util::{self, dylib_path, dylib_path_var};
use {Build, Mode}; use {Build, Mode};
use toolstate::ToolState;
const ADB_TEST_DIR: &str = "/data/tmp/work"; const ADB_TEST_DIR: &str = "/data/tmp/work";
@ -64,17 +65,21 @@ impl fmt::Display for TestKind {
} }
} }
fn try_run(build: &Build, cmd: &mut Command) { fn try_run_expecting(build: &Build, cmd: &mut Command, expect: BuildExpectation) {
if !build.fail_fast { if !build.fail_fast {
if !build.try_run(cmd) { if !build.try_run(cmd, expect) {
let failures = build.delayed_failures.get(); let failures = build.delayed_failures.get();
build.delayed_failures.set(failures + 1); build.delayed_failures.set(failures + 1);
} }
} else { } else {
build.run(cmd); build.run_expecting(cmd, expect);
} }
} }
fn try_run(build: &Build, cmd: &mut Command) {
try_run_expecting(build, cmd, BuildExpectation::None)
}
fn try_run_quiet(build: &Build, cmd: &mut Command) { fn try_run_quiet(build: &Build, cmd: &mut Command) {
if !build.fail_fast { if !build.fail_fast {
if !build.try_run_quiet(cmd) { if !build.try_run_quiet(cmd) {
@ -294,6 +299,56 @@ impl Step for Rustfmt {
} }
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Miri {
host: Interned<String>,
}
impl Step for Miri {
type Output = ();
const ONLY_HOSTS: bool = true;
const DEFAULT: bool = true;
fn should_run(run: ShouldRun) -> ShouldRun {
let test_miri = run.builder.build.config.test_miri;
run.path("src/tools/miri").default_condition(test_miri)
}
fn make_run(run: RunConfig) {
run.builder.ensure(Miri {
host: run.target,
});
}
/// Runs `cargo test` for miri.
fn run(self, builder: &Builder) {
let build = builder.build;
let host = self.host;
let compiler = builder.compiler(1, host);
let miri = builder.ensure(tool::Miri { compiler, target: self.host });
let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test");
cargo.arg("--manifest-path").arg(build.src.join("src/tools/miri/Cargo.toml"));
// Don't build tests dynamically, just a pain to work with
cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
// miri tests need to know about the stage sysroot
cargo.env("MIRI_SYSROOT", builder.sysroot(compiler));
cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler));
cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
cargo.env("MIRI_PATH", miri);
builder.add_rustc_lib_path(compiler, &mut cargo);
try_run_expecting(
build,
&mut cargo,
builder.build.config.toolstate.miri.passes(ToolState::Testing),
);
}
}
fn path_for_cargo(builder: &Builder, compiler: Compiler) -> OsString { fn path_for_cargo(builder: &Builder, compiler: Compiler) -> OsString {
// Configure PATH to find the right rustc. NB. we have to use PATH // Configure PATH to find the right rustc. NB. we have to use PATH
// and not RUSTC because the Cargo test suite has tests that will // and not RUSTC because the Cargo test suite has tests that will

View File

@ -27,6 +27,7 @@ use util::exe;
use cache::{INTERNER, Interned}; use cache::{INTERNER, Interned};
use flags::Flags; use flags::Flags;
pub use flags::Subcommand; pub use flags::Subcommand;
use toolstate::ToolStates;
/// Global configuration for the entire build and/or bootstrap. /// Global configuration for the entire build and/or bootstrap.
/// ///
@ -111,6 +112,7 @@ pub struct Config {
pub low_priority: bool, pub low_priority: bool,
pub channel: String, pub channel: String,
pub quiet_tests: bool, pub quiet_tests: bool,
pub test_miri: bool,
// Fallback musl-root for all targets // Fallback musl-root for all targets
pub musl_root: Option<PathBuf>, pub musl_root: Option<PathBuf>,
pub prefix: Option<PathBuf>, pub prefix: Option<PathBuf>,
@ -130,6 +132,8 @@ pub struct Config {
// These are either the stage0 downloaded binaries or the locally installed ones. // These are either the stage0 downloaded binaries or the locally installed ones.
pub initial_cargo: PathBuf, pub initial_cargo: PathBuf,
pub initial_rustc: PathBuf, pub initial_rustc: PathBuf,
pub toolstate: ToolStates,
} }
/// Per-target configuration stored in the global configuration structure. /// Per-target configuration stored in the global configuration structure.
@ -269,6 +273,7 @@ struct Rust {
debug: Option<bool>, debug: Option<bool>,
dist_src: Option<bool>, dist_src: Option<bool>,
quiet_tests: Option<bool>, quiet_tests: Option<bool>,
test_miri: Option<bool>,
} }
/// TOML representation of how each build target is configured. /// TOML representation of how each build target is configured.
@ -304,6 +309,7 @@ impl Config {
config.codegen_tests = true; config.codegen_tests = true;
config.ignore_git = false; config.ignore_git = false;
config.rust_dist_src = true; config.rust_dist_src = true;
config.test_miri = false;
config.on_fail = flags.on_fail; config.on_fail = flags.on_fail;
config.stage = flags.stage; config.stage = flags.stage;
@ -330,6 +336,18 @@ impl Config {
} }
}).unwrap_or_else(|| TomlConfig::default()); }).unwrap_or_else(|| TomlConfig::default());
let toolstate_toml_path = config.src.join("src/tools/toolstate.toml");
let parse_toolstate = || -> Result<_, Box<::std::error::Error>> {
let mut f = File::open(toolstate_toml_path)?;
let mut contents = String::new();
f.read_to_string(&mut contents)?;
Ok(toml::from_str(&contents)?)
};
config.toolstate = parse_toolstate().unwrap_or_else(|err| {
println!("failed to parse TOML configuration 'toolstate.toml': {}", err);
process::exit(2);
});
let build = toml.build.clone().unwrap_or(Build::default()); let build = toml.build.clone().unwrap_or(Build::default());
set(&mut config.build, build.build.clone().map(|x| INTERNER.intern_string(x))); set(&mut config.build, build.build.clone().map(|x| INTERNER.intern_string(x)));
set(&mut config.build, flags.build); set(&mut config.build, flags.build);
@ -444,6 +462,7 @@ impl Config {
set(&mut config.channel, rust.channel.clone()); set(&mut config.channel, rust.channel.clone());
set(&mut config.rust_dist_src, rust.dist_src); set(&mut config.rust_dist_src, rust.dist_src);
set(&mut config.quiet_tests, rust.quiet_tests); set(&mut config.quiet_tests, rust.quiet_tests);
set(&mut config.test_miri, rust.test_miri);
config.rustc_default_linker = rust.default_linker.clone(); config.rustc_default_linker = rust.default_linker.clone();
config.rustc_default_ar = rust.default_ar.clone(); config.rustc_default_ar = rust.default_ar.clone();
config.musl_root = rust.musl_root.clone().map(PathBuf::from); config.musl_root = rust.musl_root.clone().map(PathBuf::from);

View File

@ -38,6 +38,7 @@ o("debug", "rust.debug", "debug mode; disables optimization unless `--enable-opt
o("docs", "build.docs", "build standard library documentation") o("docs", "build.docs", "build standard library documentation")
o("compiler-docs", "build.compiler-docs", "build compiler documentation") o("compiler-docs", "build.compiler-docs", "build compiler documentation")
o("optimize-tests", "rust.optimize-tests", "build tests with optimizations") o("optimize-tests", "rust.optimize-tests", "build tests with optimizations")
o("test-miri", "rust.test-miri", "run miri's test suite")
o("debuginfo-tests", "rust.debuginfo-tests", "build tests with debugger metadata") o("debuginfo-tests", "rust.debuginfo-tests", "build tests with debugger metadata")
o("quiet-tests", "rust.quiet-tests", "enable quieter output when running tests") o("quiet-tests", "rust.quiet-tests", "enable quieter output when running tests")
o("ccache", "llvm.ccache", "invoke gcc/clang via ccache to reuse object files between builds") o("ccache", "llvm.ccache", "invoke gcc/clang via ccache to reuse object files between builds")

View File

@ -1111,6 +1111,31 @@ impl Step for Rls {
} }
} }
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct DontDistWithMiriEnabled;
impl Step for DontDistWithMiriEnabled {
type Output = PathBuf;
const DEFAULT: bool = true;
fn should_run(run: ShouldRun) -> ShouldRun {
let build_miri = run.builder.build.config.test_miri;
run.default_condition(build_miri)
}
fn make_run(run: RunConfig) {
run.builder.ensure(DontDistWithMiriEnabled);
}
fn run(self, _: &Builder) -> PathBuf {
panic!("Do not distribute with miri enabled.\n\
The distributed libraries would include all MIR (increasing binary size).
The distributed MIR would include validation statements.");
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Extended { pub struct Extended {
stage: u32, stage: u32,

View File

@ -143,7 +143,8 @@ use std::path::{PathBuf, Path};
use std::process::Command; use std::process::Command;
use std::slice; use std::slice;
use build_helper::{run_silent, run_suppressed, try_run_silent, try_run_suppressed, output, mtime}; use build_helper::{run_silent, run_suppressed, try_run_silent, try_run_suppressed, output, mtime,
BuildExpectation};
use util::{exe, libdir, OutputFolder, CiEnv}; use util::{exe, libdir, OutputFolder, CiEnv};
@ -164,6 +165,7 @@ pub mod util;
mod builder; mod builder;
mod cache; mod cache;
mod tool; mod tool;
mod toolstate;
#[cfg(windows)] #[cfg(windows)]
mod job; mod job;
@ -542,24 +544,31 @@ impl Build {
.join(libdir(&self.config.build)) .join(libdir(&self.config.build))
} }
/// Runs a command, printing out nice contextual information if its build
/// status is not the expected one
fn run_expecting(&self, cmd: &mut Command, expect: BuildExpectation) {
self.verbose(&format!("running: {:?}", cmd));
run_silent(cmd, expect)
}
/// Runs a command, printing out nice contextual information if it fails. /// Runs a command, printing out nice contextual information if it fails.
fn run(&self, cmd: &mut Command) { fn run(&self, cmd: &mut Command) {
self.verbose(&format!("running: {:?}", cmd)); self.run_expecting(cmd, BuildExpectation::None)
run_silent(cmd)
} }
/// Runs a command, printing out nice contextual information if it fails. /// Runs a command, printing out nice contextual information if it fails.
fn run_quiet(&self, cmd: &mut Command) { fn run_quiet(&self, cmd: &mut Command) {
self.verbose(&format!("running: {:?}", cmd)); self.verbose(&format!("running: {:?}", cmd));
run_suppressed(cmd) run_suppressed(cmd, BuildExpectation::None)
} }
/// Runs a command, printing out nice contextual information if it fails. /// Runs a command, printing out nice contextual information if its build
/// Exits if the command failed to execute at all, otherwise returns its /// status is not the expected one.
/// `status.success()`. /// Exits if the command failed to execute at all, otherwise returns whether
fn try_run(&self, cmd: &mut Command) -> bool { /// the expectation was met
fn try_run(&self, cmd: &mut Command, expect: BuildExpectation) -> bool {
self.verbose(&format!("running: {:?}", cmd)); self.verbose(&format!("running: {:?}", cmd));
try_run_silent(cmd) try_run_silent(cmd, expect)
} }
/// Runs a command, printing out nice contextual information if it fails. /// Runs a command, printing out nice contextual information if it fails.
@ -567,7 +576,7 @@ impl Build {
/// `status.success()`. /// `status.success()`.
fn try_run_quiet(&self, cmd: &mut Command) -> bool { fn try_run_quiet(&self, cmd: &mut Command) -> bool {
self.verbose(&format!("running: {:?}", cmd)); self.verbose(&format!("running: {:?}", cmd));
try_run_suppressed(cmd) try_run_suppressed(cmd, BuildExpectation::None)
} }
pub fn is_verbose(&self) -> bool { pub fn is_verbose(&self) -> bool {

View File

@ -56,6 +56,7 @@ check-aux:
src/tools/cargo \ src/tools/cargo \
src/tools/rls \ src/tools/rls \
src/tools/rustfmt \ src/tools/rustfmt \
src/tools/miri \
src/test/pretty \ src/test/pretty \
src/test/run-pass/pretty \ src/test/run-pass/pretty \
src/test/run-fail/pretty \ src/test/run-fail/pretty \

View File

@ -21,6 +21,8 @@ use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp};
use native; use native;
use channel::GitInfo; use channel::GitInfo;
use cache::Interned; use cache::Interned;
use toolstate::ToolState;
use build_helper::BuildExpectation;
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct CleanTools { pub struct CleanTools {
@ -64,6 +66,7 @@ struct ToolBuild {
tool: &'static str, tool: &'static str,
path: &'static str, path: &'static str,
mode: Mode, mode: Mode,
expectation: BuildExpectation,
} }
impl Step for ToolBuild { impl Step for ToolBuild {
@ -83,6 +86,7 @@ impl Step for ToolBuild {
let target = self.target; let target = self.target;
let tool = self.tool; let tool = self.tool;
let path = self.path; let path = self.path;
let expectation = self.expectation;
match self.mode { match self.mode {
Mode::Libstd => builder.ensure(compile::Std { compiler, target }), Mode::Libstd => builder.ensure(compile::Std { compiler, target }),
@ -95,7 +99,7 @@ impl Step for ToolBuild {
println!("Building stage{} tool {} ({})", compiler.stage, tool, target); println!("Building stage{} tool {} ({})", compiler.stage, tool, target);
let mut cargo = prepare_tool_cargo(builder, compiler, target, "build", path); let mut cargo = prepare_tool_cargo(builder, compiler, target, "build", path);
build.run(&mut cargo); build.run_expecting(&mut cargo, expectation);
build.cargo_out(compiler, Mode::Tool, target).join(exe(tool, &compiler.host)) build.cargo_out(compiler, Mode::Tool, target).join(exe(tool, &compiler.host))
} }
} }
@ -200,6 +204,7 @@ macro_rules! tool {
tool: $tool_name, tool: $tool_name,
mode: $mode, mode: $mode,
path: $path, path: $path,
expectation: BuildExpectation::None,
}) })
} }
} }
@ -247,6 +252,7 @@ impl Step for RemoteTestServer {
tool: "remote-test-server", tool: "remote-test-server",
mode: Mode::Libstd, mode: Mode::Libstd,
path: "src/tools/remote-test-server", path: "src/tools/remote-test-server",
expectation: BuildExpectation::None,
}) })
} }
} }
@ -359,6 +365,7 @@ impl Step for Cargo {
tool: "cargo", tool: "cargo",
mode: Mode::Librustc, mode: Mode::Librustc,
path: "src/tools/cargo", path: "src/tools/cargo",
expectation: BuildExpectation::None,
}) })
} }
} }
@ -398,6 +405,7 @@ impl Step for Clippy {
tool: "clippy", tool: "clippy",
mode: Mode::Librustc, mode: Mode::Librustc,
path: "src/tools/clippy", path: "src/tools/clippy",
expectation: BuildExpectation::None,
}) })
} }
} }
@ -441,6 +449,7 @@ impl Step for Rls {
tool: "rls", tool: "rls",
mode: Mode::Librustc, mode: Mode::Librustc,
path: "src/tools/rls", path: "src/tools/rls",
expectation: BuildExpectation::None,
}) })
} }
} }
@ -475,6 +484,43 @@ impl Step for Rustfmt {
tool: "rustfmt", tool: "rustfmt",
mode: Mode::Librustc, mode: Mode::Librustc,
path: "src/tools/rustfmt", path: "src/tools/rustfmt",
expectation: BuildExpectation::None,
})
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Miri {
pub compiler: Compiler,
pub target: Interned<String>,
}
impl Step for Miri {
type Output = PathBuf;
const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun) -> ShouldRun {
let build_miri = run.builder.build.config.test_miri;
run.path("src/tools/miri").default_condition(build_miri)
}
fn make_run(run: RunConfig) {
run.builder.ensure(Miri {
compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
target: run.target,
});
}
fn run(self, builder: &Builder) -> PathBuf {
builder.ensure(ToolBuild {
compiler: self.compiler,
target: self.target,
tool: "miri",
mode: Mode::Librustc,
path: "src/tools/miri",
expectation: builder.build.config.toolstate.miri.passes(ToolState::Compiling),
}) })
} }
} }

View File

@ -0,0 +1,48 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use build_helper::BuildExpectation;
#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq)]
/// Whether a tool can be compiled, tested or neither
pub enum ToolState {
/// The tool compiles successfully, but the test suite fails
Compiling = 1,
/// The tool compiles successfully and its test suite passes
Testing = 2,
/// The tool can't even be compiled
Broken = 0,
}
impl ToolState {
/// If a tool with the current toolstate should be working on
/// the given toolstate
pub fn passes(self, other: ToolState) -> BuildExpectation {
if self as usize >= other as usize {
BuildExpectation::Succeeding
} else {
BuildExpectation::Failing
}
}
}
impl Default for ToolState {
fn default() -> Self {
// err on the safe side
ToolState::Broken
}
}
#[derive(Copy, Clone, Debug, Deserialize, Default)]
/// Used to express which tools should (not) be compiled or tested.
/// This is created from `toolstate.toml`.
pub struct ToolStates {
pub miri: ToolState,
}

View File

@ -35,55 +35,97 @@ macro_rules! t {
}) })
} }
pub fn run(cmd: &mut Command) { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
println!("running: {:?}", cmd); pub enum BuildExpectation {
run_silent(cmd); Succeeding,
Failing,
None,
} }
pub fn run_silent(cmd: &mut Command) { pub fn run(cmd: &mut Command, expect: BuildExpectation) {
if !try_run_silent(cmd) { println!("running: {:?}", cmd);
run_silent(cmd, expect);
}
pub fn run_silent(cmd: &mut Command, expect: BuildExpectation) {
if !try_run_silent(cmd, expect) {
std::process::exit(1); std::process::exit(1);
} }
} }
pub fn try_run_silent(cmd: &mut Command) -> bool { pub fn try_run_silent(cmd: &mut Command, expect: BuildExpectation) -> bool {
let status = match cmd.status() { let status = match cmd.status() {
Ok(status) => status, Ok(status) => status,
Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}",
cmd, e)), cmd, e)),
}; };
if !status.success() { process_status(
println!("\n\ncommand did not execute successfully: {:?}\n\ cmd,
status.success(),
expect,
|| println!("\n\ncommand did not execute successfully: {:?}\n\
expected success, got: {}\n\n", expected success, got: {}\n\n",
cmd, cmd,
status); status))
}
status.success()
} }
pub fn run_suppressed(cmd: &mut Command) { fn process_status<F: FnOnce()>(
if !try_run_suppressed(cmd) { cmd: &Command,
success: bool,
expect: BuildExpectation,
f: F,
) -> bool {
use BuildExpectation::*;
match (expect, success) {
(None, false) => { f(); false },
// Non-tool build succeeds, everything is good
(None, true) => true,
// Tool expected to work and is working
(Succeeding, true) => true,
// Tool expected to fail and is failing
(Failing, false) => {
println!("This failure is expected (see `src/tools/toolstate.toml`)");
true
},
// Tool expected to work, but is failing
(Succeeding, false) => {
f();
println!("You can disable the tool in `src/tools/toolstate.toml`");
false
},
// Tool expected to fail, but is working
(Failing, true) => {
println!("Expected `{:?}` to fail, but it succeeded.\n\
Please adjust `src/tools/toolstate.toml` accordingly", cmd);
false
}
}
}
pub fn run_suppressed(cmd: &mut Command, expect: BuildExpectation) {
if !try_run_suppressed(cmd, expect) {
std::process::exit(1); std::process::exit(1);
} }
} }
pub fn try_run_suppressed(cmd: &mut Command) -> bool { pub fn try_run_suppressed(cmd: &mut Command, expect: BuildExpectation) -> bool {
let output = match cmd.output() { let output = match cmd.output() {
Ok(status) => status, Ok(status) => status,
Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}",
cmd, e)), cmd, e)),
}; };
if !output.status.success() { process_status(
println!("\n\ncommand did not execute successfully: {:?}\n\ cmd,
output.status.success(),
expect,
|| println!("\n\ncommand did not execute successfully: {:?}\n\
expected success, got: {}\n\n\ expected success, got: {}\n\n\
stdout ----\n{}\n\ stdout ----\n{}\n\
stderr ----\n{}\n\n", stderr ----\n{}\n\n",
cmd, cmd,
output.status, output.status,
String::from_utf8_lossy(&output.stdout), String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)); String::from_utf8_lossy(&output.stderr)))
}
output.status.success()
} }
pub fn gnu_target(target: &str) -> String { pub fn gnu_target(target: &str) -> String {

View File

@ -20,7 +20,7 @@ Images will output artifacts in an `obj` dir at the root of a repository.
- Each directory, excluding `scripts` and `disabled`, corresponds to a docker image - Each directory, excluding `scripts` and `disabled`, corresponds to a docker image
- `scripts` contains files shared by docker images - `scripts` contains files shared by docker images
- `disabled` contains images that are not build travis - `disabled` contains images that are not built on travis
## Cross toolchains ## Cross toolchains

View File

@ -17,5 +17,5 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
COPY scripts/sccache.sh /scripts/ COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh RUN sh /scripts/sccache.sh
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --enable-test-miri
ENV RUST_CHECK_TARGET check-aux ENV RUST_CHECK_TARGET check-aux

View File

@ -16,7 +16,7 @@ extern crate gcc;
use std::env; use std::env;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::Command; use std::process::Command;
use build_helper::{run, native_lib_boilerplate}; use build_helper::{run, native_lib_boilerplate, BuildExpectation};
fn main() { fn main() {
// FIXME: This is a hack to support building targets that don't // FIXME: This is a hack to support building targets that don't
@ -126,7 +126,7 @@ fn main() {
cmd.arg("--with-lg-quantum=4"); cmd.arg("--with-lg-quantum=4");
} }
run(&mut cmd); run(&mut cmd, BuildExpectation::None);
let mut make = Command::new(build_helper::make(&host)); let mut make = Command::new(build_helper::make(&host));
make.current_dir(&native.out_dir) make.current_dir(&native.out_dir)
@ -143,7 +143,7 @@ fn main() {
.arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set")); .arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set"));
} }
run(&mut make); run(&mut make, BuildExpectation::None);
// The pthread_atfork symbols is used by jemalloc on android but the really // The pthread_atfork symbols is used by jemalloc on android but the really
// old android we're building on doesn't have them defined, so just make // old android we're building on doesn't have them defined, so just make

View File

@ -15,7 +15,7 @@ extern crate gcc;
use std::env; use std::env;
use std::process::Command; use std::process::Command;
use build_helper::{run, native_lib_boilerplate}; use build_helper::{run, native_lib_boilerplate, BuildExpectation};
fn main() { fn main() {
let target = env::var("TARGET").expect("TARGET was not set"); let target = env::var("TARGET").expect("TARGET was not set");
@ -97,11 +97,14 @@ fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> {
.env("CC", compiler.path()) .env("CC", compiler.path())
.env("AR", &ar) .env("AR", &ar)
.env("RANLIB", format!("{} s", ar.display())) .env("RANLIB", format!("{} s", ar.display()))
.env("CFLAGS", cflags)); .env("CFLAGS", cflags),
BuildExpectation::None);
run(Command::new(build_helper::make(host)) run(Command::new(build_helper::make(host))
.current_dir(&native.out_dir) .current_dir(&native.out_dir)
.arg(format!("INCDIR={}", native.src_dir.display())) .arg(format!("INCDIR={}", native.src_dir.display()))
.arg("-j").arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set"))); .arg("-j").arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set")),
BuildExpectation::None);
Ok(()) Ok(())
} }

1
src/tools/miri Submodule

@ -0,0 +1 @@
Subproject commit 80853e2f24a01db96fe9821e468dd2af75a4d2e5

View File

@ -65,6 +65,7 @@ fn filter_dirs(path: &Path) -> bool {
"src/tools/clippy", "src/tools/clippy",
"src/tools/rust-installer", "src/tools/rust-installer",
"src/tools/rustfmt", "src/tools/rustfmt",
"src/tools/miri",
]; ];
skip.iter().any(|p| path.ends_with(p)) skip.iter().any(|p| path.ends_with(p))
} }

24
src/tools/toolstate.toml Normal file
View File

@ -0,0 +1,24 @@
# This file reflects the current status of all tools which are allowed
# to fail without failing the build.
#
# There are three states a tool can be in:
# 1. Broken: The tool doesn't build
# 2. Building: The tool builds but its tests are failing
# 3. Testing: The tool builds and its tests are passing
#
# In the future there will be further states like "Distributing", which
# configures whether the tool is included in the Rust distribution.
#
# If a tool was working before your PR but is broken now, consider
# updating the tool within your PR. How to do that is described in
# "CONTRIBUTING.md#External Dependencies". If the effort required is not
# warranted (e.g. due to the tool abusing some API that you changed, and
# fixing the tool would mean a significant refactoring), you can disable
# the tool here, by changing its state to `Broken`. Remember to ping
# the tool authors if you do not fix their tool, so they can proactively
# fix it, instead of being surprised by the breakage.
#
# Each tool has a list of people to ping
# ping @oli-obk @RalfJung @eddyb
miri = "Testing"