2. Buildroot 源码下载与目录结构解析

好,咱们正式开始动手。这一章我们聊聊怎么把 Buildroot 的源码拿到手,以及拿到手之后,你看到的这一大堆文件夹到底是干嘛用的。

我记得刚接触 Buildroot 那会儿,第一反应是「这目录也太多了吧?」。别慌,其实核心就那么几个。搞懂了它们,后面的路就好走了。

2.1 从 Git 仓库拉取 LTS 版本

我个人习惯,做产品或者做课程,一定用 LTS(Long Term Support)版本。为什么?稳定。你不会希望学到一半,发现某个包因为版本更新编译不过了。

Buildroot 的官方仓库在 GitLab 上。拉取命令很简单:

git clone https://git.buildroot.net/buildroot
cd buildroot
git checkout 2024.02.x   # 这是 2024 年的 LTS 分支

这里有个小细节。你直接 git clone 下来,默认是在 master 分支上。master 分支是开发分支,今天能编译通过,明天可能就不行了。所以我建议你像我一样,立刻切到 LTS 分支。

我的习惯: 每次拉完代码,第一件事就是 git branch -a 看看有哪些 LTS 分支。2024.02.x、2023.11.x 这种命名格式的就是。选最新的那个就行。

拉完之后,看看目录长什么样:

$ ls -l
总用量 112
drwxrwxr-x  2 user user  4096  ...  arch
drwxrwxr-x  2 user user  4096  ...  board
drwxrwxr-x  2 user user  4096  ...  boot
drwxrwxr-x  2 user user  4096  ...  configs
drwxrwxr-x  2 user user  4096  ...  docs
drwxrwxr-x  2 user user  4096  ...  fs
drwxrwxr-x  2 user user  4096  ...  linux
drwxrwxr-x  2 user user  4096  ...  package
drwxrwxr-x  2 user user  4096  ...  support
drwxrwxr-x  2 user user  4096  ...  toolchain
-rw-rw-r--  1 user user  ...  Makefile
-rw-rw-r--  1 user user  ...  Config.in

嗯,十几个目录。别怕,我们只挑最重要的几个讲。

2.2 顶层目录:项目的「大脑」

顶层目录里,有两个文件你必须要认识:Makefile 和 Config.in。

文件 作用 我的一句话总结
Makefile 整个 Buildroot 的入口。你执行 make 时,就是它在调度一切。 项目的「总控开关」
Config.in Kconfig 配置文件的根。定义了最顶层的配置选项。 项目的「菜单首页」

你想想看,每次你运行 make menuconfig,那个图形界面里的第一层菜单,就是从 Config.in 加载的。而 Makefile 则负责把你选好的配置,翻译成实际的编译动作。

我曾经踩过的坑: 有次我手痒,直接修改了顶层 Makefile 里的变量。结果整个编译链全乱了。后来我学乖了——顶层文件尽量别动。真要改配置,去 configs/ 目录下做自己的配置文件。

2.3 package 目录:软件包的「超市」

这个目录,说白了就是 Buildroot 的「软件超市」。里面放了成百上千个软件包的定义。每个包一个子目录,比如:

package/
├── busybox/
├── dropbear/
├── mosquitto/      # 我们后面要重点用的 MQTT Broker
├── openssl/
├── python/
└── ...

每个子目录里,通常包含三个文件:

  • Config.in:这个包的配置菜单。定义了「要不要编译这个包」、「有哪些编译选项」。
  • <包名>.mk:Makefile 片段。告诉 Buildroot 怎么下载、配置、编译、安装这个包。
  • <包名>.hash:校验文件。确保下载的源码包没被篡改。

举个例子,我们后面要用到的 mosquitto:

package/mosquitto/
├── Config.in
├── mosquitto.mk
└── mosquitto.hash

你在 make menuconfig 里勾选了 mosquitto,Buildroot 就会去读 mosquitto.mk,然后自动完成下载、编译、安装。你几乎不用管细节。

核心思路: Buildroot 的哲学就是「你只管选,活我来干」。package 目录就是那个「干活」的引擎。

2.4 configs 目录:一键构建的「配方」

这个目录我特别喜欢。它里面放的是各种开发板的默认配置文件。

你想想看,如果你每次都要从头开始配置——选架构、选内核、选包、选文件系统——那得多累?configs 目录就是帮你省这个事的。

configs/
├── raspberrypi4_64_defconfig
├── stm32mp157_dk_defconfig
├── qemu_x86_64_defconfig
└── ...

用法极其简单:

make raspberrypi4_64_defconfig

这一条命令,就把树莓派 4B 的所有配置都加载好了。然后你直接 make,就能得到一个完整的系统镜像。

我个人习惯是:先找一个和自己硬件最接近的 defconfig,然后在此基础上修改。比如我做 MQTT 网关,就会在 qemu_x86_64_defconfig 的基础上,加上 mosquitto 和必要的网络工具。

场景 推荐做法
你有现成的开发板 直接用板子对应的 defconfig,省时省力
你在做原型验证 用 qemu_x86_64_defconfig,在 QEMU 里跑
你要定制自己的板子 复制一份最接近的 defconfig,改名字,然后 make savedefconfig

2.5 board 目录:板级支持的「说明书」

configs 目录告诉 Buildroot 「选什么」,board 目录告诉它「怎么用」。

这个目录里,每个板子或平台都有一个子目录,里面放着:

  • 设备树文件(.dts / .dtsi):描述硬件资源,比如 GPIO、I2C、UART 接在哪。
  • 启动脚本:比如 genimage.cfg,用来生成最终的镜像文件。
  • 补丁文件:针对某些软件包的特殊修改。
  • README:告诉你这块板子怎么烧录、怎么启动。

举个例子,树莓派 4 的 board 目录结构:

board/raspberrypi/
├── rpi4/
│   ├── config_4_64bit.txt   # 启动配置
│   ├── genimage.cfg         # 镜像生成脚本
│   └── post-build.sh        # 构建后处理脚本
└── ...

如果你要自己做一块板子,我建议你完整复制一个 board 目录,然后改里面的设备树和启动脚本。这样结构清晰,不容易乱。

我的经验: board 目录和 configs 目录是「一对」的。比如 configs/raspberrypi4_64_defconfig 里,会指定 BR2_ROOTFS_POST_BUILD_SCRIPT="board/raspberrypi/rpi4/post-build.sh"。所以改板子时,这两个目录要一起改。

2.6 知识结构总览

说了这么多,咱们用一张图把关系理清楚:

Buildroot 核心目录结构关系图 顶层目录 (Makefile + Config.in) package/ configs/ board/ mosquitto / busybox / openssl ... 每个包: Config.in + .mk + .hash raspberrypi4_64_defconfig qemu_x86_64_defconfig 设备树 (.dts) / 启动脚本 genimage.cfg / post-build.sh 三者协作关系 1. configs/ 定义「选什么包、用什么架构」 2. package/ 提供「怎么下载、编译每个包」 3. board/ 提供「怎么生成最终镜像、怎么启动」

这张图你看懂了,Buildroot 的目录结构就掌握了八成。剩下的目录,比如 linux/、toolchain/、fs/,都是在为这三个核心目录服务的。

2.7 本章小结

咱们快速过一遍今天的关键点:

  • 拉代码:用 git clone 后立刻切到 LTS 分支,别在 master 上折腾。
  • 顶层目录:Makefile 是总控,Config.in 是菜单首页。尽量别改。
  • package/:软件包的「超市」。每个包三个文件:Config.in、.mk、.hash。
  • configs/:一键构建的「配方」。找最接近的 defconfig,然后改。
  • board/:板级支持的「说明书」。设备树、启动脚本都在这里。