Skip to content

Commit

Permalink
rustc_back: Add x86_64-unknown-linux-musl as a target
Browse files Browse the repository at this point in the history
This commit adds support for x86_64-unknown-linux-musl as a target of the
compiler. There's some comments in the commit about some of the more flavorful
flags passed to the linker as it's not quite as trivial as the normal specs.
  • Loading branch information
alexcrichton committed Apr 24, 2015
1 parent 98babae commit 3fa6fc3
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 29 deletions.
7 changes: 4 additions & 3 deletions src/librustc_back/target/linux_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ pub fn opts() -> TargetOptions {
linker_is_gnu: true,
has_rpath: true,
pre_link_args: vec!(
// GNU-style linkers will use this to omit linking to libraries which
// don't actually fulfill any relocations, but only for libraries which
// follow this flag. Thus, use it before specifying libraries to link to.
// GNU-style linkers will use this to omit linking to libraries
// which don't actually fulfill any relocations, but only for
// libraries which follow this flag. Thus, use it before specifying
// libraries to link to.

This comment has been minimized.

Copy link
@brson

brson Apr 24, 2015

The additional comment 'for only libraries which follow this flag' isn't clear to me. What does this mean?

This comment has been minimized.

Copy link
@alexcrichton

alexcrichton Apr 24, 2015

Author Owner

Hm this comment is a little dated, I'll just rewrite the whole thing.

"-Wl,--as-needed".to_string(),
),
position_independent_executables: true,
Expand Down
28 changes: 2 additions & 26 deletions src/librustc_back/target/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,32 +59,6 @@ mod dragonfly_base;
mod bitrig_base;
mod openbsd_base;

mod armv7_apple_ios;
mod armv7s_apple_ios;
mod i386_apple_ios;

mod arm_linux_androideabi;
mod arm_unknown_linux_gnueabi;
mod arm_unknown_linux_gnueabihf;
mod aarch64_apple_ios;
mod aarch64_linux_android;
mod aarch64_unknown_linux_gnu;
mod i686_apple_darwin;
mod i686_pc_windows_gnu;
mod i686_unknown_dragonfly;
mod i686_unknown_linux_gnu;
mod mips_unknown_linux_gnu;
mod mipsel_unknown_linux_gnu;
mod powerpc_unknown_linux_gnu;
mod x86_64_apple_darwin;
mod x86_64_apple_ios;
mod x86_64_pc_windows_gnu;
mod x86_64_unknown_freebsd;
mod x86_64_unknown_dragonfly;
mod x86_64_unknown_bitrig;
mod x86_64_unknown_linux_gnu;
mod x86_64_unknown_openbsd;

/// Everything `rustc` knows about how to compile for a specific target.
///
/// Every field here must be specified, and has no default value.
Expand Down Expand Up @@ -333,6 +307,7 @@ impl Target {
macro_rules! load_specific {
( $($name:ident),+ ) => (
{
$(mod $name;)*
let target = target.replace("-", "_");
if false { }
$(
Expand Down Expand Up @@ -362,6 +337,7 @@ impl Target {
arm_unknown_linux_gnueabi,
arm_unknown_linux_gnueabihf,
aarch64_unknown_linux_gnu,
x86_64_unknown_linux_musl,

arm_linux_androideabi,
aarch64_linux_android,
Expand Down
85 changes: 85 additions & 0 deletions src/librustc_back/target/x86_64_unknown_linux_musl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright 2014 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.

use target::Target;

pub fn target() -> Target {
let mut base = super::linux_base::opts();
base.cpu = "x86-64".to_string();
base.linker = "musl-gcc".to_string();
base.pre_link_args.push("-m64".to_string());

// 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
// when unwinding to locate the unwinding information. I'm not sure why this
// argument is *not* necessary for normal builds, but it can't hurt!
base.pre_link_args.push("-Wl,--eh-frame-hdr".to_string());

// There's a whole bunch of circular dependencies when dealing with MUSL
// unfortunately. To put this in perspective libc is statically linked to
// liblibc and libunwind is statically linked to libstd:
//
// * libcore depends on `fmod` which is in libc (transitively in liblibc).
// liblibc, however, depends on libcore.
// * compiler-rt has personality symbols that depend on libunwind, but
// libunwind is in libstd which depends on compiler-rt.
//
// Recall that linkers discard libraries and object files as much as
// possible, and with all the static linking and archives flying around with
// MUSL the linker is super aggressively stripping out objects. For example
// the first case has fmod stripped from liblibc (it's in its own object
// file) so it's not there when libcore needs it. In the second example all
// the unused symbols from libunwind are stripped (each is in its own object
// file in libstd) before we end up linking compiler-rt which depends on
// those symbols.
//
// To deal with these circular dependencies we just force the compiler to
// link everything as a group, not stripping anything out until everything
// is processed. The linker will still perform a pass to strip out object
// files but it won't do so until all objects/archives have been processed.
base.pre_link_args.push("-Wl,-(".to_string());
base.post_link_args.push("-Wl,-)".to_string());

This comment has been minimized.

Copy link
@brson

brson Apr 24, 2015

This looks scary.

This comment has been minimized.

Copy link
@alexcrichton

alexcrichton Apr 24, 2015

Author Owner

I agree! We've worked really hard to not require these flags in other targets and architectures (bending over backwards to make sure everything is ordered correctly on the command line). We do still, however, have link failure bugs due to our own circular dependencies between the standard library and libcore, for example. I just found that MUSL linkage had so many circular dependencies that it was worth just passing these arguments to make them all go away.

I believe the only downside to these options is that it may reduce the linker performance slightly as it can't discard objects as soon as it could otherwise. I haven't measure the impact of this, however.


// When generating a statically linked executable there's generally some
// small setup needed which is listed in these files. These are provided by
// a musl toolchain and are linked by default by the `musl-gcc` script. Note
// that `gcc` also does this by default, it just uses some different files.
//
// Each target directory for musl has these object files included in it so
// they'll be included from there.
base.pre_link_objects.push("crt1.o".to_string());
base.pre_link_objects.push("crti.o".to_string());
base.post_link_objects.push("crtn.o".to_string());

// MUSL support doesn't currently included the dynamic linking of MUSL, 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;

Target {
data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
llvm_target: "x86_64-unknown-linux-musl".to_string(),
target_endian: "little".to_string(),
target_pointer_width: "64".to_string(),
arch: "x86_64".to_string(),
target_os: "linux".to_string(),
target_env: "musl".to_string(),
options: base,
}
}

0 comments on commit 3fa6fc3

Please sign in to comment.