about summary refs log tree commit diff
path: root/src
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 /src
parenteb5cb9545cfa4f1e90c92266b802edc4690f584a (diff)
parent7504897e6b4b1121191bc6612bcbcce1f70f5f06 (diff)
downloadrust-ea7a6486a26af085862cd7a5596bb69e83d85e12.tar.gz
rust-ea7a6486a26af085862cd7a5596bb69e83d85e12.zip
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.
Diffstat (limited to 'src')
-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>();
+}