Cross-Compiling C++ with Bazel: Platforms, Toolchains and the Exec/Target Split
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.