Welcome back, I hope you had a great sabbatical!
It works like a charm now I'm using it regularly to build Raspberry Pi (different targets) and MIPS images including Rust components:
Welcome back, I hope you had a great sabbatical!
It works like a charm now 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 https://openwrt.org/docs/guide-developer/toolchain/crosscompile 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 Good luck!
@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
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 rust-values.mk
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)/rules.mk
PKG_NAME:=bandwhich
PKG_VERSION:=0.22.2
PKG_RELEASE:=1
PKG_SOURCE:=bandwhich-$(PKG_VERSION).tar.gz
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2024-01-27
PKG_SOURCE_VERSION:=96a7f77271106464e7a1f1060377a7d1e8d66127
PKG_SOURCE_URL:=https://github.com/imsnif/bandwhich.git
PKG_MIRROR_HASH:=skip
PKG_LICENSE_FILES:=LICENSE.md
include $(INCLUDE_DIR)/package.mk
include $(TOPDIR)/package/feeds/packages/rustup/rust-values.mk
PKG_BUILD_DEPENDS:=rustup/host
define Build/Compile
cd $(PKG_BUILD_DIR) && \
$(CARGO_PKG_CONFIG_VARS) \
$(STAGING_DIR_HOST)/bin/cargo +nightly -Z unstable-options -Z build-std build --release
endef
define Package/bandwhich
SECTION:=net
CATEGORY:=Network
DEPENDS:=@!SMALL_FLASH @!LOW_MEMORY_FOOTPRINT +zlib +libncurses +libncurses-dev
TITLE:=Terminal bandwidth utilization tool
URL:=https://github.com/imsnif/bandwhich
endef
define Package/bandwhich/description
Rust-lang based Terminal bandwidth utilization tool
endef
define Package/bandwhich/install
$(INSTALL_DIR) $(1)/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/target/$(RUSTUP_TARGET_ARCH)/release/bandwhich $(1)/bin/bandwhich
endef
$(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
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.
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.