交叉编译
在嵌入式开发或跨平台开发中,经常会遇到一个概念:交叉编译(Cross Compilation)。这篇文章将简要介绍什么是交叉编译,以及交叉编译工具链中常见的工具前缀含义。
一、什么是交叉编译?
交叉编译是指在一种平台上生成另一种平台可执行代码的编译过程。
举个例子:你在一台运行 Ubuntu(x86 架构)的 PC 上编写程序,并希望将它部署到一台运行 ARM 架构的嵌入式设备上。那么你就需要一个可以在 x86 上运行、但能编译出 ARM 平台代码的编译器,这个过程就叫交叉编译。
- 编译器运行的平台:宿主机(Host)
- 生成代码要运行的平台:目标机(Target)
通常情况下,宿主机和目标机架构不同,因此不能直接使用本地的 gcc 进行编译。
常见用途
- 嵌入式开发(如:开发板、物联网设备)
- 构建 Android/iOS 应用
- 为多平台生成二进制包
二、交叉编译工具链和前缀
交叉编译依赖于一整套工具链,包括:
gcc编译器ld链接器as汇编器ar静态库打包器strip去除符号信息
这些工具通常会以一个前缀开头,用于标识它们是为某个特定目标平台服务的。
工具前缀格式
常见格式为:
aaa-bbb-ccc-
aaa:目标架构,例如arm、aarch64、mips、riscv64bbb:厂商或系统(可选)ccc:操作系统,例如linux、none(裸机)、elf等
像 aarch64-none-linux-gnu- 这样的前缀出现在交叉工具链的每一个工具名之前,例如:
aarch64-none-linux-gnu-gccaarch64-none-linux-gnu-ldaarch64-none-linux-gnu-ar
这是 GNU 工具链使用的一种 三元组(triplet)命名格式,表示目标平台:
<arch>-<vendor>-<os>[-<abi>]
举例说明:
| 工具前缀 | 说明 |
|---|---|
arm-linux-gnueabi- |
用于 32 位 ARM Linux 系统,使用 EABI |
aarch64-none-linux-gnu- |
用于 64 位 ARM Linux 系统(无特定厂商) |
riscv64-unknown-elf- |
用于裸机 RISC-V 应用 |
mipsel-linux-gnu- |
用于小端 MIPS Linux 系统 |
这些前缀加上命令名组成实际工具命令,比如:
aarch64-none-linux-gnu-gcc
arm-linux-gnueabi-ld
是否换芯片就要换工具链?
- 同一架构,不同厂商:如果内核版本、ABI、库版本兼容,原工具链可以复用;否则推荐使用对应厂商提供的工具链。
- 不同架构(如 ARM 换成 RISC-V):必须换工具链,因为指令集、ABI 完全不同。
以下情况通常需要更换工具链:
| 情况 | 是否需要换工具链 | 说明 |
|---|---|---|
| 架构变了(aarch64 → arm) | ✅ 是 | 指令集不兼容 |
| OS 类型变了(Linux → RTOS) | ✅ 是 | 系统接口不同 |
| C 库变了(glibc → musl) | ✅ 是 | ABI 不兼容 |
| 编译为裸机(无操作系统) | ✅ 是 | 需使用 elf 工具链 |
| 仅芯片厂商变了 | ❌ 否 | 工具链兼容 |
三、如何获取工具链?
-
Linux发行版提供的交叉工具链:如 Ubuntu 提供的
gcc-arm-linux-gnueabihf、gcc-aarch64-linux-gnu。 -
Linaro、Sourcery 等组织提供的预编译工具链:通常提供 tar 包下载。
-
Yocto、Buildroot 自构建工具链:适用于高度定制的嵌入式系统。
-
厂商 SDK 提供的工具链:推荐优先使用,对目标硬件更有保障。
