Skip to content

Commit 807aec7

Browse files
committed
fix(fingerprint): clean doc dirs for only requested targets
Previously if rustc version mismatches, this removes all `doc` directories including target platforms that are not part of the build. This makes it `--target` aware and stops excessive cleanup, by putting `.rustdoc_fingerprint.json` in each target directory.
1 parent 21ba213 commit 807aec7

File tree

2 files changed

+57
-29
lines changed

2 files changed

+57
-29
lines changed

src/cargo/core/compiler/fingerprint/rustdoc.rs

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use serde::Serialize;
77

88
use crate::CargoResult;
99
use crate::core::compiler::BuildRunner;
10+
use crate::core::compiler::CompileKind;
1011

1112
/// Structure used to deal with Rustdoc fingerprinting
1213
///
@@ -43,36 +44,50 @@ impl RustDocFingerprint {
4344
{
4445
return Ok(());
4546
}
46-
let actual_rustdoc_target_data = RustDocFingerprint {
47+
let new_fingerprint = RustDocFingerprint {
4748
rustc_vv: build_runner.bcx.rustc().verbose_version.clone(),
4849
};
4950

51+
for kind in &build_runner.bcx.build_config.requested_kinds {
52+
RustDocFingerprint::check(build_runner, &new_fingerprint, *kind)?;
53+
}
54+
55+
Ok(())
56+
}
57+
58+
fn check(
59+
build_runner: &BuildRunner<'_, '_>,
60+
new_fingerprint: &RustDocFingerprint,
61+
kind: CompileKind,
62+
) -> CargoResult<()> {
5063
let fingerprint_path = build_runner
5164
.files()
52-
.host_build_root()
65+
.layout(kind)
66+
.build_dir()
67+
.root()
5368
.join(".rustdoc_fingerprint.json");
69+
5470
let write_fingerprint = || -> CargoResult<()> {
55-
paths::write(
56-
&fingerprint_path,
57-
serde_json::to_string(&actual_rustdoc_target_data)?,
58-
)
71+
paths::write(&fingerprint_path, serde_json::to_string(new_fingerprint)?)
5972
};
73+
6074
let Ok(rustdoc_data) = paths::read(&fingerprint_path) else {
6175
// If the fingerprint does not exist, do not clear out the doc
6276
// directories. Otherwise this ran into problems where projects
6377
// like bootstrap were creating the doc directory before running
6478
// `cargo doc` in a way that deleting it would break it.
6579
return write_fingerprint();
6680
};
81+
6782
match serde_json::from_str::<RustDocFingerprint>(&rustdoc_data) {
68-
Ok(fingerprint) => {
69-
if fingerprint.rustc_vv == actual_rustdoc_target_data.rustc_vv {
83+
Ok(on_disk_fingerprint) => {
84+
if on_disk_fingerprint.rustc_vv == new_fingerprint.rustc_vv {
7085
return Ok(());
7186
} else {
7287
tracing::debug!(
7388
"doc fingerprint changed:\noriginal:\n{}\nnew:\n{}",
74-
fingerprint.rustc_vv,
75-
actual_rustdoc_target_data.rustc_vv
89+
on_disk_fingerprint.rustc_vv,
90+
new_fingerprint.rustc_vv
7691
);
7792
}
7893
}
@@ -85,20 +100,16 @@ impl RustDocFingerprint {
85100
"fingerprint {:?} mismatch, clearing doc directories",
86101
fingerprint_path
87102
);
88-
build_runner
89-
.bcx
90-
.all_kinds
91-
.iter()
92-
.map(|kind| {
93-
build_runner
94-
.files()
95-
.layout(*kind)
96-
.artifact_dir()
97-
.expect("artifact-dir was not locked")
98-
.doc()
99-
})
100-
.filter(|path| path.exists())
101-
.try_for_each(|path| clean_doc(path))?;
103+
let doc_dir = build_runner
104+
.files()
105+
.layout(kind)
106+
.artifact_dir()
107+
.expect("artifact-dir was not locked")
108+
.doc();
109+
if doc_dir.exists() {
110+
clean_doc(doc_dir)?;
111+
}
112+
102113
write_fingerprint()?;
103114

104115
Ok(())

tests/testsuite/doc.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2586,7 +2586,11 @@ LLVM version: 9.0
25862586
serde_json::from_str(&fs::read_to_string(&host_fingerprint_path).unwrap())
25872587
.expect("JSON Serde fail");
25882588

2589-
assert!(!target_fingerprint_path.exists());
2589+
let target_fingerprint: RustDocFingerprint =
2590+
serde_json::from_str(&fs::read_to_string(&target_fingerprint_path).unwrap())
2591+
.expect("JSON Serde fail");
2592+
2593+
assert_eq!(host_fingerprint.rustc_vv, target_fingerprint.rustc_vv);
25902594

25912595
// Check that the fingerprint contains the actual rustc version
25922596
// which has been used to compile the docs.
@@ -2600,8 +2604,14 @@ LLVM version: 9.0
26002604
.unwrap();
26012605
assert_eq!(&host_fingerprint.rustc_vv, &current_rustc_version);
26022606

2603-
// Write random `rustc -vV` output and bogus file for host
2607+
// Write random `rustc -vV` output and bogus file for both host and target
26042608
fs::write(&host_fingerprint_path, &old_rustc_verbose_version).unwrap();
2609+
fs::write(&target_fingerprint_path, &old_rustc_verbose_version).unwrap();
2610+
fs::write(
2611+
p.build_dir().join(host).join("doc/bogus_file"),
2612+
"This is a bogus file and should be removed!",
2613+
)
2614+
.unwrap();
26052615
fs::write(
26062616
p.build_dir().join("doc/bogus_file"),
26072617
"This is a bogus file and should be removed!",
@@ -2611,10 +2621,17 @@ LLVM version: 9.0
26112621
// ...but run only target
26122622
p.cargo("doc --target").arg(host).run();
26132623

2614-
// host doc dir got cleaned
2615-
assert!(!p.build_dir().join("doc/bogus_file").exists());
2624+
// host doc dir stays the same, and the fingerprint is still the old random one
2625+
assert!(p.build_dir().join("doc/bogus_file").exists());
2626+
assert_eq!(
2627+
&fs::read_to_string(&host_fingerprint_path).unwrap(),
2628+
&old_rustc_verbose_version,
2629+
);
2630+
2631+
// target doc dir got cleaned
2632+
assert!(!p.build_dir().join(host).join("doc/bogus_file").exists());
26162633
let fingerprint: RustDocFingerprint =
2617-
serde_json::from_str(&fs::read_to_string(&host_fingerprint_path).unwrap()).unwrap();
2634+
serde_json::from_str(&fs::read_to_string(&target_fingerprint_path).unwrap()).unwrap();
26182635
assert_eq!(&fingerprint.rustc_vv, &current_rustc_version);
26192636
}
26202637

0 commit comments

Comments
 (0)