Skip to content

Commit 324a29b

Browse files
authored
Rollup merge of #40113 - smaeul:native-musl, r=alexcrichton
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.
2 parents 1785bca + d985de1 commit 324a29b

File tree

16 files changed

+110
-54
lines changed

16 files changed

+110
-54
lines changed

configure

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,8 @@ valopt musl-root-i686 "" "i686-unknown-linux-musl install directory"
487487
valopt musl-root-arm "" "arm-unknown-linux-musleabi install directory"
488488
valopt musl-root-armhf "" "arm-unknown-linux-musleabihf install directory"
489489
valopt musl-root-armv7 "" "armv7-unknown-linux-musleabihf install directory"
490+
valopt musl-root-mips "" "mips-unknown-linux-musl install directory"
491+
valopt musl-root-mipsel "" "mipsel-unknown-linux-musl install directory"
490492
valopt extra-filename "" "Additional data that is hashed and passed to the -C extra-filename flag"
491493
valopt qemu-armhf-rootfs "" "rootfs in qemu testing, you probably don't want to use this"
492494

src/bootstrap/bin/rustc.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,15 @@ fn main() {
214214
}
215215
}
216216

217-
if target.contains("pc-windows-msvc") {
218-
cmd.arg("-Z").arg("unstable-options");
219-
cmd.arg("-C").arg("target-feature=+crt-static");
217+
if let Ok(s) = env::var("RUST_CRT_STATIC") {
218+
if s == "true" {
219+
cmd.arg("-Z").arg("unstable-options");
220+
cmd.arg("-C").arg("target-feature=+crt-static");
221+
}
222+
if s == "false" {
223+
cmd.arg("-Z").arg("unstable-options");
224+
cmd.arg("-C").arg("target-feature=-crt-static");
225+
}
220226
}
221227
}
222228

src/bootstrap/compile.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,17 @@ pub fn std_link(build: &Build,
112112
t!(fs::create_dir_all(&libdir));
113113
add_to_sysroot(&out_dir, &libdir);
114114

115-
if target.contains("musl") && !target.contains("mips") {
115+
if target.contains("musl") {
116116
copy_musl_third_party_objects(build, target, &libdir);
117117
}
118118
}
119119

120120
/// Copies the crt(1,i,n).o startup objects
121121
///
122-
/// Only required for musl targets that statically link to libc
122+
/// Since musl supports fully static linking, we can cross link for it even
123+
/// with a glibc-targeting toolchain, given we have the appropriate startup
124+
/// files. As those shipped with glibc won't work, copy the ones provided by
125+
/// musl so we have them on linux-gnu hosts.
123126
fn copy_musl_third_party_objects(build: &Build, target: &str, into: &Path) {
124127
for &obj in &["crt1.o", "crti.o", "crtn.o"] {
125128
copy(&build.musl_root(target).unwrap().join("lib").join(obj), &into.join(obj));

src/bootstrap/config.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ pub struct Target {
119119
pub cc: Option<PathBuf>,
120120
pub cxx: Option<PathBuf>,
121121
pub ndk: Option<PathBuf>,
122+
pub crt_static: Option<bool>,
122123
pub musl_root: Option<PathBuf>,
123124
pub qemu_rootfs: Option<PathBuf>,
124125
}
@@ -235,6 +236,7 @@ struct TomlTarget {
235236
cc: Option<String>,
236237
cxx: Option<String>,
237238
android_ndk: Option<String>,
239+
crt_static: Option<bool>,
238240
musl_root: Option<String>,
239241
qemu_rootfs: Option<String>,
240242
}
@@ -381,6 +383,7 @@ impl Config {
381383
}
382384
target.cxx = cfg.cxx.clone().map(PathBuf::from);
383385
target.cc = cfg.cc.clone().map(PathBuf::from);
386+
target.crt_static = cfg.crt_static.clone();
384387
target.musl_root = cfg.musl_root.clone().map(PathBuf::from);
385388
target.qemu_rootfs = cfg.qemu_rootfs.clone().map(PathBuf::from);
386389

@@ -508,6 +511,18 @@ impl Config {
508511
.or_insert(Target::default());
509512
target.musl_root = Some(parse_configure_path(value));
510513
}
514+
"CFG_MUSL_ROOT_MIPS" if value.len() > 0 => {
515+
let target = "mips-unknown-linux-musl".to_string();
516+
let target = self.target_config.entry(target)
517+
.or_insert(Target::default());
518+
target.musl_root = Some(parse_configure_path(value));
519+
}
520+
"CFG_MUSL_ROOT_MIPSEL" if value.len() > 0 => {
521+
let target = "mipsel-unknown-linux-musl".to_string();
522+
let target = self.target_config.entry(target)
523+
.or_insert(Target::default());
524+
target.musl_root = Some(parse_configure_path(value));
525+
}
511526
"CFG_DEFAULT_AR" if value.len() > 0 => {
512527
self.rustc_default_ar = Some(value.to_string());
513528
}

src/bootstrap/lib.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,10 @@ impl Build {
482482
.env("RUSTC_DEBUGINFO_LINES", self.config.rust_debuginfo_lines.to_string());
483483
}
484484

485+
if let Some(x) = self.crt_static(target) {
486+
cargo.env("RUST_CRT_STATIC", x.to_string());
487+
}
488+
485489
// Enable usage of unstable features
486490
cargo.env("RUSTC_BOOTSTRAP", "1");
487491
self.add_rust_test_threads(&mut cargo);
@@ -917,6 +921,16 @@ impl Build {
917921
return base
918922
}
919923

924+
/// Returns if this target should statically link the C runtime, if specified
925+
fn crt_static(&self, target: &str) -> Option<bool> {
926+
if target.contains("pc-windows-msvc") {
927+
Some(true)
928+
} else {
929+
self.config.target_config.get(target)
930+
.and_then(|t| t.crt_static)
931+
}
932+
}
933+
920934
/// Returns the "musl root" for this `target`, if defined
921935
fn musl_root(&self, target: &str) -> Option<&Path> {
922936
self.config.target_config.get(target)

src/bootstrap/sanity.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,15 @@ pub fn check(build: &mut Build) {
157157
panic!("the iOS target is only supported on macOS");
158158
}
159159

160-
// Make sure musl-root is valid if specified
161-
if target.contains("musl") && !target.contains("mips") {
160+
// Make sure musl-root is valid
161+
if target.contains("musl") {
162+
// If this is a native target (host is also musl) and no musl-root is given,
163+
// fall back to the system toolchain in /usr before giving up
164+
if build.musl_root(target).is_none() && build.config.build == *target {
165+
let target = build.config.target_config.entry(target.clone())
166+
.or_insert(Default::default());
167+
target.musl_root = Some("/usr".into());
168+
}
162169
match build.musl_root(target) {
163170
Some(root) => {
164171
if fs::metadata(root.join("lib/libc.a")).is_err() {

src/ci/docker/cross/Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,5 +78,7 @@ ENV RUST_CONFIGURE_ARGS \
7878
--target=$TARGETS \
7979
--musl-root-arm=/usr/local/arm-linux-musleabi \
8080
--musl-root-armhf=/usr/local/arm-linux-musleabihf \
81-
--musl-root-armv7=/usr/local/armv7-linux-musleabihf
81+
--musl-root-armv7=/usr/local/armv7-linux-musleabihf \
82+
--musl-root-mips=/usr/local/mips-linux-musl \
83+
--musl-root-mipsel=/usr/local/mipsel-linux-musl
8284
ENV SCRIPT python2.7 ../x.py dist --target $TARGETS

src/librustc/session/mod.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use syntax::parse::ParseSess;
3333
use syntax::symbol::Symbol;
3434
use syntax::{ast, codemap};
3535
use syntax::feature_gate::AttributeType;
36+
use syntax::feature_gate::UnstableFeatures;
3637
use syntax_pos::{Span, MultiSpan};
3738

3839
use rustc_back::{LinkerFlavor, PanicStrategy};
@@ -394,6 +395,32 @@ impl Session {
394395
.unwrap_or(self.opts.debug_assertions)
395396
}
396397

398+
pub fn crt_static(&self) -> bool {
399+
let requested_features = self.opts.cg.target_feature.split(',');
400+
let unstable_options = self.opts.debugging_opts.unstable_options;
401+
let is_nightly = UnstableFeatures::from_environment().is_nightly_build();
402+
let found_negative = requested_features.clone().any(|r| r == "-crt-static");
403+
let found_positive = requested_features.clone().any(|r| r == "+crt-static");
404+
405+
// If we switched from the default then that's only allowed on nightly, so
406+
// gate that here.
407+
if (found_positive || found_negative) && (!is_nightly || !unstable_options) {
408+
self.fatal("specifying the `crt-static` target feature is only allowed \
409+
on the nightly channel with `-Z unstable-options` passed \
410+
as well");
411+
}
412+
413+
// If the target we're compiling for requests a static crt by default,
414+
// then see if the `-crt-static` feature was passed to disable that.
415+
// Otherwise if we don't have a static crt by default then see if the
416+
// `+crt-static` feature was passed.
417+
if self.target.target.options.crt_static_default {
418+
!found_negative
419+
} else {
420+
found_positive
421+
}
422+
}
423+
397424
pub fn must_not_eliminate_frame_pointers(&self) -> bool {
398425
self.opts.debuginfo != DebugInfoLevel::NoDebugInfo ||
399426
!self.target.target.options.eliminate_frame_pointer

src/librustc_back/target/linux_musl_base.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,7 @@ pub fn opts() -> TargetOptions {
6060
base.pre_link_objects_exe.push("crti.o".to_string());
6161
base.post_link_objects.push("crtn.o".to_string());
6262

63-
// MUSL support doesn't currently include dynamic linking, so there's no
64-
// need for dylibs or rpath business. Additionally `-pie` is incompatible
65-
// with `-static`, so we can't pass `-pie`.
66-
base.dynamic_linking = false;
67-
base.has_rpath = false;
68-
base.position_independent_executables = false;
69-
70-
// These targets statically link libc by default
63+
// Except for on MIPS, these targets statically link libc by default.
7164
base.crt_static_default = true;
7265

7366
base

src/librustc_back/target/mips_unknown_linux_musl.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub fn target() -> TargetResult {
2727
features: "+mips32r2,+soft-float".to_string(),
2828
max_atomic_width: Some(32),
2929

30+
crt_static_default: false,
3031
// see #36994
3132
exe_allocation_crate: "alloc_system".to_string(),
3233

src/librustc_back/target/mipsel_unknown_linux_musl.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub fn target() -> TargetResult {
2727
features: "+mips32,+soft-float".to_string(),
2828
max_atomic_width: Some(32),
2929

30+
crt_static_default: false,
3031
// see #36994
3132
exe_allocation_crate: "alloc_system".to_string(),
3233

src/librustc_driver/target_features.rs

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use syntax::ast;
1212
use llvm::LLVMRustHasFeature;
1313
use rustc::session::Session;
1414
use rustc_trans::back::write::create_target_machine;
15-
use syntax::feature_gate::UnstableFeatures;
1615
use syntax::symbol::Symbol;
1716
use libc::c_char;
1817

@@ -49,31 +48,7 @@ pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) {
4948
}
5049
}
5150

52-
let requested_features = sess.opts.cg.target_feature.split(',');
53-
let unstable_options = sess.opts.debugging_opts.unstable_options;
54-
let is_nightly = UnstableFeatures::from_environment().is_nightly_build();
55-
let found_negative = requested_features.clone().any(|r| r == "-crt-static");
56-
let found_positive = requested_features.clone().any(|r| r == "+crt-static");
57-
58-
// If the target we're compiling for requests a static crt by default,
59-
// then see if the `-crt-static` feature was passed to disable that.
60-
// Otherwise if we don't have a static crt by default then see if the
61-
// `+crt-static` feature was passed.
62-
let crt_static = if sess.target.target.options.crt_static_default {
63-
!found_negative
64-
} else {
65-
found_positive
66-
};
67-
68-
// If we switched from the default then that's only allowed on nightly, so
69-
// gate that here.
70-
if (found_positive || found_negative) && (!is_nightly || !unstable_options) {
71-
sess.fatal("specifying the `crt-static` target feature is only allowed \
72-
on the nightly channel with `-Z unstable-options` passed \
73-
as well");
74-
}
75-
76-
if crt_static {
51+
if sess.crt_static() {
7752
cfg.insert((tf, Some(Symbol::intern("crt-static"))));
7853
}
7954
}

src/librustc_trans/back/link.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -715,13 +715,15 @@ fn link_natively(sess: &Session,
715715
cmd.args(args);
716716
}
717717

718-
let pre_link_objects = if crate_type == config::CrateTypeExecutable {
719-
&sess.target.target.options.pre_link_objects_exe
720-
} else {
721-
&sess.target.target.options.pre_link_objects_dll
722-
};
723-
for obj in pre_link_objects {
724-
cmd.arg(root.join(obj));
718+
if sess.crt_static() {
719+
let pre_link_objects = if crate_type == config::CrateTypeExecutable {
720+
&sess.target.target.options.pre_link_objects_exe
721+
} else {
722+
&sess.target.target.options.pre_link_objects_dll
723+
};
724+
for obj in pre_link_objects {
725+
cmd.arg(root.join(obj));
726+
}
725727
}
726728

727729
if sess.target.target.options.is_like_emscripten {
@@ -742,8 +744,10 @@ fn link_natively(sess: &Session,
742744
if let Some(args) = sess.target.target.options.late_link_args.get(&flavor) {
743745
cmd.args(args);
744746
}
745-
for obj in &sess.target.target.options.post_link_objects {
746-
cmd.arg(root.join(obj));
747+
if sess.crt_static() {
748+
for obj in &sess.target.target.options.post_link_objects {
749+
cmd.arg(root.join(obj));
750+
}
747751
}
748752
if let Some(args) = sess.target.target.options.post_link_args.get(&flavor) {
749753
cmd.args(args);

src/libstd/build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ fn main() {
3030
println!("cargo:rustc-link-lib=dl");
3131
println!("cargo:rustc-link-lib=log");
3232
println!("cargo:rustc-link-lib=gcc");
33-
} else if !target.contains("musl") || target.contains("mips") {
33+
} else if !target.contains("musl") {
3434
println!("cargo:rustc-link-lib=dl");
3535
println!("cargo:rustc-link-lib=rt");
3636
println!("cargo:rustc-link-lib=pthread");

src/libunwind/build.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ fn main() {
1515
let target = env::var("TARGET").expect("TARGET was not set");
1616

1717
if target.contains("linux") {
18-
if target.contains("musl") && !target.contains("mips") {
19-
println!("cargo:rustc-link-lib=static=unwind");
18+
if target.contains("musl") {
19+
// musl is handled in lib.rs
2020
} else if !target.contains("android") {
2121
println!("cargo:rustc-link-lib=gcc_s");
2222
}

src/libunwind/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#![deny(warnings)]
1616

1717
#![feature(cfg_target_vendor)]
18+
#![feature(link_cfg)]
1819
#![feature(staged_api)]
1920
#![feature(unwind_attributes)]
2021
#![feature(static_nobundle)]
@@ -28,3 +29,8 @@ extern crate libc;
2829
mod libunwind;
2930
#[cfg(not(target_env = "msvc"))]
3031
pub use libunwind::*;
32+
33+
#[cfg(target_env = "musl")]
34+
#[link(name = "unwind", kind = "static", cfg(target_feature = "crt-static"))]
35+
#[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))]
36+
extern {}

0 commit comments

Comments
 (0)