rustc: Link entire archives of native libraries

As discovered in #15460, a particular #[link(kind = "static", ...)] line is not
actually guaranteed to link the library at all. The reason for this is that if
the external library doesn't have any referenced symbols in the object generated
by rustc, the entire library is dropped by the linker.

For dynamic native libraries, this is solved by passing -lfoo for all downstream
compilations unconditionally. For static libraries in rlibs this is solved
because the entire archive is bundled in the rlib. The only situation in which
this was a problem was when a static native library was linked to a rust dynamic
library.

This commit brings the behavior of dylibs in line with rlibs by passing the
--whole-archive flag to the linker when linking native libraries. On OSX, this
uses the -force_load flag. This flag ensures that the entire archive is
considered candidate for being linked into the final dynamic library.

This is a breaking change because if any static library is included twice in the
same compilation unit then the linker will start emitting errors about duplicate
definitions now. The fix for this would involve only statically linking to a
library once.

Closes #15460
[breaking-change]
This commit is contained in:
Alex Crichton 2014-07-30 07:44:20 -07:00
parent 31590bd349
commit 1ae1461fbf
15 changed files with 170 additions and 46 deletions

View file

@ -12,7 +12,6 @@ extern crate testcrate;
use std::mem;
#[link(name = "test", kind = "static")]
extern {
fn give_back(tu: testcrate::TestUnion) -> u64;
}

View file

@ -0,0 +1,6 @@
-include ../tools.mk
all: $(TMPDIR)/libfoo.a
$(RUSTC) foo.rs -C extra-filename=-383hf8
$(RUSTC) bar.rs
$(call RUN,bar)

View file

@ -0,0 +1,14 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
extern crate foo;
fn main() {
unsafe { foo::foo() }
}

View file

@ -0,0 +1 @@
void foo() {}

View file

@ -0,0 +1,16 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_type = "dylib"]
#[link(name = "foo", kind = "static")]
extern {
pub fn foo();
}

View file

@ -1,6 +1,7 @@
-include ../tools.mk
all: $(call STATICLIB,foo) $(call STATICLIB,bar)
all:
$(RUSTC) foo.rs
$(RUSTC) bar.rs
$(RUSTC) main.rs
$(call RUN,main)

View file

@ -0,0 +1,21 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![no_std]
#![feature(lang_items)]
#![crate_type = "dylib"]
extern crate libc;
#[no_mangle]
pub extern fn bar() {}
#[lang = "stack_exhausted"] fn stack_exhausted() {}
#[lang = "eh_personality"] fn eh_personality() {}

View file

@ -0,0 +1,21 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![no_std]
#![feature(lang_items)]
#![crate_type = "dylib"]
extern crate libc;
#[no_mangle]
pub extern fn foo() {}
#[lang = "stack_exhausted"] fn stack_exhausted() {}
#[lang = "eh_personality"] fn eh_personality() {}

View file

@ -22,7 +22,6 @@ mod rustrt1 {
mod rustrt2 {
extern crate libc;
#[link(name = "rust_test_helpers")]
extern {
pub fn rust_get_test_int() -> libc::intptr_t;
}