-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
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
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
alexcrichton
Author
Owner
|
||
"-Wl,--as-needed".to_string(), | ||
), | ||
position_independent_executables: true, | ||
|
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.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
alexcrichton
Author
Owner
|
||
|
||
// 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, | ||
} | ||
} |
The additional comment 'for only libraries which follow this flag' isn't clear to me. What does this mean?