Using Rust with Buildroot (pre-built binaries)

Rust is a modern, compiled, programming language, oriented towards safety, memory control and concurrency. Its performances are comparable to C++.

Rust's features make it a good candidate for writing programs for embedded systems.

In this article, we will build a system for QEMU ARM Vexpress using Buildroot, then add support for Rust by installing the pre-built toolchain in the Buildroot environment. Finally, we will write a test program in Rust, compile it and run it from the generated system.

Build System Image

First, grab the Buildroot source code and initialize the configuration:

# Clone Buildroot repository
git clone https://git.buildroot.net/buildroot
cd buildroot
# Configure for the desired system
make O=$HOME/build/demo-rust/qemu/arm qemu_arm_vexpress_defconfig

Then, edit the configuration:

make O=$HOME/build/demo-rust/qemu/arm menuconfig

Go to the "Toolchain" menu and select "glibc" instead of "uclibc" as the targeted C library. Also select support for C++. Save your configuration and exit, then start the build:

make O=$HOME/build/demo-rust/qemu/arm

Install Pre-built Rust Toolchain

Download the binary versions of the Rust compiler for the host machine (x86_64 PC) and the standard library compiled for the target "arm-unknown-linux-gnueabihf" (compatible with the ARM Vexpress machine):

push dl
wget https://static.rust-lang.org/dist/rust-1.7.0-x86_64-unknown-linux-gnu.tar.gz
wget https://static.rust-lang.org/dist/rust-std-1.7.0-arm-unknown-linux-gnueabihf.tar.gz
popd

Prepare for installation:

# Extract compiler binaries
mkdir -p $HOME/build/demo-rust/qemu/arm/build/host-rust-1.7.0
tar -xzf dl/rust-1.7.0-x86_64-unknown-linux-gnu.tar.gz \
    -C $HOME/build/demo-rust/qemu/arm/build/host-rust-1.7.0 \
    --strip-components=1
# Extract ARM version of standard libary binaries
mkdir -p $HOME/build/demo-rust/qemu/arm/build/host-rust-std-1.7.0
tar -xzf dl/rust-std-1.7.0-arm-unknown-linux-gnueabihf.tar.gz \
    -C $HOME/build/demo-rust/qemu/arm/build/host-rust-std-1.7.0 \
    --strip-components=1

Next, install the compiler:

pushd $HOME/build/demo-rust/qemu/arm/build/host-rust-1.7.0
./install.sh --prefix=$HOME/build/demo-rust/qemu/arm/host/usr \
             --disable-ldconfig
popd

Finally, install the cross-compiled standard library:

pushd $HOME/build/demo-rust/qemu/arm/build/host-rust-std-1.7.0
./install.sh --prefix=$HOME/build/demo-rust/qemu/arm/host/usr \
             --disable-ldconfig
popd

Build Test Program

Now is the time to test the compiler. Create the Rust source file for the "Hello World" program:

mkdir -p $HOME/src/hello-rust
cat <<EOF > $HOME/src/hello-rust/main.rs
fn main() {
    println!("Hello World!");
}
EOF

To build the hello-rust test program, execute:

export PATH=$HOME/build/demo-rust/qemu/arm/host/usr/bin:$PATH
$HOME/build/demo-rust/qemu/arm/host/usr/bin/rustc \
    --target=arm-unknown-linux-gnueabihf \
    -C linker=arm-buildroot-linux-gnueabihf-gcc \
    -o $HOME/build/demo-rust/qemu/arm/target/usr/bin/hello-rust \
    $HOME/src/hello-rust/main.rs

Note that the triplet used with the --target option is the same of the one from the downloaded standard library, which is different from the one for the linker to use.

Run Test Program from System

Rebuild the system image:

make O=$HOME/build/demo-rust/qemu/arm

Now, you can start your system using QEMU:

qemu-system-arm \
    -M vexpress-a9 \
    -m 256 \
    -kernel $HOME/build/demo-rust/qemu/arm/images/zImage \
    -dtb $HOME/build/demo-rust/qemu/arm/images/vexpress-v2p-ca9.dtb \
    -drive file=$HOME/build/demo-rust/qemu/arm/images/rootfs.ext2,if=sd,format=raw \
    -append "console=ttyAMA0,115200 root=/dev/mmcblk0" \
    -serial stdio \
    -net nic,model=lan9118 \
    -net user

Log as "root" (no password) and execute the test program:

Welcome to Buildroot
buildroot login: root
# hello-rust
Hello World!

Congratulations! You've run your first Rust program on an (emulated) embedded Linux system. Feel free to adapt the example to run the program on a real ARM system, such as Raspberry Pi.