Cross Compilation and Toolchains
This chapter explains cross compilation — building code on one machine to run on another — and the toolchains that make it possible.
Why This Matters
Embedded firmware, mobile, and many systems targets are compiled on a host different from the target. Cross compilation is how firmware gets built, and understanding toolchains is essential for embedded and low-level work.
Prerequisites
c.build.6— compilers.
Core Concept
A toolchain is the set of tools (compiler, assembler, linker, libc) that produce code for a specific target. A cross compiler runs on a host (e.g., x86-64 Linux) but generates code for a different target (e.g., ARM Cortex-M).
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -c main.c -o main.o
The compiler triple (arm-none-eabi) identifies the target.
Examples
Building firmware for ARM (illustrative)
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -ffreestanding -nostdlib \
-T linker.ld startup.c main.c -o firmware.elf
-ffreestanding: no hosted libc assumptions.-nostdlib: do not link the standard hosted startup/library.-T linker.ld: use a custom linker script (c.emb.linker-script).
Cross compiling with CMake
cmake -S . -B build \
-DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
cmake --build build
How It Works
A cross compiler knows the target's instruction set, ABI, and system interfaces. The linker combines objects into a target-format executable (ELF for embedded, often converted to a binary/hex firmware image later).
Variations
Bare-metal vs. Linux cross
- Bare-metal:
arm-none-eabi-*, no OS. - Linux cross:
aarch64-linux-gnu-*, targets Linux ABI with glibc/musl.
Sysroot
A sysroot provides the target's headers and libraries so the cross compiler can compile against them.
Common Mistakes
- Forgetting
-ffreestanding -nostdlibfor bare-metal. - Mixing host and target libraries.
- Using the wrong
-mcpu/-marchfor the target.
Undefined Behavior
- None inherent to cross compilation; producing code for the wrong target is a
toolchain error, not ISO C UB.
Portability
- Toolchain triples and flags are platform/toolchain-specific.
Under the Hood
The compiler's back end (c.compiler.3) targets a specific architecture. The assembler and linker understand that target's object format and relocations. c.cpu.5 covers the architectures.
Practical Usage
- Use the correct toolchain triple and
-mcpu/-march. - Use
-ffreestanding -nostdlibfor bare-metal. - Use CMake toolchain files to encapsulate cross settings.
Exercises
1. If a cross compiler is available, compile a tiny freestanding program for ARM and inspect the object with readelf. 2. Write a CMake toolchain file for a cross target. 3. Explain the difference between bare-metal and Linux cross toolchains.
Deep Challenge
Set up (or describe) a bare-metal ARM cross build with a custom linker script and startup code, from .c source to a .bin firmware image. Explain each step and flag.
Related Concepts
c.build.6— compilers.c.emb.10— startup and linker scripts.c.emb.1— freestanding environment.
References
- GCC cross compiler documentation, ARM toolchain docs.
Verification
- Cross compilation flags and triples are toolchain-specific.
PLATFORM-SPECIFIC - No example was executed during generation unless noted. `Execution not
verified.`
Progress
- [ ] Read
- [ ] Understand
- [ ] Complete examples
- [ ] Complete exercises
- [ ] Complete deep challenge
Concept checkboxes
- [ ] Cross compilation
- [ ] Toolchains and triples
- [ ] Bare-metal vs. Linux cross
- [ ] Sysroot
Mastery levels
| Concept | Current level (0–8) | Target level |
|---|---|---|
| c.build.cross | 0 | 6 |
| c.build.toolchain | 0 | 6 |