Skip to content

Commit

Permalink
Make -Cmetadata consistent across platforms
Browse files Browse the repository at this point in the history
This commit updates how `-Cmetadata` is calculated for each unit to
optionally exclude the `host: ...` line that rustc prints for
cross-compiled builds. Previously the full `verbose_version` was hashed
for stable builds and the `host` was explicitly hashed for non-stable
builds. For a build using `--target`, however, that means that the
`-Cmetadata` will be different when producing the same target on
different hosts (e.g. producing the binary once on Linux and once on
macOS).

This can hinder reproduction of a binary across different platforms even
when the `--target` flag is used. For example in rust-lang/rust#117597
it was seen that a WebAssembly binary produced on different platforms
was slightly different and this appears due to the differing
`-Cmetadata` flags. After this commit the `-Cmetadata` flag is the same
for two different platforms meaning that different platforms produce the
same binary.

I've tested locally and a simple project produces a different binary
before this change but produces the same binary on two platforms after
this change. Unfortunately automated testing of this change will be
difficult since it requires two different host compilers, though.
  • Loading branch information
alexcrichton committed Jun 19, 2024
1 parent ac8c6ab commit 2db0bab
Showing 1 changed file with 14 additions and 5 deletions.
19 changes: 14 additions & 5 deletions src/cargo/core/compiler/build_runner/compilation_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,7 @@ fn compute_metadata(
unit.target.name().hash(&mut hasher);
unit.target.kind().hash(&mut hasher);

hash_rustc_version(bcx, &mut hasher);
hash_rustc_version(bcx, &mut hasher, unit);

if build_runner.bcx.ws.is_member(&unit.pkg) {
// This is primarily here for clippy. This ensures that the clippy
Expand Down Expand Up @@ -656,12 +656,19 @@ fn compute_metadata(
}

/// Hash the version of rustc being used during the build process.
fn hash_rustc_version(bcx: &BuildContext<'_, '_>, hasher: &mut StableHasher) {
fn hash_rustc_version(bcx: &BuildContext<'_, '_>, hasher: &mut StableHasher, unit: &Unit) {
let vers = &bcx.rustc().version;
if vers.pre.is_empty() || bcx.gctx.cli_unstable().separate_nightlies {
// For stable, keep the artifacts separate. This helps if someone is
// testing multiple versions, to avoid recompiles.
bcx.rustc().verbose_version.hash(hasher);
// testing multiple versions, to avoid recompiles. Note though that for
// cross-compiled builds the `host:` line of `verbose_version` is
// omitted since rustc should produce the same output for each target
// regardless of the host.
for line in bcx.rustc().verbose_version.lines() {
if unit.kind.is_host() || !line.starts_with("host: ") {
line.hash(hasher);
}
}
return;
}
// On "nightly"/"beta"/"dev"/etc, keep each "channel" separate. Don't hash
Expand All @@ -674,7 +681,9 @@ fn hash_rustc_version(bcx: &BuildContext<'_, '_>, hasher: &mut StableHasher) {
// Keep "host" since some people switch hosts to implicitly change
// targets, (like gnu vs musl or gnu vs msvc). In the future, we may want
// to consider hashing `unit.kind.short_name()` instead.
bcx.rustc().host.hash(hasher);
if unit.kind.is_host() {
bcx.rustc().host.hash(hasher);
}
// None of the other lines are important. Currently they are:
// binary: rustc <-- or "rustdoc"
// commit-hash: 38114ff16e7856f98b2b4be7ab4cd29b38bed59a
Expand Down

0 comments on commit 2db0bab

Please sign in to comment.