Auto merge of #88952 - skrap:add-armv7-uclibc, r=nagisa

Add new tier-3 target: armv7-unknown-linux-uclibceabihf

This change adds a new tier-3 target: armv7-unknown-linux-uclibceabihf

This target is primarily used in embedded linux devices where system resources are slim and glibc is deemed too heavyweight.  Cross compilation C toolchains are available [here](https://toolchains.bootlin.com/) or via [buildroot](https://buildroot.org).

The change is based largely on a previous PR #79380 with a few minor modifications.  The author of that PR was unable to push the PR forward, and graciously allowed me to take it over.

Per the [target tier 3 policy](https://github.com/rust-lang/rfcs/blob/master/text/2803-target-tier-policy.md), I volunteer to be the "target maintainer".

This is my first PR to Rust itself, so I apologize if I've missed things!
This commit is contained in:
bors 2021-10-10 08:16:22 +00:00
commit 9e8356c6ad
9 changed files with 103 additions and 6 deletions

View file

@ -175,7 +175,7 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value
// should use dllimport for functions.
if cx.use_dll_storage_attrs
&& tcx.is_dllimport_foreign_item(instance_def_id)
&& tcx.sess.target.env != "gnu"
&& !matches!(tcx.sess.target.env.as_ref(), "gnu" | "uclibc")
{
llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
}

View file

@ -3012,7 +3012,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
};
let target = &self.tcx.sess.target;
let target_env_gnu_like = matches!(&target.env[..], "gnu" | "musl");
let target_env_gnu_like = matches!(&target.env[..], "gnu" | "musl" | "uclibc");
let win_x64_gnu = target.os == "windows" && target.arch == "x86_64" && target.env == "gnu";
let linux_s390x_gnu_like =
target.os == "linux" && target.arch == "s390x" && target_env_gnu_like;
@ -3110,7 +3110,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
if arg.layout.is_zst() {
// For some forsaken reason, x86_64-pc-windows-gnu
// doesn't ignore zero-sized struct arguments.
// The same is true for {s390x,sparc64,powerpc}-unknown-linux-{gnu,musl}.
// The same is true for {s390x,sparc64,powerpc}-unknown-linux-{gnu,musl,uclibc}.
if is_return
|| rust_abi
|| (!win_x64_gnu

View file

@ -0,0 +1,24 @@
use crate::spec::{Target, TargetOptions};
// This target is for uclibc Linux on ARMv7 without NEON or
// thumb-mode. See the thumbv7neon variant for enabling both.
pub fn target() -> Target {
let base = super::linux_uclibc_base::opts();
Target {
llvm_target: "armv7-unknown-linux-gnueabihf".to_string(),
pointer_width: 32,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
arch: "arm".to_string(),
options: TargetOptions {
// Info about features at https://wiki.debian.org/ArmHardFloatPort
features: "+v7,+vfp3,-d32,+thumb2,-neon".to_string(),
cpu: "generic".to_string(),
max_atomic_width: Some(64),
mcount: "_mcount".to_string(),
abi: "eabihf".to_string(),
..base
},
}
}

View file

@ -952,6 +952,8 @@ supported_targets! {
("bpfel-unknown-none", bpfel_unknown_none),
("armv6k-nintendo-3ds", armv6k_nintendo_3ds),
("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf),
}
/// Warnings encountered when parsing the target `json`.

View file

@ -307,6 +307,9 @@ cfg_if::cfg_if! {
#[link(name = "zircon")]
#[link(name = "fdio")]
extern "C" {}
} else if #[cfg(all(target_os = "linux", target_env = "uclibc"))] {
#[link(name = "dl")]
extern "C" {}
}
}

View file

@ -594,7 +594,8 @@ pub mod guard {
Some(stackaddr - guardsize..stackaddr)
} else if cfg!(all(target_os = "linux", target_env = "musl")) {
Some(stackaddr - guardsize..stackaddr)
} else if cfg!(all(target_os = "linux", target_env = "gnu")) {
} else if cfg!(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))
{
// glibc used to include the guard area within the stack, as noted in the BUGS
// section of `man pthread_attr_getguardsize`. This has been corrected starting
// with glibc 2.27, and in some distro backports, so the guard is now placed at the

View file

@ -63,7 +63,7 @@ cfg_if::cfg_if! {
// don't want to duplicate it here.
#[cfg(all(
target_os = "linux",
target_env = "gnu",
any(target_env = "gnu", target_env = "uclibc"),
not(feature = "llvm-libunwind"),
not(feature = "system-llvm-libunwind")
))]
@ -72,7 +72,7 @@ extern "C" {}
#[cfg(all(
target_os = "linux",
target_env = "gnu",
any(target_env = "gnu", target_env = "uclibc"),
not(feature = "llvm-libunwind"),
feature = "system-llvm-libunwind"
))]

View file

@ -220,6 +220,7 @@ target | std | host | notes
`armv6-unknown-netbsd-eabihf` | ? | |
`armv6k-nintendo-3ds` | * | | ARMv6K Nintendo 3DS, Horizon (Requires devkitARM toolchain)
`armv7-apple-ios` | ✓ | | ARMv7 iOS, Cortex-a8
`armv7-unknown-linux-uclibceabihf` | ✓ | ? | ARMv7 Linux uClibc
`armv7-unknown-freebsd` | ✓ | ✓ | ARMv7 FreeBSD
`armv7-unknown-netbsd-eabihf` | ✓ | ✓ |
`armv7-wrs-vxworks-eabihf` | ? | |

View file

@ -0,0 +1,66 @@
# armv7-unknown-linux-uclibceabihf
**Tier: 3**
This tier supports the ARMv7 processor running a Linux kernel and uClibc-ng standard library. It provides full support for rust and the rust standard library.
## Designated Developers
* [@skrap](https://github.com/skrap)
## Requirements
This target is cross compiled, and requires a cross toolchain. You can find suitable pre-built toolchains at [bootlin](https://toolchains.bootlin.com/) or build one yourself via [buildroot](https://buildroot.org).
## Building
### Get a C toolchain
Compiling rust for this target has been tested on `x86_64` linux hosts. Other host types have not been tested, but may work, if you can find a suitable cross compilation toolchain for them.
If you don't already have a suitable toolchain, download one [here](https://toolchains.bootlin.com/downloads/releases/toolchains/armv7-eabihf/tarballs/armv7-eabihf--uclibc--bleeding-edge-2020.08-1.tar.bz2), and unpack it into a directory.
### Configure rust
The target can be built by enabling it for a `rustc` build, by placing the following in `config.toml`:
```toml
[build]
target = ["armv7-unknown-linux-uclibceabihf"]
stage = 2
[target.armv7-unknown-linux-uclibceabihf]
# ADJUST THIS PATH TO POINT AT YOUR TOOLCHAIN
cc = "/TOOLCHAIN_PATH/bin/arm-buildroot-linux-uclibcgnueabihf-gcc"
```
### Build
```sh
# in rust dir
./x.py build --stage 2
```
## Building and Running Rust Programs
To test cross-compiled binaries on a `x86_64` system, you can use the `qemu-arm` [userspace emulation](https://qemu-project.gitlab.io/qemu/user/main.html) program. This avoids having a full emulated ARM system by doing dynamic binary translation and dynamic system call translation. It lets you run ARM programs directly on your `x86_64` kernel. It's very convenient!
To use:
* Install `qemu-arm` according to your distro.
* Link your built toolchain via:
* `rustup toolchain link stage2 ${RUST}/build/x86_64-unknown-linux-gnu/stage2`
* Create a test program
```sh
cargo new hello_world
cd hello_world
```
* Build and run
```sh
CARGO_TARGET_ARMV7_UNKNOWN_LINUX_UCLIBCEABIHF_RUNNER="qemu-arm -L ${TOOLCHAIN}/arm-buildroot-linux-uclibcgnueabihf/sysroot/" \
CARGO_TARGET_ARMV7_UNKNOWN_LINUX_UCLIBCEABIHF_LINKER=${TOOLCHAIN}/bin/arm-buildroot-linux-uclibcgnueabihf-gcc \
cargo +stage2 run --target armv7-unknown-linux-uclibceabihf
```