Skip to content

Commit c4a900f

Browse files
authored
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.
2 parents 91426e9 + 726d518 commit c4a900f

File tree

1 file changed

+67
-31
lines changed

1 file changed

+67
-31
lines changed

src/bootstrap/native.rs

+67-31
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use std::env;
1212
use std::ffi::OsString;
1313
use std::fs::{self, File};
14+
use std::io;
1415
use std::path::{Path, PathBuf};
1516
use std::process::Command;
1617

@@ -54,7 +55,6 @@ impl Step for Llvm {
5455
}
5556
}
5657

57-
let llvm_info = &builder.in_tree_llvm_info;
5858
let root = "src/llvm-project/llvm";
5959
let out_dir = builder.llvm_out(target);
6060
let mut llvm_config_ret_dir = builder.llvm_out(builder.config.build);
@@ -65,40 +65,35 @@ impl Step for Llvm {
6565

6666
let build_llvm_config =
6767
llvm_config_ret_dir.join(exe("llvm-config", &*builder.config.build));
68-
let done_stamp = out_dir.join("llvm-finished-building");
6968

70-
if done_stamp.exists() {
71-
if builder.config.llvm_skip_rebuild {
72-
builder.info(
73-
"Warning: \
74-
Using a potentially stale build of LLVM; \
75-
This may not behave well.",
76-
);
77-
return build_llvm_config;
78-
}
69+
let stamp = out_dir.join("llvm-finished-building");
70+
let stamp = HashStamp::new(stamp, builder.in_tree_llvm_info.sha());
7971

80-
if let Some(llvm_commit) = llvm_info.sha() {
81-
let done_contents = t!(fs::read(&done_stamp));
72+
if builder.config.llvm_skip_rebuild && stamp.path.exists() {
73+
builder.info(
74+
"Warning: \
75+
Using a potentially stale build of LLVM; \
76+
This may not behave well.",
77+
);
78+
return build_llvm_config;
79+
}
8280

83-
// If LLVM was already built previously and the submodule's commit didn't change
84-
// from the previous build, then no action is required.
85-
if done_contents == llvm_commit.as_bytes() {
86-
return build_llvm_config;
87-
}
88-
} else {
81+
if stamp.is_done() {
82+
if stamp.hash.is_none() {
8983
builder.info(
9084
"Could not determine the LLVM submodule commit hash. \
9185
Assuming that an LLVM rebuild is not necessary.",
9286
);
9387
builder.info(&format!(
9488
"To force LLVM to rebuild, remove the file `{}`",
95-
done_stamp.display()
89+
stamp.path.display()
9690
));
97-
return build_llvm_config;
9891
}
92+
return build_llvm_config;
9993
}
10094

10195
builder.info(&format!("Building LLVM for {}", target));
96+
t!(stamp.remove());
10297
let _time = util::timeit(&builder);
10398
t!(fs::create_dir_all(&out_dir));
10499

@@ -271,7 +266,7 @@ impl Step for Llvm {
271266

272267
cfg.build();
273268

274-
t!(fs::write(&done_stamp, llvm_info.sha().unwrap_or("")));
269+
t!(stamp.write());
275270

276271
build_llvm_config
277272
}
@@ -584,17 +579,21 @@ impl Step for Sanitizers {
584579
return runtimes;
585580
}
586581

587-
let done_stamp = out_dir.join("sanitizers-finished-building");
588-
if done_stamp.exists() {
589-
builder.info(&format!(
590-
"Assuming that sanitizers rebuild is not necessary. \
591-
To force a rebuild, remove the file `{}`",
592-
done_stamp.display()
593-
));
582+
let stamp = out_dir.join("sanitizers-finished-building");
583+
let stamp = HashStamp::new(stamp, builder.in_tree_llvm_info.sha());
584+
585+
if stamp.is_done() {
586+
if stamp.hash.is_none() {
587+
builder.info(&format!(
588+
"Rebuild sanitizers by removing the file `{}`",
589+
stamp.path.display()
590+
));
591+
}
594592
return runtimes;
595593
}
596594

597595
builder.info(&format!("Building sanitizers for {}", self.target));
596+
t!(stamp.remove());
598597
let _time = util::timeit(&builder);
599598

600599
let mut cfg = cmake::Config::new(&compiler_rt_dir);
@@ -623,8 +622,7 @@ impl Step for Sanitizers {
623622
cfg.build_target(&runtime.cmake_target);
624623
cfg.build();
625624
}
626-
627-
t!(fs::write(&done_stamp, b""));
625+
t!(stamp.write());
628626

629627
runtimes
630628
}
@@ -689,3 +687,41 @@ fn supported_sanitizers(
689687
}
690688
result
691689
}
690+
691+
struct HashStamp {
692+
path: PathBuf,
693+
hash: Option<Vec<u8>>,
694+
}
695+
696+
impl HashStamp {
697+
fn new(path: PathBuf, hash: Option<&str>) -> Self {
698+
HashStamp { path, hash: hash.map(|s| s.as_bytes().to_owned()) }
699+
}
700+
701+
fn is_done(&self) -> bool {
702+
match fs::read(&self.path) {
703+
Ok(h) => self.hash.as_deref().unwrap_or(b"") == h.as_slice(),
704+
Err(e) if e.kind() == io::ErrorKind::NotFound => false,
705+
Err(e) => {
706+
panic!("failed to read stamp file `{}`: {}", self.path.display(), e);
707+
}
708+
}
709+
}
710+
711+
fn remove(&self) -> io::Result<()> {
712+
match fs::remove_file(&self.path) {
713+
Ok(()) => Ok(()),
714+
Err(e) => {
715+
if e.kind() == io::ErrorKind::NotFound {
716+
Ok(())
717+
} else {
718+
Err(e)
719+
}
720+
}
721+
}
722+
}
723+
724+
fn write(&self) -> io::Result<()> {
725+
fs::write(&self.path, self.hash.as_deref().unwrap_or(b""))
726+
}
727+
}

0 commit comments

Comments
 (0)