From a2e63e6799aac8fa0974fa388731b30daded5ad9 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 17 Dec 2024 20:25:51 +0100 Subject: [PATCH] Do not hash absolute sysroot path into stdlib crates metadata. stdlib crates get a SourceId which has an absolute path pointing into the sysroot. This makes the metadata hash change depending on where you've installed Rust. This is causing problems because the different hashes snowball into the optimizer making different decisions which ends up changing the binary size. (Some context: at work we're working with embedded devices with little flash storage so it often happens that a binary builds locally and then fails to fit in flash in CI, just because CI has installed rustc to a different path. Improving binary size is *not* a goal of this PR, after the fix the size will be whatever, but at least it won't change based on the rustc path anymore) Overview of the fix: - For libstd crates, the metadata hash now contains the path relative to the sysroot, instead of the absolute path. - The absolute path is still hashed into the fingerprint (not the metadata) so moving the rustc installation triggers a rebuild. This ensures stdlib crates are rebuilt when upgrading nightly versions. - The rustc version is still hashed into the metadata as usual, so upgrading Rust releases (not nightly versions) does cause a metadata change. Repro of the bug: ``` $ git clone https://github.com/embassy-rs/embassy --branch cargo-nondet-repro $ cd embassy/ $ cd examples/nrf52840 $ RUSTUP_HOME=~/.rustup1 cargo build --release --bin wifi_esp_hosted .... Finished `release` profile [optimized + debuginfo] target(s) in 13.33s $ llvm-size target/thumbv7em-none-eabi/release/wifi_esp_hosted text data bss dec hex filename 114500 80 48116 162696 27b88 target/thumbv7em-none-eabi/release/wifi_esp_hosted $ RUSTUP_HOME=~/.rustup2 cargo build --release --bin wifi_esp_hosted .... Finished `release` profile [optimized + debuginfo] target(s) in 9.64s $ llvm-size target/humbv7em-none-eabi/release/wifi_esp_hosted text data bss dec hex filename 114272 80 48116 162468 27aa4 target/thumbv7em-none-eabi/release/wifi_esp_hosted ``` --- .../core/compiler/build_runner/compilation_files.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/cargo/core/compiler/build_runner/compilation_files.rs b/src/cargo/core/compiler/build_runner/compilation_files.rs index d9b6676d10a..8c7ddff7f89 100644 --- a/src/cargo/core/compiler/build_runner/compilation_files.rs +++ b/src/cargo/core/compiler/build_runner/compilation_files.rs @@ -604,11 +604,20 @@ fn compute_metadata( METADATA_VERSION.hash(&mut shared_hasher); + let ws_root = if unit.is_std { + // SourceId for stdlib crates is an absolute path inside the sysroot. + // Pass the sysroot as workspace root so that we hash a relative path. + // This avoids the metadata hash changing depending on where the user installed rustc. + &bcx.target_data.get_info(unit.kind).unwrap().sysroot + } else { + bcx.ws.root() + }; + // Unique metadata per (name, source, version) triple. This'll allow us // to pull crates from anywhere without worrying about conflicts. unit.pkg .package_id() - .stable_hash(bcx.ws.root()) + .stable_hash(ws_root) .hash(&mut shared_hasher); // Also mix in enabled features to our metadata. This'll ensure that