Skip to content

Commit 22da16a

Browse files
committed
rustc_back: Add x86_64-unknown-linux-musl as a target
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.
1 parent cd980b3 commit 22da16a

File tree

3 files changed

+96
-31
lines changed

3 files changed

+96
-31
lines changed

src/librustc_back/target/linux_base.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,16 @@ pub fn opts() -> TargetOptions {
1919
morestack: true,
2020
linker_is_gnu: true,
2121
has_rpath: true,
22-
pre_link_args: vec!(
23-
// GNU-style linkers will use this to omit linking to libraries which
24-
// don't actually fulfill any relocations, but only for libraries which
25-
// follow this flag. Thus, use it before specifying libraries to link to.
22+
pre_link_args: vec![
23+
// We want to be able to strip as much executable code as possible
24+
// from the linker command line, and this flag indicates to the
25+
// linker that it can avoid linking in dynamic libraries that don't
26+
// actually satisfy any symbols up to that point (as with many other
27+
// resolutions the linker does). This option only applies to all
28+
// following libraries so we're sure to pass it as one of the first
29+
// arguments.
2630
"-Wl,--as-needed".to_string(),
27-
),
31+
],
2832
position_independent_executables: true,
2933
.. Default::default()
3034
}

src/librustc_back/target/mod.rs

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -59,32 +59,6 @@ mod dragonfly_base;
5959
mod bitrig_base;
6060
mod openbsd_base;
6161

62-
mod armv7_apple_ios;
63-
mod armv7s_apple_ios;
64-
mod i386_apple_ios;
65-
66-
mod arm_linux_androideabi;
67-
mod arm_unknown_linux_gnueabi;
68-
mod arm_unknown_linux_gnueabihf;
69-
mod aarch64_apple_ios;
70-
mod aarch64_linux_android;
71-
mod aarch64_unknown_linux_gnu;
72-
mod i686_apple_darwin;
73-
mod i686_pc_windows_gnu;
74-
mod i686_unknown_dragonfly;
75-
mod i686_unknown_linux_gnu;
76-
mod mips_unknown_linux_gnu;
77-
mod mipsel_unknown_linux_gnu;
78-
mod powerpc_unknown_linux_gnu;
79-
mod x86_64_apple_darwin;
80-
mod x86_64_apple_ios;
81-
mod x86_64_pc_windows_gnu;
82-
mod x86_64_unknown_freebsd;
83-
mod x86_64_unknown_dragonfly;
84-
mod x86_64_unknown_bitrig;
85-
mod x86_64_unknown_linux_gnu;
86-
mod x86_64_unknown_openbsd;
87-
8862
/// Everything `rustc` knows about how to compile for a specific target.
8963
///
9064
/// Every field here must be specified, and has no default value.
@@ -333,6 +307,7 @@ impl Target {
333307
macro_rules! load_specific {
334308
( $($name:ident),+ ) => (
335309
{
310+
$(mod $name;)*
336311
let target = target.replace("-", "_");
337312
if false { }
338313
$(
@@ -362,6 +337,7 @@ impl Target {
362337
arm_unknown_linux_gnueabi,
363338
arm_unknown_linux_gnueabihf,
364339
aarch64_unknown_linux_gnu,
340+
x86_64_unknown_linux_musl,
365341

366342
arm_linux_androideabi,
367343
aarch64_linux_android,
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use target::Target;
12+
13+
pub fn target() -> Target {
14+
let mut base = super::linux_base::opts();
15+
base.cpu = "x86-64".to_string();
16+
base.linker = "musl-gcc".to_string();
17+
base.pre_link_args.push("-m64".to_string());
18+
19+
// Make sure that the linker/gcc really don't pull in anything, including
20+
// default objects, libs, etc.
21+
base.pre_link_args.push("-nostdlib".to_string());
22+
base.pre_link_args.push("-static".to_string());
23+
24+
// At least when this was tested, the linker would not add the
25+
// `GNU_EH_FRAME` program header to executables generated, which is required
26+
// when unwinding to locate the unwinding information. I'm not sure why this
27+
// argument is *not* necessary for normal builds, but it can't hurt!
28+
base.pre_link_args.push("-Wl,--eh-frame-hdr".to_string());
29+
30+
// There's a whole bunch of circular dependencies when dealing with MUSL
31+
// unfortunately. To put this in perspective libc is statically linked to
32+
// liblibc and libunwind is statically linked to libstd:
33+
//
34+
// * libcore depends on `fmod` which is in libc (transitively in liblibc).
35+
// liblibc, however, depends on libcore.
36+
// * compiler-rt has personality symbols that depend on libunwind, but
37+
// libunwind is in libstd which depends on compiler-rt.
38+
//
39+
// Recall that linkers discard libraries and object files as much as
40+
// possible, and with all the static linking and archives flying around with
41+
// MUSL the linker is super aggressively stripping out objects. For example
42+
// the first case has fmod stripped from liblibc (it's in its own object
43+
// file) so it's not there when libcore needs it. In the second example all
44+
// the unused symbols from libunwind are stripped (each is in its own object
45+
// file in libstd) before we end up linking compiler-rt which depends on
46+
// those symbols.
47+
//
48+
// To deal with these circular dependencies we just force the compiler to
49+
// link everything as a group, not stripping anything out until everything
50+
// is processed. The linker will still perform a pass to strip out object
51+
// files but it won't do so until all objects/archives have been processed.
52+
base.pre_link_args.push("-Wl,-(".to_string());
53+
base.post_link_args.push("-Wl,-)".to_string());
54+
55+
// When generating a statically linked executable there's generally some
56+
// small setup needed which is listed in these files. These are provided by
57+
// a musl toolchain and are linked by default by the `musl-gcc` script. Note
58+
// that `gcc` also does this by default, it just uses some different files.
59+
//
60+
// Each target directory for musl has these object files included in it so
61+
// they'll be included from there.
62+
base.pre_link_objects.push("crt1.o".to_string());
63+
base.pre_link_objects.push("crti.o".to_string());
64+
base.post_link_objects.push("crtn.o".to_string());
65+
66+
// MUSL support doesn't currently include dynamic linking, so there's no
67+
// need for dylibs or rpath business. Additionally `-pie` is incompatible
68+
// with `-static`, so we can't pass `-pie`.
69+
base.dynamic_linking = false;
70+
base.has_rpath = false;
71+
base.position_independent_executables = false;
72+
73+
Target {
74+
data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
75+
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
76+
s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
77+
llvm_target: "x86_64-unknown-linux-musl".to_string(),
78+
target_endian: "little".to_string(),
79+
target_pointer_width: "64".to_string(),
80+
arch: "x86_64".to_string(),
81+
target_os: "linux".to_string(),
82+
target_env: "musl".to_string(),
83+
options: base,
84+
}
85+
}

0 commit comments

Comments
 (0)