Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not reproducible when a project is copied to another directory #13586

Open
cathy-sjh opened this issue Mar 14, 2024 · 3 comments · May be fixed by #14953
Open

Not reproducible when a project is copied to another directory #13586

cathy-sjh opened this issue Mar 14, 2024 · 3 comments · May be fixed by #14953
Labels
A-reproducibility Area: reproducible / deterministic builds C-bug Category: bug S-needs-info Status: Needs more info, such as a reproduction or more background for a feature request.

Comments

@cathy-sjh
Copy link

cathy-sjh commented Mar 14, 2024

The Compiled Binary Files Are Inconsistent After the Directory of the Rust Package Is Changed.
It is important to have reproducible builds.
Let's say I have two crate in my project, crate mangle2 depends on crate mangle1 and they are located in directory1.

root -> /usr1/directory1 $  tree 
.
├── mangle1
│   ├── Cargo.toml
│   └── src
│       └── lib.rs
└── mangle2
    ├── Cargo.toml
    └── src
        └── lib.rs

mangle1/Cargo.toml file:

[package]
name = "mangle1"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

mangle1/src/lib.rs file:

pub fn sjhadd(left: usize, right: usize) -> usize {
    left + right
}

in mangle2/Cargo.toml file, we see mangle2 depends on mangle1.

[package]
name = "mangle2"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
mangle1 = { path = "../mangle1" }

in mangle2/src/lib.rs file

use mangle1::sjhadd;

#[inline(never)]
pub fn super_add(left: usize, right: usize) -> usize {
    sjhadd(left, right)
}

Then I went into the mangle2 directory and compiled the whole project.

root -> /usr1/directory1/mangle2 $ cargo build --release -v
   Compiling mangle1 v0.1.0 (/usr1/s00659936/rust_program/mangle_disambiguator_test/test2/mangle1)
     Running `/root/.rustup/toolchains/nightly-aarch64-unknown-linux-gnu/bin/rustc --crate-name mangle1 --edition=2021 /usr1/s00659936/rust_program/mangle_disambiguator_test/test2/mangle1/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=187 --crate-type lib --emit=dep-info,metadata,link -C opt-level=3 -C embed-bitcode=no -C metadata=feabc6ec5051cf34 -C extra-filename=-feabc6ec5051cf34 --out-dir /usr1/s00659936/rust_program/mangle_disambiguator_test/test2/mangle2/target/release/deps -L dependency=/usr1/s00659936/rust_program/mangle_disambiguator_test/test2/mangle2/target/release/deps`
   Compiling mangle2 v0.1.0 (/usr1/s00659936/rust_program/mangle_disambiguator_test/test2/mangle2)
     Running `/root/.rustup/toolchains/nightly-aarch64-unknown-linux-gnu/bin/rustc --crate-name mangle2 --edition=2021 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=187 --crate-type lib --emit=dep-info,metadata,link -C opt-level=3 -C embed-bitcode=no -C metadata=b27aeebcd77b3cf1 -C extra-filename=-b27aeebcd77b3cf1 --out-dir /usr1/s00659936/rust_program/mangle_disambiguator_test/test2/mangle2/target/release/deps -L dependency=/usr1/s00659936/rust_program/mangle_disambiguator_test/test2/mangle2/target/release/deps --extern mangle1=/usr1/s00659936/rust_program/mangle_disambiguator_test/test2/mangle2/target/release/deps/libmangle1-feabc6ec5051cf34.rmeta`
    Finished release [optimized] target(s) in 0.19s

when compiling mangle2, we see -C metadata=b27aeebcd77b3cf1.

Then I copied the directory1 directory to another location directory2.

root -> /usr1 $  cp directory1 directory2  -rf
root -> /usr1 $  cd directory2
root -> /usr1/directory2 $  tree 
.
├── mangle1
│   ├── Cargo.toml
│   └── src
│       └── lib.rs
└── mangle2
    ├── Cargo.toml
    └── src
        └── lib.rs

As before, I went into the mangle2 directory and compiled the whole project.

root -> /usr1/directory2/mangle2 $ cargo build --release -v
   Compiling mangle1 v0.1.0 (/usr1/s00659936/rust_program/mangle_disambiguator_test/test2_ba/mangle1)
     Running `/root/.rustup/toolchains/nightly-aarch64-unknown-linux-gnu/bin/rustc --crate-name mangle1 --edition=2021 /usr1/s00659936/rust_program/mangle_disambiguator_test/test2_ba/mangle1/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=187 --crate-type lib --emit=dep-info,metadata,link -C opt-level=3 -C embed-bitcode=no -C metadata=4bd5b689377ef005 -C extra-filename=-4bd5b689377ef005 --out-dir /usr1/s00659936/rust_program/mangle_disambiguator_test/test2_ba/mangle2/target/release/deps -L dependency=/usr1/s00659936/rust_program/mangle_disambiguator_test/test2_ba/mangle2/target/release/deps`
   Compiling mangle2 v0.1.0 (/usr1/s00659936/rust_program/mangle_disambiguator_test/test2_ba/mangle2)
     Running `/root/.rustup/toolchains/nightly-aarch64-unknown-linux-gnu/bin/rustc --crate-name mangle2 --edition=2021 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=187 --crate-type lib --emit=dep-info,metadata,link -C opt-level=3 -C embed-bitcode=no -C metadata=6bc8f0dbcefdbca3 -C extra-filename=-6bc8f0dbcefdbca3 --out-dir /usr1/s00659936/rust_program/mangle_disambiguator_test/test2_ba/mangle2/target/release/deps -L dependency=/usr1/s00659936/rust_program/mangle_disambiguator_test/test2_ba/mangle2/target/release/deps --extern mangle1=/usr1/s00659936/rust_program/mangle_disambiguator_test/test2_ba/mangle2/target/release/deps/libmangle1-4bd5b689377ef005.rmeta`
    Finished release [optimized] target(s) in 0.21s

this time when compiling mangle2, we see -C metadata=6bc8f0dbcefdbca3.
The metadata of the two compilations is different. Therefore, the symbol table names in the generated binary files are different.
_ZN7mangle29super_add17heef584606885c889E change to _ZN7mangle29super_add17h7cd0a6fdff1a3985E

I just copied the project to a different directory and didn't change any code. Compiling in different directories caused binary inconsistencies.
If a single crate is copied to another directory for compilation, this problem does not occur. Binary inconsistency occurs when two crates depend on each other and both crates are copied to another directory.

rustc --version --verbose:

rustc 1.76.0-nightly (f5dc2653f 2023-11-25)
binary: rustc
commit-hash: f5dc2653fdd8b5d177b2ccbd84057954340a89fc
commit-date: 2023-11-25
host: aarch64-unknown-linux-gnu
release: 1.76.0-nightly
LLVM version: 17.0.5
@cathy-sjh cathy-sjh added the C-bug Category: bug label Mar 14, 2024
@jieyouxu jieyouxu added the A-reproducibility Area: reproducible / deterministic builds label Mar 14, 2024
@jyn514
Copy link
Member

jyn514 commented Mar 14, 2024

this is a cargo issue, not a compiler one. -C metadata is passed by cargo.

@weihanglo weihanglo transferred this issue from rust-lang/rust Mar 15, 2024
@weihanglo weihanglo added S-triage Status: This issue is waiting on initial triage. A-reproducibility Area: reproducible / deterministic builds and removed A-reproducibility Area: reproducible / deterministic builds labels Mar 15, 2024
@weihanglo
Copy link
Member

/// Hashes `self`.
///
/// For paths, remove the workspace prefix so the same source will give the
/// same hash in different locations, helping reproducible builds.
pub fn stable_hash<S: hash::Hasher>(self, workspace: &Path, into: &mut S) {

If crates are in the same workspace, their paths will be relative to workspace and get hashed into metadata. This is likely by design to avoid reuse cache coming from different workspace when sharing CARGO_TARGET_DIR. Not 100% sure because I wasn't there when #3611 landed.

So for you, mangle1 is outside the workspace (where mangle2 is located), so its metadata always contains absolute paths. And mangle1's metadata will hash into mangle2's.

The straightforward solution for you is putting these crates under a single workspace.

@weihanglo weihanglo added S-needs-info Status: Needs more info, such as a reproduction or more background for a feature request. and removed S-triage Status: This issue is waiting on initial triage. labels Mar 16, 2024
@weihanglo
Copy link
Member

It is tempted to use pathdiff and hash relative paths instead of absolutes. Yet it doesn't help reproducibility when you move and change the relative path of the crate to the workspace, without any code change.

Dirbaio added a commit to Dirbaio/cargo that referenced this issue Dec 18, 2024
@Dirbaio Dirbaio linked a pull request Dec 18, 2024 that will close this issue
Dirbaio added a commit to embassy-rs/cargo-batch that referenced this issue Dec 18, 2024
Dirbaio added a commit to embassy-rs/cargo-batch that referenced this issue Dec 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-reproducibility Area: reproducible / deterministic builds C-bug Category: bug S-needs-info Status: Needs more info, such as a reproduction or more background for a feature request.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants