Skip to content

Commit 83487e4

Browse files
committed
Detect changes for JSON spec targets.
1 parent ccf781a commit 83487e4

File tree

5 files changed

+219
-96
lines changed

5 files changed

+219
-96
lines changed

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ impl TargetInfo {
137137
kind,
138138
"RUSTFLAGS",
139139
)?;
140+
let extra_fingerprint = kind.fingerprint_hash();
140141
let mut process = rustc.process();
141142
process
142143
.arg("-")
@@ -163,14 +164,17 @@ impl TargetInfo {
163164
process.arg("--crate-type").arg(crate_type.as_str());
164165
}
165166
let supports_split_debuginfo = rustc
166-
.cached_output(process.clone().arg("-Csplit-debuginfo=packed"))
167+
.cached_output(
168+
process.clone().arg("-Csplit-debuginfo=packed"),
169+
extra_fingerprint,
170+
)
167171
.is_ok();
168172

169173
process.arg("--print=sysroot");
170174
process.arg("--print=cfg");
171175

172176
let (output, error) = rustc
173-
.cached_output(&process)
177+
.cached_output(&process, extra_fingerprint)
174178
.chain_err(|| "failed to run `rustc` to learn about target-specific information")?;
175179

176180
let mut lines = output.lines();

src/cargo/core/compiler/compile_kind.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
use crate::core::Target;
22
use crate::util::errors::{CargoResult, CargoResultExt};
33
use crate::util::interning::InternedString;
4-
use crate::util::Config;
4+
use crate::util::{Config, StableHasher};
55
use anyhow::bail;
66
use serde::Serialize;
77
use std::collections::BTreeSet;
8+
use std::fs;
9+
use std::hash::{Hash, Hasher};
810
use std::path::Path;
911

1012
/// Indicator for how a unit is being compiled.
@@ -78,6 +80,18 @@ impl CompileKind {
7880
};
7981
Ok(vec![kind])
8082
}
83+
84+
/// Hash used for fingerprinting.
85+
///
86+
/// Metadata hashing uses the normal Hash trait, which does not
87+
/// differentiate on `.json` file contents. The fingerprint hash does
88+
/// check the contents.
89+
pub fn fingerprint_hash(&self) -> u64 {
90+
match self {
91+
CompileKind::Host => 0,
92+
CompileKind::Target(target) => target.fingerprint_hash(),
93+
}
94+
}
8195
}
8296

8397
impl serde::ser::Serialize for CompileKind {
@@ -166,4 +180,19 @@ impl CompileTarget {
166180
&self.name
167181
}
168182
}
183+
184+
/// See [`CompileKind::fingerprint_hash`].
185+
pub fn fingerprint_hash(&self) -> u64 {
186+
let mut hasher = StableHasher::new();
187+
self.name.hash(&mut hasher);
188+
if self.name.ends_with(".json") {
189+
// This may have some performance concerns, since it is called
190+
// fairly often. If that ever seems worth fixing, consider
191+
// embedding this in `CompileTarget`.
192+
if let Ok(contents) = fs::read_to_string(self.name) {
193+
contents.hash(&mut hasher);
194+
}
195+
}
196+
hasher.finish()
197+
}
169198
}

src/cargo/core/compiler/fingerprint.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@
6060
//! `cargo rustc` extra args | ✓ | ✓
6161
//! CompileMode | ✓ | ✓
6262
//! Target Name | ✓ | ✓
63-
//! Target CompileKind (bin/lib/etc.) | ✓ | ✓
63+
//! TargetKind (bin/lib/etc.) | ✓ | ✓
6464
//! Enabled Features | ✓ | ✓
6565
//! Immediate dependency’s hashes | ✓[^1] | ✓
66-
//! Target or Host mode | | ✓
66+
//! CompileKind (host/target) | ✓ | ✓
6767
//! __CARGO_DEFAULT_LIB_METADATA[^4] | | ✓
6868
//! package_id | | ✓
6969
//! authors, description, homepage, repo | ✓ |
@@ -542,6 +542,9 @@ pub struct Fingerprint {
542542
metadata: u64,
543543
/// Hash of various config settings that change how things are compiled.
544544
config: u64,
545+
/// The rustc target. This is only relevant for `.json` files, otherwise
546+
/// the metadata hash segregates the units.
547+
compile_kind: u64,
545548
/// Description of whether the filesystem status for this unit is up to date
546549
/// or should be considered stale.
547550
#[serde(skip)]
@@ -780,6 +783,7 @@ impl Fingerprint {
780783
rustflags: Vec::new(),
781784
metadata: 0,
782785
config: 0,
786+
compile_kind: 0,
783787
fs_status: FsStatus::Stale,
784788
outputs: Vec::new(),
785789
}
@@ -843,6 +847,9 @@ impl Fingerprint {
843847
if self.config != old.config {
844848
bail!("configuration settings have changed")
845849
}
850+
if self.compile_kind != old.compile_kind {
851+
bail!("compile kind (rustc target) changed")
852+
}
846853
let my_local = self.local.lock().unwrap();
847854
let old_local = old.local.lock().unwrap();
848855
if my_local.len() != old_local.len() {
@@ -1090,12 +1097,22 @@ impl hash::Hash for Fingerprint {
10901097
ref local,
10911098
metadata,
10921099
config,
1100+
compile_kind,
10931101
ref rustflags,
10941102
..
10951103
} = *self;
10961104
let local = local.lock().unwrap();
10971105
(
1098-
rustc, features, target, path, profile, &*local, metadata, config, rustflags,
1106+
rustc,
1107+
features,
1108+
target,
1109+
path,
1110+
profile,
1111+
&*local,
1112+
metadata,
1113+
config,
1114+
compile_kind,
1115+
rustflags,
10991116
)
11001117
.hash(h);
11011118

@@ -1318,6 +1335,7 @@ fn calculate_normal(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Finger
13181335
} else {
13191336
0
13201337
};
1338+
let compile_kind = unit.kind.fingerprint_hash();
13211339
Ok(Fingerprint {
13221340
rustc: util::hash_u64(&cx.bcx.rustc().verbose_version),
13231341
target: util::hash_u64(&unit.target),
@@ -1331,6 +1349,7 @@ fn calculate_normal(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Finger
13311349
memoized_hash: Mutex::new(None),
13321350
metadata,
13331351
config,
1352+
compile_kind,
13341353
rustflags: extra_flags,
13351354
fs_status: FsStatus::Stale,
13361355
outputs,

src/cargo/util/rustc.rs

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ impl Rustc {
4949

5050
let mut cmd = util::process(&path);
5151
cmd.arg("-vV");
52-
let verbose_version = cache.cached_output(&cmd)?.0;
52+
let verbose_version = cache.cached_output(&cmd, 0)?.0;
5353

5454
let extract = |field: &str| -> CargoResult<&str> {
5555
verbose_version
@@ -100,8 +100,25 @@ impl Rustc {
100100
util::process(&self.path)
101101
}
102102

103-
pub fn cached_output(&self, cmd: &ProcessBuilder) -> CargoResult<(String, String)> {
104-
self.cache.lock().unwrap().cached_output(cmd)
103+
/// Gets the output for the given command.
104+
///
105+
/// This will return the cached value if available, otherwise it will run
106+
/// the command and cache the output.
107+
///
108+
/// `extra_fingerprint` is extra data to include in the cache fingerprint.
109+
/// Use this if there is other information about the environment that may
110+
/// affect the output that is not part of `cmd`.
111+
///
112+
/// Returns a tuple of strings `(stdout, stderr)`.
113+
pub fn cached_output(
114+
&self,
115+
cmd: &ProcessBuilder,
116+
extra_fingerprint: u64,
117+
) -> CargoResult<(String, String)> {
118+
self.cache
119+
.lock()
120+
.unwrap()
121+
.cached_output(cmd, extra_fingerprint)
105122
}
106123
}
107124

@@ -187,8 +204,12 @@ impl Cache {
187204
}
188205
}
189206

190-
fn cached_output(&mut self, cmd: &ProcessBuilder) -> CargoResult<(String, String)> {
191-
let key = process_fingerprint(cmd);
207+
fn cached_output(
208+
&mut self,
209+
cmd: &ProcessBuilder,
210+
extra_fingerprint: u64,
211+
) -> CargoResult<(String, String)> {
212+
let key = process_fingerprint(cmd, extra_fingerprint);
192213
if self.data.outputs.contains_key(&key) {
193214
debug!("rustc info cache hit");
194215
} else {
@@ -295,8 +316,9 @@ fn rustc_fingerprint(path: &Path, rustup_rustc: &Path) -> CargoResult<u64> {
295316
Ok(hasher.finish())
296317
}
297318

298-
fn process_fingerprint(cmd: &ProcessBuilder) -> u64 {
319+
fn process_fingerprint(cmd: &ProcessBuilder, extra_fingerprint: u64) -> u64 {
299320
let mut hasher = StableHasher::new();
321+
extra_fingerprint.hash(&mut hasher);
300322
cmd.get_args().hash(&mut hasher);
301323
let mut env = cmd.get_envs().iter().collect::<Vec<_>>();
302324
env.sort_unstable();

0 commit comments

Comments
 (0)