diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 87ba2edbfda7d..a228689363fc3 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -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) { diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index aa42364f951c7..20842ea3fe54d 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -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 @@ -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 @@ -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) { @@ -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 diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index a147b598940a2..7f352f1da517d 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -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(()) diff --git a/src/test/run-make/static-nobundle/Makefile b/src/test/run-make/static-nobundle/Makefile index b184d54ff9c6f..3eac12f5cc9fd 100644 --- a/src/test/run-make/static-nobundle/Makefile +++ b/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) diff --git a/src/test/run-make/static-nobundle/foo.c b/src/test/run-make/static-nobundle/aaa.c similarity index 82% rename from src/test/run-make/static-nobundle/foo.c rename to src/test/run-make/static-nobundle/aaa.c index 5ccf713f79c61..806ef878c7052 100644 --- a/src/test/run-make/static-nobundle/foo.c +++ b/src/test/run-make/static-nobundle/aaa.c @@ -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. // @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -void func() {} +void native_func() {} diff --git a/src/test/run-make/static-nobundle/bar.rs b/src/test/run-make/static-nobundle/bbb.rs similarity index 76% rename from src/test/run-make/static-nobundle/bar.rs rename to src/test/run-make/static-nobundle/bbb.rs index c5d6237c9d594..2bd69c9932723 100644 --- a/src/test/run-make/static-nobundle/bar.rs +++ b/src/test/run-make/static-nobundle/bbb.rs @@ -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. // @@ -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(); } } diff --git a/src/test/run-make/static-nobundle/ccc.rs b/src/test/run-make/static-nobundle/ccc.rs new file mode 100644 index 0000000000000..bd34753a00d12 --- /dev/null +++ b/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 or the MIT license +// , 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() { + unsafe { bbb::native_func(); } + bbb::wrapped_func(); +} diff --git a/src/test/run-make/static-nobundle/main.rs b/src/test/run-make/static-nobundle/ddd.rs similarity index 81% rename from src/test/run-make/static-nobundle/main.rs rename to src/test/run-make/static-nobundle/ddd.rs index 7aa730f1dd26b..f7d23a899f758 100644 --- a/src/test/run-make/static-nobundle/main.rs +++ b/src/test/run-make/static-nobundle/ddd.rs @@ -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::(); + ccc::do_work_generic::(); }