Skip to content

Commit 33747b0

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 33747b0

File tree

2 files changed

+96
-60
lines changed

2 files changed

+96
-60
lines changed

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

Lines changed: 74 additions & 55 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
///
@@ -30,10 +31,17 @@ impl RustDocFingerprint {
3031
/// was the same as the one is currently being used in this `cargo doc` call.
3132
///
3233
/// In case it's not,
33-
/// it takes care of removing the `<artifact-dir>/doc/` folder
34+
/// it takes care of removing the `<build-dir>/doc/` folder
3435
/// as well as overwriting the rustdoc fingerprint info.
3536
/// This is to guarantee that we won't end up with mixed versions of the `js/html/css` files
3637
/// which `rustdoc` autogenerates without any versioning.
38+
///
39+
/// Each requested target platform maintains its own fingerprint file.
40+
/// That is, if you run `cargo doc` and then `cargo doc --target wasm32-wasip1`,
41+
/// you will have two separate fingerprint files:
42+
///
43+
/// * `<build-dir>/.rustdoc_fingerprint.json` for host
44+
/// * `<build-dir>/wasm32-wasip1/.rustdoc_fingerprint.json`
3745
pub fn check_rustdoc_fingerprint(build_runner: &BuildRunner<'_, '_>) -> CargoResult<()> {
3846
if build_runner
3947
.bcx
@@ -43,68 +51,79 @@ impl RustDocFingerprint {
4351
{
4452
return Ok(());
4553
}
46-
let actual_rustdoc_target_data = RustDocFingerprint {
54+
let new_fingerprint = RustDocFingerprint {
4755
rustc_vv: build_runner.bcx.rustc().verbose_version.clone(),
4856
};
4957

50-
let fingerprint_path = build_runner
51-
.files()
52-
.host_build_root()
53-
.join(".rustdoc_fingerprint.json");
54-
let write_fingerprint = || -> CargoResult<()> {
55-
paths::write(
56-
&fingerprint_path,
57-
serde_json::to_string(&actual_rustdoc_target_data)?,
58-
)
59-
};
60-
let Ok(rustdoc_data) = paths::read(&fingerprint_path) else {
61-
// If the fingerprint does not exist, do not clear out the doc
62-
// directories. Otherwise this ran into problems where projects
63-
// like bootstrap were creating the doc directory before running
64-
// `cargo doc` in a way that deleting it would break it.
65-
return write_fingerprint();
66-
};
67-
match serde_json::from_str::<RustDocFingerprint>(&rustdoc_data) {
68-
Ok(fingerprint) => {
69-
if fingerprint.rustc_vv == actual_rustdoc_target_data.rustc_vv {
70-
return Ok(());
71-
} else {
72-
tracing::debug!(
73-
"doc fingerprint changed:\noriginal:\n{}\nnew:\n{}",
74-
fingerprint.rustc_vv,
75-
actual_rustdoc_target_data.rustc_vv
76-
);
77-
}
78-
}
79-
Err(e) => {
80-
tracing::debug!("could not deserialize {:?}: {}", fingerprint_path, e);
81-
}
82-
};
83-
// Fingerprint does not match, delete the doc directories and write a new fingerprint.
84-
tracing::debug!(
85-
"fingerprint {:?} mismatch, clearing doc directories",
86-
fingerprint_path
87-
);
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))?;
102-
write_fingerprint()?;
58+
for kind in &build_runner.bcx.build_config.requested_kinds {
59+
check_fingerprint(build_runner, &new_fingerprint, *kind)?;
60+
}
10361

10462
Ok(())
10563
}
10664
}
10765

66+
/// Checks rustdoc fingerprint file for a given [`CompileKind`].
67+
fn check_fingerprint(
68+
build_runner: &BuildRunner<'_, '_>,
69+
new_fingerprint: &RustDocFingerprint,
70+
kind: CompileKind,
71+
) -> CargoResult<()> {
72+
let fingerprint_path = build_runner
73+
.files()
74+
.layout(kind)
75+
.build_dir()
76+
.root()
77+
.join(".rustdoc_fingerprint.json");
78+
79+
let write_fingerprint = || -> CargoResult<()> {
80+
paths::write(&fingerprint_path, serde_json::to_string(new_fingerprint)?)
81+
};
82+
83+
let Ok(rustdoc_data) = paths::read(&fingerprint_path) else {
84+
// If the fingerprint does not exist, do not clear out the doc
85+
// directories. Otherwise this ran into problems where projects
86+
// like bootstrap were creating the doc directory before running
87+
// `cargo doc` in a way that deleting it would break it.
88+
return write_fingerprint();
89+
};
90+
91+
match serde_json::from_str::<RustDocFingerprint>(&rustdoc_data) {
92+
Ok(on_disk_fingerprint) => {
93+
if on_disk_fingerprint.rustc_vv == new_fingerprint.rustc_vv {
94+
return Ok(());
95+
} else {
96+
tracing::debug!(
97+
"doc fingerprint changed:\noriginal:\n{}\nnew:\n{}",
98+
on_disk_fingerprint.rustc_vv,
99+
new_fingerprint.rustc_vv
100+
);
101+
}
102+
}
103+
Err(e) => {
104+
tracing::debug!("could not deserialize {:?}: {}", fingerprint_path, e);
105+
}
106+
};
107+
// Fingerprint does not match, delete the doc directories and write a new fingerprint.
108+
tracing::debug!(
109+
"fingerprint {:?} mismatch, clearing doc directories",
110+
fingerprint_path
111+
);
112+
let doc_dir = build_runner
113+
.files()
114+
.layout(kind)
115+
.artifact_dir()
116+
.expect("artifact-dir was not locked")
117+
.doc();
118+
if doc_dir.exists() {
119+
clean_doc(doc_dir)?;
120+
}
121+
122+
write_fingerprint()?;
123+
124+
Ok(())
125+
}
126+
108127
fn clean_doc(path: &Path) -> CargoResult<()> {
109128
let entries = path
110129
.read_dir()

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)