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

#[link(kind="static")] extern still prefers .so #12557

Closed
kmcallister opened this issue Feb 26, 2014 · 2 comments
Closed

#[link(kind="static")] extern still prefers .so #12557

kmcallister opened this issue Feb 26, 2014 · 2 comments
Labels
A-FFI Area: Foreign function interface (FFI) A-linkage Area: linking into static, shared libraries and binaries

Comments

@kmcallister
Copy link
Contributor

foo.c:

#include <stdio.h>

void foo() {
    puts("Hello, foo()!");
}

bar.rs:

#[link(name="foo", kind="static")]
extern {
    fn foo();
}

pub fn bar() {
    unsafe { foo(); }
}

When I build only a static libfoo.a I get the expected behavior, with foo statically linked into the Rust crate .so.

$ rm -f *.o *.so *.a
$ gcc -Wall -fPIC -c foo.c
$ ar rcs libfoo.a foo.o
$ rustc -v
rustc 0.10-pre (6ae5de0 2014-02-19 12:51:48 -0800)
host: x86_64-unknown-linux-gnu
$ rustc --crate-type dylib bar.rs
$ objdump -d libbar-*.so
...
0000000000000a80 <foo>:
 a80:   55                      push   %rbp
 a81:   48 89 e5                mov    %rsp,%rbp
 a84:   48 8d 3d 22 00 00 00    lea    0x22(%rip),%rdi        # aad <_fini+0x9>
 a8b:   e8 80 fe ff ff          callq  910 <puts@plt>
 a90:   5d                      pop    %rbp
 a91:   c3                      retq   
 a92:   90                      nop

But when I also have libfoo.so in the same directory, rustc prefers that even though kind="static" is set.

$ gcc -shared -o libfoo.so foo.o
$ file libfoo.*
libfoo.a:  current ar archive
libfoo.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked
$ rustc --crate-type dylib bar.rs 
$ objdump -d libbar-*.so | grep foo
00000000000008b0 <foo@plt>:
 9f6:   e8 b5 fe ff ff          callq  8b0 <foo@plt>

strace confirms that it looks for both libfoo.so and libfoo.a, in that order, in each directory of the library search path, and it stops when it finds ./libfoo.so.

@alexcrichton
Copy link
Member

I believe this has to do with the system linker's preference on dynamic/static libraries. Looks like we need to give it flags to override it's behavior if we've got a static library in play.

alexcrichton added a commit that referenced this issue Apr 17, 2014
If a linker finds both a static and a dynamic version of the same library, then
the linker often chooses the dynamic version. This is surprising when a native
library is specified as being "static" in rust source. This modifies the linker
command line to obey the hints given in rust source files and instructing the
linker to prefer a particular version of a found library.

Unfortunately, this patch has no effect on osx because the linker supports
no such hint, and it also has no effect on windows because the linker apparently
just ignores it. For now this is predominately used to enable the previous patch
of linking to libstdc++ statically, but more support would need to be added for
this in the future if we wanted to officially support it.

cc #12557 (doesn't close because it doesn't support OSX and windows)
@alexcrichton
Copy link
Member

Closed by ad3de7f on platforms where this is supported (those that aren't OSX)

flip1995 pushed a commit to flip1995/rust that referenced this issue Apr 4, 2024
…on-remove-dot, r=y21

Remove unnecessary dot in the 'unconditional recursion' lint description

I don't think such changes should be reflected in the changelog.

changelog: none
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-FFI Area: Foreign function interface (FFI) A-linkage Area: linking into static, shared libraries and binaries
Projects
None yet
Development

No branches or pull requests

3 participants