Skip to content

Linking a static native library to a dynamic rust library doesn't necessarily actually link #15460

Closed
@alexcrichton

Description

@alexcrichton
// foo.c
void foo() {}
// foo.rs
#![crate_type = "dylib"]
#[link(name = "foo", kind = "static")]
extern {
    pub fn foo();
}
// bar.rs
extern crate foo;
fn main() { unsafe { foo::foo() } }
$ gcc -c foo.c                         
$ ar crus libfoo.a foo.o    
$ rustc foo.rs -L.                  
$ rustc bar.rs -L.      
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' '-nodefaultlibs' '-Wl,-dead_strip' '-L' '/Users/acrichton/code/rust/lib/rustlib/x86_64-apple-darwin/lib' '-lnative-1fb5e2c0-0.11.0-pre' '-L' '/Users/acrichton/tmp' '-lfoo-aab0fa9e-0.0' '-L' '/Users/acrichton/code/rust/lib/rustlib/x86_64-apple-darwin/lib' '-lstd-59beb4f7-0.11.0-pre' '-L' '/Users/acrichton/code/rust/lib/rustlib/x86_64-apple-darwin/lib' '-lsync-305341d2-0.11.0-pre' '-L' '/Users/acrichton/code/rust/lib/rustlib/x86_64-apple-darwin/lib' '-lrustrt-d8560cb2-0.11.0-pre' '-L' '.' '-L' '/Users/acrichton/tmp/.rust' '-L' '/Users/acrichton/tmp' '-L' '/Users/acrichton/.rust' '-lSystem' '-lpthread' '-lc' '-lm' '-Wl,-rpath,@loader_path/../code/rust/lib/rustlib/x86_64-apple-darwin/lib' '-Wl,-rpath,@loader_path/.' '-Wl,-rpath,/usr/local/lib/rustlib/x86_64-apple-darwin/lib' '-lcompiler-rt'
note: ld: warning: directory not found for option '-L/Users/acrichton/tmp/.rust'
Undefined symbols for architecture x86_64:
  "_foo", referenced from:
      main::hdcb342faf114af9efaa::v0.0 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

The problem is that if the dynamic library doesn't actually reference any symbols from the native library then the native library is stripped from the command line.

Possible solutions

  • Stop using -Wl,--as-needed
  • Pass -Wl,--whole-archive for immediately dependent static libraries
  • For all extern blocks with a #[link(kind = "static")], generate a reference to all symbols in the extern block to force the library to be linked. (in some sort of 0-cost manner)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-linkageArea: linking into static, shared libraries and binaries

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions