-
Notifications
You must be signed in to change notification settings - Fork 0
Cross Compiling for Other Boards
Theia cross-compiles its C++ runtime (the supervisor) to other Linux targets —
Raspberry Pi 4, BeagleBone AI-64, any Debian/aarch64 board — and packs the
result as a .deb. This page explains the moving parts and walks through
targeting a board the project doesn't ship a config for.
The in-repo
--config=rpi4is an example target, not special. The same mechanism cross-compiles to any board once you supply its toolchain and rootfs.
These two config names are convenient shorthands, but they conflate three independent concerns. Read them as:
| Shorthand | Really means |
|---|---|
--config=linux |
host build — build on and for this machine (typically host-amd64) |
--config=rpi4 |
cross build — build on the host, for a different target (target-aarch64) using an exchangeable rootfs + toolchain |
A cross-compile is the composition of three exchangeable pieces — the "linux" and "rpi4" labels just bundle a particular choice of each:
| Piece | What it is | rpi4 example |
|---|---|---|
| 1. Platform | the target CPU + OS constraints Bazel selects on |
//rules/config:rpi4 = cpu:aarch64, os:linux
|
| 2. Toolchain | the cross-compiler (gcc triple) |
aarch64-linux-gnu-gcc (apt: gcc-aarch64-linux-gnu) |
| 3. Sysroot (rootfs) | the target's libraries + headers to link against | a Debian bookworm aarch64 rootfs at third_party/sysroot/rpi4
|
Same CPU family → same platform + toolchain; only the sysroot changes. That is the key to retargeting: an aarch64 board built on a different Debian release reuses pieces 1 and 2 and swaps only piece 3.
Just the supervisor binary (/opt/theia/bin/supervisor) — the runtime
fabric an app system runs under. It is headless (no GUI), so desktop
environments on the board (XFCE, GNOME, …) are irrelevant to the build.
The BeagleBone AI-64 (TI TDA4VM / J721E, Cortex-A72) is aarch64 — the same CPU family as the Pi 4. So it reuses the rpi4 platform + toolchain unchanged; the only difference is the rootfs: Debian 13.5 (trixie) instead of the Pi's bookworm.
target: BeagleBone AI-64 (Cortex-A72, aarch64)
OS: Debian 13.5 "trixie" (the XFCE image — desktop is irrelevant here)
reuse: platform //rules/config:rpi4 + aarch64-linux-gnu toolchain
change: the sysroot → a trixie aarch64 rootfs
third_party/sysroot/setup_rpi4.sh bootstraps a bookworm rootfs. Make a
trixie one the same way — debootstrap the trixie suite with the libs the runtime
links, plus nanopb (the runtime/protos #include <pb.h> and link
libprotobuf-nanopb.a, which isn't reliably in the Debian arm64 archive):
SR=$HOME/sysroots/bbai64-trixie
sudo debootstrap --arch=arm64 --foreign --variant=minbase \
--include=libc6-dev,libstdc++-13-dev,libprotobuf-dev,libgrpc++-dev,libabsl-dev \
trixie "$SR" http://deb.debian.org/debian
sudo cp /usr/bin/qemu-aarch64-static "$SR/usr/bin/"
sudo chroot "$SR" /debootstrap/debootstrap --second-stage
# stage nanopb (3 tiny .c → aarch64 lib + headers)
np=$(mktemp -d); curl -fsSL https://github.com/nanopb/nanopb/archive/refs/tags/0.4.7.tar.gz | tar xz -C "$np"
( cd "$np"/nanopb-0.4.7 && for c in pb_common pb_encode pb_decode; do
aarch64-linux-gnu-gcc -c -O2 -fPIC -I. $c.c -o $c.o; done
aarch64-linux-gnu-ar rcs libprotobuf-nanopb.a pb_*.o )
sudo cp "$np"/nanopb-0.4.7/pb*.h "$SR/usr/include/"
sudo cp "$np"/nanopb-0.4.7/libprotobuf-nanopb.a "$SR/usr/lib/aarch64-linux-gnu/"(Trixie ships newer libs than bookworm — libstdc++6/libprotobuf sonames
differ. That's fine: cross-linking against the trixie rootfs binds the trixie
sonames, which is exactly what the board runs.)
The @rpi4_sysroot repo rule reads THEIA_RPI4_SYSROOT — point it at the
trixie rootfs and the same toolchain links against it:
THEIA_RPI4_SYSROOT="$SR" bazel build //platform/supervisor/main:supervisor --config=rpi4
file bazel-bin/platform/supervisor/main/supervisor # → ELF ARM aarch64
qemu-aarch64-static -L "$SR" bazel-bin/platform/supervisor/main/supervisor # smoke-runTHEIA_RPI4_SYSROOT="$SR" ./.github/scripts/build-rpi4-runtime-deb.sh
# → dist/debian/theia-runtime/theia-runtime_0.1.0_arm64.debEdit the script's Depends: to the trixie sonames (e.g. the newer
libstdc++6 / libprotobuf versions the binary links — dpkg-shlibdeps on the
board, or read them from the rootfs), then dpkg -i on the BeagleBone.
A non-aarch64 board needs all three pieces, not just the rootfs:
-
Platform — add a
//rules/config:<board>with the rightcpu:constraint (copy therpi4stanza inrules/config/BUILD.bazel). -
Toolchain — add a
toolchains/<triple>/mirroringtoolchains/aarch64_linux_gnu/with that board's cross-gcc triple (e.g.arm-linux-gnueabihffor armv7,riscv64-linux-gnufor RISC-V), andregister_toolchainsit inMODULE.bazel. - Sysroot — a Debian rootfs for that arch, as above.
Then bazel build … --platforms=//rules/config:<board>.
- Runtime only. This cross-compiles the supervisor. The ARA services (com/per/sm/ucm/log/shwa) additionally need gRPC + etcd cross-built against the target rootfs — a larger lift, not covered here.
- Not in CI. The release pipeline ships amd64 (22.04/24.04) debs; board debs are a user-driven cross-compile (the rootfs is large + board-specific). This page is the recipe.
-
No AF_TIPC under qemu.
qemu-aarch64-staticruns the binary but doesn't emulate TIPC sockets — the full supervisor↔FC smoke needs the real board.
See also: Deployment + Serialization, Tutorial.