Rust-lang (rustc/cargo) for OpenWrt - testing needed

Welcome back, I hope you had a great sabbatical!

It works like a charm now :slight_smile: I'm using it regularly to build Raspberry Pi (different targets) and MIPS images including Rust components:

@brocaar @Grommish I am also in need of cross compiling a Rust code from ubuntu to an ath79/generic device. I would like to try this out since I did not have much luck with cargo-cross or specifying the target while doing cargo build.

Can you help me with what is the genral steps required to use the openwrt toolchain/sdk to build rust code ? I am finding it quite confusing.

Till now, I have followed to build the toolchain for ath79/generic. I can also build a test C code and cross compile it. Just not sure what the steps are for Rust.

@Grommish thanks for doing this !

I'm building complete OpenWrt images, not using the toolchain/sdk. An example:

Below is a complete different approach and not within the context of this topic, but maybe this could be helpful:

If you just want to cross-compile to ath79 (MIPS), you could also just use cargo build --target TARGET where target is either mips-unknown-linux-musl or mipsel-unknown-linux-musl (the difference is little-endian vs big-endian, please check what is right for your platform).

For this I'm using cross-rs as I do need a little bit more than just the Rust toolchain form MIPS (I also need to cross-compile some C code).

Some examples that might be helpful:

The result is a static binary that also works on OpenWrt.

Again, the above is off-topic, if you want to continue a discussion about the cross-rs approach for compiling Rust to OpenWrt, then maybe creating a different topic might be better.

I'm using a mix of both approaches. For Raspberry Pi and one of the OpenWrt based LoRa gateways I'm building complete images (first approach), for other gateways I'm just providing .ipk packages that can be installed on Yocto or OpenWrt based LoRa gateways. If you browse around the above repositories you will find all the scripts for this :slight_smile: Good luck!

1 Like

@Grommish maybe this is a GitHub issue that could use your feedback:

The current (unless explicitly defined) is that Rust packages built using OpenWrt will not use the Cargo.lock file, instead the latest versions as specified in the Cargo.toml are pulled in. I don't like this, because building the same package at two different times could result in two different versions of the same package. For my packages I'm explicitly using the --locked argument.

I would be looking to your feedback on this as well :slight_smile:

As an FYI, while there is a rust-lang package for OpenWrt now, I've been working on integrating rustup because of the existing issues with multiple targets in building rust-lang from source. Namely, having to rebuild LLVM and the stage 0/1 artifacts and whatnot each time for the host, which is a huge waste of resources that aren't needed. Having rustup takes like 5 minutes versus hours for rust-lang.

Using rustup allows for the precompiled host artifacts to be used and installed and handle the cross-compile natively. It also significantly makes rust-based packages MUCH easier to create.. This is my new bandwhich package I'm testing with, with being held by the rustup package itself for system environmentals. There is still quite a bit of testing I need to do, but so far it's gone better than I hoped considering the original rust-lang implementation hassles I had.

That being said, @brocaar I'll take a look at the post/issue you linked.

EDIT: Well, the new way I do things would make your issues a non-issue, since you can just pass the --locked to the cargo build call directly per-package.

include $(TOPDIR)/



include $(INCLUDE_DIR)/
include $(TOPDIR)/package/feeds/packages/rustup/


define Build/Compile
        cd $(PKG_BUILD_DIR) && \
        $(STAGING_DIR_HOST)/bin/cargo +nightly -Z unstable-options -Z build-std build --release

define Package/bandwhich
    DEPENDS:=@!SMALL_FLASH @!LOW_MEMORY_FOOTPRINT +zlib +libncurses +libncurses-dev
    TITLE:=Terminal bandwidth utilization tool

define Package/bandwhich/description
  Rust-lang based Terminal bandwidth utilization tool

define Package/bandwhich/install
        $(INSTALL_DIR) $(1)/bin
        $(INSTALL_BIN) $(PKG_BUILD_DIR)/target/$(RUSTUP_TARGET_ARCH)/release/bandwhich $(1)/bin/bandwhich

$(eval $(call BuildPackage,bandwhich))

Rustup thread.

For the targets not covered by rustup ideally LLVM can be either the copy built anyway as part of openwrt toolchain and it is always 1 build since llvm and rustc are inherent cross compilers (c.f. gcc requiring separate builds).

But having the option of leveraging rustup can be overall a nicer experience.

The issue I ran into with rust-lang as a full fat-source is that LLVM had to be rebuilt everytime you switched targets outside of the arch. Took forever, but it worked for the most part.

It's a Chicken/Egg problem, because I can create the triples for openwrt and send them upstream for inclusion into rust natively. I'd need to do that before inclusion of rustup, so that rustup will work :smiley:

Only the mips triple isn't the same as the normal ones, so that part is fine and for those the pre-compiled LLVM images rust can provide are surely be sufficient.

The LLVM needs can also be satisfied by the one built for the eBPF support as long the additional targets are used.

Once build-std and custom-target-json hit stable it can get even simpler, but it isn't really different from having to rebuild gcc.

Incidentally the now released gcc-14.1 sports the initial rust support but I think we have a long way till that point.

1 Like

I've got rustup working in the buildroot/fakeroot

Currently, it only works for the mips64-openwrt-linux-musl triple because that is what I have and that is what I upstreamed to rust-lang way back when.

Future triples I'm looking to support without having to upstream everything using JSON defines at compile.