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.
This commit is contained in:
commit
ea7a6486a2
13 changed files with 148 additions and 5 deletions
|
@ -47,7 +47,7 @@ use rustc_back::target::Target;
|
||||||
use hir;
|
use hir;
|
||||||
use rustc_back::PanicStrategy;
|
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
|
// 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)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
|
||||||
pub enum NativeLibraryKind {
|
pub enum NativeLibraryKind {
|
||||||
NativeStatic, // native static library (.a archive)
|
NativeStatic, // native static library (.a archive)
|
||||||
|
NativeStaticNobundle, // native static library, which doesn't get bundled into .rlibs
|
||||||
NativeFramework, // OSX-specific
|
NativeFramework, // OSX-specific
|
||||||
NativeUnknown, // default way to specify a dynamic library
|
NativeUnknown, // default way to specify a dynamic library
|
||||||
}
|
}
|
||||||
|
|
|
@ -1476,12 +1476,17 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
|
||||||
(Some(name), "dylib") => (name, cstore::NativeUnknown),
|
(Some(name), "dylib") => (name, cstore::NativeUnknown),
|
||||||
(Some(name), "framework") => (name, cstore::NativeFramework),
|
(Some(name), "framework") => (name, cstore::NativeFramework),
|
||||||
(Some(name), "static") => (name, cstore::NativeStatic),
|
(Some(name), "static") => (name, cstore::NativeStatic),
|
||||||
|
(Some(name), "static-nobundle") => (name, cstore::NativeStaticNobundle),
|
||||||
(_, s) => {
|
(_, s) => {
|
||||||
early_error(error_format, &format!("unknown library kind `{}`, expected \
|
early_error(error_format, &format!("unknown library kind `{}`, expected \
|
||||||
one of dylib, framework, or static",
|
one of dylib, framework, or static",
|
||||||
s));
|
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 mut name_parts = name.splitn(2, ':');
|
||||||
let name = name_parts.next().unwrap();
|
let name = name_parts.next().unwrap();
|
||||||
let new_name = name_parts.next();
|
let new_name = name_parts.next();
|
||||||
|
|
|
@ -111,6 +111,13 @@ fn register_native_lib(sess: &Session,
|
||||||
GateIssue::Language,
|
GateIssue::Language,
|
||||||
"is feature gated");
|
"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);
|
cstore.add_used_library(lib);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -688,6 +695,9 @@ impl<'a> CrateLoader<'a> {
|
||||||
for id in self.get_foreign_items_of_kind(cstore::NativeStatic) {
|
for id in self.get_foreign_items_of_kind(cstore::NativeStatic) {
|
||||||
self.cstore.add_statically_included_foreign_item(id);
|
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) {
|
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);
|
}).and_then(|a| a.value_str()).map(Symbol::as_str);
|
||||||
let kind = match kind.as_ref().map(|s| &s[..]) {
|
let kind = match kind.as_ref().map(|s| &s[..]) {
|
||||||
Some("static") => cstore::NativeStatic,
|
Some("static") => cstore::NativeStatic,
|
||||||
|
Some("static-nobundle") => cstore::NativeStaticNobundle,
|
||||||
Some("dylib") => cstore::NativeUnknown,
|
Some("dylib") => cstore::NativeUnknown,
|
||||||
Some("framework") => cstore::NativeFramework,
|
Some("framework") => cstore::NativeFramework,
|
||||||
Some(k) => {
|
Some(k) => {
|
||||||
|
|
|
@ -32,7 +32,7 @@ use syntax::symbol::Symbol;
|
||||||
use syntax_pos;
|
use syntax_pos;
|
||||||
|
|
||||||
pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePreference};
|
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};
|
pub use rustc::middle::cstore::{CrateSource, LinkMeta, LibSource};
|
||||||
|
|
||||||
// A map from external crate numbers (as decoded from some crate file) to
|
// A map from external crate numbers (as decoded from some crate file) to
|
||||||
|
|
|
@ -476,6 +476,7 @@ fn link_rlib<'a>(sess: &'a Session,
|
||||||
for lib in sess.cstore.used_libraries() {
|
for lib in sess.cstore.used_libraries() {
|
||||||
match lib.kind {
|
match lib.kind {
|
||||||
NativeLibraryKind::NativeStatic => {}
|
NativeLibraryKind::NativeStatic => {}
|
||||||
|
NativeLibraryKind::NativeStaticNobundle |
|
||||||
NativeLibraryKind::NativeFramework |
|
NativeLibraryKind::NativeFramework |
|
||||||
NativeLibraryKind::NativeUnknown => continue,
|
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)) {
|
for lib in all_native_libs.iter().filter(|l| relevant_lib(sess, l)) {
|
||||||
let name = match lib.kind {
|
let name = match lib.kind {
|
||||||
|
NativeLibraryKind::NativeStaticNobundle |
|
||||||
NativeLibraryKind::NativeUnknown => "library",
|
NativeLibraryKind::NativeUnknown => "library",
|
||||||
NativeLibraryKind::NativeFramework => "framework",
|
NativeLibraryKind::NativeFramework => "framework",
|
||||||
// These are included, no need to print them
|
// 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).
|
// on other dylibs (e.g. other native deps).
|
||||||
add_local_native_libraries(cmd, sess);
|
add_local_native_libraries(cmd, sess);
|
||||||
add_upstream_rust_crates(cmd, sess, crate_type, tmpdir);
|
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
|
// # Telling the linker what we're doing
|
||||||
|
|
||||||
|
@ -985,6 +987,7 @@ fn add_local_native_libraries(cmd: &mut Linker, sess: &Session) {
|
||||||
match lib.kind {
|
match lib.kind {
|
||||||
NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()),
|
NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()),
|
||||||
NativeLibraryKind::NativeFramework => cmd.link_framework(&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!(),
|
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
|
// generic function calls a native function, then the generic function must
|
||||||
// be instantiated in the target crate, meaning that the native symbol must
|
// be instantiated in the target crate, meaning that the native symbol must
|
||||||
// also be resolved in the target crate.
|
// 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
|
// Be sure to use a topological sorting of crates because there may be
|
||||||
// interdependencies between native libraries. When passing -nodefaultlibs,
|
// interdependencies between native libraries. When passing -nodefaultlibs,
|
||||||
// for example, almost all native libraries depend on libc, so we have to
|
// 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,
|
// This passes RequireStatic, but the actual requirement doesn't matter,
|
||||||
// we're just getting an ordering of crate numbers, we're not worried about
|
// we're just getting an ordering of crate numbers, we're not worried about
|
||||||
// the paths.
|
// the paths.
|
||||||
|
let formats = sess.dependency_formats.borrow();
|
||||||
|
let data = formats.get(&crate_type).unwrap();
|
||||||
|
|
||||||
let crates = sess.cstore.used_crates(LinkagePreference::RequireStatic);
|
let crates = sess.cstore.used_crates(LinkagePreference::RequireStatic);
|
||||||
for (cnum, _) in crates {
|
for (cnum, _) in crates {
|
||||||
for lib in sess.cstore.native_libraries(cnum) {
|
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 {
|
match lib.kind {
|
||||||
NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()),
|
NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()),
|
||||||
NativeLibraryKind::NativeFramework => cmd.link_framework(&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
|
// ignore statically included native libraries here as we've
|
||||||
// already included them when we included the rust library
|
// already included them when we included the rust library
|
||||||
// previously
|
// previously
|
||||||
|
|
|
@ -450,6 +450,7 @@ impl<'a> Linker for MsvcLinker<'a> {
|
||||||
writeln!(f, "LIBRARY")?;
|
writeln!(f, "LIBRARY")?;
|
||||||
writeln!(f, "EXPORTS")?;
|
writeln!(f, "EXPORTS")?;
|
||||||
for symbol in self.info.exports[&crate_type].iter() {
|
for symbol in self.info.exports[&crate_type].iter() {
|
||||||
|
debug!(" _{}", symbol);
|
||||||
writeln!(f, " {}", symbol)?;
|
writeln!(f, " {}", symbol)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -323,6 +323,9 @@ declare_features! (
|
||||||
// Allows attributes on struct literal fields.
|
// Allows attributes on struct literal fields.
|
||||||
(active, struct_field_attributes, "1.16.0", Some(38814)),
|
(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()`
|
// `extern "msp430-interrupt" fn()`
|
||||||
(active, abi_msp430_interrupt, "1.16.0", Some(38487)),
|
(active, abi_msp430_interrupt, "1.16.0", Some(38487)),
|
||||||
);
|
);
|
||||||
|
|
13
src/test/compile-fail/feature-gate-static-nobundle.rs
Normal file
13
src/test/compile-fail/feature-gate-static-nobundle.rs
Normal file
|
@ -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 {}
|
21
src/test/run-make/static-nobundle/Makefile
Normal file
21
src/test/run-make/static-nobundle/Makefile
Normal file
|
@ -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)
|
11
src/test/run-make/static-nobundle/aaa.c
Normal file
11
src/test/run-make/static-nobundle/aaa.c
Normal file
|
@ -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() {}
|
23
src/test/run-make/static-nobundle/bbb.rs
Normal file
23
src/test/run-make/static-nobundle/bbb.rs
Normal file
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
23
src/test/run-make/static-nobundle/ccc.rs
Normal file
23
src/test/run-make/static-nobundle/ccc.rs
Normal file
|
@ -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();
|
||||||
|
}
|
17
src/test/run-make/static-nobundle/ddd.rs
Normal file
17
src/test/run-make/static-nobundle/ddd.rs
Normal file
|
@ -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>();
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue