Skip to content

Commit 627d980

Browse files
timonvoJorge Aparicio
authored and
Jorge Aparicio
committed
Add ARM MUSL targets.
The targets are: - `arm-unknown-linux-musleabi` - `arm-unknown-linux-musleabihf` - `armv7-unknown-linux-musleabihf` These mirror the existing `gnueabi` targets. All of these targets produce fully static binaries, similar to the x86 MUSL targets. For now these targets can only be used with `--rustbuild` builds, as rust-lang/compiler-rt#22 only made the necessary compiler-rt changes in the CMake configs, not the plain GNU Make configs. I've tested these targets GCC 5.3.0 compiled again musl-1.1.12 (downloaded from http://musl.codu.org/). An example `./configure` invocation is: ``` ./configure \ --enable-rustbuild --target=arm-unknown-linux-musleabi \ --musl-root="$MUSL_ROOT" ``` where `MUSL_ROOT` points to the `arm-linux-musleabi` prefix. Usually that path will be of the form `/foobar/arm-linux-musleabi/arm-linux-musleabi`. Usually the cross-compile toolchain will live under `/foobar/arm-linux-musleabi/bin`. That path should either by added to your `PATH` variable, or you should add a section to your `config.toml` as follows: ``` [target.arm-unknown-linux-musleabi] cc = "/foobar/arm-linux-musleabi/bin/arm-linux-musleabi-gcc" cxx = "/foobar/arm-linux-musleabi/bin/arm-linux-musleabi-g++" ``` As a prerequisite you'll also have to put a cross-compiled static `libunwind.a` library in `$MUSL_ROOT/lib`. This is similar to [how the x86_64 MUSL targets are built] (https://doc.rust-lang.org/book/advanced-linking.html).
1 parent ccfec65 commit 627d980

15 files changed

+210
-9
lines changed

configure

+1-1
Original file line numberDiff line numberDiff line change
@@ -1192,7 +1192,7 @@ do
11921192
;;
11931193

11941194

1195-
x86_64-*-musl)
1195+
x86_64-*-musl | arm-*-musleabi)
11961196
if [ ! -f $CFG_MUSL_ROOT/lib/libc.a ]
11971197
then
11981198
err "musl libc $CFG_MUSL_ROOT/lib/libc.a not found"

mk/cfg/arm-unknown-linux-musleabi.mk

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# This file is intentially left empty to indicate that, while this target is
2+
# supported, it's not supported using plain GNU Make builds. Use a --rustbuild
3+
# instead.
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# This file is intentially left empty to indicate that, while this target is
2+
# supported, it's not supported using plain GNU Make builds. Use a --rustbuild
3+
# instead.
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# This file is intentially left empty to indicate that, while this target is
2+
# supported, it's not supported using plain GNU Make builds. Use a --rustbuild
3+
# instead.

src/bootstrap/compile.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,7 @@ pub fn std_link(build: &Build,
9292
}
9393
add_to_sysroot(&out_dir, &libdir);
9494

95-
if target.contains("musl") &&
96-
(target.contains("x86_64") || target.contains("i686")) {
95+
if target.contains("musl") && !target.contains("mips") {
9796
copy_third_party_objects(build, target, &libdir);
9897
}
9998
}

src/bootstrap/sanity.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ pub fn check(build: &mut Build) {
100100
}
101101

102102
// Make sure musl-root is valid if specified
103-
if target.contains("musl") && (target.contains("x86_64") || target.contains("i686")) {
103+
if target.contains("musl") && !target.contains("mips") {
104104
match build.config.musl_root {
105105
Some(ref root) => {
106106
if fs::metadata(root.join("lib/libc.a")).is_err() {

src/liballoc_jemalloc/build.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,16 @@ fn main() {
7373
.replace("\\", "/"))
7474
.current_dir(&build_dir)
7575
.env("CC", compiler.path())
76-
.env("EXTRA_CFLAGS", cflags)
76+
.env("EXTRA_CFLAGS", cflags.clone())
77+
// jemalloc generates Makefile deps using GCC's "-MM" flag. This means
78+
// that GCC will run the preprocessor, and only the preprocessor, over
79+
// jemalloc's source files. If we don't specify CPPFLAGS, then at least
80+
// on ARM that step fails with a "Missing implementation for 32-bit
81+
// atomic operations" error. This is because no "-march" flag will be
82+
// passed to GCC, and then GCC won't define the
83+
// "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4" macro that jemalloc needs to
84+
// select an atomic operation implementation.
85+
.env("CPPFLAGS", cflags.clone())
7786
.env("AR", &ar)
7887
.env("RANLIB", format!("{} s", ar.display()));
7988

src/liballoc_jemalloc/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ use libc::{c_int, c_void, size_t};
3636
#[cfg_attr(target_os = "android", link(name = "gcc"))]
3737
#[cfg_attr(all(not(windows),
3838
not(target_os = "android"),
39-
not(target_env = "musl")),
39+
not(target_env = "musl"),
40+
not(target_env = "musleabi"),
41+
not(target_env = "musleabihf")),
4042
link(name = "pthread"))]
4143
#[cfg(not(cargobuild))]
4244
extern "C" {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2016 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::musl_base::opts();
15+
16+
// Most of these settings are copied from the arm_unknown_linux_gnueabi
17+
// target.
18+
base.features = "+v6".to_string();
19+
Target {
20+
// It's important we use "gnueabi" and not "musleabi" here. LLVM uses it
21+
// to determine the calling convention and float ABI, and it doesn't
22+
// support the "musleabi" value.
23+
llvm_target: "arm-unknown-linux-gnueabi".to_string(),
24+
target_endian: "little".to_string(),
25+
target_pointer_width: "32".to_string(),
26+
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
27+
arch: "arm".to_string(),
28+
target_os: "linux".to_string(),
29+
target_env: "musleabi".to_string(),
30+
target_vendor: "unknown".to_string(),
31+
options: base,
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2016 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::musl_base::opts();
15+
16+
// Most of these settings are copied from the arm_unknown_linux_gnueabihf
17+
// target.
18+
base.features = "+v6,+vfp2".to_string();
19+
Target {
20+
// It's important we use "gnueabihf" and not "musleabihf" here. LLVM
21+
// uses it to determine the calling convention and float ABI, and it
22+
// doesn't support the "musleabihf" value.
23+
llvm_target: "arm-unknown-linux-gnueabihf".to_string(),
24+
target_endian: "little".to_string(),
25+
target_pointer_width: "32".to_string(),
26+
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
27+
arch: "arm".to_string(),
28+
target_os: "linux".to_string(),
29+
target_env: "musleabi".to_string(),
30+
target_vendor: "unknown".to_string(),
31+
options: base,
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2016 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::musl_base::opts();
15+
16+
// Most of these settings are copied from the armv7_unknown_linux_gnueabihf
17+
// target.
18+
base.features = "+v7,+vfp3,+neon".to_string();
19+
base.cpu = "cortex-a8".to_string();
20+
Target {
21+
// It's important we use "gnueabihf" and not "musleabihf" here. LLVM
22+
// uses it to determine the calling convention and float ABI, and LLVM
23+
// doesn't support the "musleabihf" value.
24+
llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
25+
target_endian: "little".to_string(),
26+
target_pointer_width: "32".to_string(),
27+
data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
28+
arch: "arm".to_string(),
29+
target_os: "linux".to_string(),
30+
target_env: "musleabi".to_string(),
31+
target_vendor: "unknown".to_string(),
32+
options: base,
33+
}
34+
}

src/librustc_back/target/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ mod freebsd_base;
5858
mod linux_base;
5959
mod linux_musl_base;
6060
mod openbsd_base;
61+
mod musl_base;
6162
mod netbsd_base;
6263
mod solaris_base;
6364
mod windows_base;
@@ -99,7 +100,10 @@ supported_targets! {
99100
("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
100101
("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
101102
("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf),
103+
("arm-unknown-linux-musleabi", arm_unknown_linux_musleabi),
104+
("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf),
102105
("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
106+
("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
103107
("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
104108
("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
105109
("i686-unknown-linux-musl", i686_unknown_linux_musl),

src/librustc_back/target/musl_base.rs

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Copyright 2016 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::TargetOptions;
12+
13+
pub fn opts() -> TargetOptions {
14+
let mut base = super::linux_base::opts();
15+
16+
// Make sure that the linker/gcc really don't pull in anything, including
17+
// default objects, libs, etc.
18+
base.pre_link_args.push("-nostdlib".to_string());
19+
base.pre_link_args.push("-static".to_string());
20+
21+
// At least when this was tested, the linker would not add the
22+
// `GNU_EH_FRAME` program header to executables generated, which is required
23+
// when unwinding to locate the unwinding information. I'm not sure why this
24+
// argument is *not* necessary for normal builds, but it can't hurt!
25+
base.pre_link_args.push("-Wl,--eh-frame-hdr".to_string());
26+
27+
// There's a whole bunch of circular dependencies when dealing with MUSL
28+
// unfortunately. To put this in perspective libc is statically linked to
29+
// liblibc and libunwind is statically linked to libstd:
30+
//
31+
// * libcore depends on `fmod` which is in libc (transitively in liblibc).
32+
// liblibc, however, depends on libcore.
33+
// * compiler-rt has personality symbols that depend on libunwind, but
34+
// libunwind is in libstd which depends on compiler-rt.
35+
//
36+
// Recall that linkers discard libraries and object files as much as
37+
// possible, and with all the static linking and archives flying around with
38+
// MUSL the linker is super aggressively stripping out objects. For example
39+
// the first case has fmod stripped from liblibc (it's in its own object
40+
// file) so it's not there when libcore needs it. In the second example all
41+
// the unused symbols from libunwind are stripped (each is in its own object
42+
// file in libstd) before we end up linking compiler-rt which depends on
43+
// those symbols.
44+
//
45+
// To deal with these circular dependencies we just force the compiler to
46+
// link everything as a group, not stripping anything out until everything
47+
// is processed. The linker will still perform a pass to strip out object
48+
// files but it won't do so until all objects/archives have been processed.
49+
base.pre_link_args.push("-Wl,-(".to_string());
50+
base.post_link_args.push("-Wl,-)".to_string());
51+
52+
// When generating a statically linked executable there's generally some
53+
// small setup needed which is listed in these files. These are provided by
54+
// a musl toolchain and are linked by default by the `musl-gcc` script. Note
55+
// that `gcc` also does this by default, it just uses some different files.
56+
//
57+
// Each target directory for musl has these object files included in it so
58+
// they'll be included from there.
59+
base.pre_link_objects_exe.push("crt1.o".to_string());
60+
base.pre_link_objects_exe.push("crti.o".to_string());
61+
base.post_link_objects.push("crtn.o".to_string());
62+
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+
return base;
71+
}
72+

src/libstd/rtdeps.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
//
2020
// On Linux, librt and libdl are indirect dependencies via std,
2121
// and binutils 2.22+ won't add them automatically
22-
#[cfg(all(target_os = "linux", not(target_env = "musl")))]
22+
#[cfg(all(target_os = "linux", not(any(target_env = "musl",
23+
target_env = "musleabi",
24+
target_env = "musleabihf"))))]
2325
#[link(name = "dl")]
2426
#[link(name = "pthread")]
2527
extern {}

src/libstd/sys/unix/thread.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,9 @@ impl Drop for Thread {
171171
}
172172
}
173173

174-
#[cfg(all(not(all(target_os = "linux", not(target_env = "musl"))),
174+
#[cfg(all(not(all(target_os = "linux", not(any(target_env = "musl",
175+
target_env = "musleabi",
176+
target_env = "musleabihf")))),
175177
not(target_os = "freebsd"),
176178
not(target_os = "macos"),
177179
not(target_os = "bitrig"),
@@ -185,7 +187,9 @@ pub mod guard {
185187
}
186188

187189

188-
#[cfg(any(all(target_os = "linux", not(target_env = "musl")),
190+
#[cfg(any(all(target_os = "linux", not(any(target_env = "musl",
191+
target_env = "musleabi",
192+
target_env = "musleabihf"))),
189193
target_os = "freebsd",
190194
target_os = "macos",
191195
target_os = "bitrig",

0 commit comments

Comments
 (0)