Skip to content

Commit ea7a648

Browse files
committed
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.
2 parents eb5cb95 + 7504897 commit ea7a648

File tree

13 files changed

+148
-5
lines changed

13 files changed

+148
-5
lines changed

Diff for: src/librustc/middle/cstore.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ use rustc_back::target::Target;
4747
use hir;
4848
use rustc_back::PanicStrategy;
4949

50-
pub use self::NativeLibraryKind::{NativeStatic, NativeFramework, NativeUnknown};
50+
pub use self::NativeLibraryKind::*;
5151

5252
// lonely orphan structs and enums looking for a better home
5353

@@ -123,6 +123,7 @@ pub enum LinkagePreference {
123123
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
124124
pub enum NativeLibraryKind {
125125
NativeStatic, // native static library (.a archive)
126+
NativeStaticNobundle, // native static library, which doesn't get bundled into .rlibs
126127
NativeFramework, // OSX-specific
127128
NativeUnknown, // default way to specify a dynamic library
128129
}

Diff for: src/librustc/session/config.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1476,12 +1476,17 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
14761476
(Some(name), "dylib") => (name, cstore::NativeUnknown),
14771477
(Some(name), "framework") => (name, cstore::NativeFramework),
14781478
(Some(name), "static") => (name, cstore::NativeStatic),
1479+
(Some(name), "static-nobundle") => (name, cstore::NativeStaticNobundle),
14791480
(_, s) => {
14801481
early_error(error_format, &format!("unknown library kind `{}`, expected \
14811482
one of dylib, framework, or static",
14821483
s));
14831484
}
14841485
};
1486+
if kind == cstore::NativeStaticNobundle && !nightly_options::is_nightly_build() {
1487+
early_error(error_format, &format!("the library kind 'static-nobundle' is only \
1488+
accepted on the nightly compiler"));
1489+
}
14851490
let mut name_parts = name.splitn(2, ':');
14861491
let name = name_parts.next().unwrap();
14871492
let new_name = name_parts.next();

Diff for: src/librustc_metadata/creader.rs

+11
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@ fn register_native_lib(sess: &Session,
111111
GateIssue::Language,
112112
"is feature gated");
113113
}
114+
if lib.kind == cstore::NativeStaticNobundle && !sess.features.borrow().static_nobundle {
115+
feature_gate::emit_feature_err(&sess.parse_sess,
116+
"static_nobundle",
117+
span.unwrap(),
118+
GateIssue::Language,
119+
"kind=\"static-nobundle\" is feature gated");
120+
}
114121
cstore.add_used_library(lib);
115122
}
116123

@@ -688,6 +695,9 @@ impl<'a> CrateLoader<'a> {
688695
for id in self.get_foreign_items_of_kind(cstore::NativeStatic) {
689696
self.cstore.add_statically_included_foreign_item(id);
690697
}
698+
for id in self.get_foreign_items_of_kind(cstore::NativeStaticNobundle) {
699+
self.cstore.add_statically_included_foreign_item(id);
700+
}
691701
}
692702

693703
fn register_dllimport_foreign_items(&mut self) {
@@ -927,6 +937,7 @@ impl<'a> CrateLoader<'a> {
927937
}).and_then(|a| a.value_str()).map(Symbol::as_str);
928938
let kind = match kind.as_ref().map(|s| &s[..]) {
929939
Some("static") => cstore::NativeStatic,
940+
Some("static-nobundle") => cstore::NativeStaticNobundle,
930941
Some("dylib") => cstore::NativeUnknown,
931942
Some("framework") => cstore::NativeFramework,
932943
Some(k) => {

Diff for: src/librustc_metadata/cstore.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use syntax::symbol::Symbol;
3232
use syntax_pos;
3333

3434
pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePreference};
35-
pub use rustc::middle::cstore::{NativeStatic, NativeFramework, NativeUnknown};
35+
pub use rustc::middle::cstore::NativeLibraryKind::*;
3636
pub use rustc::middle::cstore::{CrateSource, LinkMeta, LibSource};
3737

3838
// A map from external crate numbers (as decoded from some crate file) to

Diff for: src/librustc_trans/back/link.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ fn link_rlib<'a>(sess: &'a Session,
476476
for lib in sess.cstore.used_libraries() {
477477
match lib.kind {
478478
NativeLibraryKind::NativeStatic => {}
479+
NativeLibraryKind::NativeStaticNobundle |
479480
NativeLibraryKind::NativeFramework |
480481
NativeLibraryKind::NativeUnknown => continue,
481482
}
@@ -674,6 +675,7 @@ fn link_staticlib(sess: &Session, objects: &[PathBuf], out_filename: &Path,
674675

675676
for lib in all_native_libs.iter().filter(|l| relevant_lib(sess, l)) {
676677
let name = match lib.kind {
678+
NativeLibraryKind::NativeStaticNobundle |
677679
NativeLibraryKind::NativeUnknown => "library",
678680
NativeLibraryKind::NativeFramework => "framework",
679681
// These are included, no need to print them
@@ -894,7 +896,7 @@ fn link_args(cmd: &mut Linker,
894896
// on other dylibs (e.g. other native deps).
895897
add_local_native_libraries(cmd, sess);
896898
add_upstream_rust_crates(cmd, sess, crate_type, tmpdir);
897-
add_upstream_native_libraries(cmd, sess);
899+
add_upstream_native_libraries(cmd, sess, crate_type);
898900

899901
// # Telling the linker what we're doing
900902

@@ -985,6 +987,7 @@ fn add_local_native_libraries(cmd: &mut Linker, sess: &Session) {
985987
match lib.kind {
986988
NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()),
987989
NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name.as_str()),
990+
NativeLibraryKind::NativeStaticNobundle => cmd.link_staticlib(&lib.name.as_str()),
988991
NativeLibraryKind::NativeStatic => bug!(),
989992
}
990993
}
@@ -1210,7 +1213,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
12101213
// generic function calls a native function, then the generic function must
12111214
// be instantiated in the target crate, meaning that the native symbol must
12121215
// also be resolved in the target crate.
1213-
fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session) {
1216+
fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session, crate_type: config::CrateType) {
12141217
// Be sure to use a topological sorting of crates because there may be
12151218
// interdependencies between native libraries. When passing -nodefaultlibs,
12161219
// 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) {
12201223
// This passes RequireStatic, but the actual requirement doesn't matter,
12211224
// we're just getting an ordering of crate numbers, we're not worried about
12221225
// the paths.
1226+
let formats = sess.dependency_formats.borrow();
1227+
let data = formats.get(&crate_type).unwrap();
1228+
12231229
let crates = sess.cstore.used_crates(LinkagePreference::RequireStatic);
12241230
for (cnum, _) in crates {
12251231
for lib in sess.cstore.native_libraries(cnum) {
@@ -1229,7 +1235,15 @@ fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session) {
12291235
match lib.kind {
12301236
NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()),
12311237
NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name.as_str()),
1232-
1238+
NativeLibraryKind::NativeStaticNobundle => {
1239+
// Link "static-nobundle" native libs only if the crate they originate from
1240+
// is being linked statically to the current crate. If it's linked dynamically
1241+
// or is an rlib already included via some other dylib crate, the symbols from
1242+
// native libs will have already been included in that dylib.
1243+
if data[cnum.as_usize() - 1] == Linkage::Static {
1244+
cmd.link_staticlib(&lib.name.as_str())
1245+
}
1246+
},
12331247
// ignore statically included native libraries here as we've
12341248
// already included them when we included the rust library
12351249
// previously

Diff for: src/librustc_trans/back/linker.rs

+1
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,7 @@ impl<'a> Linker for MsvcLinker<'a> {
450450
writeln!(f, "LIBRARY")?;
451451
writeln!(f, "EXPORTS")?;
452452
for symbol in self.info.exports[&crate_type].iter() {
453+
debug!(" _{}", symbol);
453454
writeln!(f, " {}", symbol)?;
454455
}
455456
Ok(())

Diff for: src/libsyntax/feature_gate.rs

+3
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,9 @@ declare_features! (
323323
// Allows attributes on struct literal fields.
324324
(active, struct_field_attributes, "1.16.0", Some(38814)),
325325

326+
// Allows #[link(kind="static-nobundle"...]
327+
(active, static_nobundle, "1.16.0", Some(37403)),
328+
326329
// `extern "msp430-interrupt" fn()`
327330
(active, abi_msp430_interrupt, "1.16.0", Some(38487)),
328331
);
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[link(name="foo", kind="static-nobundle")]
12+
//~^ ERROR: kind="static-nobundle" is feature gated
13+
extern {}

Diff for: src/test/run-make/static-nobundle/Makefile

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
-include ../tools.mk
2+
3+
# aaa is a native static library
4+
# bbb is a rlib
5+
# ccc is a dylib
6+
# ddd is an executable
7+
8+
all: $(call NATIVE_STATICLIB,aaa)
9+
$(RUSTC) bbb.rs --crate-type=rlib
10+
11+
# Check that bbb does NOT contain the definition of `native_func`
12+
nm $(TMPDIR)/libbbb.rlib | (! grep "T _*native_func")
13+
nm $(TMPDIR)/libbbb.rlib | grep "U _*native_func"
14+
15+
# Check that aaa gets linked (either as `-l aaa` or `aaa.lib`) when building ccc.
16+
$(RUSTC) ccc.rs -C prefer-dynamic --crate-type=dylib -Z print-link-args | grep -e "-l[\" ]*aaa" -e "aaa.lib"
17+
18+
# Check that aaa does NOT get linked when building ddd.
19+
$(RUSTC) ddd.rs -Z print-link-args | (! grep -e "-l[\" ]*aaa" -e "aaa.lib")
20+
21+
$(call RUN,ddd)

Diff for: src/test/run-make/static-nobundle/aaa.c

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
void native_func() {}

Diff for: src/test/run-make/static-nobundle/bbb.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![crate_type = "rlib"]
12+
#![feature(static_nobundle)]
13+
14+
#[link(name = "aaa", kind = "static-nobundle")]
15+
extern {
16+
pub fn native_func();
17+
}
18+
19+
pub fn wrapped_func() {
20+
unsafe {
21+
native_func();
22+
}
23+
}

Diff for: src/test/run-make/static-nobundle/ccc.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![crate_type = "dylib"]
12+
13+
extern crate bbb;
14+
15+
pub fn do_work() {
16+
unsafe { bbb::native_func(); }
17+
bbb::wrapped_func();
18+
}
19+
20+
pub fn do_work_generic<T>() {
21+
unsafe { bbb::native_func(); }
22+
bbb::wrapped_func();
23+
}

Diff for: src/test/run-make/static-nobundle/ddd.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
extern crate ccc;
12+
13+
fn main() {
14+
ccc::do_work();
15+
ccc::do_work_generic::<i16>();
16+
ccc::do_work_generic::<i32>();
17+
}

0 commit comments

Comments
 (0)