4、交叉编译工具链安装:ARM GCC工具链下载与安装、环境变量配置、验证工具链是否可用
好,咱们接着往下走。上一节我们把 Ubuntu 虚拟机搞定了,现在它就像一张白纸。但要让这张白纸能编译出 ARM 芯片能跑的代码,我们得给它装上「翻译官」——也就是交叉编译工具链。
说白了,交叉编译就是「我在 x86 电脑上写代码,编译出 ARM 架构的机器码」。你想想看,RMC 固件跑在 ARM 核上,可我们开发机是 x86,没有这个工具链,你写再多代码也跑不起来。
4.1 什么是 ARM GCC 工具链?
ARM GCC 工具链,全称是 GNU Arm Embedded Toolchain。它是一套完整的工具集合,包含编译器、链接器、调试器等等。我习惯把它理解成一个「翻译团队」:
- arm-none-eabi-gcc:C 语言编译器,把源码变成汇编
- arm-none-eabi-g++:C++ 编译器,同理
- arm-none-eabi-ld:链接器,把多个目标文件合成一个可执行文件
- arm-none-eabi-objcopy:格式转换器,把 ELF 转成 bin/hex
- arm-none-eabi-gdb:调试器,用来单步跟踪代码
这里有个关键点:none 表示没有操作系统(裸机),eabi 是嵌入式应用二进制接口。我们做 RMC 固件,跑的就是裸机程序,所以选这个版本最合适。
4.2 下载 ARM GCC 工具链
下载方式有两种,我推荐第一种,省心。
方式一:从 ARM 官网下载(推荐)
ARM 官方维护着最新的工具链,地址是:https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm
进去之后,找到 Downloads 区域,选择对应你系统的版本。我们是 Ubuntu 64位,所以选:
gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2
为什么选 10.3 版本?嗯,这个版本比较稳定,我在多个项目里验证过。太新的版本可能有兼容性问题,太老的又缺特性。10.3 是个黄金版本。
方式二:命令行下载(适合脚本自动化)
如果你喜欢用命令行,也可以直接 wget:
wget https://developer.arm.com/-/media/Files/downloads/gnu-rm/10.3-2021.10/gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2
下载完成后,你会得到一个 .tar.bz2 压缩包。大概 200MB 左右,网速慢的话可以先去喝杯咖啡。
4.3 安装工具链
安装其实就是解压,然后放到一个固定的目录。我个人习惯放在 /opt 下,这样所有用户都能用。
# 创建目录
sudo mkdir -p /opt/gcc-arm-none-eabi
# 解压到目标目录
sudo tar -xjf gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2 -C /opt/gcc-arm-none-eabi
# 查看解压后的结构
ls /opt/gcc-arm-none-eabi/
解压后,你会看到 bin、lib、share 等目录。其中 bin 目录里就是咱们需要的可执行文件。
-j 参数,因为这是 bz2 格式。如果你用 -z(gzip),会报错说格式不对。我曾经犯过这个低级错误,还以为是下载的包坏了。
4.4 配置环境变量
工具链装好了,但系统还不知道它在哪。每次敲 arm-none-eabi-gcc,系统会去 PATH 环境变量里找。所以我们要把 bin 目录加进去。
编辑 ~/.bashrc 文件(如果你用 zsh,就编辑 ~/.zshrc):
vim ~/.bashrc
在文件末尾添加一行:
export PATH=$PATH:/opt/gcc-arm-none-eabi/gcc-arm-none-eabi-10.3-2021.10/bin
然后让配置生效:
source ~/.bashrc
这里有个细节:$PATH 放在前面还是后面?我习惯放在前面,这样系统会优先搜索系统目录,再搜索我们的工具链。但如果你有多个 GCC 版本,要注意优先级问题。
/,结果 source 之后所有命令都找不到了。因为 PATH 被覆盖了。所以改完 .bashrc 后,先不要关终端,用另一个终端测试一下。万一出问题,还能切回来修复。
4.5 验证工具链是否可用
配置完环境变量,咱们得验证一下。这一步不能省,不然你辛辛苦苦写了一天代码,最后发现编译器没装好,那可就尴尬了。
验证一:查看版本信息
arm-none-eabi-gcc --version
如果输出类似下面的信息,说明安装成功:
arm-none-eabi-gcc (GNU Arm Embedded Toolchain 10.3-2021.10) 10.3.1 20210824 (release)
Copyright (C) 2020 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.
验证二:编译一个测试程序
写一个最简单的 C 文件,验证编译流程:
// test.c
int main(void) {
return 0;
}
然后编译:
arm-none-eabi-gcc -c test.c -o test.o
如果没有任何错误,并且生成了 test.o 文件,说明编译器工作正常。
再用 file 命令看看目标文件的架构:
file test.o
输出应该是:
test.o: ELF 32-bit LSB relocatable, ARM, EABI5 version 1 (SYSV), not stripped
看到 ARM 和 EABI5 了吗?这说明我们编译出来的确实是 ARM 架构的代码,不是 x86 的。
验证三:完整编译链接
再进一步,试试完整的编译+链接流程:
arm-none-eabi-gcc test.c -o test.elf -nostdlib -ffreestanding
-nostdlib 表示不使用标准库,-ffreestanding 表示独立环境。这两个参数在裸机开发中很常用。
然后查看生成的 ELF 文件:
arm-none-eabi-objdump -d test.elf
你会看到 ARM 汇编指令,比如 mov r0, #0、bx lr 之类的。嗯,看到这些就放心了,工具链完全可用。
4.6 知识体系梳理
为了让你对整个流程有个直观的认识,我画了一张图:
4.7 常见问题与解决
安装过程中,你可能会遇到一些问题。我把常见的列出来:
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
command not found |
环境变量没配好,或没 source | 检查 ~/.bashrc 中的路径是否正确,重新 source |
Permission denied |
解压时没用 sudo,权限不够 | 用 sudo chmod -R 755 /opt/gcc-arm-none-eabi 修复权限 |
No such file or directory |
解压路径写错了 | 用 ls 确认解压后的目录结构 |
| 编译出来的文件是 x86 架构 | 用了系统自带的 gcc,不是交叉编译器 | 用 which arm-none-eabi-gcc 确认调用的路径 |
lib32z1 和 lib32ncurses5。命令是:sudo apt install lib32z1 lib32ncurses5。我当年第一次装的时候就被这个坑过,折腾了半小时才反应过来。
好了,到这里交叉编译工具链就装好了。你可以用 arm-none-eabi-gcc --version 再确认一下。看到版本号跳出来,心里就踏实了。接下来,我们就可以开始写真正的 RMC 固件代码了。