Skip to content

Raspberry Pi

Cross-Compiling C++ with Bazel: Platforms, Toolchains and the Exec/Target Split

Alamedin gorge. The tent goes where the ground is flat, not where the view is. Nothing required those to be the same place.

As far as I'm concerned, Bazel is the best build tool you can pick today, as long as it supports your language. A real dependency graph, hermetic toolchains, a remote cache that actually works, one command to build and test everything. And yet every time I bring it up with embedded people, the first question is the same: fine, but what about cross-compilation?

Fair question. Most of us grew up with a vendor SDK that hijacks the shell through an environment-setup script, or with the "just build it on the board" approach because it looks simpler. It isn't simpler. A Raspberry Pi 5 is a decent target and a lousy build machine, and nothing about an ARM CPU requires the compiler to run on it.

So here's a small and fairly well-known example, done the way I think it should be done: C++23 built on an x86_64 Linux host for an aarch64 Linux device. The device is a Pi 5 because that's the board sitting on my desk. Swap in any ARM64 Linux board and the mechanics stay the same. The code lives in pi-bazel1, and the whole cross setup is a 137-line MODULE.bazel, a 23-line .bazelrc and two platform() declarations. No hand-written cc_toolchain_config, no select() anywhere in the tree, no #ifdef on architecture in the sources.

Cross-Compiling Rust for Raspberry Pi

I just started a new embedded pet project on the Raspberry Pi, and I expect it'll be a pretty big one, so I've been thinking about the technology from the beginning. The overall goal is to create a glass-to-glass video pipeline example. Let's see how it's going. For now, I'm using a USB V4L2 camera while waiting for the native Pi modules to arrive, but it's enough to sketch the capture loop and start testing the build pipeline. The application itself is minimal—open /dev/video0, request YUYV at 1280x720, set up MMAP buffers, and iterate over frames—but the real challenge occurs when v4l triggers bindgen, and the build must cross-compile cleanly for aarch64. 

The language choice immediately becomes part of the equation right away. Go is my favorite and, usually, is not considered as an option by many embedded developers. But it's a good choice for small embedded utilities because its cross-compilation story is nearly effortless. Need an ARM binary? One command and you have it!

GOOS=linux GOARCH=arm64 go build