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).
This commit is contained in:
parent
57cad5722d
commit
f7247d1071
2
configure
vendored
2
configure
vendored
@ -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"
|
||||
|
3
mk/cfg/arm-unknown-linux-musleabi.mk
Normal file
3
mk/cfg/arm-unknown-linux-musleabi.mk
Normal file
@ -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.
|
3
mk/cfg/arm-unknown-linux-musleabihf.mk
Normal file
3
mk/cfg/arm-unknown-linux-musleabihf.mk
Normal file
@ -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.
|
3
mk/cfg/armv7-unknown-linux-musleabihf.mk
Normal file
3
mk/cfg/armv7-unknown-linux-musleabihf.mk
Normal file
@ -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.
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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()));
|
||||
|
||||
|
@ -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" {}
|
||||
|
33
src/librustc_back/target/arm_unknown_linux_musleabi.rs
Normal file
33
src/librustc_back/target/arm_unknown_linux_musleabi.rs
Normal file
@ -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,
|
||||
}
|
||||
}
|
33
src/librustc_back/target/arm_unknown_linux_musleabihf.rs
Normal file
33
src/librustc_back/target/arm_unknown_linux_musleabihf.rs
Normal file
@ -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,
|
||||
}
|
||||
}
|
34
src/librustc_back/target/armv7_unknown_linux_musleabihf.rs
Normal file
34
src/librustc_back/target/armv7_unknown_linux_musleabihf.rs
Normal file
@ -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,
|
||||
}
|
||||
}
|
@ -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),
|
||||
|
72
src/librustc_back/target/musl_base.rs
Normal file
72
src/librustc_back/target/musl_base.rs
Normal file
@ -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;
|
||||
}
|
||||
|
@ -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 {}
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user