Skip to content

Commit 658bde1

Browse files
committed
Auto merge of #7373 - alexcrichton:clear-memos, r=ehuss
Clear out memoized hashes before building crates Build script updates during execution can change the memoized hash of a `Fingerprint`, and while previously we cleared out a single build script's memoized hash we forgot to clear out everything that depended on it as well. This commit pessimistically clears out all `Fingerprint` memoized hashes just before building to ensure that during the build everything has the most up-to-date view of the world, and when build scripts change fingerprints everything that depends on them won't have run yet. Closes #7362
2 parents 3b735c6 + c3868bb commit 658bde1

File tree

3 files changed

+91
-1
lines changed

3 files changed

+91
-1
lines changed

src/cargo/core/compiler/context/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,16 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
147147
super::compile(&mut self, &mut queue, &mut plan, unit, exec, force_rebuild)?;
148148
}
149149

150+
// Now that we've got the full job queue and we've done all our
151+
// fingerprint analysis to determine what to run, bust all the memoized
152+
// fingerprint hashes to ensure that during the build they all get the
153+
// most up-to-date values. In theory we only need to bust hashes that
154+
// transitively depend on a dirty build script, but it shouldn't matter
155+
// that much for performance anyway.
156+
for fingerprint in self.fingerprints.values() {
157+
fingerprint.clear_memoized();
158+
}
159+
150160
// Now that we've figured out everything that we're going to do, do it!
151161
queue.execute(&mut self, &mut plan)?;
152162

src/cargo/core/compiler/fingerprint.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,6 @@ pub fn prepare_target<'a, 'cfg>(
301301
// hobble along if it happens to return `Some`.
302302
if let Some(new_local) = (gen_local)(&deps, None)? {
303303
*fingerprint.local.lock().unwrap() = new_local;
304-
*fingerprint.memoized_hash.lock().unwrap() = None;
305304
}
306305

307306
write_fingerprint(&loc, &fingerprint)
@@ -604,6 +603,16 @@ impl Fingerprint {
604603
}
605604
}
606605

606+
/// For performance reasons fingerprints will memoize their own hash, but
607+
/// there's also internal mutability with its `local` field which can
608+
/// change, for example with build scripts, during a build.
609+
///
610+
/// This method can be used to bust all memoized hashes just before a build
611+
/// to ensure that after a build completes everything is up-to-date.
612+
pub fn clear_memoized(&self) {
613+
*self.memoized_hash.lock().unwrap() = None;
614+
}
615+
607616
fn hash(&self) -> u64 {
608617
if let Some(s) = *self.memoized_hash.lock().unwrap() {
609618
return s;

tests/testsuite/freshness.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2049,3 +2049,74 @@ fn move_target_directory_with_path_deps() {
20492049
.with_stderr("[FINISHED] [..]")
20502050
.run();
20512051
}
2052+
2053+
#[cargo_test]
2054+
fn rerun_if_changes() {
2055+
let p = project()
2056+
.file(
2057+
"build.rs",
2058+
r#"
2059+
fn main() {
2060+
println!("cargo:rerun-if-env-changed=FOO");
2061+
if std::env::var("FOO").is_ok() {
2062+
println!("cargo:rerun-if-env-changed=BAR");
2063+
}
2064+
}
2065+
"#,
2066+
)
2067+
.file("src/lib.rs", "")
2068+
.build();
2069+
2070+
p.cargo("build").run();
2071+
p.cargo("build").with_stderr("[FINISHED] [..]").run();
2072+
2073+
p.cargo("build -v")
2074+
.env("FOO", "1")
2075+
.with_stderr(
2076+
"\
2077+
[COMPILING] foo [..]
2078+
[RUNNING] `[..]build-script-build`
2079+
[RUNNING] `rustc [..]
2080+
[FINISHED] [..]
2081+
",
2082+
)
2083+
.run();
2084+
p.cargo("build")
2085+
.env("FOO", "1")
2086+
.with_stderr("[FINISHED] [..]")
2087+
.run();
2088+
2089+
p.cargo("build -v")
2090+
.env("FOO", "1")
2091+
.env("BAR", "1")
2092+
.with_stderr(
2093+
"\
2094+
[COMPILING] foo [..]
2095+
[RUNNING] `[..]build-script-build`
2096+
[RUNNING] `rustc [..]
2097+
[FINISHED] [..]
2098+
",
2099+
)
2100+
.run();
2101+
p.cargo("build")
2102+
.env("FOO", "1")
2103+
.env("BAR", "1")
2104+
.with_stderr("[FINISHED] [..]")
2105+
.run();
2106+
2107+
p.cargo("build -v")
2108+
.env("BAR", "2")
2109+
.with_stderr(
2110+
"\
2111+
[COMPILING] foo [..]
2112+
[RUNNING] `[..]build-script-build`
2113+
[RUNNING] `rustc [..]
2114+
[FINISHED] [..]
2115+
",
2116+
)
2117+
.run();
2118+
p.cargo("build")
2119+
.env("BAR", "2")
2120+
.with_stderr("[FINISHED] [..]")
2121+
.run();
2122+
}

0 commit comments

Comments
 (0)