Rollup merge of #69735 - tmiasko:bootstrap-sanitizers-hash, r=Mark-Simulacrum

bootstrap: Use hash to determine if sanitizers needs to be rebuilt

* Rebuild sanitizers runtimes when LLVM submodule commit changes.
* When rebuilding LLVM / sanitizers, remove the stamp file before
  starting the build process to invalidate previous build output.
This commit is contained in:
Mazdak Farrokhzad 2020-03-17 12:16:14 +01:00 committed by GitHub
commit c4a900f57c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -11,6 +11,7 @@
use std::env; use std::env;
use std::ffi::OsString; use std::ffi::OsString;
use std::fs::{self, File}; use std::fs::{self, File};
use std::io;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::Command; use std::process::Command;
@ -54,7 +55,6 @@ impl Step for Llvm {
} }
} }
let llvm_info = &builder.in_tree_llvm_info;
let root = "src/llvm-project/llvm"; let root = "src/llvm-project/llvm";
let out_dir = builder.llvm_out(target); let out_dir = builder.llvm_out(target);
let mut llvm_config_ret_dir = builder.llvm_out(builder.config.build); let mut llvm_config_ret_dir = builder.llvm_out(builder.config.build);
@ -65,10 +65,11 @@ impl Step for Llvm {
let build_llvm_config = let build_llvm_config =
llvm_config_ret_dir.join(exe("llvm-config", &*builder.config.build)); llvm_config_ret_dir.join(exe("llvm-config", &*builder.config.build));
let done_stamp = out_dir.join("llvm-finished-building");
if done_stamp.exists() { let stamp = out_dir.join("llvm-finished-building");
if builder.config.llvm_skip_rebuild { let stamp = HashStamp::new(stamp, builder.in_tree_llvm_info.sha());
if builder.config.llvm_skip_rebuild && stamp.path.exists() {
builder.info( builder.info(
"Warning: \ "Warning: \
Using a potentially stale build of LLVM; \ Using a potentially stale build of LLVM; \
@ -77,28 +78,22 @@ impl Step for Llvm {
return build_llvm_config; return build_llvm_config;
} }
if let Some(llvm_commit) = llvm_info.sha() { if stamp.is_done() {
let done_contents = t!(fs::read(&done_stamp)); if stamp.hash.is_none() {
// If LLVM was already built previously and the submodule's commit didn't change
// from the previous build, then no action is required.
if done_contents == llvm_commit.as_bytes() {
return build_llvm_config;
}
} else {
builder.info( builder.info(
"Could not determine the LLVM submodule commit hash. \ "Could not determine the LLVM submodule commit hash. \
Assuming that an LLVM rebuild is not necessary.", Assuming that an LLVM rebuild is not necessary.",
); );
builder.info(&format!( builder.info(&format!(
"To force LLVM to rebuild, remove the file `{}`", "To force LLVM to rebuild, remove the file `{}`",
done_stamp.display() stamp.path.display()
)); ));
return build_llvm_config;
} }
return build_llvm_config;
} }
builder.info(&format!("Building LLVM for {}", target)); builder.info(&format!("Building LLVM for {}", target));
t!(stamp.remove());
let _time = util::timeit(&builder); let _time = util::timeit(&builder);
t!(fs::create_dir_all(&out_dir)); t!(fs::create_dir_all(&out_dir));
@ -271,7 +266,7 @@ impl Step for Llvm {
cfg.build(); cfg.build();
t!(fs::write(&done_stamp, llvm_info.sha().unwrap_or(""))); t!(stamp.write());
build_llvm_config build_llvm_config
} }
@ -584,17 +579,21 @@ impl Step for Sanitizers {
return runtimes; return runtimes;
} }
let done_stamp = out_dir.join("sanitizers-finished-building"); let stamp = out_dir.join("sanitizers-finished-building");
if done_stamp.exists() { let stamp = HashStamp::new(stamp, builder.in_tree_llvm_info.sha());
if stamp.is_done() {
if stamp.hash.is_none() {
builder.info(&format!( builder.info(&format!(
"Assuming that sanitizers rebuild is not necessary. \ "Rebuild sanitizers by removing the file `{}`",
To force a rebuild, remove the file `{}`", stamp.path.display()
done_stamp.display()
)); ));
}
return runtimes; return runtimes;
} }
builder.info(&format!("Building sanitizers for {}", self.target)); builder.info(&format!("Building sanitizers for {}", self.target));
t!(stamp.remove());
let _time = util::timeit(&builder); let _time = util::timeit(&builder);
let mut cfg = cmake::Config::new(&compiler_rt_dir); let mut cfg = cmake::Config::new(&compiler_rt_dir);
@ -623,8 +622,7 @@ impl Step for Sanitizers {
cfg.build_target(&runtime.cmake_target); cfg.build_target(&runtime.cmake_target);
cfg.build(); cfg.build();
} }
t!(stamp.write());
t!(fs::write(&done_stamp, b""));
runtimes runtimes
} }
@ -689,3 +687,41 @@ fn supported_sanitizers(
} }
result result
} }
struct HashStamp {
path: PathBuf,
hash: Option<Vec<u8>>,
}
impl HashStamp {
fn new(path: PathBuf, hash: Option<&str>) -> Self {
HashStamp { path, hash: hash.map(|s| s.as_bytes().to_owned()) }
}
fn is_done(&self) -> bool {
match fs::read(&self.path) {
Ok(h) => self.hash.as_deref().unwrap_or(b"") == h.as_slice(),
Err(e) if e.kind() == io::ErrorKind::NotFound => false,
Err(e) => {
panic!("failed to read stamp file `{}`: {}", self.path.display(), e);
}
}
}
fn remove(&self) -> io::Result<()> {
match fs::remove_file(&self.path) {
Ok(()) => Ok(()),
Err(e) => {
if e.kind() == io::ErrorKind::NotFound {
Ok(())
} else {
Err(e)
}
}
}
}
fn write(&self) -> io::Result<()> {
fs::write(&self.path, self.hash.as_deref().unwrap_or(b""))
}
}