Record build and test result of extended tools into toolstates.json.

This commit is contained in:
kennytm 2017-11-30 18:18:47 +08:00
parent 128199e39c
commit 971b1ba42b
No known key found for this signature in database
GPG Key ID: FEF6C8051D0E013C
7 changed files with 68 additions and 12 deletions

View File

@ -301,6 +301,10 @@
# As a side-effect also generates MIR for all libraries.
#test-miri = false
# After building or testing extended tools (e.g. clippy and rustfmt), append the
# result (broken, compiling, testing) into this JSON file.
#save-toolstates = "/path/to/toolstates.json"
# =============================================================================
# Options for specific targets
#

View File

@ -65,19 +65,21 @@ impl fmt::Display for TestKind {
}
}
fn try_run_expecting(build: &Build, cmd: &mut Command, expect: BuildExpectation) {
fn try_run_expecting(build: &Build, cmd: &mut Command, expect: BuildExpectation) -> bool {
if !build.fail_fast {
if !build.try_run(cmd, expect) {
let mut failures = build.delayed_failures.borrow_mut();
failures.push(format!("{:?}", cmd));
return false;
}
} else {
build.run_expecting(cmd, expect);
}
true
}
fn try_run(build: &Build, cmd: &mut Command) {
try_run_expecting(build, cmd, BuildExpectation::None)
try_run_expecting(build, cmd, BuildExpectation::None);
}
fn try_run_quiet(build: &Build, cmd: &mut Command) {
@ -257,11 +259,13 @@ impl Step for Rls {
builder.add_rustc_lib_path(compiler, &mut cargo);
try_run_expecting(
if try_run_expecting(
build,
&mut cargo,
builder.build.config.toolstate.rls.passes(ToolState::Testing),
);
) {
build.save_toolstate("rls", ToolState::Testing);
}
}
}
@ -305,11 +309,13 @@ impl Step for Rustfmt {
builder.add_rustc_lib_path(compiler, &mut cargo);
try_run_expecting(
if try_run_expecting(
build,
&mut cargo,
builder.build.config.toolstate.rustfmt.passes(ToolState::Testing),
);
) {
build.save_toolstate("rustfmt", ToolState::Testing);
}
}
}
@ -354,11 +360,13 @@ impl Step for Miri {
builder.add_rustc_lib_path(compiler, &mut cargo);
try_run_expecting(
if try_run_expecting(
build,
&mut cargo,
builder.build.config.toolstate.miri.passes(ToolState::Testing),
);
) {
build.save_toolstate("miri", ToolState::Testing);
}
} else {
eprintln!("failed to test miri: could not build");
}
@ -411,11 +419,13 @@ impl Step for Clippy {
builder.add_rustc_lib_path(compiler, &mut cargo);
try_run_expecting(
if try_run_expecting(
build,
&mut cargo,
builder.build.config.toolstate.clippy.passes(ToolState::Testing),
);
) {
build.save_toolstate("clippy-driver", ToolState::Testing);
}
} else {
eprintln!("failed to test clippy: could not build");
}

View File

@ -112,6 +112,8 @@ pub struct Config {
pub channel: String,
pub quiet_tests: bool,
pub test_miri: bool,
pub save_toolstates: Option<PathBuf>,
// Fallback musl-root for all targets
pub musl_root: Option<PathBuf>,
pub prefix: Option<PathBuf>,
@ -279,6 +281,7 @@ struct Rust {
dist_src: Option<bool>,
quiet_tests: Option<bool>,
test_miri: Option<bool>,
save_toolstates: Option<String>,
}
/// TOML representation of how each build target is configured.
@ -473,6 +476,7 @@ impl Config {
set(&mut config.test_miri, rust.test_miri);
config.rustc_default_linker = rust.default_linker.clone();
config.musl_root = rust.musl_root.clone().map(PathBuf::from);
config.save_toolstates = rust.save_toolstates.clone().map(PathBuf::from);
match rust.codegen_units {
Some(0) => config.rust_codegen_units = Some(num_cpus::get() as u32),

View File

@ -77,6 +77,7 @@ o("debuginfo", "rust.debuginfo", "build with debugger metadata")
o("debuginfo-lines", "rust.debuginfo-lines", "build with line number debugger metadata")
o("debuginfo-only-std", "rust.debuginfo-only-std", "build only libstd with debugging information")
o("debug-jemalloc", "rust.debug-jemalloc", "build jemalloc with --enable-debug --enable-fill")
v("save-toolstates", "rust.save-toolstates", "save build and test status of external tools into this file")
v("prefix", "install.prefix", "set installation prefix")
v("localstatedir", "install.localstatedir", "local state directory")

View File

@ -190,6 +190,7 @@ mod job {
pub use config::Config;
use flags::Subcommand;
use cache::{Interned, INTERNER};
use toolstate::ToolState;
/// A structure representing a Rust compiler.
///
@ -874,6 +875,30 @@ impl Build {
}
}
/// Updates the actual toolstate of a tool.
///
/// The toolstates are saved to the file specified by the key
/// `rust.save-toolstates` in `config.toml`. If unspecified, nothing will be
/// done. The file is updated immediately after this function completes.
pub fn save_toolstate(&self, tool: &str, state: ToolState) {
use std::io::{Seek, SeekFrom};
if let Some(ref path) = self.config.save_toolstates {
let mut file = t!(fs::OpenOptions::new()
.create(true)
.read(true)
.write(true)
.open(path));
let mut current_toolstates: HashMap<Box<str>, ToolState> =
serde_json::from_reader(&mut file).unwrap_or_default();
current_toolstates.insert(tool.into(), state);
t!(file.seek(SeekFrom::Start(0)));
t!(file.set_len(0));
t!(serde_json::to_writer(file, &current_toolstates));
}
}
/// Get a list of crates from a root crate.
///
/// Returns Vec<(crate, path to crate, is_root_crate)>

View File

@ -115,7 +115,19 @@ impl Step for ToolBuild {
println!("Building stage{} tool {} ({})", compiler.stage, tool, target);
let mut cargo = prepare_tool_cargo(builder, compiler, target, "build", path);
if !build.try_run(&mut cargo, expectation) {
let is_expected = build.try_run(&mut cargo, expectation);
// If the expectation is "Failing", `try_run` returning true actually
// means a build-failure is successfully observed, i.e. the tool is
// broken. Thus the XOR here.
// Sorry for the complicated logic, but we can remove this expectation
// logic after #45861 is fully fixed.
build.save_toolstate(tool, if is_expected ^ (expectation == BuildExpectation::Failing) {
ToolState::Compiling
} else {
ToolState::Broken
});
if !is_expected {
if expectation == BuildExpectation::None {
exit(1);
} else {

View File

@ -10,7 +10,7 @@
use build_helper::BuildExpectation;
#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq)]
#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
/// Whether a tool can be compiled, tested or neither
pub enum ToolState {
/// The tool compiles successfully, but the test suite fails