cross-gcc

Installation
SKILL.md

Cross-GCC(GCC 交叉编译)

用途

引导开发者搭建和使用交叉编译 GCC 工具链:三元组、sysroot、pkg-config、基于 QEMU 的测试及常见失败模式。

触发场景

  • "如何在 x86 机器上编译 ARM 程序?"
  • "出现 'wrong ELF class' 或 'cannot execute binary file' 怎么办?"
  • "如何为交叉编译设置 sysroot?"
  • "pkg-config 在我的交叉构建中返回了宿主库路径"
  • "如何使用 QEMU + GDB 调试交叉编译的二进制文件?"

工作流程

1. 理解三元组

GNU 三元组的形式为 <arch>-<vendor>-<os>-<abi>(通常为 3 或 4 部分):

三元组 目标
aarch64-linux-gnu 64 位 ARM Linux(glibc)
arm-linux-gnueabihf 32 位 ARM Linux 硬浮点
arm-none-eabi 裸机 ARM(无操作系统)
riscv64-linux-gnu 64 位 RISC-V Linux
x86_64-w64-mingw32 从 Linux 构建 Windows(MinGW)
mipsel-linux-gnu 小端 MIPS Linux

2. 安装工具链

# Debian/Ubuntu
sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu binutils-aarch64-linux-gnu

# 裸机 ARM(Cortex-M)
sudo apt install gcc-arm-none-eabi binutils-arm-none-eabi

# 验证
aarch64-linux-gnu-gcc --version

3. 基础交叉编译

# C
aarch64-linux-gnu-gcc -O2 -o hello hello.c

# C++
aarch64-linux-gnu-g++ -O2 -std=c++17 -o hello hello.cpp

# 裸机(无标准库,无操作系统)
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 \
    -ffreestanding -nostdlib -T linker.ld -o firmware.elf startup.s main.c

4. Sysroot(系统根目录)

sysroot 是包含目标平台头文件和库的目录。当代码需要链接目标平台特定的库时必须使用。

# 使用 sysroot
aarch64-linux-gnu-gcc --sysroot=/path/to/aarch64-sysroot -O2 -o prog main.c

# 常见 sysroot 来源:
# - Raspberry Pi:从 raspbian/raspios 下载
# - Debian 多架构:debootstrap --arch arm64 bullseye /tmp/sysroot
# - Yocto/Buildroot:在构建输出中自动生成

验证 sysroot 是否正确:

aarch64-linux-gnu-gcc --sysroot=/path/to/sysroot -v -E - < /dev/null 2>&1 | grep sysroot

5. 交叉构建的 pkg-config

pkg-config 默认会返回宿主库路径。需要覆盖:

export PKG_CONFIG_SYSROOT_DIR=/path/to/sysroot
export PKG_CONFIG_LIBDIR=${PKG_CONFIG_SYSROOT_DIR}/usr/lib/aarch64-linux-gnu/pkgconfig:${PKG_CONFIG_SYSROOT_DIR}/usr/share/pkgconfig
export PKG_CONFIG_PATH=   # 清除宿主路径

pkg-config --libs libssl  # 现在返回目标路径

6. CMake 交叉编译

创建工具链文件 aarch64.cmake

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)

set(CMAKE_C_COMPILER   aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)

set(CMAKE_SYSROOT /path/to/aarch64-sysroot)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=aarch64.cmake
cmake --build build

7. 使用 QEMU 测试

# 用户模式仿真(Linux 二进制,无需完整操作系统)
sudo apt install qemu-user-static

qemu-aarch64-static ./hello
# 或设置 binfmt_misc 实现透明执行:
# 然后直接:./hello

# 通过 QEMU 进行 GDB 远程调试
qemu-aarch64-static -g 1234 ./hello &
aarch64-linux-gnu-gdb -ex "target remote :1234" ./hello

8. 常见错误

错误 原因 解决方法
cannot execute binary file: Exec format error 在没有 QEMU 的宿主上运行目标二进制 使用 qemu-<arch>-static
wrong ELF class: ELFCLASS64(或 32) 链接了错误架构的目标文件 检查三元组;确保所有目标文件使用同一工具链
/usr/bin/ld: cannot find -lfoo 交叉链接时使用了宿主库路径 设置 --sysroot;修复 PKG_CONFIG_LIBDIR
undefined reference to '__aeabi_*' 缺少 ARM ABI 运行时 链接 -lgcc-lclang_rt.builtins
relocation R_AARCH64_ADR_PREL_PG_HI21 out of range 距离过大 使用 -mcmodel=large 或重构代码
unrecognized opcode -mcpu-march 错误 为目标设置正确的 CPU 标志

9. 环境变量

# 告知构建系统使用交叉编译器
export CC=aarch64-linux-gnu-gcc
export CXX=aarch64-linux-gnu-g++
export AR=aarch64-linux-gnu-ar
export STRIP=aarch64-linux-gnu-strip
export OBJDUMP=aarch64-linux-gnu-objdump

# 用于 autoconf 项目
./configure --host=aarch64-linux-gnu --prefix=/usr

ARM 特定 GCC 标志参考见 references/arm-flags.md

相关技能

  • GCC 标志详情使用 skills/compilers/gcc
  • 使用 gdbserver 进行远程调试使用 skills/debuggers/gdb
  • AArch64 汇编特性使用 skills/low-level-programming/assembly-arm
  • 工具链文件设置使用 skills/build-systems/cmake
Related skills

More from killvxk/low-level-dev-skills-zh

Installs
1
First Seen
Mar 21, 2026