Hi!
In order to build programs written in Rust and/or Cargo crates for embedded
systems, I'm currently working on adding support for Rust in Buildroot.
Buildroot is a set of Makefiles which makes building Linux embedded systems
easy. It enables the user to build a cross-compilation toolchain (or use an
existing one), then a Linux kernel and a root filesystem populated with a
selection of applications.
It supports a wide variety of embbeded devices (Raspberry Pi, etc) and provides
configurations for many QEMU architectures (ARM, MIPS, x86_64, ...).
Support for Rust and Cargo is available in the "feature/rust" branch of this
Buildroot repository. It may need some polishing before being upstreamed.
Here is the method used to add this feature, as well as the issues encountered.
Two packages have been added in Buildroot:
- package/rust: this package fetches a snapshot of the Rust compiler to
bootstrap the build a host version of the Rust compiler and cross-compiles the
standard library for the configured target (e.g. an ARM device). - package/cargo: this package fetches a snapshot of Cargo to bootstrap the
build of a host version of Cargo, then generate a configuration file suitable
for the target (stored, along with the downloaded crates, in a dedicated $CARGO_HOME).
Either when using an internal or an external cross-compilation toolchain,
Buildroot will refer to the target using a GNU triple in the form of
<cpu>-buildroot-linux-<system> (e.g. "arm-buildroot-linux-gnueabihf").
Futhermore, Buildroot allows the user to fine-tune the description of the target
architecture (e.g. NEON instruction set is supported, CPU type is cortex-a57,
etc) and use this information to tune some packages.
So, to properly configure the build of the host Rust compiler, a tool named
rust-target-gen
is used. This Python script has two purposes:
- creation of a dedicated target configuration file by searching for a
matching one among mk/cfg/*.cfg and patching it with the correct target
name/cross-compiler prefix. - creation of a dedicated target specification file (in JSON format), with the
given target information and LLVM features.
The creation of the target configuration is easy (basic search/replace). For the
creation of the target specification file, it is a bit more tricky, as the
information for the "blessed" platforms is only available as Rust code in
src/librustc_back/target/*.rs files.
So, I decided to collect the information from the Rust source files in a CSV
file, that rust-target-gen
uses internally. Maybe there is a better way to do
this.
I also have a few patches for Rust (harmonization of the target configuration
files) as well as for Cargo.
Additionally, this tutorial explains how to properly add a Cargo crate as a Buildroot package. I
successfully ran an "Hello World" program on QEMU ARM, x86_64, i386, MIPSEL and
AARCH64 systems.
Comments and suggestions welcomed.