====== Cross Platform Development for Raspberry ====== ---- Cross-development means developing and compiling programs on another platform then it intended to run upon. It is a common approach for Pi, since it’s also how Raspian is built. For quite some time I did compile Pi applications on the Pi itself. Which works quite well, but has one large drawback: performance. Being able to compile these programs on my 8 core 16GB desktop, improved compilation time enorm. And it is quite simple. There are multiple approaches to setup a cross-compile environment. The most essential aspect is the following: - Exact **identical Linux/Debian versions** on X86 build host and Raspberry runtime target - **Different Linux/Debian versions** on X86 build host and Raspberry runtime target - [[raspberry:cross-platform-compile:check-architecture|Check the architecture of Host and Target]] - [[raspberry:cross-platform-compile:setup-for-identical-Debian-versions|For identical Debian distro/version]] - [[raspberry:cross-platform-compile:setup-for-different-Debian-versions|For different Debian distro/version]] - [[raspberry:cross-platform-compile:cross-platform-debugging|Cross Platform Debugging]] ===== Compatibility rule ===== Build against the oldest operating-system release and CPU that the resulting binary must support. Do not link a Bookworm target against Trixie ARM libraries. Doing so can create dependencies on newer glibc or library symbols that are unavailable on the Bookworm target. For example: Incorrect: Trixie compiler + Trixie armhf libraries -> Bookworm target Correct: Trixie compiler + Bookworm armhf sysroot -> Bookworm target ===== The problem with different host and target ARM libraries ===== The important guideline is that **the target system's ABI, headers, libraries and library versions vs. what you build against.** For example: HOST Debian Trixie x86-64 │ │ cross compiler ▼ arm-linux-gnueabihf-gcc │ ┌───────┴────────┐ WRONG approach CORRECT approach │ │ ▼ ▼ Trixie armhf libs Bookworm Raspbian armhf libs │ │ ▼ ▼ ARM executable ARM executable │ │ └───────┬────────┘ ▼ Raspbian Bookworm Suppose your **x86 host is Debian Trixie**, and you install **libc6:armhf** from Trixie. Your compiler might then build against something like **glibc 2.41** while your Raspberry Pi's Raspbian Bookworm has **glibc 2.36**. Your executable may therefore acquire a dependency on a newer GLIBC symbol. For example, conceptually: program └── was linked against and requires GLIBC_2.41 │ ▼ Raspbian Bookworm only has GLIBC_2.36 │ ✗ program won't run, with errors like: ".../lib/arm-linux-gnueabihf/libc.so.6: version `GLIBC_2.41' not found..." This is one of the most common reasons why **building on a newer distribution for an older target** causes trouble. It isn't only the **libraries** that matter. The headers matter too. Suppose you compile against Trixie's headers (///usr/include//), but run on Bookworm. You can potentially get differences in: * API definitions * feature macros * structure definitions * constants * kernel interfaces * glibc interfaces * library-specific APIs So the ideal relationship is: That's why a **target-specific sysroot** is the clean solution. ===== But the reverse is usually fine ===== If you deliberately want to require a newer target system, that's perfectly legitimate. For example: Build against Trixie armhf ↓ Deploy only to Trixie armhf ↓ No problem. The rule is simple: **Don't build against a newer userspace than the oldest target you intend to support.** This is particularly important for `glibc`. ====== Raspberry Pi OS vs Debian armhf ====== One important distinction: Raspberry Pi OS vs Debian armhf. Raspberry Pi OS is Debian-derived, but its 32-bit repository contains packages built for Raspberry Pi hardware and may contain versions or patches marked with `+rpt`. Use the Raspberry Pi OS repositories when Raspberry Pi OS is the target. Use Debian repositories only when the target is Debian armhf. If your target is **Raspberry Pi OS 32-bit**, don't blindly assume that Debian Bookworm's armhf libraries are an exact match. Debian itself points this out: > Raspberry Pi OS armhf can be subtly incompatible with Debian armhf. In particular, Raspberry Pi OS/Raspbian has historically had differences in its ARM ABI/build configuration. Debian recommends using a target-specific chroot when cross-compiling packages for Raspberry Pi OS armhf. ([Debian Wiki][2]) ====== Links ====== * https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads * https://www.acmesystems.it/arm9_toolchain * https://jensd.be/1126/linux/cross-compiling-for-arm-or-aarch64-on-debian-or-ubuntu * https://learn.arm.com/install-guides/gcc/cross/ * https://packages.debian.org/search?keywords=crossbuild-essential * https://www.get-edi.io/assets/pdfs/DebianCross.pdf * https://prashanth.entertolearn.in/debian-arm-architecture-and-emulation/using-debian-arm-cross-compiler-for-bare-metal-programming