Skip to content

Commit

Permalink
Don't link "nobundle" libs which had already been included in upstrea…
Browse files Browse the repository at this point in the history
…m crate.
  • Loading branch information
vadimcn committed Feb 4, 2017
1 parent 3ae2174 commit 7504897
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 21 deletions.
3 changes: 3 additions & 0 deletions src/librustc_metadata/creader.rs
Expand Up @@ -685,6 +685,9 @@ impl<'a> CrateLoader<'a> {
for id in self.get_foreign_items_of_kind(cstore::NativeStatic) {
self.cstore.add_statically_included_foreign_item(id);
}
for id in self.get_foreign_items_of_kind(cstore::NativeStaticNobundle) {
self.cstore.add_statically_included_foreign_item(id);
}
}

fn register_dllimport_foreign_items(&mut self) {
Expand Down
18 changes: 14 additions & 4 deletions src/librustc_trans/back/link.rs
Expand Up @@ -896,7 +896,7 @@ fn link_args(cmd: &mut Linker,
// on other dylibs (e.g. other native deps).
add_local_native_libraries(cmd, sess);
add_upstream_rust_crates(cmd, sess, crate_type, tmpdir);
add_upstream_native_libraries(cmd, sess);
add_upstream_native_libraries(cmd, sess, crate_type);

// # Telling the linker what we're doing

Expand Down Expand Up @@ -1213,7 +1213,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
// generic function calls a native function, then the generic function must
// be instantiated in the target crate, meaning that the native symbol must
// also be resolved in the target crate.
fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session) {
fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session, crate_type: config::CrateType) {
// Be sure to use a topological sorting of crates because there may be
// interdependencies between native libraries. When passing -nodefaultlibs,
// for example, almost all native libraries depend on libc, so we have to
Expand All @@ -1223,6 +1223,9 @@ fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session) {
// This passes RequireStatic, but the actual requirement doesn't matter,
// we're just getting an ordering of crate numbers, we're not worried about
// the paths.
let formats = sess.dependency_formats.borrow();
let data = formats.get(&crate_type).unwrap();

let crates = sess.cstore.used_crates(LinkagePreference::RequireStatic);
for (cnum, _) in crates {
for lib in sess.cstore.native_libraries(cnum) {
Expand All @@ -1232,8 +1235,15 @@ fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session) {
match lib.kind {
NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()),
NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name.as_str()),
NativeLibraryKind::NativeStaticNobundle => cmd.link_staticlib(&lib.name.as_str()),

NativeLibraryKind::NativeStaticNobundle => {
// Link "static-nobundle" native libs only if the crate they originate from
// is being linked statically to the current crate. If it's linked dynamically
// or is an rlib already included via some other dylib crate, the symbols from
// native libs will have already been included in that dylib.
if data[cnum.as_usize() - 1] == Linkage::Static {
cmd.link_staticlib(&lib.name.as_str())
}
},
// ignore statically included native libraries here as we've
// already included them when we included the rust library
// previously
Expand Down
1 change: 1 addition & 0 deletions src/librustc_trans/back/linker.rs
Expand Up @@ -450,6 +450,7 @@ impl<'a> Linker for MsvcLinker<'a> {
writeln!(f, "LIBRARY")?;
writeln!(f, "EXPORTS")?;
for symbol in self.info.exports[&crate_type].iter() {
debug!(" _{}", symbol);
writeln!(f, " {}", symbol)?;
}
Ok(())
Expand Down
24 changes: 16 additions & 8 deletions src/test/run-make/static-nobundle/Makefile
@@ -1,13 +1,21 @@
-include ../tools.mk

all: $(call NATIVE_STATICLIB,foo)
$(RUSTC) bar.rs
# aaa is a native static library
# bbb is a rlib
# ccc is a dylib
# ddd is an executable

# Check that libbar.rlib does not contain the definition of `func`
nm $(TMPDIR)/libbar.rlib | (! grep "T _*func")
nm $(TMPDIR)/libbar.rlib | grep "U _*func"
all: $(call NATIVE_STATICLIB,aaa)
$(RUSTC) bbb.rs --crate-type=rlib

# Check that foo gets passed to the linker (as either `-l foo` or `foo.lib`)
$(RUSTC) main.rs -Z print-link-args | grep -e "-l[\" ]*foo" -e "foo.lib"
# Check that bbb does NOT contain the definition of `native_func`
nm $(TMPDIR)/libbbb.rlib | (! grep "T _*native_func")
nm $(TMPDIR)/libbbb.rlib | grep "U _*native_func"

$(call RUN,main)
# Check that aaa gets linked (either as `-l aaa` or `aaa.lib`) when building ccc.
$(RUSTC) ccc.rs -C prefer-dynamic --crate-type=dylib -Z print-link-args | grep -e "-l[\" ]*aaa" -e "aaa.lib"

# Check that aaa does NOT get linked when building ddd.
$(RUSTC) ddd.rs -Z print-link-args | (! grep -e "-l[\" ]*aaa" -e "aaa.lib")

$(call RUN,ddd)
@@ -1,4 +1,4 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand All @@ -8,4 +8,4 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

void func() {}
void native_func() {}
@@ -1,4 +1,4 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
Expand All @@ -11,13 +11,13 @@
#![crate_type = "rlib"]
#![feature(static_nobundle)]

#[link(name = "foo", kind = "static-nobundle")]
#[link(name = "aaa", kind = "static-nobundle")]
extern {
pub fn func();
pub fn native_func();
}

pub fn wrapped_func() {
unsafe {
func();
native_func();
}
}
23 changes: 23 additions & 0 deletions src/test/run-make/static-nobundle/ccc.rs
@@ -0,0 +1,23 @@
// Copyright 2017 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"]

extern crate bbb;

pub fn do_work() {
unsafe { bbb::native_func(); }
bbb::wrapped_func();
}

pub fn do_work_generic<T>() {
unsafe { bbb::native_func(); }
bbb::wrapped_func();
}
Expand Up @@ -8,9 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate bar;
extern crate ccc;

fn main() {
unsafe { bar::func(); }
bar::wrapped_func();
ccc::do_work();
ccc::do_work_generic::<i16>();
ccc::do_work_generic::<i32>();
}

0 comments on commit 7504897

Please sign in to comment.