C 交叉编译入门:host/build/target 与三元组
更新时间:2026-09-21。嵌入式视角。编译过程见 编译链接过程。
一句话回答
交叉编译就是「在一种机器上编译,产出在另一种机器上运行的程序」——比如在 x86 PC(host)上编译出给 ARM 单片机(target)跑的固件;你用的是带目标三元组前缀的交叉工具链(如 arm-none-eabi-gcc),并通过 --sysroot、-mcpu 等参数指定目标的库和 CPU。
一、host / build / target
- build:执行编译的机器(你的 PC,通常 x86_64 Linux/Windows)。
- host:编译产物运行的机器(目标开发板/MCU)。
- target:仅在「工具链本身」被构建时有意义,表示该工具链产出的代码给谁跑。
普通应用交叉编译时 host ≠ build;做固件时 host 就是那块 ARM 芯片。
二、目标三元组(target triple)
格式通常是 架构-厂商-操作系统-ABI,例如:
arm-none-eabi:ARM 架构、无厂商、无操作系统(裸机)、EABI(嵌入式 ABI),常用于 STM32 等 Cortex-M;arm-linux-gnueabihf:ARM、跑 Linux、硬浮点 ABI;x86_64-pc-linux-gnu:普通 x86_64 Linux 本机。
none 是裸机的关键标志:没有 OS、没有标准动态库,链接常需自己提供链接脚本和启动文件。
三、最小命令
bash
# 裸机 Cortex-M3 示例
arm-none-eabi-gcc \
-mcpu=cortex-m3 -mthumb \
--sysroot=/path/to/target/sysroot \
-T linker.ld -nostartfiles \
main.c startup.c -o firmware.elf
arm-none-eabi-objcopy -O binary firmware.elf firmware.bin常用参数:
-mcpu=/-mthumb:指定 CPU 型号和 Thumb 指令集;--sysroot:目标系统根目录,工具链据此找目标库和头文件;-T:指定裸机链接脚本,-nostartfiles:不用默认启动文件;- 再用
objcopy把 ELF 转成可烧录的 bin/hex。
常见坑
- 拿本机 gcc 编固件:产出 x86 指令,目标板完全无法执行。
- 搞混三元组的 OS 段:裸机要用
none-eabi,用成linux-gnu会引入不存在的系统依赖。 - sysroot/工具链没装对:找不到目标头文件和库(libc、libgcc)。
-mcpu与实际芯片不符:用了芯片不支持的指令导致硬件异常。- 混用不同 ABI(硬/软浮点):目标库和你编译选项 ABI 不一致会链接/运行出错。
- 忘记交叉版 binutils:
objcopy/objdump也要用arm-none-eabi-前缀的版本。
总结
交叉编译是在 build(PC)上产出在 host(目标板)运行的程序,用带三元组前缀的工具链如 arm-none-eabi-gcc;三元组 arch-vendor-os-abi 里 none 表示裸机;通过 -mcpu、--sysroot、-T 等指定 CPU、目标库和链接脚本,产物再用对应 objcopy 转成可烧录格式,务必保证 ABI 和工具链版本一致。