Table of Contents
GCC Cross-Compilation
Cross-compilation produces binaries for a different architecture than the build machine. Useful for embedded systems, bare-metal firmware, and HPC clusters with different CPU architectures.
# Build on x86, produce ARM binary arm-linux-gnueabihf-gcc -o app app.c # Build on x86, produce RISC-V binary riscv64-linux-gnu-gcc -o app app.c
The compiler prefix indicates the target architecture. arm-linux-gnueabihf-gcc is the ARM cross-compiler (part of cross-compilation toolchain).
Installing cross-toolchains:
sudo apt install gcc-arm-linux-gnueabihf # ARM sudo apt install gcc-aarch64-linux-gnu # ARM 64-bit sudo apt install gcc-riscv64-linux-gnu # RISC-V
Each toolchain includes the compiler, linker, and target C library headers and binaries.
Compilation flags for targets:
# 32-bit ARM (Cortex-A7/A9) arm-linux-gnueabihf-gcc -O3 -march=armv7-a -mfpu=neon -o app app.c # ARM Cortex-M4 (embedded, no OS) arm-none-eabi-gcc -O3 -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -o app app.c # RISC-V 64-bit riscv64-linux-gnu-gcc -O3 -march=rv64imac -o app app.c
-march specifies the target architecture; -mcpu specifies the CPU model. Without these, the compiler uses a conservative baseline.
Cross-compilation with libraries: When using third-party libraries, compile them for the target architecture first:
./configure --host=arm-linux-gnueabihf # tell build system target architecture make make install DESTDIR=/path/to/target
The --host flag tells the build system you're cross-compiling. It configures for the target, not the build machine.
Linking against cross-compiled libraries:
arm-linux-gnueabihf-gcc -I/path/to/target/include -L/path/to/target/lib \ -o app app.c -lmylib
-I points to target headers; -L points to target libraries. The linker uses target libraries, not the host libraries.
Bare-metal (no OS): For firmware without an OS (microcontroller, bare-metal runtime):
# ARM Cortex-M4 (embedded) arm-none-eabi-gcc -O3 -mcpu=cortex-m4 -mthumb \ --specs=nosys.specs -o app.elf app.c objcopy -O binary app.elf app.bin
arm-none-eabi-gcc (no Linux) targets bare metal. --specs=nosys.specs removes OS dependencies. objcopy converts ELF to raw binary for flashing.
Testing cross-compiled binaries: You can't run a cross-compiled ARM binary on x86. Test on actual hardware or use an emulator:
qemu-arm ./arm_binary # emulate ARM binary on x86 qemu-riscv64 ./riscv_binary # emulate RISC-V binary on x86
See QEMU for emulation.
