Skip to content

Commit

Permalink
Rollup merge of rust-lang#40113 - smaeul:native-musl, r=alexcrichton
Browse files Browse the repository at this point in the history
Support dynamically-linked and/or native musl targets

These changes allow native compilation on musl-based distributions and the use of dynamic libraries on linux-musl targets. This is intended to remove limitations based on past assumptions about musl targets, while maintaining existing behavior by default.

A minor related bugfix is included.
  • Loading branch information
frewsxcv committed Mar 8, 2017
2 parents ee60afa + 706fc55 commit d9f633f
Show file tree
Hide file tree
Showing 14 changed files with 95 additions and 53 deletions.
12 changes: 9 additions & 3 deletions src/bootstrap/bin/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,15 @@ fn main() {
}
}

if target.contains("pc-windows-msvc") {
cmd.arg("-Z").arg("unstable-options");
cmd.arg("-C").arg("target-feature=+crt-static");
if let Ok(s) = env::var("RUST_CRT_STATIC") {
if s == "true" {
cmd.arg("-Z").arg("unstable-options");
cmd.arg("-C").arg("target-feature=+crt-static");
}
if s == "false" {
cmd.arg("-Z").arg("unstable-options");
cmd.arg("-C").arg("target-feature=-crt-static");
}
}
}

Expand Down
7 changes: 5 additions & 2 deletions src/bootstrap/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,17 @@ pub fn std_link(build: &Build,
t!(fs::create_dir_all(&libdir));
add_to_sysroot(&out_dir, &libdir);

if target.contains("musl") && !target.contains("mips") {
if target.contains("musl") {
copy_musl_third_party_objects(build, target, &libdir);
}
}

/// Copies the crt(1,i,n).o startup objects
///
/// Only required for musl targets that statically link to libc
/// Since musl supports fully static linking, we can cross link for it even
/// with a glibc-targeting toolchain, given we have the appropriate startup
/// files. As those shipped with glibc won't work, copy the ones provided by
/// musl so we have them on linux-gnu hosts.
fn copy_musl_third_party_objects(build: &Build, target: &str, into: &Path) {
for &obj in &["crt1.o", "crti.o", "crtn.o"] {
copy(&build.musl_root(target).unwrap().join("lib").join(obj), &into.join(obj));
Expand Down
3 changes: 3 additions & 0 deletions src/bootstrap/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ pub struct Target {
pub cc: Option<PathBuf>,
pub cxx: Option<PathBuf>,
pub ndk: Option<PathBuf>,
pub crt_static: Option<bool>,
pub musl_root: Option<PathBuf>,
pub qemu_rootfs: Option<PathBuf>,
}
Expand Down Expand Up @@ -231,6 +232,7 @@ struct TomlTarget {
cc: Option<String>,
cxx: Option<String>,
android_ndk: Option<String>,
crt_static: Option<bool>,
musl_root: Option<String>,
qemu_rootfs: Option<String>,
}
Expand Down Expand Up @@ -375,6 +377,7 @@ impl Config {
}
target.cxx = cfg.cxx.clone().map(PathBuf::from);
target.cc = cfg.cc.clone().map(PathBuf::from);
target.crt_static = cfg.crt_static.clone();
target.musl_root = cfg.musl_root.clone().map(PathBuf::from);
target.qemu_rootfs = cfg.qemu_rootfs.clone().map(PathBuf::from);

Expand Down
14 changes: 14 additions & 0 deletions src/bootstrap/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,10 @@ impl Build {
.env("RUSTDOC_REAL", self.rustdoc(compiler))
.env("RUSTC_FLAGS", self.rustc_flags(target).join(" "));

if let Some(x) = self.crt_static(target) {
cargo.env("RUST_CRT_STATIC", x.to_string());
}

// Enable usage of unstable features
cargo.env("RUSTC_BOOTSTRAP", "1");
self.add_rust_test_threads(&mut cargo);
Expand Down Expand Up @@ -880,6 +884,16 @@ impl Build {
return base
}

/// Returns if this target should statically link the C runtime, if specified
fn crt_static(&self, target: &str) -> Option<bool> {
if target.contains("pc-windows-msvc") {
Some(true)
} else {
self.config.target_config.get(target)
.and_then(|t| t.crt_static)
}
}

/// Returns the "musl root" for this `target`, if defined
fn musl_root(&self, target: &str) -> Option<&Path> {
self.config.target_config.get(target)
Expand Down
11 changes: 9 additions & 2 deletions src/bootstrap/sanity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,15 @@ pub fn check(build: &mut Build) {
panic!("the iOS target is only supported on OSX");
}

// Make sure musl-root is valid if specified
if target.contains("musl") && !target.contains("mips") {
// Make sure musl-root is valid
if target.contains("musl") {
// If this is a native target (host is also musl) and no musl-root is given,
// fall back to the system toolchain in /usr before giving up
if build.musl_root(target).is_none() && build.config.build == *target {
let target = build.config.target_config.entry(target.clone())
.or_insert(Default::default());
target.musl_root = Some("/usr".into());
}
match build.musl_root(target) {
Some(root) => {
if fs::metadata(root.join("lib/libc.a")).is_err() {
Expand Down
29 changes: 29 additions & 0 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use syntax::parse::ParseSess;
use syntax::symbol::Symbol;
use syntax::{ast, codemap};
use syntax::feature_gate::AttributeType;
use syntax::feature_gate::UnstableFeatures;
use syntax_pos::{Span, MultiSpan};

use rustc_back::PanicStrategy;
Expand Down Expand Up @@ -378,6 +379,34 @@ impl Session {
.unwrap_or(self.opts.debug_assertions)
}

pub fn 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 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 self.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) {
self.fatal("specifying the `crt-static` target feature is only allowed \
on the nightly channel with `-Z unstable-options` passed \
as well");
}

return crt_static;
}

pub fn must_not_eliminate_frame_pointers(&self) -> bool {
self.opts.debuginfo != DebugInfoLevel::NoDebugInfo ||
!self.target.target.options.eliminate_frame_pointer
Expand Down
9 changes: 1 addition & 8 deletions src/librustc_back/target/linux_musl_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,7 @@ pub fn opts() -> TargetOptions {
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;
base.has_rpath = false;
base.position_independent_executables = false;

// These targets statically link libc by default
// Except for on MIPS, these targets statically link libc by default.
base.crt_static_default = true;

base
Expand Down
1 change: 1 addition & 0 deletions src/librustc_back/target/mips_unknown_linux_musl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub fn target() -> TargetResult {
features: "+mips32r2,+soft-float".to_string(),
max_atomic_width: Some(32),

crt_static_default: false,
// see #36994
exe_allocation_crate: "alloc_system".to_string(),

Expand Down
1 change: 1 addition & 0 deletions src/librustc_back/target/mipsel_unknown_linux_musl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub fn target() -> TargetResult {
features: "+mips32,+soft-float".to_string(),
max_atomic_width: Some(32),

crt_static_default: false,
// see #36994
exe_allocation_crate: "alloc_system".to_string(),

Expand Down
27 changes: 1 addition & 26 deletions src/librustc_driver/target_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -49,31 +48,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.crt_static() {
cfg.insert((tf, Some(Symbol::intern("crt-static"))));
}
}
22 changes: 13 additions & 9 deletions src/librustc_trans/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -715,13 +715,15 @@ fn link_natively(sess: &Session,
let root = sess.target_filesearch(PathKind::Native).get_lib_path();
cmd.args(&sess.target.target.options.pre_link_args);

let pre_link_objects = if crate_type == config::CrateTypeExecutable {
&sess.target.target.options.pre_link_objects_exe
} else {
&sess.target.target.options.pre_link_objects_dll
};
for obj in pre_link_objects {
cmd.arg(root.join(obj));
if sess.crt_static() {
let pre_link_objects = if crate_type == config::CrateTypeExecutable {
&sess.target.target.options.pre_link_objects_exe
} else {
&sess.target.target.options.pre_link_objects_dll
};
for obj in pre_link_objects {
cmd.arg(root.join(obj));
}
}

if sess.target.target.options.is_like_emscripten {
Expand All @@ -739,8 +741,10 @@ 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));
if sess.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);

Expand Down
2 changes: 1 addition & 1 deletion src/libstd/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ fn main() {
println!("cargo:rustc-link-lib=dl");
println!("cargo:rustc-link-lib=log");
println!("cargo:rustc-link-lib=gcc");
} else if !target.contains("musl") || target.contains("mips") {
} else if !target.contains("musl") {
println!("cargo:rustc-link-lib=dl");
println!("cargo:rustc-link-lib=rt");
println!("cargo:rustc-link-lib=pthread");
Expand Down
4 changes: 2 additions & 2 deletions src/libunwind/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ fn main() {
let target = env::var("TARGET").expect("TARGET was not set");

if target.contains("linux") {
if target.contains("musl") && !target.contains("mips") {
println!("cargo:rustc-link-lib=static=unwind");
if target.contains("musl") {
// musl is handled in lib.rs
} else if !target.contains("android") {
println!("cargo:rustc-link-lib=gcc_s");
}
Expand Down
6 changes: 6 additions & 0 deletions src/libunwind/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#![deny(warnings)]

#![feature(cfg_target_vendor)]
#![feature(link_cfg)]
#![feature(staged_api)]
#![feature(unwind_attributes)]

Expand All @@ -27,3 +28,8 @@ extern crate libc;
mod libunwind;
#[cfg(not(target_env = "msvc"))]
pub use libunwind::*;

#[cfg(target_env = "musl")]
#[link(name = "unwind", kind = "static", cfg(target_feature = "crt-static"))]
#[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))]
extern {}

0 comments on commit d9f633f

Please sign in to comment.