about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-02-04 21:13:07 +0000
committerbors <bors@rust-lang.org>2017-02-04 21:13:07 +0000
commitea7a6486a26af085862cd7a5596bb69e83d85e12 (patch)
tree4d191736bf2197b11ba614b62612fa1636533066
parenteb5cb9545cfa4f1e90c92266b802edc4690f584a (diff)
parent7504897e6b4b1121191bc6612bcbcce1f70f5f06 (diff)
Auto merge of #38426 - vadimcn:nobundle, r=alexcrichton
Implement kind="static-nobundle" (RFC 1717)

This implements the "static-nobundle" library kind (last item from #37403).

Rustc handles "static-nobundle" libs very similarly to dylibs, except that on Windows, uses of their symbols do not get marked with "dllimport".  Which is the whole point of this feature.
-rw-r--r--src/librustc/middle/cstore.rs3
-rw-r--r--src/librustc/session/config.rs5
-rw-r--r--src/librustc_metadata/creader.rs11
-rw-r--r--src/librustc_metadata/cstore.rs2
-rw-r--r--src/librustc_trans/back/link.rs20
-rw-r--r--src/librustc_trans/back/linker.rs1
-rw-r--r--src/libsyntax/feature_gate.rs3
-rw-r--r--src/test/compile-fail/feature-gate-static-nobundle.rs13
-rw-r--r--src/test/run-make/static-nobundle/Makefile21
-rw-r--r--src/test/run-make/static-nobundle/aaa.c11
-rw-r--r--src/test/run-make/static-nobundle/bbb.rs23
-rw-r--r--src/test/run-make/static-nobundle/ccc.rs23
-rw-r--r--src/test/run-make/static-nobundle/ddd.rs17
13 files changed, 148 insertions, 5 deletions
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index d11e6e3fc72..6537cc1adce 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -47,7 +47,7 @@ use rustc_back::target::Target;
 use hir;
 use rustc_back::PanicStrategy;
 
-pub use self::NativeLibraryKind::{NativeStatic, NativeFramework, NativeUnknown};
+pub use self::NativeLibraryKind::*;
 
 // lonely orphan structs and enums looking for a better home
 
@@ -123,6 +123,7 @@ pub enum LinkagePreference {
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
 pub enum NativeLibraryKind {
     NativeStatic,    // native static library (.a archive)
+    NativeStaticNobundle, // native static library, which doesn't get bundled into .rlibs
     NativeFramework, // OSX-specific
     NativeUnknown,   // default way to specify a dynamic library
 }
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 7419d74287b..d41c2ba93b9 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -1476,12 +1476,17 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
             (Some(name), "dylib") => (name, cstore::NativeUnknown),
             (Some(name), "framework") => (name, cstore::NativeFramework),
             (Some(name), "static") => (name, cstore::NativeStatic),
+            (Some(name), "static-nobundle") => (name, cstore::NativeStaticNobundle),
             (_, s) => {
                 early_error(error_format, &format!("unknown library kind `{}`, expected \
                                                   one of dylib, framework, or static",
                                                  s));
             }
         };
+        if kind == cstore::NativeStaticNobundle && !nightly_options::is_nightly_build() {
+            early_error(error_format, &format!("the library kind 'static-nobundle' is only \
+                                                accepted on the nightly compiler"));
+        }
         let mut name_parts = name.splitn(2, ':');
         let name = name_parts.next().unwrap();
         let new_name = name_parts.next();
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 161331b1728..f0d056b96f1 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -111,6 +111,13 @@ fn register_native_lib(sess: &Session,
                                        GateIssue::Language,
                                        "is feature gated");
     }
+    if lib.kind == cstore::NativeStaticNobundle && !sess.features.borrow().static_nobundle {
+        feature_gate::emit_feature_err(&sess.parse_sess,
+                                       "static_nobundle",
+                                       span.unwrap(),
+                                       GateIssue::Language,
+                                       "kind=\"static-nobundle\" is feature gated");
+    }
     cstore.add_used_library(lib);
 }
 
@@ -688,6 +695,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) {
@@ -927,6 +937,7 @@ impl<'a> CrateLoader<'a> {
             }).and_then(|a| a.value_str()).map(Symbol::as_str);
             let kind = match kind.as_ref().map(|s| &s[..]) {
                 Some("static") => cstore::NativeStatic,
+                Some("static-nobundle") => cstore::NativeStaticNobundle,
                 Some("dylib") => cstore::NativeUnknown,
                 Some("framework") => cstore::NativeFramework,
                 Some(k) => {
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index 761041ad719..beba5faf3d0 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -32,7 +32,7 @@ use syntax::symbol::Symbol;
 use syntax_pos;
 
 pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePreference};
-pub use rustc::middle::cstore::{NativeStatic, NativeFramework, NativeUnknown};
+pub use rustc::middle::cstore::NativeLibraryKind::*;
 pub use rustc::middle::cstore::{CrateSource, LinkMeta, LibSource};
 
 // A map from external crate numbers (as decoded from some crate file) to
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
index defbb44448a..20842ea3fe5 100644
--- a/src/librustc_trans/back/link.rs
+++ b/src/librustc_trans/back/link.rs
@@ -476,6 +476,7 @@ fn link_rlib<'a>(sess: &'a Session,
     for lib in sess.cstore.used_libraries() {
         match lib.kind {
             NativeLibraryKind::NativeStatic => {}
+            NativeLibraryKind::NativeStaticNobundle |
             NativeLibraryKind::NativeFramework |
             NativeLibraryKind::NativeUnknown => continue,
         }
@@ -674,6 +675,7 @@ fn link_staticlib(sess: &Session, objects: &[PathBuf], out_filename: &Path,
 
     for lib in all_native_libs.iter().filter(|l| relevant_lib(sess, l)) {
         let name = match lib.kind {
+            NativeLibraryKind::NativeStaticNobundle |
             NativeLibraryKind::NativeUnknown => "library",
             NativeLibraryKind::NativeFramework => "framework",
             // These are included, no need to print them
@@ -894,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
 
@@ -985,6 +987,7 @@ fn add_local_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::NativeStatic => bug!(),
         }
     }
@@ -1210,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
@@ -1220,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) {
@@ -1229,7 +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 => {
+                    // 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 a147b598940..7f352f1da51 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/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 112211851ec..970c37045df 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -323,6 +323,9 @@ declare_features! (
     // Allows attributes on struct literal fields.
     (active, struct_field_attributes, "1.16.0", Some(38814)),
 
+    // Allows #[link(kind="static-nobundle"...]
+    (active, static_nobundle, "1.16.0", Some(37403)),
+
     // `extern "msp430-interrupt" fn()`
     (active, abi_msp430_interrupt, "1.16.0", Some(38487)),
 );
diff --git a/src/test/compile-fail/feature-gate-static-nobundle.rs b/src/test/compile-fail/feature-gate-static-nobundle.rs
new file mode 100644
index 00000000000..bc0025c7c95
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-static-nobundle.rs
@@ -0,0 +1,13 @@
+// Copyright 2016 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.
+
+#[link(name="foo", kind="static-nobundle")]
+//~^ ERROR: kind="static-nobundle" is feature gated
+extern {}
diff --git a/src/test/run-make/static-nobundle/Makefile b/src/test/run-make/static-nobundle/Makefile
new file mode 100644
index 00000000000..3eac12f5cc9
--- /dev/null
+++ b/src/test/run-make/static-nobundle/Makefile
@@ -0,0 +1,21 @@
+-include ../tools.mk
+
+# aaa is a native static library
+# bbb is a rlib
+# ccc is a dylib
+# ddd is an executable
+
+all: $(call NATIVE_STATICLIB,aaa)
+	$(RUSTC) bbb.rs --crate-type=rlib
+
+	# 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"
+
+	# 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/aaa.c b/src/test/run-make/static-nobundle/aaa.c
new file mode 100644
index 00000000000..806ef878c70
--- /dev/null
+++ b/src/test/run-make/static-nobundle/aaa.c
@@ -0,0 +1,11 @@
+// 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.
+
+void native_func() {}
diff --git a/src/test/run-make/static-nobundle/bbb.rs b/src/test/run-make/static-nobundle/bbb.rs
new file mode 100644
index 00000000000..2bd69c99327
--- /dev/null
+++ b/src/test/run-make/static-nobundle/bbb.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 = "rlib"]
+#![feature(static_nobundle)]
+
+#[link(name = "aaa", kind = "static-nobundle")]
+extern {
+    pub fn native_func();
+}
+
+pub fn wrapped_func() {
+    unsafe {
+        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 00000000000..bd34753a00d
--- /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 <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();
+}
diff --git a/src/test/run-make/static-nobundle/ddd.rs b/src/test/run-make/static-nobundle/ddd.rs
new file mode 100644
index 00000000000..f7d23a899f7
--- /dev/null
+++ b/src/test/run-make/static-nobundle/ddd.rs
@@ -0,0 +1,17 @@
+// Copyright 2015 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 ccc;
+
+fn main() {
+    ccc::do_work();
+    ccc::do_work_generic::<i16>();
+    ccc::do_work_generic::<i32>();
+}