Add a file to trivially disable tool building or testing
This commit is contained in:
parent
f0b5402283
commit
ab018c76e1
@ -23,7 +23,7 @@
|
||||
use std::process::Command;
|
||||
use std::io::Read;
|
||||
|
||||
use build_helper::{self, output};
|
||||
use build_helper::{self, output, BuildExpectation};
|
||||
|
||||
use builder::{Kind, RunConfig, ShouldRun, Builder, Compiler, Step};
|
||||
use cache::{INTERNER, Interned};
|
||||
@ -33,6 +33,7 @@
|
||||
use tool::{self, Tool};
|
||||
use util::{self, dylib_path, dylib_path_var};
|
||||
use {Build, Mode};
|
||||
use toolstate::ToolState;
|
||||
|
||||
const ADB_TEST_DIR: &str = "/data/tmp/work";
|
||||
|
||||
@ -64,17 +65,21 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
}
|
||||
}
|
||||
|
||||
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.try_run(cmd) {
|
||||
if !build.try_run(cmd, expect) {
|
||||
let failures = build.delayed_failures.get();
|
||||
build.delayed_failures.set(failures + 1);
|
||||
}
|
||||
} 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) {
|
||||
if !build.fail_fast {
|
||||
if !build.try_run_quiet(cmd) {
|
||||
@ -333,7 +338,11 @@ fn run(self, builder: &Builder) {
|
||||
|
||||
builder.add_rustc_lib_path(compiler, &mut cargo);
|
||||
|
||||
try_run(build, &mut cargo);
|
||||
try_run_expecting(
|
||||
build,
|
||||
&mut cargo,
|
||||
builder.build.config.toolstate.miri.passes(ToolState::Testing),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
use cache::{INTERNER, Interned};
|
||||
use flags::Flags;
|
||||
pub use flags::Subcommand;
|
||||
use toolstate::ToolStates;
|
||||
|
||||
/// Global configuration for the entire build and/or bootstrap.
|
||||
///
|
||||
@ -131,6 +132,8 @@ pub struct Config {
|
||||
// These are either the stage0 downloaded binaries or the locally installed ones.
|
||||
pub initial_cargo: PathBuf,
|
||||
pub initial_rustc: PathBuf,
|
||||
|
||||
pub toolstate: ToolStates,
|
||||
}
|
||||
|
||||
/// Per-target configuration stored in the global configuration structure.
|
||||
@ -333,6 +336,18 @@ pub fn parse(args: &[String]) -> Config {
|
||||
}
|
||||
}).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());
|
||||
set(&mut config.build, build.build.clone().map(|x| INTERNER.intern_string(x)));
|
||||
set(&mut config.build, flags.build);
|
||||
|
@ -143,7 +143,8 @@
|
||||
use std::process::Command;
|
||||
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};
|
||||
|
||||
@ -164,6 +165,7 @@
|
||||
mod builder;
|
||||
mod cache;
|
||||
mod tool;
|
||||
mod toolstate;
|
||||
|
||||
#[cfg(windows)]
|
||||
mod job;
|
||||
@ -542,24 +544,31 @@ fn rustc_snapshot_libdir(&self) -> PathBuf {
|
||||
.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.
|
||||
fn run(&self, cmd: &mut Command) {
|
||||
self.verbose(&format!("running: {:?}", cmd));
|
||||
run_silent(cmd)
|
||||
self.run_expecting(cmd, BuildExpectation::None)
|
||||
}
|
||||
|
||||
/// Runs a command, printing out nice contextual information if it fails.
|
||||
fn run_quiet(&self, cmd: &mut Command) {
|
||||
self.verbose(&format!("running: {:?}", cmd));
|
||||
run_suppressed(cmd)
|
||||
run_suppressed(cmd, BuildExpectation::None)
|
||||
}
|
||||
|
||||
/// Runs a command, printing out nice contextual information if it fails.
|
||||
/// Exits if the command failed to execute at all, otherwise returns its
|
||||
/// `status.success()`.
|
||||
fn try_run(&self, cmd: &mut Command) -> bool {
|
||||
/// Runs a command, printing out nice contextual information if its build
|
||||
/// status is not the expected one.
|
||||
/// Exits if the command failed to execute at all, otherwise returns whether
|
||||
/// the expectation was met
|
||||
fn try_run(&self, cmd: &mut Command, expect: BuildExpectation) -> bool {
|
||||
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.
|
||||
@ -567,7 +576,7 @@ fn try_run(&self, cmd: &mut Command) -> bool {
|
||||
/// `status.success()`.
|
||||
fn try_run_quiet(&self, cmd: &mut Command) -> bool {
|
||||
self.verbose(&format!("running: {:?}", cmd));
|
||||
try_run_suppressed(cmd)
|
||||
try_run_suppressed(cmd, BuildExpectation::None)
|
||||
}
|
||||
|
||||
pub fn is_verbose(&self) -> bool {
|
||||
|
@ -21,6 +21,8 @@
|
||||
use native;
|
||||
use channel::GitInfo;
|
||||
use cache::Interned;
|
||||
use toolstate::ToolState;
|
||||
use build_helper::BuildExpectation;
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub struct CleanTools {
|
||||
@ -64,6 +66,7 @@ struct ToolBuild {
|
||||
tool: &'static str,
|
||||
path: &'static str,
|
||||
mode: Mode,
|
||||
expectation: BuildExpectation,
|
||||
}
|
||||
|
||||
impl Step for ToolBuild {
|
||||
@ -83,6 +86,7 @@ fn run(self, builder: &Builder) -> PathBuf {
|
||||
let target = self.target;
|
||||
let tool = self.tool;
|
||||
let path = self.path;
|
||||
let expectation = self.expectation;
|
||||
|
||||
match self.mode {
|
||||
Mode::Libstd => builder.ensure(compile::Std { compiler, target }),
|
||||
@ -95,7 +99,7 @@ fn run(self, builder: &Builder) -> PathBuf {
|
||||
println!("Building stage{} tool {} ({})", compiler.stage, tool, target);
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
@ -200,6 +204,7 @@ fn run(self, builder: &Builder) -> PathBuf {
|
||||
tool: $tool_name,
|
||||
mode: $mode,
|
||||
path: $path,
|
||||
expectation: BuildExpectation::None,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -247,6 +252,7 @@ fn run(self, builder: &Builder) -> PathBuf {
|
||||
tool: "remote-test-server",
|
||||
mode: Mode::Libstd,
|
||||
path: "src/tools/remote-test-server",
|
||||
expectation: BuildExpectation::None,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -359,6 +365,7 @@ fn run(self, builder: &Builder) -> PathBuf {
|
||||
tool: "cargo",
|
||||
mode: Mode::Librustc,
|
||||
path: "src/tools/cargo",
|
||||
expectation: BuildExpectation::None,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -398,6 +405,7 @@ fn run(self, builder: &Builder) -> PathBuf {
|
||||
tool: "clippy",
|
||||
mode: Mode::Librustc,
|
||||
path: "src/tools/clippy",
|
||||
expectation: BuildExpectation::None,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -441,6 +449,7 @@ fn run(self, builder: &Builder) -> PathBuf {
|
||||
tool: "rls",
|
||||
mode: Mode::Librustc,
|
||||
path: "src/tools/rls",
|
||||
expectation: BuildExpectation::None,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -492,8 +501,8 @@ impl Step for Miri {
|
||||
const ONLY_HOSTS: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun) -> ShouldRun {
|
||||
let builder = run.builder;
|
||||
run.path("src/tools/miri").default_condition(builder.build.config.test_miri)
|
||||
let build_miri = run.builder.build.config.test_miri;
|
||||
run.path("src/tools/miri").default_condition(build_miri)
|
||||
}
|
||||
|
||||
fn make_run(run: RunConfig) {
|
||||
@ -510,6 +519,7 @@ fn run(self, builder: &Builder) -> PathBuf {
|
||||
tool: "miri",
|
||||
mode: Mode::Librustc,
|
||||
path: "src/tools/miri",
|
||||
expectation: builder.build.config.toolstate.miri.passes(ToolState::Compiling),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
48
src/bootstrap/toolstate.rs
Normal file
48
src/bootstrap/toolstate.rs
Normal 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,
|
||||
}
|
@ -35,55 +35,97 @@ macro_rules! t {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn run(cmd: &mut Command) {
|
||||
println!("running: {:?}", cmd);
|
||||
run_silent(cmd);
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub enum BuildExpectation {
|
||||
Succeeding,
|
||||
Failing,
|
||||
None,
|
||||
}
|
||||
|
||||
pub fn run_silent(cmd: &mut Command) {
|
||||
if !try_run_silent(cmd) {
|
||||
pub fn run(cmd: &mut Command, expect: BuildExpectation) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
Ok(status) => status,
|
||||
Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}",
|
||||
cmd, e)),
|
||||
};
|
||||
if !status.success() {
|
||||
println!("\n\ncommand did not execute successfully: {:?}\n\
|
||||
expected success, got: {}\n\n",
|
||||
cmd,
|
||||
status);
|
||||
}
|
||||
status.success()
|
||||
process_status(
|
||||
cmd,
|
||||
status.success(),
|
||||
expect,
|
||||
|| println!("\n\ncommand did not execute successfully: {:?}\n\
|
||||
expected success, got: {}\n\n",
|
||||
cmd,
|
||||
status))
|
||||
}
|
||||
|
||||
pub fn run_suppressed(cmd: &mut Command) {
|
||||
if !try_run_suppressed(cmd) {
|
||||
fn process_status<F: FnOnce()>(
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
Ok(status) => status,
|
||||
Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}",
|
||||
cmd, e)),
|
||||
};
|
||||
if !output.status.success() {
|
||||
println!("\n\ncommand did not execute successfully: {:?}\n\
|
||||
process_status(
|
||||
cmd,
|
||||
output.status.success(),
|
||||
expect,
|
||||
|| println!("\n\ncommand did not execute successfully: {:?}\n\
|
||||
expected success, got: {}\n\n\
|
||||
stdout ----\n{}\n\
|
||||
stderr ----\n{}\n\n",
|
||||
cmd,
|
||||
output.status,
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr));
|
||||
}
|
||||
output.status.success()
|
||||
String::from_utf8_lossy(&output.stderr)))
|
||||
}
|
||||
|
||||
pub fn gnu_target(target: &str) -> String {
|
||||
|
@ -16,7 +16,7 @@
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use build_helper::{run, native_lib_boilerplate};
|
||||
use build_helper::{run, native_lib_boilerplate, BuildExpectation};
|
||||
|
||||
fn main() {
|
||||
// FIXME: This is a hack to support building targets that don't
|
||||
@ -126,7 +126,7 @@ fn main() {
|
||||
cmd.arg("--with-lg-quantum=4");
|
||||
}
|
||||
|
||||
run(&mut cmd);
|
||||
run(&mut cmd, BuildExpectation::None);
|
||||
|
||||
let mut make = Command::new(build_helper::make(&host));
|
||||
make.current_dir(&native.out_dir)
|
||||
@ -143,7 +143,7 @@ fn main() {
|
||||
.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
|
||||
// old android we're building on doesn't have them defined, so just make
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
use std::env;
|
||||
use std::process::Command;
|
||||
use build_helper::{run, native_lib_boilerplate};
|
||||
use build_helper::{run, native_lib_boilerplate, BuildExpectation};
|
||||
|
||||
fn main() {
|
||||
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("AR", &ar)
|
||||
.env("RANLIB", format!("{} s", ar.display()))
|
||||
.env("CFLAGS", cflags));
|
||||
.env("CFLAGS", cflags),
|
||||
BuildExpectation::None);
|
||||
|
||||
run(Command::new(build_helper::make(host))
|
||||
.current_dir(&native.out_dir)
|
||||
.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(())
|
||||
}
|
||||
|
24
src/tools/toolstate.toml
Normal file
24
src/tools/toolstate.toml
Normal 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"
|
Loading…
Reference in New Issue
Block a user