Avoid fingerprint busting during builds (#4244)

* Avoid fingerprint busting during builds

* delete `.fingerprint/package-hash` instead of modifying source code

---------

Co-authored-by: Jonathan Kelley <jkelleyrtp@gmail.com>
This commit is contained in:
HéctorandJonathan Kelley authored and GitHub committed 2025-06-23 20:05:56 -07:00
1 parent f40f7a5aeb
commit e477e0b485
2 files changed
+40 -14

No files matched your search

+23 -7
View File
@@ -3802,7 +3802,7 @@ impl BuildRequest {
Ok(()) Ok(())
} }
/// update the mtime of the "main" file to bust the fingerprint, forcing rustc to recompile it. /// Blow away the fingerprint for this package, forcing rustc to recompile it.
/// ///
/// This prevents rustc from using the cached version of the binary, which can cause issues /// This prevents rustc from using the cached version of the binary, which can cause issues
/// with our hotpatching setup since it uses linker interception. /// with our hotpatching setup since it uses linker interception.
@@ -3812,13 +3812,29 @@ impl BuildRequest {
/// ///
/// This might stop working if/when cargo stabilizes contents-based fingerprinting. /// This might stop working if/when cargo stabilizes contents-based fingerprinting.
fn bust_fingerprint(&self, ctx: &BuildContext) -> Result<()> { fn bust_fingerprint(&self, ctx: &BuildContext) -> Result<()> {
if !matches!(ctx.mode, BuildMode::Thin { .. }) { if matches!(ctx.mode, BuildMode::Fat) {
std::fs::File::open(&self.crate_target.src_path)?.set_modified(SystemTime::now())?; // `dx` compiles everything with `--target` which ends up with a structure like:
// target/<triple>/<profile>/.fingerprint/<package_name>-<hash>
//
// normally you can't rely on this structure (ie with `cargo build`) but the explicit
// target arg guarantees this will work.
let fingerprint_dir = self
.target_dir
.join(self.triple.to_string())
.join(&self.profile)
.join(".fingerprint");
// read and write the file to update the mtime // split at the last `-` used to separate the hash from the name
if cfg!(target_os = "windows") { // This causes to more aggressively bust hashes for all combinations of features
let contents = std::fs::read_to_string(&self.crate_target.src_path)?; // and fingerprints for this package since we're just ignoring the hash
_ = std::fs::write(&self.crate_target.src_path, contents); for entry in std::fs::read_dir(&fingerprint_dir)?.flatten() {
if let Some(fname) = entry.file_name().to_str() {
if let Some((name, _)) = fname.rsplit_once('-') {
if name == self.package().name {
_ = std::fs::remove_dir_all(entry.path());
}
}
}
} }
} }
Ok(()) Ok(())
+17 -7
View File
@@ -54,13 +54,23 @@ pub async fn run_rustc() {
link_args: Default::default(), link_args: Default::default(),
}; };
std::fs::create_dir_all(var_file.parent().expect("Failed to get parent dir")) // Another terrible hack to avoid caching non-sensical args when
.expect("Failed to create parent dir"); // a build is completely fresh (rustc is invoked with --crate-name ___)
std::fs::write( if rustc_args
&var_file, .args
serde_json::to_string(&rustc_args).expect("Failed to serialize rustc args"), .iter()
) .skip_while(|arg| *arg != "--crate-name")
.expect("Failed to write rustc args to file"); .nth(1)
.is_some_and(|name| name != "___")
{
std::fs::create_dir_all(var_file.parent().expect("Failed to get parent dir"))
.expect("Failed to create parent dir");
std::fs::write(
&var_file,
serde_json::to_string(&rustc_args).expect("Failed to serialize rustc args"),
)
.expect("Failed to write rustc args to file");
}
// Run the actual rustc command // Run the actual rustc command
// We want all stdout/stderr to be inherited, so the running process can see the output // We want all stdout/stderr to be inherited, so the running process can see the output