4、编译工具链安装:安装gcc-arm-none-eabi交叉编译器,配置环境变量

好,到了这一步,我们得给电脑装上能编译 ArduPilot 的“翻译官”。

ArduPilot 的代码是在我们电脑上写的,但最终要跑到飞控板(比如 Pixhawk)的 STM32 芯片上。电脑是 x86 架构,飞控是 ARM 架构,这俩“语言”不通。所以我们需要一个交叉编译器——说白了,就是在电脑上运行,但能生成 ARM 芯片能识别的机器码的工具。

这个工具就是 gcc-arm-none-eabi。我个人习惯叫它“ARM 裸机 GCC”。

核心概念:交叉编译 = 在 A 平台上编译出能在 B 平台上运行的程序。我们这里是 x86_64 → ARM Cortex-M4/M7。

4.1 为什么是 arm-none-eabi?

这个名字其实暴露了它的身世:

  • arm:目标架构是 ARM。
  • none:没有操作系统(bare-metal)。飞控上跑的是 RTOS(实时操作系统),但不是 Linux 这种完整 OS。
  • eabi:嵌入式应用二进制接口。规定了函数怎么调用、寄存器怎么用,大家按这个标准来,链接才不会出错。

我在项目里见过有人用错了版本,拿 arm-linux-gnueabihf 去编译飞控固件,结果链接阶段报一堆莫名其妙的错误。嗯,工具链选错,后面全是坑。

4.2 下载与安装(Ubuntu 20.04/22.04)

我推荐直接从 ARM 官方获取,或者用 Ubuntu 的包管理器。但包管理器里的版本往往比较旧。我个人习惯用 ARM 官方的预编译包,干净、可控。

方法一:从 ARM 官方下载(推荐)

  1. 打开浏览器,访问 ARM 官方 GNU 工具链下载页面(developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain)。
  2. 找到 gcc-arm-none-eabi 的最新稳定版本(写稿时是 10.3-2021.10 或 12.x)。
  3. 选择 Linux 64-bit 的 .tar.bz2 包下载。
# 假设下载到了 ~/Downloads 目录
cd ~/Downloads
# 解压到 /opt 目录(需要 sudo)
sudo tar -xjf gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2 -C /opt
# 解压后会得到 /opt/gcc-arm-none-eabi-10.3-2021.10 目录

方法二:apt 安装(省事但版本可能旧)

sudo apt update
sudo apt install gcc-arm-none-eabi

装完后检查版本:

arm-none-eabi-gcc --version

如果输出类似 arm-none-eabi-gcc (GNU Arm Embedded Toolchain 10.3-2021.10) 10.3.1 20210824,就对了。

注意:apt 安装的版本可能低于 9.x。ArduPilot 的编译脚本对工具链版本有最低要求。如果版本太旧,编译时会出现 internal compiler error 或某些 C++17 特性不支持。我曾经在 Ubuntu 18.04 上踩过这个坑,折腾了半天才发现是工具链太老。

4.3 配置环境变量

装好了,但系统还不知道它在哪里。我们需要把工具链的路径告诉系统。

如果你用的是方法一(手动解压到 /opt),需要配置环境变量。方法二(apt 安装)通常会自动配置,但为了保险,也可以检查一下。

编辑 ~/.bashrc

# 打开 .bashrc
nano ~/.bashrc

# 在文件末尾添加以下内容(路径根据你的实际解压位置调整)
export PATH="/opt/gcc-arm-none-eabi-10.3-2021.10/bin:$PATH"

# 保存并退出(Ctrl+O, Ctrl+X)
# 使配置生效
source ~/.bashrc

验证环境变量

# 检查是否能在任意路径下找到 arm-none-eabi-gcc
which arm-none-eabi-gcc
# 应该输出类似 /opt/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gcc

# 检查版本
arm-none-eabi-gcc --version

如果 which 找不到,说明 PATH 没配好。检查路径是否写错,或者有没有执行 source ~/.bashrc。

小技巧:我习惯在 ~/.bashrc 里加一行注释,比如 # ARM toolchain for ArduPilot,方便以后维护。另外,如果你用 zsh,就编辑 ~/.zshrc,别搞混了。

4.4 验证编译是否正常

光能执行还不够,我们得确认它真的能编译代码。写个简单的 C 程序测试一下。

# 创建一个测试文件
nano test.c

# 输入以下内容
#include <stdio.h>
int main() {
    printf("Hello from ARM!\n");
    return 0;
}

# 保存退出,然后编译
arm-none-eabi-gcc -c test.c -o test.o

# 查看生成的目标文件信息
arm-none-eabi-objdump -f test.o

如果输出显示 architecture: arm,说明交叉编译器工作正常。你生成的是 ARM 架构的目标文件,不是 x86 的。

注意:这里用 -c 只编译不链接,因为我们没有 ARM 的运行时库,链接会报错。但能生成 .o 文件就证明工具链没问题。

4.5 常见问题与避坑

  • Permission denied:解压到 /opt 时忘了加 sudo,或者解压后文件权限不对。用 sudo chmod -R +r /opt/gcc-arm-none-eabi-* 修复。
  • 版本冲突:系统里可能装了多个版本的 ARM 工具链。用 which -a arm-none-eabi-gcc 查看所有路径,确保 PATH 里排在最前面的是你想要的版本。
  • 32 位库缺失:如果你用的是 64 位系统,但工具链是 32 位的(老版本),需要安装 32 位兼容库:sudo apt install libc6:i386。

我曾经在配置 CI 服务器时,因为 PATH 顺序问题,导致编译脚本用了系统自带的旧版本工具链,编译出来的固件在飞控上跑起来就死机。查了两天才发现是工具链版本不对。所以,装完后一定要验证版本和 PATH。

4.6 本章知识体系

下面这张图帮你理清工具链安装的完整逻辑:

交叉编译器安装流程 交叉编译器安装与配置流程 为什么需要? x86 → ARM 交叉编译 选择版本 arm-none-eabi >= 9.x 下载安装 官方包 / apt 配置环境变量 编辑 ~/.bashrc 验证安装 --version / which 测试编译 arm-none-eabi-gcc -c 关键检查点 1. 工具链版本 ≥ 9.x,否则 ArduPilot 编译可能失败 2. PATH 配置后必须 source 或重启终端 3. 用 which 确认使用的是你安装的版本,不是系统自带的

4.7 小结

到这一步,你的电脑已经能“说”ARM 话了。工具链是后面所有编译工作的基础,装好了后面就顺了。

装完别忘了验证一下。我每次在新环境配完工具链,都会先写个 test.c 编译一下,确认无误再继续。这个习惯帮我避免过好几次“装了半天结果没用对版本”的尴尬。