Cross-Compilation of Packages
Cross-Compilation of Packages
When building an entire distribution from scratch, you have two choices: 1. Native Chroot Compilation: Compile software inside an emulated or native container using the target CPU architecture. (Slow if building ARM64 on x86 via QEMU user emulation). 2. True Cross-Compilation: Run cross-compilers (aarch64-linux-gnu-gcc) natively on high-powered x86_64 host hardware to emit target machine code directly.
+-------------------------------------------------------------+
| Cross-Compilation Package Setup |
| |
| Host System (x86_64): |
| - Cross Compiler: aarch64-linux-gnu-gcc |
| - Target Sysroot: /opt/sysroots/aarch64 |
| ├── usr/include (target C headers) |
| └── usr/lib (target shared libraries) |
| |
| pkg-config Configuration: |
| - PKG_CONFIG_SYSROOT_DIR=/opt/sysroots/aarch64 |
| - PKG_CONFIG_LIBDIR=/opt/sysroots/aarch64/usr/lib/pkgconfig|
+-------------------------------------------------------------+
The Pitfall: pkg-config Poisoning
When building packages that depend on external libraries (e.g., compiling curl which depends on openssl), the build system invokes pkg-config to discover library paths and CFLAGS:
$ pkg-config --cflags --libs openssl
-I/usr/include -L/usr/lib -lssl -lcrypto # DANGER: Points to host libraries!If your build system uses the host’s /usr/bin/pkg-config, it will return the host machine’s library paths! The linker will link against host x86_64 binaries, causing immediate cross-compilation linker errors.
The Solution: Cross-pkg-config Wrappers
Create an architecture-specific wrapper script at $TOOLS/bin/aarch64-linux-gnu-pkg-config:
#!/bin/sh
# aarch64-linux-gnu-pkg-config
export PKG_CONFIG_SYSROOT_DIR="/opt/sysroots/aarch64"
export PKG_CONFIG_LIBDIR="/opt/sysroots/aarch64/usr/lib/pkgconfig:/opt/sysroots/aarch64/usr/share/pkgconfig"
export PKG_CONFIG_SYSTEM_INCLUDE_PATH="/opt/sysroots/aarch64/usr/include"
export PKG_CONFIG_SYSTEM_LIBRARY_PATH="/opt/sysroots/aarch64/usr/lib"
exec /usr/bin/pkg-config "$@"Cross-Compiling with Meson Cross-Files
Meson provides first-class support for cross-compilation via declarative INI files:
# /opt/cross/aarch64-linux.ini
[binaries]
c = 'aarch64-linux-gnu-gcc'
cpp = 'aarch64-linux-gnu-g++'
ar = 'aarch64-linux-gnu-ar'
strip = 'aarch64-linux-gnu-strip'
pkg-config = 'aarch64-linux-gnu-pkg-config'
[host_machine]
system = 'linux'
cpu_family = 'aarch64'
cpu = 'cortex-a72'
endian = 'little'
[properties]
sys_root = '/opt/sysroots/aarch64'Invoking the build requires a single flag:
$ meson setup build --cross-file /opt/cross/aarch64-linux.ini
$ ninja -C buildThe resulting binaries are guaranteed to run natively on the target architecture without host pollution.