Building OpenWrt on the Apple M1

Hi there! Thanks for providing OpenWrt!

I'm completely new to OpenWrt development but I'm keen to develop Rust-based applications that target the Onion Omega2 devices. I'm not particularly interested in building OpenWrt images at this stage; just applications.

I'm having difficulties setting up the OpenWrt development environment on my Apple M1 Max. I realise this development platform is unsupported, but I'm wondering what it'd take to get the toolchain built at least.

Upon having invoked make menuconfig and configuring my target, I'm then met with the following when attempting to then make:

time: tools/xz/compile#0.07#0.09#0.20
    ERROR: tools/xz failed to build.
make[2]: *** [tools/Makefile:159: tools/xz/compile] Error 1
make[2]: Leaving directory '/Volumes/OpenWrt/openwrt'
make[1]: *** [tools/Makefile:155: /Volumes/OpenWrt/openwrt/staging_dir/host/stamp/.tools_compile_yyynyynnyyyynyyyyyynyynnyyyynyyyyyyyyyyyyyyyynynnyyyyyyy] Error 2
make[1]: Leaving directory '/Volumes/OpenWrt/openwrt'
make: *** [/Volumes/OpenWrt/openwrt/include/ toolchain/install] Error 2

Am I doomed? Thanks. :slight_smile:

rust-lang isn't supported. It may never be officially supported; I'm still working on it.

rust-lang requires LLVM support, and it was just added ( I'm not sure what hoops need to be jumped through to support a rust-lang HOST tuple, but I do support mipsel-openwrt-linux-musl TARGET tuples on x86_64-unknown-linux-gnu Hosts.

To build out the rust-lang toolchain, you'd have to be willing to build from source, creating your own packages (although that's simplified these days). If you're willing to do the testing (I don't have an M1 platform) I can take a look after I settle out the x86_64 hosts and the target tuples.

Thanks so much for the fast reply. I probably shouldn't have conflated my question with Rust, as I'm actually just having difficulty with setting up the build environment for OpenWrt v21.02.2.

I've also just switched to the master branch of OpenWrt and it now appears to be building... I'll report back here.

Definitely want to help where I can re. supporting Rust on OpenWrt (I've previously used it with the gcc toolchain on Arm). The Omega2 is going to become important to me...

You can follow the draft PR here, and any help testing you'd like to do is always appreciated. I just didn't want you to go through all the trouble of cloning, building, etc, and then find out rust isn't available, if that was your primary goal :slightly_smiling_face:

1 Like

Some developers are working on x86_64/ MacOS, but with Apple M1/ ARM64 you're probably the first to find, debug and having to fix issues. Both ARM64/ linux (yeah, I know, not quite there yet for the M1 hardware) or x86_84/ MacOS would be easier on your mind (and x86_64 on a semi-recent general purpose distribution the most tested combination for a build host).


UPDATE: Managed to build the OpenWrt SDK on my Apple M1. Had to use master though. v21.02.2 didn't work for me. Now for Rust... :slight_smile:

Should I be able to use make menuconfig again once built? It barfs with the following:

* Unable to find the ncurses package.
* Install ncurses (ncurses-devel or libncurses-dev
* depending on your distribution).
* You may also need to install pkg-config to find the
* ncurses installed in a non-default location.

...which didn't occur prior to everything building ok...

ncurses development packages are necessary for menuconfig (or qt for xconfig, or…).

Yeah, funny how it worked first time, but not the subsequent time...

Righto - goals achieved today. Installed OpenWrt on my Apple M1 by using the master branch and following the macOS instructions on the Wiki. Reasonably smooth overall.

I then successfully built a Rust hello world:

rustup target add mips-unknown-linux-gnu

cargo new --bin mips-test
cd mips-test

STAGING_DIR=/Volumes/OpenWrt/openwrt/staging_dir \
CARGO_TARGET_MIPSEL_UNKNOWN_LINUX_MUSL_LINKER=$STAGING_DIR/toolchain-mipsel_24kc_gcc-11.2.0_musl/bin/mipsel-openwrt-linux-musl-gcc \
cargo build --release --target=mipsel-unknown-linux-musl

I then copied the binary over to my Omega2+ and it worked. :slight_smile:

Note that I can tidy a few things up with a Cargo config, and will. But this shows what's required to build and run. HTH someone.

1 Like

As an FYI, if you use rustup you are going to run into issues at some point.. Not only is rustup statically links (MUSL requires dyanmically linked libraries), but rustup doesn't recognize the proper build system tuples for OpenWrt.

The good news is that aarch64-apple-darwin is a supported LLVM and Rust target, so, down the line you should be able to build out the rust OpenWrt toolchain.

Thanks for the follow-up. I bow to your knowledge on this. I'm confused though, using ldd on my executable shows that it dynamically links to MUSL and other libs at least:

# ldd mips-test 
	/lib/ (0x77efc000) => /lib/ (0x77e6c000) => /lib/ (0x77efc000)

Similarly, if I run ldd on the ls command tool then I get:

# ldd /bin/ls
	/lib/ (0x77f27000) => /lib/ (0x77f03000) => /lib/ (0x77f27000)

In what way is mipsel-unknown-linux-musl not sufficient (this is for the Onion Omega2 device at least)? Thanks.

Well, in this particular case, probably not much. Although your --print target-features may not line up, it hasn't been a huge issue until you get into the arm/armv5/armv6/armv7 tuples where not only does it need to know soft-float vs hard-float, but which vfp revision, whether it has NEON support, -d16 calls, etc.

In the mips64 arena, since OpenWrt doesn't support anything but soft-float for the Octeon branch (the device SoC I have), it also required a custom tuple.

Trying to use rustup inside OpenWrt will not work because OpenWrt's REAL_GNU_TARGET_NAME is xxxx-openwrt-linux-yyyy and those aren't known to rustup. The mvebu platform reports as arm-openwrt-linux-muslgnueabihf for example.. Which then has to be changed to armv7-openwrt-linux-muslgnueabihf, and neither of those are supported by rustup

If you can deal with packaging the ipk yourself, you could, in theory, do everything outside of OpenWrt, but you'll not get it integrated.

All of the current integral MUSL targets are built against the linux_musl_base defines. You could use a CodeGen flag -C target-features=-crt_statc I suppose, but you're doing it for each and every invoke of cargo or rustc.

grommish@DESKTOP-AW:~/openwrt/build_dir/hostpkg/rust-1.60.0/compiler/rustc_target/src/spec$ cat
use crate::spec::crt_objects::{self, CrtObjectsFallback};
use crate::spec::TargetOptions;

pub fn opts() -> TargetOptions {
    let mut base = super::linux_base::opts();

    base.env = "musl".to_string();
    base.pre_link_objects_fallback = crt_objects::pre_musl_fallback();
    base.post_link_objects_fallback = crt_objects::post_musl_fallback();
    base.crt_objects_fallback = Some(CrtObjectsFallback::Musl);

    // These targets statically link libc by default
    base.crt_static_default = true;


If it works for you, use what you know :slight_smile: I just want you to know you may run into issues even if you don't use rustup (see the PR regarding the ring crate)

Edit: In the future, rustup MAY be possible as I'm upstreaming the OpenWrt specific tuples, but it took freom 1.57 to 1.60 for the Tier 3 mips64-openwrt-linux-musl to get officially rolled out after it was merged.

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.