Add a file to trivially disable tool building or testing

This commit is contained in:
Oliver Schneider 2017-08-30 18:59:26 +02:00 committed by Oliver Schneider
parent f0b5402283
commit ab018c76e1
No known key found for this signature in database
GPG Key ID: 1D5CB4FC597C3004
9 changed files with 205 additions and 45 deletions

View File

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

View File

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

View File

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

View File

@ -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),
})
}
}

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) {
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 {

View File

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

View File

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