Skip to content

Commit 9d1a486

Browse files
committed
Auto merge of #8755 - ehuss:fingerprint-lto, r=alexcrichton
Add LTO to the metadata filename hash. There are some rare cases where different cargo commands end up building dependencies with different LTO settings. This adds the LTO value to the filename hash so that the cache does not thrash when switching between these commands. Fixes #8669
2 parents f5e5e0e + a2e48fd commit 9d1a486

File tree

5 files changed

+86
-11
lines changed

5 files changed

+86
-11
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@ fn compute_metadata(
519519
// settings like debuginfo and whatnot.
520520
unit.profile.hash(&mut hasher);
521521
unit.mode.hash(&mut hasher);
522+
cx.lto[unit].hash(&mut hasher);
522523

523524
// Artifacts compiled for the host should have a different metadata
524525
// piece than those compiled for the target, so make sure we throw in

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,10 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
126126
let mut queue = JobQueue::new(self.bcx);
127127
let mut plan = BuildPlan::new();
128128
let build_plan = self.bcx.build_config.build_plan;
129+
self.lto = super::lto::generate(&self.bcx)?;
129130
self.prepare_units()?;
130131
self.prepare()?;
131132
custom_build::build_map(&mut self)?;
132-
super::lto::generate(&mut self)?;
133133
self.check_collistions()?;
134134

135135
for unit in &self.bcx.roots {

src/cargo/core/compiler/fingerprint.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
//! -C incremental=… flag | ✓ |
7373
//! mtime of sources | ✓[^3] |
7474
//! RUSTFLAGS/RUSTDOCFLAGS | ✓ |
75-
//! LTO flags | ✓ |
75+
//! LTO flags | ✓ |
7676
//! config settings[^5] | ✓ |
7777
//! is_std | | ✓
7878
//!

src/cargo/core/compiler/lto.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::core::compiler::{CompileMode, Context, CrateType, Unit};
1+
use crate::core::compiler::{BuildContext, CompileMode, CrateType, Unit};
22
use crate::core::profiles;
33
use crate::util::interning::InternedString;
44

@@ -40,9 +40,9 @@ pub enum Lto {
4040
OnlyObject,
4141
}
4242

43-
pub fn generate(cx: &mut Context<'_, '_>) -> CargoResult<()> {
43+
pub fn generate(bcx: &BuildContext<'_, '_>) -> CargoResult<HashMap<Unit, Lto>> {
4444
let mut map = HashMap::new();
45-
for unit in cx.bcx.roots.iter() {
45+
for unit in bcx.roots.iter() {
4646
let root_lto = match unit.profile.lto {
4747
// LTO not requested, no need for bitcode.
4848
profiles::Lto::Bool(false) | profiles::Lto::Off => Lto::OnlyObject,
@@ -60,10 +60,9 @@ pub fn generate(cx: &mut Context<'_, '_>) -> CargoResult<()> {
6060
}
6161
}
6262
};
63-
calculate(cx, &mut map, unit, root_lto)?;
63+
calculate(bcx, &mut map, unit, root_lto)?;
6464
}
65-
cx.lto = map;
66-
Ok(())
65+
Ok(map)
6766
}
6867

6968
/// Whether or not any of these crate types need object code.
@@ -87,7 +86,7 @@ fn lto_when_needs_object(crate_types: &[CrateType]) -> Lto {
8786
}
8887

8988
fn calculate(
90-
cx: &Context<'_, '_>,
89+
bcx: &BuildContext<'_, '_>,
9190
map: &mut HashMap<Unit, Lto>,
9291
unit: &Unit,
9392
parent_lto: Lto,
@@ -185,8 +184,8 @@ fn calculate(
185184
}
186185
};
187186

188-
for dep in cx.unit_deps(unit) {
189-
calculate(cx, map, &dep.unit, merged_lto)?;
187+
for dep in &bcx.unit_graph[unit] {
188+
calculate(bcx, map, &dep.unit, merged_lto)?;
190189
}
191190
Ok(())
192191
}

tests/testsuite/lto.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -778,3 +778,78 @@ fn dylib_rlib_bin() {
778778
);
779779
verify_lto(&output, "foo", "--crate-type bin", Lto::Run(None));
780780
}
781+
782+
#[cargo_test]
783+
fn fresh_swapping_commands() {
784+
// In some rare cases, different commands end up building dependencies
785+
// with different LTO settings. This checks that it doesn't cause the
786+
// cache to thrash in that scenario.
787+
Package::new("bar", "1.0.0").publish();
788+
789+
let p = project()
790+
.file(
791+
"Cargo.toml",
792+
r#"
793+
[package]
794+
name = "foo"
795+
version = "0.1.0"
796+
797+
[dependencies]
798+
bar = "1.0"
799+
800+
[profile.release]
801+
lto = true
802+
"#,
803+
)
804+
.file("src/lib.rs", "pub fn foo() { println!(\"hi!\"); }")
805+
.build();
806+
807+
p.cargo("build --release -v")
808+
.with_stderr(
809+
"\
810+
[UPDATING] [..]
811+
[DOWNLOADING] crates ...
812+
[DOWNLOADED] bar v1.0.0 [..]
813+
[COMPILING] bar v1.0.0
814+
[RUNNING] `rustc --crate-name bar [..]-C linker-plugin-lto[..]
815+
[COMPILING] foo v0.1.0 [..]
816+
[RUNNING] `rustc --crate-name foo src/lib.rs [..]-C linker-plugin-lto[..]
817+
[FINISHED] [..]
818+
",
819+
)
820+
.run();
821+
p.cargo("test --release -v")
822+
.with_stderr_unordered(
823+
"\
824+
[COMPILING] bar v1.0.0
825+
[RUNNING] `rustc --crate-name bar [..]-C embed-bitcode=no[..]
826+
[COMPILING] foo v0.1.0 [..]
827+
[RUNNING] `rustc --crate-name foo src/lib.rs [..]--crate-type lib[..]-C embed-bitcode=no[..]
828+
[RUNNING] `rustc --crate-name foo src/lib.rs [..]-C embed-bitcode=no[..]--test[..]
829+
[FINISHED] [..]
830+
[RUNNING] `[..]/foo[..]`
831+
[DOCTEST] foo
832+
[RUNNING] `rustdoc [..]-C embed-bitcode=no[..]
833+
",
834+
)
835+
.run();
836+
837+
p.cargo("build --release -v")
838+
.with_stderr(
839+
"\
840+
[FRESH] bar v1.0.0
841+
[FRESH] foo [..]
842+
[FINISHED] [..]
843+
",
844+
)
845+
.run();
846+
p.cargo("test --release -v --no-run -v")
847+
.with_stderr(
848+
"\
849+
[FRESH] bar v1.0.0
850+
[FRESH] foo [..]
851+
[FINISHED] [..]
852+
",
853+
)
854+
.run();
855+
}

0 commit comments

Comments
 (0)