4、PX4源码编译:从GitHub拉取到第一个固件

好,咱们进入正题。这一章要干的事,说白了就是把PX4的源码从GitHub上拽下来,再把编译环境搭好,最后编译出一个能跑的固件。我刚开始接触PX4时,光编译环境就折腾了两天——嗯,现在回头看,其实没那么复杂。

4.1 从GitHub拉取PX4-Autopilot

先说说拉代码。我个人习惯用SSH方式克隆,省得每次输密码。如果你还没配SSH Key,也可以用HTTPS。

# 用SSH(推荐)
git clone git@github.com:PX4/PX4-Autopilot.git --recursive

# 或者用HTTPS
git clone https://github.com/PX4/PX4-Autopilot.git --recursive

这里有个关键点:--recursive 参数。PX4依赖很多子模块,比如mavlink、uavcan等。不加这个参数,你拉下来的代码编译时会报一堆找不到头文件的错误。我曾经吃过这个亏,拉完代码直接make,结果卡了半小时才发现子模块没更新。

注意:拉取完成后,务必检查子模块是否完整。可以用 git submodule status 查看。如果某个子模块前面有个减号(-),说明没拉全,执行 git submodule update --init --recursive 补上。

4.2 编译环境搭建:make、cmake、gcc

编译环境说白了就三样东西:make(构建工具)、cmake(生成构建配置)、gcc(编译器)。但PX4对版本有要求,不是随便装一个就能用。

4.2.1 安装基础工具链

如果你用的是Ubuntu 20.04或22.04,官方推荐用以下命令一键安装:

sudo apt update
sudo apt install git zip qtcreator cmake build-essential genromfs ninja-build exiftool -y

# 安装依赖库
sudo apt install libxml2-dev libxslt1-dev libssl-dev -y

这里我多说一句:ninja-build 很多人会漏掉。虽然不用ninja也能编译,但用了之后编译速度能快30%左右。我项目里编译px4_fmu-v5,用make大概要8分钟,换成ninja只要5分半。

4.2.2 安装ARM交叉编译器

PX4固件跑在STM32这类ARM芯片上,所以需要交叉编译器。官方推荐gcc-arm-none-eabi,版本要求9-2020-q2-update或更高。

# 下载并安装ARM编译器
wget https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu-rm/9-2020-q2-update/gcc-arm-none-eabi-9-2020-q2-update-x86_64-linux.tar.bz2
sudo tar xjf gcc-arm-none-eabi-9-2020-q2-update-x86_64-linux.tar.bz2 -C /opt/

# 配置环境变量
echo 'export PATH=$PATH:/opt/gcc-arm-none-eabi-9-2020-q2-update/bin' >> ~/.bashrc
source ~/.bashrc

# 验证安装
arm-none-eabi-gcc --version
小技巧:如果你同时做其他ARM开发,可能装了多个版本的编译器。我建议在PX4项目根目录下建一个 toolchain.cmake 文件,指定编译器路径,避免版本冲突。

4.2.3 验证环境

装完之后,跑一下PX4自带的检查脚本:

cd PX4-Autopilot
make check

这个脚本会检查所有依赖是否齐全。如果输出全是绿色的 OK,说明环境没问题。如果有红色报错,按提示补装就行。

4.3 编译第一个固件:px4_fmu-v5

环境搭好了,咱们来编译第一个固件。我选 px4_fmu-v5 是因为它是Pixhawk 4的主控固件,也是目前最常用的版本之一。

4.3.1 编译命令

cd PX4-Autopilot
make px4_fmu-v5

就这么简单?对,就这么简单。第一次编译会下载一些依赖包,大概需要10-15分钟。后面再编译就快了,增量编译一般1-2分钟搞定。

4.3.2 编译过程解读

编译时你会看到一堆输出,我挑几个关键阶段说说:

阶段 输出示例 说明
配置 -- Configuring done cmake生成构建配置,检查依赖
编译 [ 45%] Building CXX object ... 百分比从0到100,编译各个模块
链接 Linking CXX executable px4_fmu-v5.elf 把所有目标文件链接成可执行文件
生成固件 Built target px4_fmu-v5 生成 .px4 固件文件

4.3.3 编译产物

编译完成后,在 build/px4_fmu-v5_default/ 目录下能找到这些文件:

  • px4_fmu-v5.elf:带调试信息的可执行文件,用于GDB调试
  • px4_fmu-v5.px4:固件文件,直接烧录到飞控
  • px4_fmu-v5.bin:纯二进制文件,某些烧录工具需要

核心要点:我们真正需要的是 .px4 文件。这个文件包含了引导加载程序和固件本身,通过QGroundControl或命令行工具就能烧录到飞控里。

4.4 常见编译错误与避坑

编译过程中难免遇到问题。我把自己踩过的坑整理了一下:

  • 错误:arm-none-eabi-gcc not found —— 环境变量没配好,重新source一下.bashrc
  • 错误:submodule not updated —— 执行 git submodule update --init --recursive
  • 错误:cmake版本过低 —— PX4要求cmake 3.10+,用 cmake --version 检查,低了就升级
  • 错误:内存不足 —— 编译时加 -j2 限制并行任务数,比如 make px4_fmu-v5 -j2

我曾经在编译时遇到一个诡异的错误:undefined reference to 'px4_log'。查了半天,发现是某个模块的日志宏定义没包含头文件。这种问题一般清理一下重新编译就能解决:

make clean
make px4_fmu-v5

4.5 本章知识体系

下面这张图把本章的核心流程串起来了:

PX4源码编译流程 GitHub拉取源码 编译环境搭建 make cmake gcc-arm-none-eabi 编译 px4_fmu-v5 编译产物:.elf / .px4 / .bin 核心产物是 .px4 文件,用于烧录到飞控硬件

这张图把整个流程分成了四个阶段:拉取源码 → 搭建环境 → 编译固件 → 生成产物。每个阶段都有对应的工具和输出,环环相扣。

4.6 验证编译结果

编译完成后,我习惯做两件事验证固件是否正常:

  1. 检查文件大小:ls -lh build/px4_fmu-v5_default/px4_fmu-v5.px4,正常应该在1MB左右
  2. 查看固件信息:strings build/px4_fmu-v5_default/px4_fmu-v5.px4 | grep "PX4",能看到固件版本和编译时间
个人习惯:我会在编译成功后,把 .px4 文件重命名加上日期,比如 px4_fmu-v5_20250101.px4。这样方便回溯,知道哪个版本是啥时候编译的。