====== 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