Skip to content

Commit 700d0f0

Browse files
committed
feat: maximizes artifact reuse between different modes.
As of this writing, it aims to reuse `rmeta` between build and check modes. (one emits rmeta + rlib, and the other emits rmeta) This has a caveat that `DefId` in rmeta files might not match between rustc invocations with different `--emits` values, and that might lead to rustc rejecting the input rmeta. To avoid failures in rustc, this is currently guarded by fingerprint to ensure all output files present, if not, rerun. This make running `check` after `build` safe: `build`'s rmeta files might have more information and rustc is correct on rejection.
1 parent a7715cb commit 700d0f0

File tree

7 files changed

+37
-7
lines changed

7 files changed

+37
-7
lines changed

src/cargo/core/compiler/build_config.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,26 @@ impl CompileMode {
250250
pub fn generates_executable(self) -> bool {
251251
matches!(self, CompileMode::Test | CompileMode::Build)
252252
}
253+
254+
/// Maximizes artifact reuse between different modes.
255+
///
256+
/// As of this writing, it aims to reuse `rmeta` between build and check modes.
257+
/// (one emits rmeta + rlib, and the other emits rmeta)
258+
///
259+
/// This has a caveat that `DefId` in rmeta files might not match between rustc
260+
/// invocations with different `--emits` values, and that might lead to rustc
261+
/// rejecting the input rmeta. To avoid failures in rustc, this is currently
262+
/// guarded by fingerprint to ensure all output files present, if not, rerun.
263+
/// This make running `check` after `build` safe: `build`'s rmeta files might
264+
/// have more information and rustc is correct on rejection.
265+
pub fn for_reuse(self) -> CompileMode {
266+
match self {
267+
// We might want to reuse `Test` and `Check { test: true }`,
268+
// but those are usually local so dont bother it
269+
CompileMode::Build | CompileMode::Check { test: false } => CompileMode::Build,
270+
m => m,
271+
}
272+
}
253273
}
254274

255275
/// Represents the high-level operation requested by the user.

src/cargo/core/compiler/build_runner/compilation_files.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,7 @@ fn compute_metadata(
650650
// `panic=abort` and `panic=unwind` artifacts, additionally with various
651651
// settings like debuginfo and whatnot.
652652
unit.profile.hash(&mut shared_hasher);
653-
unit.mode.hash(&mut shared_hasher);
653+
unit.mode.for_reuse().hash(&mut shared_hasher);
654654
build_runner.lto[unit].hash(&mut shared_hasher);
655655

656656
// Artifacts compiled for the host should have a different

src/cargo/core/compiler/build_runner/mod.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,12 +600,23 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> {
600600
}
601601
for output in self.outputs(unit)?.iter() {
602602
if let Some(other_unit) = output_collisions.insert(output.path.clone(), unit) {
603+
let is_check = |u: &Unit| matches!(u.mode, CompileMode::Check { test: false });
604+
let is_build = |u: &Unit| matches!(u.mode, CompileMode::Build);
605+
let is_build_check_reuse =
606+
|a, b| (is_check(a) && is_build(b)) || (is_check(b) && is_build(a));
607+
603608
if unit.mode.is_doc() {
604609
// See https://github.com/rust-lang/rust/issues/56169
605610
// and https://github.com/rust-lang/rust/issues/61378
606611
report_collision(unit, other_unit, &output.path, rustdoc_suggestion)?;
607612
} else {
608-
report_collision(unit, other_unit, &output.path, suggestion)?;
613+
if is_build_check_reuse(unit, other_unit) {
614+
tracing::debug!(
615+
"reusing artifacts between {unit:?} and {other_unit:?}"
616+
);
617+
} else {
618+
report_collision(unit, other_unit, &output.path, suggestion)?;
619+
}
609620
}
610621
}
611622
if let Some(hardlink) = output.hardlink.as_ref() {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1537,7 +1537,7 @@ fn calculate_normal(
15371537

15381538
let profile_hash = util::hash_u64((
15391539
&unit.profile,
1540-
unit.mode,
1540+
unit.mode.for_reuse(),
15411541
build_runner.bcx.extra_args_for(unit),
15421542
build_runner.lto[unit],
15431543
unit.pkg.manifest().lint_rustflags(),

tests/testsuite/artifact_dep.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2416,7 +2416,7 @@ fn doc_lib_true() {
24162416

24172417
// Verify that it emits rmeta for the bin and lib dependency.
24182418
assert_eq!(p.glob("target/debug/artifact/*.rlib").count(), 0);
2419-
assert_eq!(p.glob("target/debug/deps/libbar-*.rmeta").count(), 2);
2419+
assert_eq!(p.glob("target/debug/deps/libbar-*.rmeta").count(), 1);
24202420

24212421
p.cargo("doc -Z bindeps")
24222422
.masquerade_as_nightly_cargo(&["bindeps"])

tests/testsuite/collisions.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,6 @@ fn collision_doc_profile_split() {
404404
p.cargo("doc")
405405
.with_stderr_data(
406406
str![[r#"
407-
[CHECKING] common v1.0.0
408407
[DOCUMENTING] common v1.0.0
409408
[DOCUMENTING] pm v0.1.0 ([ROOT]/foo/pm)
410409
[DOCUMENTING] foo v0.1.0 ([ROOT]/foo)

tests/testsuite/freshness.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3210,8 +3210,7 @@ fn rmeta_reuse() {
32103210

32113211
p.cargo("check --verbose")
32123212
.with_stderr_data(str![[r#"
3213-
[CHECKING] foo v0.0.0 ([ROOT]/foo)
3214-
[RUNNING] `rustc [..]`
3213+
[FRESH] foo v0.0.0 ([ROOT]/foo)
32153214
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
32163215
32173216
"#]])
@@ -3229,6 +3228,7 @@ fn rmeta_reuse() {
32293228

32303229
p.cargo("build --verbose")
32313230
.with_stderr_data(str![[r#"
3231+
[DIRTY] foo v0.0.0 ([ROOT]/foo): couldn't read metadata for file `target/debug/deps/libfoo-[HASH].rlib`
32323232
[COMPILING] foo v0.0.0 ([ROOT]/foo)
32333233
[RUNNING] `rustc [..]`
32343234
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s

0 commit comments

Comments
 (0)