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

Rustc does not warn when .so/.rlib files are not in sync #10786

Closed
alexcrichton opened this issue Dec 3, 2013 · 10 comments · Fixed by #113695
Closed

Rustc does not warn when .so/.rlib files are not in sync #10786

alexcrichton opened this issue Dec 3, 2013 · 10 comments · Fixed by #113695
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-linkage Area: linking into static, shared libraries and binaries A-metadata Area: Crate metadata C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@alexcrichton
Copy link
Member

Right now the logic for reading metadata for a crate is to read it the first time the crate's dylib or rlib file is found. On the second file that's found, the metadata isn't read at all because metadata reading is one of the known slow portions of the compiler.

This implies that if an rlib file is regenerated, but the dylib isn't, then the two are out of sync and rustc will read the old metadata from the dylib and link to the rlib, resulting in linker errors.

I don't want to slow down rustc by reading metadata from all rlibs and dylibs, but this situation is far less than optimal. Perhaps this is a job for a rustpkg-like tool?

@emberian
Copy link
Member

emberian commented Apr 7, 2014

@alexcrichton is this still relevant? we don't do this checking, but the metadata isn't pulled from the dylib.

@alexcrichton
Copy link
Member Author

This has an interesting development:

$ RUST_LOG=rustc::metadata::loader=info rustc foo.rs 2>&1 | grep '^reading'
reading libstd-aad93cea-0.11-pre.rlib => 0ms
reading libstd-aad93cea-0.11-pre.so => 47ms
reading liblibc-8f65d5a8-0.10-pre.rlib => 0ms
reading liblibc-8f65d5a8-0.10-pre.so => 0ms
reading libstd-aad93cea-0.11-pre.rlib => 0ms
reading libstd-aad93cea-0.11-pre.so => 46ms
reading liblibc-8f65d5a8-0.10-pre.rlib => 0ms
reading liblibc-8f65d5a8-0.10-pre.so => 0ms
reading libnative-83574243-0.11-pre.rlib => 0ms
reading libnative-83574243-0.11-pre.so => 1ms

This issue is supposed to be relevant, but it looks like we're reading metadata of rlibs and dylibs. This is not necessary, and it looks like we could shave ~100ms off compiling hello world if it were taken care of.

In short, I'd like to keep this issue open.

alexcrichton added a commit to alexcrichton/rust that referenced this issue Apr 7, 2014
This is an optimization which is quite impactful for compiling small crates.
Reading libstd's metadata takes about 50ms, and a hello world before this change
took about 100ms (this change halves that time).

Recent changes made it such that this optimization wasn't performed, but I think
it's a better idea do to this for now. See rust-lang#10786 for tracking this issue.
alexcrichton added a commit to alexcrichton/rust that referenced this issue Apr 8, 2014
This is an optimization which is quite impactful for compiling small crates.
Reading libstd's metadata takes about 50ms, and a hello world before this change
took about 100ms (this change halves that time).

Recent changes made it such that this optimization wasn't performed, but I think
it's a better idea do to this for now. See rust-lang#10786 for tracking this issue.
@reem
Copy link
Contributor

reem commented Dec 1, 2014

Triage: I see that some progress has been made on this issue in the above commits. Does that re-enable this issue?

@steveklabnik
Copy link
Member

$ RUST_LOG=rustc::metadata::loader=info rustc hello.rs 2>&1 | grep reading
INFO:rustc::metadata::loader: rlib reading metadata from: /home/steve/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-4e7c5e5c.rlib
INFO:rustc::metadata::loader: reading libstd-4e7c5e5c.rlib => 0ms

just rlibs now, apparently. I'm giving this a close, @alexcrichton , feel free to reopen.

@alexcrichton
Copy link
Member Author

I think this is still an issue (reopening)

In this test case below a blank file is compiled to an rlib/dylib pair, then the rlib is recompiled with a new function. A later executable is then linked against the dylib (using the rlib metadata), succeeding all the way until the linker actually fails.

$ touch foo.rs
$ rustc --crate-type dylib,rlib foo.rs
$ ls
foo.rs       libfoo.dylib libfoo.rlib
$ echo 'pub fn foo() {}' > foo.rs
$ rustc --crate-type rlib foo.rs
$ echo 'extern crate foo; fn main() { foo::foo(); }' > bar.rs
$ rustc bar.rs -L. -C prefer-dynamic
error: linking with `cc` failed: exit code: 1
note: cc '-m64' '-L' '/Users/acrichton/code/rust/lib/rustlib/x86_64-apple-darwin/lib' '-o' 'bar' 'bar.o' '-Wl,-force_load,/Users/acrichton/code/rust/lib/rustlib/x86_64-apple-darwin/lib/libmorestack.a' '-Wl,-dead_strip' '-nodefaultlibs' '-L' '/Users/acrichton/test' '-lfoo' '-L' '/Users/acrichton/code/rust/lib/rustlib/x86_64-apple-darwin/lib' '-lstd-4e7c5e5c' '-L' '.' '-L' '/Users/acrichton/code/rust/lib/rustlib/x86_64-apple-darwin/lib' '-L' '/Users/acrichton/test/.rust/lib/x86_64-apple-darwin' '-L' '/Users/acrichton/test/lib/x86_64-apple-darwin' '-L' '/Users/acrichton/.rust/lib/x86_64-apple-darwin' '-lSystem' '-lpthread' '-lc' '-lm' '-lcompiler-rt'
note: ld: warning: directory not found for option '-L/Users/acrichton/test/.rust/lib/x86_64-apple-darwin'
ld: warning: directory not found for option '-L/Users/acrichton/test/lib/x86_64-apple-darwin'
ld: warning: directory not found for option '-L/Users/acrichton/.rust/lib/x86_64-apple-darwin'
Undefined symbols for architecture x86_64:
  "foo::ha37403d109b4e734eaa", referenced from:
      main::h7e1981c1a43d0b7afaa in bar.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

error: aborting due to previous error

@alexcrichton alexcrichton reopened this Jan 23, 2015
@steveklabnik
Copy link
Member

Ahh, I forgot the crate-types. :(

@steveklabnik
Copy link
Member

Triage: the error is slightly different:

error: linking with `cc` failed: exit code: 1
note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/home/steve/.multirust/toolchains/nightly/lib/rustlib/x86_64-unknown-linux-gnu/lib" "bar.0.o" "-o" "bar" "-Wl,--gc-sections" "-pie" "-nodefaultlibs" "-L" "." "-L" "/home/steve/.multirust/toolchains/nightly/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "-Wl,-Bdynamic" "-L" "/home/steve/tmp" "-l" "foo" "-L" "/home/steve/.multirust/toolchains/nightly/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-l" "std-fd663c41" "-l" "dl" "-l" "pthread" "-l" "gcc_s" "-l" "pthread" "-l" "c" "-l" "m" "-l" "rt" "-l" "compiler-rt"
note: bar.0.o: In function `main::h7afac322a1b32d81faa':
bar.0.rs:(.text._ZN4main20h7afac322a1b32d81faaE+0x2): undefined reference to `foo::hfe26232f3a6cc9a1eaa'
collect2: error: ld returned 1 exit status

error: aborting due to previous error

@Mark-Simulacrum Mark-Simulacrum added A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. C-feature-request Category: A feature request, i.e: not implemented / a PR. and removed C-enhancement Category: An issue proposing an enhancement or a PR with one. labels Jul 20, 2017
@jonas-schievink jonas-schievink added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. A-metadata Area: Crate metadata A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug. and removed C-feature-request Category: A feature request, i.e: not implemented / a PR. labels Jan 12, 2020
@jonas-schievink
Copy link
Contributor

jonas-schievink commented Jan 12, 2020

Triage: This still happens, and seems like a bug with metadata loading and linkage, rather than just a diagnostics issue.

The compiler should not load metadata from one file and then link against another while assuming its contents match.

@gilescope
Copy link
Contributor

Would #75594 help here? If we use libcrate_name-svh.rmeta as the metadata filename then we could check if the metadata was up to date without having to read more than the filename in the archive.

@tmandry
Copy link
Member

tmandry commented Dec 4, 2020

I just got bit by this, except instead of a Rust rlib and dylib, the compiler found a Rust rlib and a .so file of the same name compiled by clang. (The Rust library wraps the C++ one which is why they have the same name.)

It then proceeded as if the .so was the dynamic version of the Rust library, leading to a linker error. Definitely confusing.

flip1995 pushed a commit to flip1995/rust that referenced this issue May 20, 2023
…one-from-needless-collect-example, r=Alexendoo

Remove unnecessary `clone` from `needless_collect` example

The example for [clippy::needless_collect](https://rust-lang.github.io/rust-clippy/master/#needless_collect) is written as follows:

```rust
let len = iterator.clone().collect::<Vec<_>>().len();
// should be
let len = iterator.count();
```

With this change, the unnecessary `clone()` is removed and the the standard

    ### Example
    ```rust
    // original
    ```
    Use instead:
    ```rust
    // improved
    ```

structure is followed.

Discussion: rust-lang/rust-clippy#10784 (comment)

changelog: [`needless_collect`]: Cleaned up the example in the lint documentation.
@bors bors closed this as completed in b14fd23 Jul 20, 2023
github-actions bot pushed a commit to rust-lang/miri that referenced this issue Jul 22, 2023
…nkfelix,petrochenkov

Verify that all crate sources are in sync

This ensures that rustc will not attempt to link against a cdylib as if it is a rust dylib when an rlib for the same crate is available. Previously rustc didn't actually check if any further formats of a crate which has been loaded are of the same version and if they are actually valid. This caused a cdylib to be interpreted as rust dylib as soon as the corresponding rlib was loaded. As cdylibs don't export any rust symbols, linking would fail if rustc decides to link against the cdylib rather than the rlib.

Two crates depended on the previous behavior by separately compiling a test crate as both rlib and dylib. These have been changed to capture their original spirit to the best of my ability while still working when rustc verifies that all crates are in sync. It is unlikely that build systems depend on the current behavior and in any case we are taking a lot of measures to ensure that any change to either the source or the compilation options (including crate type) results in rustc rejecting it as incompatible. We merely didn't do this check here for now obsolete perf reasons.

Fixes rust-lang/rust#10786
Fixes rust-lang/rust#82151
Fixes rust-lang/rust#82972
Closes bevy-cheatbook/bevy-cheatbook#114
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-linkage Area: linking into static, shared libraries and binaries A-metadata Area: Crate metadata C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
8 participants