3、交叉编译工具链的获取与安装:从Linaro下载预编译工具链、解压与配置环境变量、验证工具链
好,咱们进入正题。上一章聊了什么是交叉编译,这一章直接动手——把工具链请进你的开发机。
说白了,交叉编译工具链就是一套能在你的 x86 电脑上生成 ARM 可执行文件的「编译器全家桶」。你不需要在 ARM 板子上装 gcc,那太慢了,也装不全。我刚开始做嵌入式那会儿,就傻乎乎地在 ARM 板子上编译内核,结果一个晚上没编译完……后来才明白,交叉编译才是正道。
3.1 从哪里下载?Linaro 预编译工具链
工具链的获取方式有好几种:
- 芯片厂商提供:比如 NXP、TI 官方 SDK 里自带的工具链,最省心,但版本可能偏旧。
- 自己用 crosstool-NG 编译:自由度最高,但耗时,适合有特殊需求的场景。
- Linaro 预编译工具链:我推荐这个。Linaro 是 ARM 生态的顶级组织,他们维护的预编译工具链稳定、更新快、支持全。
我个人习惯用 Linaro 的 gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf 这个版本。为什么选 7.5.0?因为它在稳定性和新特性之间平衡得不错,而且很多 BSP(板级支持包)默认就依赖这个版本。
3.2 解压与安装
下载下来的文件是一个 .tar.xz 压缩包。解压命令很简单:
# 假设文件下载到了 ~/Downloads 目录
cd ~/Downloads
tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
解压后你会得到一个文件夹。我习惯把它放到 /opt 目录下,方便管理:
sudo mv gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf /opt/
cd /opt/
ls -l
你会看到类似这样的目录结构:
gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/
├── arm-linux-gnueabihf/
├── bin/
├── include/
├── lib/
├── libexec/
└── share/
其中 bin/ 目录里放的就是所有可执行工具,比如 arm-linux-gnueabihf-gcc、arm-linux-gnueabihf-g++、arm-linux-gnueabihf-ld 等等。
/usr/bin 或 /usr/local/bin。那样会污染系统环境,而且多个工具链版本共存时容易冲突。我见过有人这么干,结果换项目时编译器版本对不上,折腾了一整天。
3.3 配置环境变量
解压完只是第一步。你得让系统知道这些工具在哪里。配置环境变量有两种方式:
方式一:临时生效(适合测试)
export PATH=/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin:$PATH
这种方式只在当前终端窗口有效。关掉终端就没了。
方式二:永久生效(推荐)
编辑 ~/.bashrc 文件(如果你用 zsh,就编辑 ~/.zshrc):
echo 'export PATH=/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
这样每次打开终端,工具链就自动在 PATH 里了。
~/.bashrc 里加一个别名,方便切换不同版本的工具链。比如:
alias arm-gcc='export PATH=/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin:$PATH'
这样我只需要输入 arm-gcc 就能切换到对应的工具链环境。
3.4 验证工具链
配置完环境变量,别急着写代码。先验证一下工具链是否正常工作。
3.4.1 检查编译器版本
arm-linux-gnueabihf-gcc --version
如果输出类似下面这样,说明工具链已经就绪:
arm-linux-gnueabihf-gcc (Linaro GCC 7.5.0-2019.12) 7.5.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
3.4.2 编译一个简单的测试程序
写一个最简单的 C 程序:
// hello.c
#include <stdio.h>
int main() {
printf("Hello, Embedded Linux!\n");
return 0;
}
用交叉编译器编译:
arm-linux-gnueabihf-gcc -o hello hello.c
编译完成后,用 file 命令查看生成的可执行文件:
file hello
你应该会看到类似这样的输出:
hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, not stripped
看到 ARM 字样了吗?这说明这个程序是给 ARM 架构的 CPU 用的,不能在你的 x86 电脑上直接运行。这就是交叉编译的证明。
./hello,会报错 cannot execute binary file: Exec format error。别慌,这是正常的。这个程序只能放到 ARM 板子上跑。
3.4.3 检查工具链的完整工具集
一个完整的工具链不止有 gcc。我建议你检查一下这些工具是否都在:
| 工具名 | 作用 | 验证命令 |
|---|---|---|
| arm-linux-gnueabihf-gcc | C 编译器 | --version |
| arm-linux-gnueabihf-g++ | C++ 编译器 | --version |
| arm-linux-gnueabihf-ld | 链接器 | --version |
| arm-linux-gnueabihf-ar | 静态库打包工具 | --version |
| arm-linux-gnueabihf-objdump | 反汇编工具 | --version |
| arm-linux-gnueabihf-strip | 去除调试符号 | --version |
如果这些工具都能正常输出版本信息,那你的工具链就完全可用了。
3.5 避坑指南
我在项目中遇到过几个常见问题,这里列出来,你遇到了可以少走弯路:
- PATH 顺序问题:如果你系统里本来就装了 ARM 版的 gcc(比如用 apt 装的),注意 PATH 里要把 Linaro 的 bin 目录放在前面。否则系统可能调用到错误的编译器。
- 32 位库缺失:Linaro 工具链是 64 位的,但某些依赖库是 32 位的。如果你在 64 位系统上运行报错
No such file or directory,试试安装sudo apt install lib32z1 lib32ncurses5。 - 权限问题:放在
/opt下的工具链,普通用户可能没有执行权限。记得chmod +x或者用sudo执行。
3.6 本章知识结构图
下面这张图帮你梳理了工具链获取与安装的完整流程: