Skip to content

Commit

Permalink
Rollup merge of #92383 - lancethepants:armv7-unknown-linux-uclibceabi…
Browse files Browse the repository at this point in the history
…, r=nagisa

Add new target armv7-unknown-linux-uclibceabi (softfloat)

This adds the new target `armv7-unknown-linux-uclibceabi (softfloat)`. It is of course similar to `armv7-unknown-linux-uclibceabihf (hardfloat)` which was just recently added to rust except that it is `softfloat`.

My interest lies in the Broadcom BCM4707/4708/BCM4709 family, notably found in some Netgear and Asus consumer routers. The armv7 Cortex-A9 cpus found in these devices do not have an fpu or NEON support.

With this patch I've been able to bootstrap rustc, std and host tools `(extended = true)` to run on the target device for native compilation, allowing the target to be used as a development platform.

With the recent addition of `armv7-unknown-linux-uclibceabihf (hardfloat)` it looks like many of the edge cases of using the uclibc c-library are getting worked out nicely. I've been able to compile some complex projects. Some patching still needed in some crates, but getting there for sure.  I think `armv7-unknown-linux-uclibceabi` is ready to be a tier 3 target.

I use a cross-toolchain from my project to bootstrap rust.
https://github.com/lancethepants/tomatoware
The goal of this project is to create a native development environment with support for various languages.
  • Loading branch information
matthiaskrgr committed Feb 6, 2022
2 parents 0eda3fa + 8c6f7fd commit 4a3be6e
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 1 deletion.
23 changes: 23 additions & 0 deletions compiler/rustc_target/src/spec/armv7_unknown_linux_uclibceabi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use crate::spec::{Target, TargetOptions};

// This target is for uclibc Linux on ARMv7 without NEON,
// thumb-mode or hardfloat.

pub fn target() -> Target {
let base = super::linux_uclibc_base::opts();
Target {
llvm_target: "armv7-unknown-linux-gnueabi".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 {
features: "+v7,+thumb2,+soft-float,-neon".to_string(),
cpu: "generic".to_string(),
max_atomic_width: Some(64),
mcount: "_mcount".to_string(),
abi: "eabi".to_string(),
..base
},
}
}
1 change: 1 addition & 0 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,7 @@ supported_targets! {

("armv6k-nintendo-3ds", armv6k_nintendo_3ds),

("armv7-unknown-linux-uclibceabi", armv7_unknown_linux_uclibceabi),
("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf),

("x86_64-unknown-none", x86_64_unknown_none),
Expand Down
1 change: 1 addition & 0 deletions src/doc/rustc/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
- [Platform Support](platform-support.md)
- [Template for target-specific documentation](platform-support/TEMPLATE.md)
- [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md)
- [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md)
- [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md)
- [\*-kmc-solid_\*](platform-support/kmc-solid.md)
- [*-unknown-openbsd](platform-support/openbsd.md)
Expand Down
3 changes: 2 additions & 1 deletion src/doc/rustc/src/platform-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,8 @@ 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`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | ARMv7 Linux uClibc
[`armv7-unknown-linux-uclibceabi`](platform-support/armv7-unknown-linux-uclibceabi.md) | ✓ | ✓ | ARMv7 Linux with uClibc, softfloat
[`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | ARMv7 Linux with uClibc, hardfloat
`armv7-unknown-freebsd` | ✓ | ✓ | ARMv7 FreeBSD
`armv7-unknown-netbsd-eabihf` | ✓ | ✓ |
`armv7-wrs-vxworks-eabihf` | ? | |
Expand Down
121 changes: 121 additions & 0 deletions src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# `armv7-unknown-linux-uclibceabi`

**Tier: 3**

This target supports ARMv7 softfloat CPUs and uses the uclibc-ng standard library. This is a common configuration on many consumer routers (e.g., Netgear R7000, Asus RT-AC68U).

## Target maintainers

* [@lancethepants](https://github.com/lancethepants)

## Requirements

This target is cross compiled, and requires a cross toolchain.

This target supports host tools and std.

## Building the target

You will need to download or build a `'C'` cross toolchain that targets ARMv7 softfloat and that uses the uclibc-ng standard library. If your target hardware is something like a router or an embedded device, keep in mind that manufacturer supplied SDKs for this class of CPU could be outdated and potentially unsuitable for bootstrapping rust.

[Here](https://github.com/lancethepants/tomatoware-toolchain) is a sample toolchain that is built using [buildroot](https://buildroot.org/). It uses modern toolchain components, older thus universal kernel headers (2.6.36.4), and is used for a project called [Tomatoware](https://github.com/lancethepants/tomatoware). This toolchain is patched so that its sysroot is located at /mmc (e.g., /mmc/bin, /mmc/lib, /mmc/include). This is useful in scenarios where the root filesystem is read-only but you are able attach external storage loaded with user applications. Tomatoware is an example of this that even allows you to run various compilers and developer tools natively on the target device.

Utilizing the Tomatoware toolchain this target can be built for cross compilation and native compilation (host tools) with project

[rust-bootstrap-armv7-unknown-linux-uclibceabi](https://github.com/lancethepants/rust-bootstrap-armv7-unknown-linux-uclibceabi).


Here is a sample config if using your own toolchain.

```toml
[build]
build-stage = 2
target = ["armv7-unknown-linux-uclibceabi"]

[target.armv7-unknown-linux-uclibceabi]
cc = "/path/to/arm-unknown-linux-uclibcgnueabi-gcc"
cxx = "/path/to/arm-unknown-linux-uclibcgnueabi-g++"
ar = "path/to/arm-unknown-linux-uclibcgnueabi-ar"
ranlib = "path/to/arm-unknown-linux-uclibcgnueabi-"
linker = "/path/to/arm-unknown-linux-uclibcgnueabi-"
```

## Building Rust programs

The following assumes you are using the Tomatoware toolchain and environment. Adapt if you are using your own toolchain.

### Native compilation

Since this target supports host tools, you can natively build rust applications directly on your target device. This can be convenient because it removes the complexities of cross compiling and you can immediately test and deploy your binaries. One downside is that compiling on your ARMv7 CPU will probably be much slower than cross compilation on your x86 machine.

To setup native compilation:

* Download Tomatoware to your device using the latest nightly release found [here](https://files.lancethepants.com/Tomatoware/Nightly/).
* Extract `tar zxvf arm-soft-mmc.tgz -C /mmc`
* Add `/mmc/bin:/mmc:sbin/` to your PATH, or `source /mmc/etc/profile`
* `apt update && apt install rust`

If you bootstrap rust on your own using the project above, it will create a .deb file that you then can install with
```text
dpkg -i rust_1.xx.x-x_arm.deb
```

After completing these steps you can use rust normally in a native environment.

### Cross Compilation

To cross compile, you'll need to:

* Build the rust cross toochain using [rust-bootstrap-armv7-unknown-linux-uclibceabi](https://github.com/lancethepants/rust-bootstrap-armv7-unknown-linux-uclibceabi) or your own built toolchain.
* Link your built toolchain with

```text
rustup toolchain link stage2 \
${HOME}/rust-bootstrap-armv7-unknown-linux-uclibceabi/src/rust/rust/build/x86_64-unknown-linux-gnu/stage2
```
* Build with:
```text
CC=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-gcc \
CXX=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-g++ \
AR=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-ar \
CARGO_TARGET_ARMV7_UNKNOWN_LINUX_UCLIBCEABI_LINKER=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-gcc \
CARGO_TARGET_ARMV7_UNKNOWN_LINUX_UCLIBCEABI_RUSTFLAGS='-Clink-arg=-s -Clink-arg=-Wl,--dynamic-linker=/mmc/lib/ld-uClibc.so.1 -Clink-arg=-Wl,-rpath,/mmc/lib' \
cargo +stage2 build --target armv7-unknown-linux-uclibceabi --release
```
* Copy the binary to your target device and run.

We specify `CC`, `CXX`, and `AR` because somtimes a project or a subproject requires the use of your `'C'` cross toolchain. Since Tomatoware has a modified sysroot we also pass via RUSTFLAGS the location of the dynamic-linker and rpath.

### Test with QEMU

To test a cross-compiled binary on your build system follow the instructions for `Cross Compilation`, install `qemu-arm-static`, and run with the following.
```text
CC=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-gcc \
CXX=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-g++ \
AR=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-ar \
CARGO_TARGET_ARMV7_UNKNOWN_LINUX_UCLIBCEABI_LINKER=/opt/tomatoware/arm-soft-mmc/bin/arm-linux-gcc \
CARGO_TARGET_ARMV7_UNKNOWN_LINUX_UCLIBCEABI_RUNNER="qemu-arm-static -L /opt/tomatoware/arm-soft-mmc/arm-tomatoware-linux-uclibcgnueabi/sysroot/" \
cargo +stage2 run --target armv7-unknown-linux-uclibceabi --release
```
### Run in a chroot

It's also possible to build in a chroot environment. This is a convenient way to work without needing to access the target hardware.

To build the chroot:

* `sudo debootstrap --arch armel bullseye $HOME/debian`
* `sudo chroot $HOME/debian/ /bin/bash`
* `mount proc /proc -t proc`
* `mount -t sysfs /sys sys/`
* `export PATH=/mmc/bin:/mmc/sbin:$PATH`

From here you can setup your environment (e.g., add user, install wget).

* Download Tomatoware to the chroot environment using the latest nightly release found [here](https://files.lancethepants.com/Tomatoware/Nightly/).
* Extract `tar zxvf arm-soft-mmc.tgz -C /mmc`
* Add `/mmc/bin:/mmc:sbin/` to your PATH, or `source /mmc/etc/profile`
* `sudo /mmc/bin/apt update && sudo /mmc/bin/apt install rust`

After completing these steps you can use rust normally in a chroot environment.

Remember when using `sudo` the root user's PATH could differ from your user's PATH.

0 comments on commit 4a3be6e

Please sign in to comment.