Skip to content

Commit 7c45021

Browse files
committed
Check target-dependant doc folders
When checking the fingerprint for rustdoc and applying the corresponding logic, we don't only need to consider the `target/doc` folder (Host target) but also triple targets. So now the actual compilation targets are checked during the rustdoc_fingerprint processing and they're treated as the Host/doc folder.
1 parent d2572a2 commit 7c45021

File tree

2 files changed

+117
-25
lines changed

2 files changed

+117
-25
lines changed

src/cargo/core/compiler/build_context/target_info.rs

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize};
99
use std::cell::RefCell;
1010
use std::collections::hash_map::{Entry, HashMap};
1111
use std::env;
12-
use std::path::PathBuf;
12+
use std::path::{Path, PathBuf};
1313
use std::str::{self, FromStr};
1414

1515
/// Information about the platform target gleaned from querying rustc.
@@ -755,28 +755,20 @@ impl RustcTargetData {
755755
/// Structure used to deal with Rustdoc fingerprinting
756756
#[derive(Debug, Serialize, Deserialize)]
757757
pub struct RustDocFingerprint {
758-
rustc_vv: String,
758+
pub rustc_vv: String,
759759
}
760760

761761
impl RustDocFingerprint {
762762
/// Read the `RustDocFingerprint` info from the fingerprint file.
763763
fn read<'a, 'cfg>(cx: &Context<'a, 'cfg>) -> CargoResult<Self> {
764-
let rustdoc_data = paths::read(
765-
&cx.files()
766-
.host_root()
767-
.join(".rustdoc_fingerprint")
768-
.with_extension("json"),
769-
)?;
764+
let rustdoc_data = paths::read(&cx.files().host_root().join(".rustdoc_fingerprint.json"))?;
770765
serde_json::from_str(&rustdoc_data).map_err(|e| anyhow::anyhow!("{:?}", e))
771766
}
772767

773768
/// Write the `RustDocFingerprint` info into the fingerprint file.
774769
fn write<'a, 'cfg>(&self, cx: &Context<'a, 'cfg>) -> CargoResult<()> {
775770
paths::write(
776-
&cx.files()
777-
.host_root()
778-
.join(".rustdoc_fingerprint.json")
779-
.with_extension("json"),
771+
&cx.files().host_root().join(".rustdoc_fingerprint.json"),
780772
serde_json::to_string(&self)?.as_bytes(),
781773
)
782774
}
@@ -793,14 +785,28 @@ impl RustDocFingerprint {
793785
let actual_rustdoc_target_data = RustDocFingerprint {
794786
rustc_vv: cx.bcx.rustc().verbose_version.clone(),
795787
};
796-
let doc_dir = cx.files().host_root().join("doc");
788+
789+
// Collect all of the target doc paths for which the docs need to be compiled for.
790+
let doc_dirs: Vec<PathBuf> = cx
791+
.compilation
792+
.root_output
793+
.iter()
794+
.map(|(ck, _)| match ck {
795+
CompileKind::Host => cx.files().host_root().to_path_buf(),
796+
CompileKind::Target(t) => cx.files().host_root().join(Path::new(t.rustc_target())),
797+
})
798+
.map(|path| path.join("doc"))
799+
.collect();
800+
797801
// Check wether `.rustdoc_fingerprint.json` exists
798802
match Self::read(cx) {
799803
Ok(fingerprint) => {
800804
// Check if rustc_version matches the one we just used. Otherways,
801805
// remove the `doc` folder to trigger a re-compilation of the docs.
802806
if fingerprint.rustc_vv != actual_rustdoc_target_data.rustc_vv {
803-
paths::remove_dir_all(&doc_dir)?;
807+
doc_dirs
808+
.iter()
809+
.try_for_each(|path| paths::remove_dir_all(&path))?;
804810
actual_rustdoc_target_data.write(cx)?
805811
}
806812
}
@@ -810,7 +816,9 @@ impl RustDocFingerprint {
810816
// exists neither, we simply do nothing and continue.
811817
Err(_) => {
812818
// We don't care if this suceeds as explained above.
813-
let _ = paths::remove_dir_all(doc_dir);
819+
let _ = doc_dirs
820+
.iter()
821+
.try_for_each(|path| paths::remove_dir_all(&path));
814822
actual_rustdoc_target_data.write(cx)?
815823
}
816824
}

tests/testsuite/doc.rs

Lines changed: 94 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
//! Tests for the `cargo doc` command.
22
3+
use cargo::core::compiler::RustDocFingerprint;
34
use cargo_test_support::paths::CargoPathExt;
45
use cargo_test_support::registry::Package;
56
use cargo_test_support::{basic_lib_manifest, basic_manifest, git, project};
67
use cargo_test_support::{is_nightly, rustc_host};
7-
use serde::{Deserialize, Serialize};
88
use std::fs;
99
use std::str;
1010

@@ -1641,15 +1641,7 @@ fn crate_versions_flag_is_overridden() {
16411641
}
16421642

16431643
#[cargo_test]
1644-
fn doc_fingerprint_versioning_consistent() {
1645-
#[derive(Debug, Serialize, Deserialize)]
1646-
pub struct RustDocFingerprint {
1647-
rustc_vv: String,
1648-
}
1649-
1650-
// Test that using different Rustc versions forces a
1651-
// doc re-compilation producing new html, css & js files.
1652-
1644+
fn doc_fingerprint_is_versioning_consistent() {
16531645
// Random rustc verbose version
16541646
let old_rustc_verbose_version = format!(
16551647
"\
@@ -1730,3 +1722,95 @@ LLVM version: 9.0
17301722
(String::from_utf8_lossy(&output.stdout).as_ref())
17311723
);
17321724
}
1725+
1726+
#[cargo_test]
1727+
fn doc_fingerprint_respects_target_paths() {
1728+
// Random rustc verbose version
1729+
let old_rustc_verbose_version = format!(
1730+
"\
1731+
rustc 1.41.1 (f3e1a954d 2020-02-24)
1732+
binary: rustc
1733+
commit-hash: f3e1a954d2ead4e2fc197c7da7d71e6c61bad196
1734+
commit-date: 2020-02-24
1735+
host: {}
1736+
release: 1.41.1
1737+
LLVM version: 9.0
1738+
",
1739+
rustc_host()
1740+
);
1741+
1742+
// Create the dummy project.
1743+
let dummy_project = project()
1744+
.file(
1745+
"Cargo.toml",
1746+
r#"
1747+
[package]
1748+
name = "foo"
1749+
version = "1.2.4"
1750+
authors = []
1751+
"#,
1752+
)
1753+
.file("src/lib.rs", "//! These are the docs!")
1754+
.build();
1755+
1756+
dummy_project
1757+
.cargo("doc --target x86_64-unknown-linux-gnu")
1758+
.run();
1759+
1760+
let fingerprint: RustDocFingerprint =
1761+
serde_json::from_str(&dummy_project.read_file("target/.rustdoc_fingerprint.json"))
1762+
.expect("JSON Serde fail");
1763+
1764+
// Check that the fingerprint contains the actual rustc version
1765+
// which has been used to compile the docs.
1766+
let output = std::process::Command::new("rustc")
1767+
.arg("-vV")
1768+
.output()
1769+
.expect("Failed to get actual rustc verbose version");
1770+
assert_eq!(
1771+
fingerprint.rustc_vv,
1772+
(String::from_utf8_lossy(&output.stdout).as_ref())
1773+
);
1774+
1775+
// As the test shows above. Now we have generated the `doc/` folder and inside
1776+
// the rustdoc fingerprint file is located with the correct rustc version.
1777+
// So we will remove it and create a new fingerprint with an old rustc version
1778+
// inside it. We will also place a bogus file inside of the `doc/` folder to ensure
1779+
// it gets removed as we expect on the next doc compilation.
1780+
dummy_project.change_file(
1781+
"target/.rustdoc_fingerprint.json",
1782+
&old_rustc_verbose_version,
1783+
);
1784+
1785+
fs::write(
1786+
dummy_project
1787+
.build_dir()
1788+
.join("x86_64-unknown-linux-gnu/doc/bogus_file"),
1789+
String::from("This is a bogus file and should be removed!"),
1790+
)
1791+
.expect("Error writing test bogus file");
1792+
1793+
// Now if we trigger another compilation, since the fingerprint contains an old version
1794+
// of rustc, cargo should remove the entire `/doc` folder (including the fingerprint)
1795+
// and generating another one with the actual version.
1796+
// It should also remove the bogus file we created above.
1797+
dummy_project
1798+
.cargo("doc --target x86_64-unknown-linux-gnu")
1799+
.run();
1800+
1801+
assert!(!dummy_project
1802+
.build_dir()
1803+
.join("x86_64-unknown-linux-gnu/doc/bogus_file")
1804+
.exists());
1805+
1806+
let fingerprint: RustDocFingerprint =
1807+
serde_json::from_str(&dummy_project.read_file("target/.rustdoc_fingerprint.json"))
1808+
.expect("JSON Serde fail");
1809+
1810+
// Check that the fingerprint contains the actual rustc version
1811+
// which has been used to compile the docs.
1812+
assert_eq!(
1813+
fingerprint.rustc_vv,
1814+
(String::from_utf8_lossy(&output.stdout).as_ref())
1815+
);
1816+
}

0 commit comments

Comments
 (0)