about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTimon Van Overveldt <timonvo@gmail.com>2016-04-27 18:02:31 -0700
committerJorge Aparicio <japaricious@gmail.com>2016-07-30 15:39:13 -0500
commitf7247d1071206db45103c994b0077fcb0d8f75cf (patch)
tree33d5ac9fa78bce8d09e6f6e0a3271b1fa2b53fa6
parent57cad5722db3043804bc4c38ec3b456e9ff497be (diff)
downloadrust-f7247d1071206db45103c994b0077fcb0d8f75cf.tar.gz
rust-f7247d1071206db45103c994b0077fcb0d8f75cf.zip
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
https://github.com/rust-lang/compiler-rt/pull/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).
-rwxr-xr-xconfigure2
-rw-r--r--mk/cfg/arm-unknown-linux-musleabi.mk3
-rw-r--r--mk/cfg/arm-unknown-linux-musleabihf.mk3
-rw-r--r--mk/cfg/armv7-unknown-linux-musleabihf.mk3
-rw-r--r--src/bootstrap/compile.rs3
-rw-r--r--src/bootstrap/sanity.rs2
-rw-r--r--src/liballoc_jemalloc/build.rs11
-rw-r--r--src/liballoc_jemalloc/lib.rs4
-rw-r--r--src/librustc_back/target/arm_unknown_linux_musleabi.rs33
-rw-r--r--src/librustc_back/target/arm_unknown_linux_musleabihf.rs33
-rw-r--r--src/librustc_back/target/armv7_unknown_linux_musleabihf.rs34
-rw-r--r--src/librustc_back/target/mod.rs4
-rw-r--r--src/librustc_back/target/musl_base.rs72
-rw-r--r--src/libstd/rtdeps.rs4
-rw-r--r--src/libstd/sys/unix/thread.rs8
15 files changed, 210 insertions, 9 deletions
diff --git a/configure b/configure
index d2ec457a1c8..a7e24a506fb 100755
--- a/configure
+++ b/configure
@@ -1192,7 +1192,7 @@ do
             ;;
 
 
-        x86_64-*-musl)
+        x86_64-*-musl | arm-*-musleabi)
             if [ ! -f $CFG_MUSL_ROOT/lib/libc.a ]
             then
                 err "musl libc $CFG_MUSL_ROOT/lib/libc.a not found"
diff --git a/mk/cfg/arm-unknown-linux-musleabi.mk b/mk/cfg/arm-unknown-linux-musleabi.mk
new file mode 100644
index 00000000000..8120250150d
--- /dev/null
+++ b/mk/cfg/arm-unknown-linux-musleabi.mk
@@ -0,0 +1,3 @@
+# This file is intentially left empty to indicate that, while this target is
+# supported, it's not supported using plain GNU Make builds. Use a --rustbuild
+# instead.
\ No newline at end of file
diff --git a/mk/cfg/arm-unknown-linux-musleabihf.mk b/mk/cfg/arm-unknown-linux-musleabihf.mk
new file mode 100644
index 00000000000..8120250150d
--- /dev/null
+++ b/mk/cfg/arm-unknown-linux-musleabihf.mk
@@ -0,0 +1,3 @@
+# This file is intentially left empty to indicate that, while this target is
+# supported, it's not supported using plain GNU Make builds. Use a --rustbuild
+# instead.
\ No newline at end of file
diff --git a/mk/cfg/armv7-unknown-linux-musleabihf.mk b/mk/cfg/armv7-unknown-linux-musleabihf.mk
new file mode 100644
index 00000000000..8120250150d
--- /dev/null
+++ b/mk/cfg/armv7-unknown-linux-musleabihf.mk
@@ -0,0 +1,3 @@
+# This file is intentially left empty to indicate that, while this target is
+# supported, it's not supported using plain GNU Make builds. Use a --rustbuild
+# instead.
\ No newline at end of file
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 8ec9c7f0109..061192ebd13 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -92,8 +92,7 @@ pub fn std_link(build: &Build,
     }
     add_to_sysroot(&out_dir, &libdir);
 
-    if target.contains("musl") &&
-       (target.contains("x86_64") || target.contains("i686")) {
+    if target.contains("musl") && !target.contains("mips") {
         copy_third_party_objects(build, target, &libdir);
     }
 }
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index 73749246758..09f96782e71 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -109,7 +109,7 @@ pub fn check(build: &mut Build) {
         }
 
         // Make sure musl-root is valid if specified
-        if target.contains("musl") && (target.contains("x86_64") || target.contains("i686")) {
+        if target.contains("musl") && !target.contains("mips") {
             match build.config.musl_root {
                 Some(ref root) => {
                     if fs::metadata(root.join("lib/libc.a")).is_err() {
diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs
index d1b3583d256..dc1b8d6ea98 100644
--- a/src/liballoc_jemalloc/build.rs
+++ b/src/liballoc_jemalloc/build.rs
@@ -73,7 +73,16 @@ fn main() {
                    .replace("\\", "/"))
        .current_dir(&build_dir)
        .env("CC", compiler.path())
-       .env("EXTRA_CFLAGS", cflags)
+       .env("EXTRA_CFLAGS", cflags.clone())
+       // jemalloc generates Makefile deps using GCC's "-MM" flag. This means
+       // that GCC will run the preprocessor, and only the preprocessor, over
+       // jemalloc's source files. If we don't specify CPPFLAGS, then at least
+       // on ARM that step fails with a "Missing implementation for 32-bit
+       // atomic operations" error. This is because no "-march" flag will be
+       // passed to GCC, and then GCC won't define the
+       // "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4" macro that jemalloc needs to
+       // select an atomic operation implementation.
+       .env("CPPFLAGS", cflags.clone())
        .env("AR", &ar)
        .env("RANLIB", format!("{} s", ar.display()));
 
diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs
index 347e97e6ffc..ccf3d978fe4 100644
--- a/src/liballoc_jemalloc/lib.rs
+++ b/src/liballoc_jemalloc/lib.rs
@@ -36,7 +36,9 @@ use libc::{c_int, c_void, size_t};
 #[cfg_attr(target_os = "android", link(name = "gcc"))]
 #[cfg_attr(all(not(windows),
                not(target_os = "android"),
-               not(target_env = "musl")),
+               not(target_env = "musl"),
+               not(target_env = "musleabi"),
+               not(target_env = "musleabihf")),
            link(name = "pthread"))]
 #[cfg(not(cargobuild))]
 extern "C" {}
diff --git a/src/librustc_back/target/arm_unknown_linux_musleabi.rs b/src/librustc_back/target/arm_unknown_linux_musleabi.rs
new file mode 100644
index 00000000000..906f60f1c9a
--- /dev/null
+++ b/src/librustc_back/target/arm_unknown_linux_musleabi.rs
@@ -0,0 +1,33 @@
+// Copyright 2016 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::musl_base::opts();
+
+    // Most of these settings are copied from the arm_unknown_linux_gnueabi
+    // target.
+    base.features = "+v6".to_string();
+    Target {
+        // It's important we use "gnueabi" and not "musleabi" here. LLVM uses it
+        // to determine the calling convention and float ABI, and it doesn't
+        // support the "musleabi" value.
+        llvm_target: "arm-unknown-linux-gnueabi".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        arch: "arm".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "musleabi".to_string(),
+        target_vendor: "unknown".to_string(),
+        options: base,
+    }
+}
diff --git a/src/librustc_back/target/arm_unknown_linux_musleabihf.rs b/src/librustc_back/target/arm_unknown_linux_musleabihf.rs
new file mode 100644
index 00000000000..3051721b8c2
--- /dev/null
+++ b/src/librustc_back/target/arm_unknown_linux_musleabihf.rs
@@ -0,0 +1,33 @@
+// Copyright 2016 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::musl_base::opts();
+
+    // Most of these settings are copied from the arm_unknown_linux_gnueabihf
+    // target.
+    base.features = "+v6,+vfp2".to_string();
+    Target {
+        // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
+        // uses it to determine the calling convention and float ABI, and it
+        // doesn't support the "musleabihf" value.
+        llvm_target: "arm-unknown-linux-gnueabihf".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        arch: "arm".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "musleabi".to_string(),
+        target_vendor: "unknown".to_string(),
+        options: base,
+    }
+}
diff --git a/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs b/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs
new file mode 100644
index 00000000000..8732681fb49
--- /dev/null
+++ b/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs
@@ -0,0 +1,34 @@
+// Copyright 2016 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::musl_base::opts();
+
+    // Most of these settings are copied from the armv7_unknown_linux_gnueabihf
+    // target.
+    base.features = "+v7,+vfp3,+neon".to_string();
+    base.cpu = "cortex-a8".to_string();
+    Target {
+        // It's important we use "gnueabihf" and not "musleabihf" here. LLVM
+        // uses it to determine the calling convention and float ABI, and LLVM
+        // doesn't support the "musleabihf" value.
+        llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        arch: "arm".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "musleabi".to_string(),
+        target_vendor: "unknown".to_string(),
+        options: base,
+    }
+}
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index f5314809228..694b1340bbb 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -59,6 +59,7 @@ mod freebsd_base;
 mod linux_base;
 mod linux_musl_base;
 mod openbsd_base;
+mod musl_base;
 mod netbsd_base;
 mod solaris_base;
 mod windows_base;
@@ -134,7 +135,10 @@ supported_targets! {
     ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
     ("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi),
     ("arm-unknown-linux-gnueabihf", arm_unknown_linux_gnueabihf),
+    ("arm-unknown-linux-musleabi", arm_unknown_linux_musleabi),
+    ("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf),
     ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf),
+    ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
     ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
     ("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
     ("i686-unknown-linux-musl", i686_unknown_linux_musl),
diff --git a/src/librustc_back/target/musl_base.rs b/src/librustc_back/target/musl_base.rs
new file mode 100644
index 00000000000..77cf015e1d9
--- /dev/null
+++ b/src/librustc_back/target/musl_base.rs
@@ -0,0 +1,72 @@
+// Copyright 2016 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::TargetOptions;
+
+pub fn opts() -> TargetOptions {
+    let mut base = super::linux_base::opts();
+
+    // 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());
+
+    // 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_exe.push("crt1.o".to_string());
+    base.pre_link_objects_exe.push("crti.o".to_string());
+    base.post_link_objects.push("crtn.o".to_string());
+
+    // MUSL support doesn't currently include dynamic linking, 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;
+
+    return base;
+}
+
diff --git a/src/libstd/rtdeps.rs b/src/libstd/rtdeps.rs
index a11200873d5..f23ac32f51c 100644
--- a/src/libstd/rtdeps.rs
+++ b/src/libstd/rtdeps.rs
@@ -19,7 +19,9 @@
 //
 // On Linux, librt and libdl are indirect dependencies via std,
 // and binutils 2.22+ won't add them automatically
-#[cfg(all(target_os = "linux", not(target_env = "musl")))]
+#[cfg(all(target_os = "linux", not(any(target_env = "musl",
+                                       target_env = "musleabi",
+                                       target_env = "musleabihf"))))]
 #[link(name = "dl")]
 #[link(name = "pthread")]
 extern {}
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index 1061ca87f64..7f05aec4e6e 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -171,7 +171,9 @@ impl Drop for Thread {
     }
 }
 
-#[cfg(all(not(all(target_os = "linux", not(target_env = "musl"))),
+#[cfg(all(not(all(target_os = "linux", not(any(target_env = "musl",
+                                               target_env = "musleabi",
+                                               target_env = "musleabihf")))),
           not(target_os = "freebsd"),
           not(target_os = "macos"),
           not(target_os = "bitrig"),
@@ -185,7 +187,9 @@ pub mod guard {
 }
 
 
-#[cfg(any(all(target_os = "linux", not(target_env = "musl")),
+#[cfg(any(all(target_os = "linux", not(any(target_env = "musl",
+                                           target_env = "musleabi",
+                                           target_env = "musleabihf"))),
           target_os = "freebsd",
           target_os = "macos",
           target_os = "bitrig",