diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 3d8cfd199615e..0c7f3c4f6f311 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -35,6 +35,7 @@ use syntax::symbol::Symbol; use syntax::{ast, codemap}; use syntax::feature_gate::AttributeType; use syntax_pos::{Span, MultiSpan}; +use syntax::feature_gate::UnstableFeatures; use rustc_back::PanicStrategy; use rustc_back::target::Target; @@ -499,6 +500,33 @@ impl Session { println!("Total time spent computing symbol hashes: {}", duration_to_secs_str(self.perf_stats.symbol_hash_time.get())); } + + /// Checks if the target is going to be statically linked to the C runtime + pub fn target_is_crt_static(&self) -> bool { + let requested_features = self.opts.cg.target_feature.split(','); + let unstable_options = self.opts.debugging_opts.unstable_options; + let is_nightly = UnstableFeatures::from_environment().is_nightly_build(); + let found_negative = requested_features.clone().any(|r| r == "-crt-static"); + let found_positive = requested_features.clone().any(|r| r == "+crt-static"); + + // 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) { + self.fatal("specifying the `crt-static` target feature is only allowed \ + on the nightly channel with `-Z unstable-options` passed \ + as well"); + } + + // 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. + if self.target.target.options.crt_static_default { + !found_negative + } else { + found_positive + } + } } pub fn build_session(sopts: config::Options, diff --git a/src/librustc_back/target/linux_musl_base.rs b/src/librustc_back/target/linux_musl_base.rs index 18cca425a32c8..5d45e1295ad64 100644 --- a/src/librustc_back/target/linux_musl_base.rs +++ b/src/librustc_back/target/linux_musl_base.rs @@ -55,16 +55,19 @@ pub fn opts() -> TargetOptions { // // Each target directory for musl has these object files included in it so // they'll be included from there. + // + // Note that when linking dynamically, these won't be passed to the linker base.pre_link_objects_exe.push("crt1.o".to_string()); base.pre_link_objects_exe.push("crti.o".to_string()); base.post_link_objects.push("crtn.o".to_string()); - // MUSL support doesn't currently include dynamic linking, so there's no - // need for dylibs or rpath business. Additionally `-pie` is incompatible - // with `-static`, so we can't pass `-pie`. - base.dynamic_linking = false; + // Dynamically linking to MUSL is opt-in (via the -crt-static target + // feature). The `true`s here are not ultimate and depend on whether one is + // actually linking to MUSL dynamically. + base.dynamic_linking = true; base.has_rpath = false; - base.position_independent_executables = false; + // actually only true if linking dynamically + base.position_independent_executables = true; // These targets statically link libc by default base.crt_static_default = true; diff --git a/src/librustc_driver/target_features.rs b/src/librustc_driver/target_features.rs index 876323d599e85..80a2fce9ed15e 100644 --- a/src/librustc_driver/target_features.rs +++ b/src/librustc_driver/target_features.rs @@ -12,7 +12,6 @@ use syntax::ast; use llvm::LLVMRustHasFeature; use rustc::session::Session; use rustc_trans::back::write::create_target_machine; -use syntax::feature_gate::UnstableFeatures; use syntax::symbol::Symbol; use libc::c_char; @@ -48,31 +47,7 @@ pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) { } } - let 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.clone().any(|r| r == "-crt-static"); - let found_positive = requested_features.clone().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 { + if sess.target_is_crt_static() { cfg.insert((tf, Some(Symbol::intern("crt-static")))); } } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 648dc4c24c9a6..3c0e63f4edc7c 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -237,7 +237,7 @@ pub fn default_output_for_target(sess: &Session) -> config::CrateType { /// Checks if target supports crate_type as output pub fn invalid_output_for_target(sess: &Session, crate_type: config::CrateType) -> bool { - match (sess.target.target.options.dynamic_linking, + match (sess.target.target.options.dynamic_linking && !sess.target_is_crt_static(), sess.target.target.options.executables, crate_type) { (false, _, config::CrateTypeCdylib) | (false, _, config::CrateTypeProcMacro) | @@ -668,6 +668,9 @@ fn link_natively(sess: &Session, let (pname, mut cmd, extra) = get_linker(sess); cmd.env("PATH", command_path(sess, extra)); + let musl = sess.target.target.llvm_target.contains("musl"); + let crt_static = sess.target_is_crt_static(); + let root = sess.target_filesearch(PathKind::Native).get_lib_path(); cmd.args(&sess.target.target.options.pre_link_args); @@ -676,8 +679,12 @@ fn link_natively(sess: &Session, } else { &sess.target.target.options.pre_link_objects_dll }; - for obj in pre_link_objects { - cmd.arg(root.join(obj)); + // When dynamically linking to MUSL we don't need to pass our startup + // objects as those will be provided by the MUSL toolchain + if !musl || crt_static { + for obj in pre_link_objects { + cmd.arg(root.join(obj)); + } } { @@ -686,8 +693,11 @@ fn link_natively(sess: &Session, objects, out_filename, outputs, trans); } cmd.args(&sess.target.target.options.late_link_args); - for obj in &sess.target.target.options.post_link_objects { - cmd.arg(root.join(obj)); + // Same as above + if !musl || crt_static { + for obj in &sess.target.target.options.post_link_objects { + cmd.arg(root.join(obj)); + } } cmd.args(&sess.target.target.options.post_link_args); @@ -813,8 +823,9 @@ fn link_args(cmd: &mut Linker, let mut args = args.iter().chain(more_args.iter()).chain(used_link_args.iter()); let relocation_model = sess.opts.cg.relocation_model.as_ref() .unwrap_or(&empty_str); + let crt_static = sess.target_is_crt_static(); if (t.options.relocation_model == "pic" || *relocation_model == "pic") - && !args.any(|x| *x == "-static") { + && !args.any(|x| *x == "-static") && !crt_static { cmd.position_independent_executable(); } }