Skip to content

Commit 1243c37

Browse files
committed
Auto merge of #9348 - matklad:wrapper-fingerprint, r=ehuss
Don't re-use rustc cache when RUSTC_WRAPPER changes We cache initial `rustc --version` invocations, to speed up noop builds. We check the mtime of `rustc` to bust the cache if the complier changed. However, before this PR, we didn't look at mtimes of `RUSTC_WRAPPER` / `RUSTC_WORKSPACE_WRAPPER`, so we could've re-use old cache with new wrapper.
2 parents 97edf92 + f6070b3 commit 1243c37

File tree

3 files changed

+146
-33
lines changed

3 files changed

+146
-33
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ impl TargetInfo {
140140
"RUSTFLAGS",
141141
)?;
142142
let extra_fingerprint = kind.fingerprint_hash();
143-
let mut process = rustc.process();
143+
let mut process = rustc.workspace_process();
144144
process
145145
.arg("-")
146146
.arg("--crate-name")

src/cargo/util/rustc.rs

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,13 @@ impl Rustc {
4646
) -> CargoResult<Rustc> {
4747
let _p = profile::start("Rustc::new");
4848

49-
let mut cache = Cache::load(&path, rustup_rustc, cache_location);
49+
let mut cache = Cache::load(
50+
wrapper.as_deref(),
51+
workspace_wrapper.as_deref(),
52+
&path,
53+
rustup_rustc,
54+
cache_location,
55+
);
5056

5157
let mut cmd = ProcessBuilder::new(&path);
5258
cmd.arg("-vV");
@@ -155,8 +161,17 @@ struct Output {
155161
}
156162

157163
impl Cache {
158-
fn load(rustc: &Path, rustup_rustc: &Path, cache_location: Option<PathBuf>) -> Cache {
159-
match (cache_location, rustc_fingerprint(rustc, rustup_rustc)) {
164+
fn load(
165+
wrapper: Option<&Path>,
166+
workspace_wrapper: Option<&Path>,
167+
rustc: &Path,
168+
rustup_rustc: &Path,
169+
cache_location: Option<PathBuf>,
170+
) -> Cache {
171+
match (
172+
cache_location,
173+
rustc_fingerprint(wrapper, workspace_wrapper, rustc, rustup_rustc),
174+
) {
160175
(Some(cache_location), Ok(rustc_fingerprint)) => {
161176
let empty = CacheData {
162177
rustc_fingerprint,
@@ -273,13 +288,29 @@ impl Drop for Cache {
273288
}
274289
}
275290

276-
fn rustc_fingerprint(path: &Path, rustup_rustc: &Path) -> CargoResult<u64> {
291+
fn rustc_fingerprint(
292+
wrapper: Option<&Path>,
293+
workspace_wrapper: Option<&Path>,
294+
rustc: &Path,
295+
rustup_rustc: &Path,
296+
) -> CargoResult<u64> {
277297
let mut hasher = StableHasher::new();
278298

279-
let path = paths::resolve_executable(path)?;
280-
path.hash(&mut hasher);
299+
let hash_exe = |hasher: &mut _, path| -> CargoResult<()> {
300+
let path = paths::resolve_executable(path)?;
301+
path.hash(hasher);
302+
303+
paths::mtime(&path)?.hash(hasher);
304+
Ok(())
305+
};
281306

282-
paths::mtime(&path)?.hash(&mut hasher);
307+
hash_exe(&mut hasher, rustc)?;
308+
if let Some(wrapper) = wrapper {
309+
hash_exe(&mut hasher, wrapper)?;
310+
}
311+
if let Some(workspace_wrapper) = workspace_wrapper {
312+
hash_exe(&mut hasher, workspace_wrapper)?;
313+
}
283314

284315
// Rustup can change the effective compiler without touching
285316
// the `rustc` binary, so we try to account for this here.
@@ -292,7 +323,7 @@ fn rustc_fingerprint(path: &Path, rustup_rustc: &Path) -> CargoResult<u64> {
292323
//
293324
// If we don't see rustup env vars, but it looks like the compiler
294325
// is managed by rustup, we conservatively bail out.
295-
let maybe_rustup = rustup_rustc == path;
326+
let maybe_rustup = rustup_rustc == rustc;
296327
match (
297328
maybe_rustup,
298329
env::var("RUSTUP_HOME"),

tests/testsuite/rustc_info_cache.rs

Lines changed: 106 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,40 @@
11
//! Tests for the cache file for the rustc version info.
22
3-
use cargo_test_support::paths::CargoPathExt;
3+
use cargo_test_support::{basic_bin_manifest, paths::CargoPathExt};
44
use cargo_test_support::{basic_manifest, project};
55
use std::env;
66

7+
const MISS: &str = "[..] rustc info cache miss[..]";
8+
const HIT: &str = "[..]rustc info cache hit[..]";
9+
const UPDATE: &str = "[..]updated rustc info cache[..]";
10+
711
#[cargo_test]
812
fn rustc_info_cache() {
913
let p = project()
1014
.file("src/main.rs", r#"fn main() { println!("hello"); }"#)
1115
.build();
1216

13-
let miss = "[..] rustc info cache miss[..]";
14-
let hit = "[..]rustc info cache hit[..]";
15-
let update = "[..]updated rustc info cache[..]";
16-
1717
p.cargo("build")
1818
.env("CARGO_LOG", "cargo::util::rustc=debug")
1919
.with_stderr_contains("[..]failed to read rustc info cache[..]")
20-
.with_stderr_contains(miss)
21-
.with_stderr_does_not_contain(hit)
22-
.with_stderr_contains(update)
20+
.with_stderr_contains(MISS)
21+
.with_stderr_does_not_contain(HIT)
22+
.with_stderr_contains(UPDATE)
2323
.run();
2424

2525
p.cargo("build")
2626
.env("CARGO_LOG", "cargo::util::rustc=debug")
2727
.with_stderr_contains("[..]reusing existing rustc info cache[..]")
28-
.with_stderr_contains(hit)
29-
.with_stderr_does_not_contain(miss)
30-
.with_stderr_does_not_contain(update)
28+
.with_stderr_contains(HIT)
29+
.with_stderr_does_not_contain(MISS)
30+
.with_stderr_does_not_contain(UPDATE)
3131
.run();
3232

3333
p.cargo("build")
3434
.env("CARGO_LOG", "cargo::util::rustc=debug")
3535
.env("CARGO_CACHE_RUSTC_INFO", "0")
3636
.with_stderr_contains("[..]rustc info cache disabled[..]")
37-
.with_stderr_does_not_contain(update)
37+
.with_stderr_does_not_contain(UPDATE)
3838
.run();
3939

4040
let other_rustc = {
@@ -68,18 +68,18 @@ fn rustc_info_cache() {
6868
.env("CARGO_LOG", "cargo::util::rustc=debug")
6969
.env("RUSTC", other_rustc.display().to_string())
7070
.with_stderr_contains("[..]different compiler, creating new rustc info cache[..]")
71-
.with_stderr_contains(miss)
72-
.with_stderr_does_not_contain(hit)
73-
.with_stderr_contains(update)
71+
.with_stderr_contains(MISS)
72+
.with_stderr_does_not_contain(HIT)
73+
.with_stderr_contains(UPDATE)
7474
.run();
7575

7676
p.cargo("build")
7777
.env("CARGO_LOG", "cargo::util::rustc=debug")
7878
.env("RUSTC", other_rustc.display().to_string())
7979
.with_stderr_contains("[..]reusing existing rustc info cache[..]")
80-
.with_stderr_contains(hit)
81-
.with_stderr_does_not_contain(miss)
82-
.with_stderr_does_not_contain(update)
80+
.with_stderr_contains(HIT)
81+
.with_stderr_does_not_contain(MISS)
82+
.with_stderr_does_not_contain(UPDATE)
8383
.run();
8484

8585
other_rustc.move_into_the_future();
@@ -88,17 +88,99 @@ fn rustc_info_cache() {
8888
.env("CARGO_LOG", "cargo::util::rustc=debug")
8989
.env("RUSTC", other_rustc.display().to_string())
9090
.with_stderr_contains("[..]different compiler, creating new rustc info cache[..]")
91-
.with_stderr_contains(miss)
92-
.with_stderr_does_not_contain(hit)
93-
.with_stderr_contains(update)
91+
.with_stderr_contains(MISS)
92+
.with_stderr_does_not_contain(HIT)
93+
.with_stderr_contains(UPDATE)
9494
.run();
9595

9696
p.cargo("build")
9797
.env("CARGO_LOG", "cargo::util::rustc=debug")
9898
.env("RUSTC", other_rustc.display().to_string())
9999
.with_stderr_contains("[..]reusing existing rustc info cache[..]")
100-
.with_stderr_contains(hit)
101-
.with_stderr_does_not_contain(miss)
102-
.with_stderr_does_not_contain(update)
100+
.with_stderr_contains(HIT)
101+
.with_stderr_does_not_contain(MISS)
102+
.with_stderr_does_not_contain(UPDATE)
103103
.run();
104104
}
105+
106+
#[cargo_test]
107+
fn rustc_info_cache_with_wrappers() {
108+
let wrapper_project = project()
109+
.at("wrapper")
110+
.file("Cargo.toml", &basic_bin_manifest("wrapper"))
111+
.file("src/main.rs", r#"fn main() { }"#)
112+
.build();
113+
let wrapper = wrapper_project.bin("wrapper");
114+
115+
let p = project()
116+
.file(
117+
"Cargo.toml",
118+
r#"
119+
[package]
120+
name = "test"
121+
version = "0.0.0"
122+
authors = []
123+
[workspace]
124+
"#,
125+
)
126+
.file("src/main.rs", r#"fn main() { println!("hello"); }"#)
127+
.build();
128+
129+
for &wrapper_env in ["RUSTC_WRAPPER", "RUSTC_WORKSPACE_WRAPPER"].iter() {
130+
p.cargo("clean").with_status(0).run();
131+
wrapper_project.change_file(
132+
"src/main.rs",
133+
r#"
134+
fn main() {
135+
let mut args = std::env::args_os();
136+
let _me = args.next().unwrap();
137+
let rustc = args.next().unwrap();
138+
let status = std::process::Command::new(rustc).args(args).status().unwrap();
139+
std::process::exit(if status.success() { 0 } else { 1 })
140+
}
141+
"#,
142+
);
143+
wrapper_project.cargo("build").with_status(0).run();
144+
145+
p.cargo("build")
146+
.env("CARGO_LOG", "cargo::util::rustc=debug")
147+
.env(wrapper_env, &wrapper)
148+
.with_stderr_contains("[..]failed to read rustc info cache[..]")
149+
.with_stderr_contains(MISS)
150+
.with_stderr_contains(UPDATE)
151+
.with_stderr_does_not_contain(HIT)
152+
.with_status(0)
153+
.run();
154+
p.cargo("build")
155+
.env("CARGO_LOG", "cargo::util::rustc=debug")
156+
.env(wrapper_env, &wrapper)
157+
.with_stderr_contains("[..]reusing existing rustc info cache[..]")
158+
.with_stderr_contains(HIT)
159+
.with_stderr_does_not_contain(UPDATE)
160+
.with_stderr_does_not_contain(MISS)
161+
.with_status(0)
162+
.run();
163+
164+
wrapper_project.change_file("src/main.rs", r#"fn main() { panic!() }"#);
165+
wrapper_project.cargo("build").with_status(0).run();
166+
167+
p.cargo("build")
168+
.env("CARGO_LOG", "cargo::util::rustc=debug")
169+
.env(wrapper_env, &wrapper)
170+
.with_stderr_contains("[..]different compiler, creating new rustc info cache[..]")
171+
.with_stderr_contains(MISS)
172+
.with_stderr_contains(UPDATE)
173+
.with_stderr_does_not_contain(HIT)
174+
.with_status(101)
175+
.run();
176+
p.cargo("build")
177+
.env("CARGO_LOG", "cargo::util::rustc=debug")
178+
.env(wrapper_env, &wrapper)
179+
.with_stderr_contains("[..]reusing existing rustc info cache[..]")
180+
.with_stderr_contains(HIT)
181+
.with_stderr_does_not_contain(UPDATE)
182+
.with_stderr_does_not_contain(MISS)
183+
.with_status(101)
184+
.run();
185+
}
186+
}

0 commit comments

Comments
 (0)