diff --git a/src/liblibc b/src/liblibc
index 7d9b71f0971f8..6e8c1b490ccbe 160000
--- a/src/liblibc
+++ b/src/liblibc
@@ -1 +1 @@
-Subproject commit 7d9b71f0971f8fa196d864d7071f216a59036d6e
+Subproject commit 6e8c1b490ccbe5e84d248bab883515bc85394b5f
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 3583ccdb97bad..f61978271e7f6 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -89,6 +89,13 @@ pub enum NativeLibraryKind {
NativeUnknown, // default way to specify a dynamic library
}
+#[derive(Clone, Hash, RustcEncodable, RustcDecodable)]
+pub struct NativeLibrary {
+ pub kind: NativeLibraryKind,
+ pub name: String,
+ pub cfg: Option
>,
+}
+
/// The data we save and restore about an inlined item or method. This is not
/// part of the AST that we parse from a file, but it becomes part of the tree
/// that we trans.
@@ -204,7 +211,7 @@ pub trait CrateStore<'tcx> {
fn crate_hash(&self, cnum: CrateNum) -> Svh;
fn crate_disambiguator(&self, cnum: CrateNum) -> InternedString;
fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option;
- fn native_libraries(&self, cnum: CrateNum) -> Vec<(NativeLibraryKind, String)>;
+ fn native_libraries(&self, cnum: CrateNum) -> Vec;
fn reachable_ids(&self, cnum: CrateNum) -> Vec;
fn is_no_builtins(&self, cnum: CrateNum) -> bool;
@@ -231,7 +238,7 @@ pub trait CrateStore<'tcx> {
// This is basically a 1-based range of ints, which is a little
// silly - I may fix that.
fn crates(&self) -> Vec;
- fn used_libraries(&self) -> Vec<(String, NativeLibraryKind)>;
+ fn used_libraries(&self) -> Vec;
fn used_link_args(&self) -> Vec;
// utility functions
@@ -377,7 +384,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
-> InternedString { bug!("crate_disambiguator") }
fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option
{ bug!("plugin_registrar_fn") }
- fn native_libraries(&self, cnum: CrateNum) -> Vec<(NativeLibraryKind, String)>
+ fn native_libraries(&self, cnum: CrateNum) -> Vec
{ bug!("native_libraries") }
fn reachable_ids(&self, cnum: CrateNum) -> Vec { bug!("reachable_ids") }
fn is_no_builtins(&self, cnum: CrateNum) -> bool { bug!("is_no_builtins") }
@@ -412,7 +419,9 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
// This is basically a 1-based range of ints, which is a little
// silly - I may fix that.
fn crates(&self) -> Vec { vec![] }
- fn used_libraries(&self) -> Vec<(String, NativeLibraryKind)> { vec![] }
+ fn used_libraries(&self) -> Vec {
+ vec![]
+ }
fn used_link_args(&self) -> Vec { vec![] }
// utility functions
diff --git a/src/librustc_back/target/linux_musl_base.rs b/src/librustc_back/target/linux_musl_base.rs
index d55907aeedfbc..18cca425a32c8 100644
--- a/src/librustc_back/target/linux_musl_base.rs
+++ b/src/librustc_back/target/linux_musl_base.rs
@@ -16,7 +16,6 @@ pub fn opts() -> TargetOptions {
// Make sure that the linker/gcc really don't pull in anything, including
// default objects, libs, etc.
base.pre_link_args.push("-nostdlib".to_string());
- base.pre_link_args.push("-static".to_string());
// At least when this was tested, the linker would not add the
// `GNU_EH_FRAME` program header to executables generated, which is required
@@ -67,5 +66,8 @@ pub fn opts() -> TargetOptions {
base.has_rpath = false;
base.position_independent_executables = false;
+ // These targets statically link libc by default
+ base.crt_static_default = true;
+
base
}
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index cc04582b19e28..f195ccb3f4292 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -373,6 +373,9 @@ pub struct TargetOptions {
/// A blacklist of ABIs unsupported by the current target. Note that generic
/// ABIs are considered to be supported on all platforms and cannot be blacklisted.
pub abi_blacklist: Vec,
+
+ /// Whether or not the CRT is statically linked by default.
+ pub crt_static_default: bool,
}
impl Default for TargetOptions {
@@ -425,6 +428,7 @@ impl Default for TargetOptions {
max_atomic_width: None,
panic_strategy: PanicStrategy::Unwind,
abi_blacklist: vec![],
+ crt_static_default: false,
}
}
}
@@ -585,6 +589,7 @@ impl Target {
key!(no_integrated_as, bool);
key!(max_atomic_width, Option);
try!(key!(panic_strategy, PanicStrategy));
+ key!(crt_static_default, bool);
if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
for name in array.iter().filter_map(|abi| abi.as_string()) {
@@ -745,6 +750,7 @@ impl ToJson for Target {
target_option_val!(no_integrated_as);
target_option_val!(max_atomic_width);
target_option_val!(panic_strategy);
+ target_option_val!(crt_static_default);
if default.abi_blacklist != self.options.abi_blacklist {
d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter()
diff --git a/src/librustc_driver/target_features.rs b/src/librustc_driver/target_features.rs
index ba51947a33301..d0ed81bcffcbc 100644
--- a/src/librustc_driver/target_features.rs
+++ b/src/librustc_driver/target_features.rs
@@ -12,6 +12,7 @@ use syntax::{ast, attr};
use llvm::LLVMRustHasFeature;
use rustc::session::Session;
use rustc_trans::back::write::create_target_machine;
+use syntax::feature_gate::UnstableFeatures;
use syntax::parse::token::InternedString;
use syntax::parse::token::intern_and_get_ident as intern;
use libc::c_char;
@@ -47,4 +48,32 @@ pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) {
cfg.push(attr::mk_name_value_item_str(tf.clone(), intern(&feat[..feat.len() - 1])))
}
}
+
+ let mut requested_features = sess.opts.cg.target_feature.split(',');
+ let unstable_options = sess.opts.debugging_opts.unstable_options;
+ let is_nightly = UnstableFeatures::from_environment().is_nightly_build();
+ let found_negative = requested_features.any(|r| r == "-crt-static");
+ let found_positive = requested_features.any(|r| r == "+crt-static");
+
+ // If the target we're compiling for requests a static crt by default,
+ // then see if the `-crt-static` feature was passed to disable that.
+ // Otherwise if we don't have a static crt by default then see if the
+ // `+crt-static` feature was passed.
+ let crt_static = if sess.target.target.options.crt_static_default {
+ found_negative
+ } else {
+ found_positive
+ };
+
+ // If we switched from the default then that's only allowed on nightly, so
+ // gate that here.
+ if (found_positive || found_negative) && (!is_nightly || !unstable_options) {
+ sess.fatal("specifying the `crt-static` target feature is only allowed \
+ on the nightly channel with `-Z unstable-options` passed \
+ as well");
+ }
+
+ if crt_static {
+ cfg.push(attr::mk_name_value_item_str(tf.clone(), intern("crt-static")));
+ }
}
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 75944122f5c10..4298bb47fea62 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -23,6 +23,7 @@ use rustc::session::search_paths::PathKind;
use rustc::middle;
use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate};
use rustc::util::nodemap::{FxHashMap, FxHashSet};
+use rustc::middle::cstore::NativeLibrary;
use rustc::hir::map::Definitions;
use std::cell::{RefCell, Cell};
@@ -35,6 +36,7 @@ use syntax::ast;
use syntax::abi::Abi;
use syntax::attr;
use syntax::ext::base::SyntaxExtension;
+use syntax::feature_gate::{self, GateIssue};
use syntax::parse::token::{InternedString, intern};
use syntax_pos::{Span, DUMMY_SP};
use log;
@@ -77,9 +79,8 @@ struct ExternCrateInfo {
fn register_native_lib(sess: &Session,
cstore: &CStore,
span: Option,
- name: String,
- kind: cstore::NativeLibraryKind) {
- if name.is_empty() {
+ lib: NativeLibrary) {
+ if lib.name.is_empty() {
match span {
Some(span) => {
struct_span_err!(sess, span, E0454,
@@ -94,17 +95,21 @@ fn register_native_lib(sess: &Session,
return
}
let is_osx = sess.target.target.options.is_like_osx;
- if kind == cstore::NativeFramework && !is_osx {
+ if lib.kind == cstore::NativeFramework && !is_osx {
let msg = "native frameworks are only available on OSX targets";
match span {
- Some(span) => {
- span_err!(sess, span, E0455,
- "{}", msg)
- }
+ Some(span) => span_err!(sess, span, E0455, "{}", msg),
None => sess.err(msg),
}
}
- cstore.add_used_library(name, kind);
+ if lib.cfg.is_some() && !sess.features.borrow().link_cfg {
+ feature_gate::emit_feature_err(&sess.parse_sess,
+ "link_cfg",
+ span.unwrap(),
+ GateIssue::Language,
+ "is feature gated");
+ }
+ cstore.add_used_library(lib);
}
// Extra info about a crate loaded for plugins or exported macros.
@@ -635,9 +640,9 @@ impl<'a> CrateLoader<'a> {
fn register_statically_included_foreign_items(&mut self) {
let libs = self.cstore.get_used_libraries();
- for (lib, list) in self.foreign_item_map.iter() {
- let is_static = libs.borrow().iter().any(|&(ref name, kind)| {
- lib == name && kind == cstore::NativeStatic
+ for (foreign_lib, list) in self.foreign_item_map.iter() {
+ let is_static = libs.borrow().iter().any(|lib| {
+ *foreign_lib == lib.name && lib.kind == cstore::NativeStatic
});
if is_static {
for id in list {
@@ -898,7 +903,18 @@ impl<'a> CrateLoader<'a> {
InternedString::new("foo")
}
};
- register_native_lib(self.sess, self.cstore, Some(m.span), n.to_string(), kind);
+ let cfg = items.iter().find(|k| {
+ k.check_name("cfg")
+ }).and_then(|a| a.meta_item_list());
+ let cfg = cfg.map(|list| {
+ list[0].meta_item().unwrap().clone()
+ });
+ let lib = NativeLibrary {
+ name: n.to_string(),
+ kind: kind,
+ cfg: cfg,
+ };
+ register_native_lib(self.sess, self.cstore, Some(m.span), lib);
}
// Finally, process the #[linked_from = "..."] attribute
@@ -924,7 +940,12 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
}
for &(ref name, kind) in &self.sess.opts.libs {
- register_native_lib(self.sess, self.cstore, None, name.clone(), kind);
+ let lib = NativeLibrary {
+ name: name.clone(),
+ kind: kind,
+ cfg: None,
+ };
+ register_native_lib(self.sess, self.cstore, None, lib);
}
self.register_statically_included_foreign_items();
}
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index 8c95e4aec0a04..37853b7473a65 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -31,7 +31,7 @@ use syntax::{ast, attr};
use syntax::ext::base::SyntaxExtension;
use syntax_pos;
-pub use rustc::middle::cstore::{NativeLibraryKind, LinkagePreference};
+pub use rustc::middle::cstore::{NativeLibrary, LinkagePreference};
pub use rustc::middle::cstore::{NativeStatic, NativeFramework, NativeUnknown};
pub use rustc::middle::cstore::{CrateSource, LinkMeta};
@@ -97,7 +97,7 @@ pub struct CStore {
metas: RefCell>>,
/// Map from NodeId's of local extern crate statements to crate numbers
extern_mod_crate_map: RefCell>,
- used_libraries: RefCell>,
+ used_libraries: RefCell>,
used_link_args: RefCell>,
statically_included_foreign_items: RefCell,
pub inlined_item_cache: RefCell>>,
@@ -212,12 +212,12 @@ impl CStore {
libs
}
- pub fn add_used_library(&self, lib: String, kind: NativeLibraryKind) {
- assert!(!lib.is_empty());
- self.used_libraries.borrow_mut().push((lib, kind));
+ pub fn add_used_library(&self, lib: NativeLibrary) {
+ assert!(!lib.name.is_empty());
+ self.used_libraries.borrow_mut().push(lib);
}
- pub fn get_used_libraries<'a>(&'a self) -> &'a RefCell> {
+ pub fn get_used_libraries(&self) -> &RefCell> {
&self.used_libraries
}
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 83de8acdb6056..5419f9955e44e 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -14,7 +14,7 @@ use locator;
use schema;
use rustc::middle::cstore::{InlinedItem, CrateStore, CrateSource, DepKind, ExternCrate};
-use rustc::middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference, LoadedMacro};
+use rustc::middle::cstore::{NativeLibrary, LinkMeta, LinkagePreference, LoadedMacro};
use rustc::hir::def::{self, Def};
use rustc::middle::lang_items;
use rustc::session::Session;
@@ -295,7 +295,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
})
}
- fn native_libraries(&self, cnum: CrateNum) -> Vec<(NativeLibraryKind, String)>
+ fn native_libraries(&self, cnum: CrateNum) -> Vec
{
self.get_crate_data(cnum).get_native_libraries()
}
@@ -524,7 +524,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
result
}
- fn used_libraries(&self) -> Vec<(String, NativeLibraryKind)>
+ fn used_libraries(&self) -> Vec
{
self.get_used_libraries().borrow().clone()
}
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index ba85544326f8f..6ffe53345332f 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -11,7 +11,7 @@
// Decoding metadata from a single crate's metadata
use astencode::decode_inlined_item;
-use cstore::{self, CrateMetadata, MetadataBlob, NativeLibraryKind};
+use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary};
use index::Index;
use schema::*;
@@ -980,7 +980,7 @@ impl<'a, 'tcx> CrateMetadata {
}
- pub fn get_native_libraries(&self) -> Vec<(NativeLibraryKind, String)> {
+ pub fn get_native_libraries(&self) -> Vec {
self.root.native_libraries.decode(self).collect()
}
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 778a9d185e145..823c50e1e5fd6 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -13,7 +13,7 @@ use index::Index;
use schema::*;
use rustc::middle::cstore::{InlinedItemRef, LinkMeta};
-use rustc::middle::cstore::{LinkagePreference, NativeLibraryKind};
+use rustc::middle::cstore::{LinkagePreference, NativeLibrary};
use rustc::hir::def;
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId};
use rustc::middle::dependency_format::Linkage;
@@ -1134,14 +1134,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
self.lazy_seq_ref(&tcx.lang_items.missing))
}
- fn encode_native_libraries(&mut self) -> LazySeq<(NativeLibraryKind, String)> {
+ fn encode_native_libraries(&mut self) -> LazySeq {
let used_libraries = self.tcx.sess.cstore.used_libraries();
- self.lazy_seq(used_libraries.into_iter().filter_map(|(lib, kind)| {
- match kind {
- cstore::NativeStatic => None, // these libraries are not propagated
- cstore::NativeFramework | cstore::NativeUnknown => Some((kind, lib)),
- }
- }))
+ self.lazy_seq(used_libraries)
}
fn encode_codemap(&mut self) -> LazySeq {
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index d7a5f7ad71544..5292a4a7c3768 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -14,7 +14,7 @@ use index;
use rustc::hir;
use rustc::hir::def::{self, CtorKind};
use rustc::hir::def_id::{DefIndex, DefId};
-use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibraryKind};
+use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary};
use rustc::middle::lang_items;
use rustc::mir;
use rustc::ty::{self, Ty};
@@ -175,7 +175,7 @@ pub struct CrateRoot {
pub dylib_dependency_formats: LazySeq