Skip to content

Commit e1a45ff

Browse files
committed
feat: maximize 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 e1a45ff

File tree

7 files changed

+27
-6
lines changed

7 files changed

+27
-6
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: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,8 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> {
604604
// See https://github.com/rust-lang/rust/issues/56169
605605
// and https://github.com/rust-lang/rust/issues/61378
606606
report_collision(unit, other_unit, &output.path, rustdoc_suggestion)?;
607+
} else if unit.mode.for_reuse() == other_unit.mode.for_reuse() {
608+
tracing::debug!("reusing artifacts between {unit:?} and {other_unit:?}");
607609
} else {
608610
report_collision(unit, other_unit, &output.path, suggestion)?;
609611
}

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)