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

Symbols from static libraries used by dependent crates are no longer included into cdylib #96192

Closed
goffrie opened this issue Apr 18, 2022 · 3 comments
Labels
C-bug Category: This is a bug.

Comments

@goffrie
Copy link
Contributor

goffrie commented Apr 18, 2022

Here is the setup. This is all on x86_64-unknown-linux-gnu.

lib.c:

void symbol(void) {}

dep.rs:

extern "C" { fn symbol(); }
pub unsafe fn inner() { symbol(); }

test.rs:

#[no_mangle]
pub unsafe extern "C" fn outer() { dep::inner(); }

Then we run these commands:

# make a static library containing `symbol`
gcc lib.c -o lib.o -c
ar rc liblib.a lib.o
# compile an rlib that uses `symbol`
rustc dep.rs --crate-type rlib
# compile a cdylib that uses the rlib, and attempt to link the static library
rustc test.rs --crate-type cdylib -Lnative=. -lstatic=lib --extern dep=libdep.rlib

Previously, this worked and linked symbol into the resulting cdylib:

# nm libtest.so | grep -w symbol
00000000000066b5 t symbol

However, it now results in an unresolved symbol:

# nm libtest.so | grep -w symbol
                 U symbol

Which seems wrong, since we asked to link liblib.a into libtest.so. The issue also doesn't occur if the static library is used directly from the cdylib crate.

Bisection reveals that the regression occurred in #95501, which is a rollup; the most likely culprit appears to be #93901.

@goffrie goffrie added the C-bug Category: This is a bug. label Apr 18, 2022
@goffrie
Copy link
Contributor Author

goffrie commented Apr 18, 2022

I had hoped that #95604 would fix this since it seems very related, but I downloaded the try build and it does not appear to.

@petrochenkov petrochenkov self-assigned this Apr 18, 2022
@petrochenkov
Copy link
Contributor

petrochenkov commented Apr 19, 2022

It becomes clearer what happens if you build test.rs as an executable.

rustc test.rs --crate-type bin -Lnative=. -lstatic=lib --extern dep=libdep.rlib
  = note: /usr/bin/ld: /home/we/linkrepr/libdep.rlib(dep.dep.468be17b-cgu.0.rcgu.o): in function `dep::inner':
          dep.468be17b-cgu.0:(.text._ZN3dep5inner17h014ce670d35af615E+0x3): undefined reference to `symbol'

The build will just fail, while with cdylibs remaining unresolved symbols are ok by default.

rustc sorts libraries (both rlibs and native libraries) in topological order, so dependency libraries come after libraries that depend on them.
In your build nothing says that dep.rs (libdep.rlib) depends on lib.c (liblib.a), so rustc puts liblib before libdep on the command line (besides the topological sorting the order may be considered random).
So liblib is simply dropped by the linker when it's encountered, because it doesn't provide any necessary symbols at that point.

What saved the build before #93901 is that rustc linked liblib as whole-archive in that particular case, so it wasn't dropped even if it wasn't needed.
After #93901 we try not to use whole-archive unless explicitly requested, so this case is broken.

The right fix here is to specify that dep.rs depends on lib.c, by using #[link(name = "lib")] or -l lib when compiling dep.rs.

@petrochenkov petrochenkov removed their assignment Apr 19, 2022
@goffrie
Copy link
Contributor Author

goffrie commented Apr 20, 2022

Thanks for the detailed response! That makes sense, and the solution seems reasonable. I'm fine with saying that this is not a bug then.

For what it's worth this happened because we're using Bazel and rules_rust, wherein adding native dependencies to a Rust target causes them to be added only to the final crate's command line, not intermediate ones. So it's possible that other people will hit this too. But that's a rules_rust issue, not really a rustc one.

@goffrie goffrie closed this as completed Apr 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests

2 participants