其他
在 x86-64 主机上为…
当需要从 x86-64 主机为嵌入式或多架构目标构建、链接、运行和调试 GCC 程序时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 35/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 38/100 ×0.15
适用场景
在 x86-64 主机上为 ARM/AA特定
解决思路
- 识别 GNU triplet 形式:`<arch>-<vendor>-<os>-<abi>`(通常 3 或 4 段),根据目标选择正确 triplet。
- 常见 triplet 对应关系:`aarch64-linux-gnu` = 64 位 ARM Linux(glibc);`arm-linux-gnueabihf` = 32 位 ARM Linux hard-float;`arm-none-eabi` = 裸机 ARM(无 OS);`riscv64-linux-gnu` = 64 位 RISC-V Linux;`x86_64-w64-mingw32` = 从 Linux 交叉编译到 Windows(MinGW);`mipsel-linux-gnu` = 小端 MIPS Linux。
- 在 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`。
- 交叉编译 C:`aarch64-linux-gnu-gcc -O2 -o hello hello.c`。
- 交叉编译 C++:`aarch64-linux-gnu-g++ -O2 -std=c++17 -o hello hello.cpp`。
- 裸机交叉编译(无 stdlib、无 OS):`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`。
- 理解 sysroot:sysroot 是包含目标平台头文件和库的目录;当代码链接目标特定库时必须使用。
- 使用 sysroot 编译:`aarch64-linux-gnu-gcc --sysroot=/path/to/aarch64-sysroot -O2 -o prog main.c`。
- 获取常见 sysroot:Raspberry Pi 从 raspbian/raspios 下载;Debian multiarch 用 `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`。
- 交叉构建时覆盖 pkg-config,避免返回宿主库路径:`export PKG_CONFIG_SYSROOT_DIR=/path/to/sysroot`。
- 继续设置 pkg-config 库目录:`export PKG_CONFIG_LIBDIR=${PKG_CONFIG_SYSROOT_DIR}/usr/lib/aarch64-linux-gnu/pkgconfig:${PKG_CONFIG_SYSROOT_DIR}/usr/share/pkgconfig`。
- 清空宿主 pkg-config 路径:`export PKG_CONFIG_PATH= # clear host path`。
- 验证 pkg-config 返回目标路径:`pkg-config --libs libssl`。
- 为 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 工具链文件配置:`cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=aarch64.cmake`。
- 使用 CMake 构建:`cmake --build build`。
- 安装 QEMU user-mode 静态版本以测试目标二进制:`sudo apt install qemu-user-static`。
- 用 QEMU 运行交叉编译的 Linux 二进制:`qemu-aarch64-static ./hello`。
- 或设置 binfmt_misc 实现透明执行:设置后可直接运行 `./hello`。
- 通过 QEMU 进行 GDB 远程调试:先启动 `qemu-aarch64-static -g 1234 ./hello &`,再执行 `aarch64-linux-gnu-gdb -ex "target remote :1234" ./hello`。
- 处理 `cannot execute binary file: Exec format error`:原因是未用 QEMU 在宿主上运行目标二进制;修复:使用 `qemu-<arch>-static`。
- 处理 `wrong ELF class: ELFCLASS64`(或 32):原因是链接了错误架构目标文件;修复:检查 triplet,确保所有对象使用同一工具链。
- 处理 `/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 flags。
- 设置构建系统使用交叉编译器:`export CC=aarch64-linux-gnu-gcc`。
- 设置 C++ 编译器:`export CXX=aarch64-linux-gnu-g++`。
- 设置 AR:`export AR=aarch64-linux-gnu-ar`。
- 设置 STRIP:`export STRIP=aarch64-linux-gnu-strip`。
- 设置 OBJDUMP:`export OBJDUMP=aarch64-linux-gnu-objdump`。
- 对 autoconf 项目执行配置:`./configure --host=aarch64-linux-gnu --prefix=/usr`。
- 参考 ARM 专用 GCC flags:见 `references/arm-flags.md`。
适用边界 · 注意事项
- 目标平台不是 GNU/Linux、裸机 ARM、MinGW 等 GCC 支持的平台,或使用非 GCC 工具链(如 MSVC)时,不能直接套用。
- 只需要在同架构主机上本地编译/运行,且没有跨架构需求时,不需要交叉编译流程。
- 无法获得目标 sysroot 且必须链接目标特定库时,仅设置 triplet 不够,需先准备 sysroot 或改用能提供 sysroot 的构建系统。