2、源码获取与目录结构:下载 Buildroot 源码、理解顶层目录、了解关键子目录

好,咱们正式开始动手。这一章我带你把 Buildroot 源码拿到手,再把它的目录结构摸清楚。很多初学者拿到源码就急着 make,结果出了问题根本不知道去哪找原因。说白了,你得先知道每个文件夹是干嘛的,出了问题才知道往哪看。

2.1 获取 Buildroot 源码

获取源码的方式很简单,两种主流方法:

  • 从官方仓库克隆:git clone git://git.buildroot.net/buildroot
  • 下载稳定版压缩包:去 https://buildroot.org/downloads/ 选一个版本

我个人习惯用 git 克隆,因为方便切换版本和查看历史。但如果你做产品,我建议下载一个稳定版压缩包,比如 buildroot-2023.02.tar.gz,这样版本锁死,不会因为上游更新出问题。

我的习惯: 我会在 /home/<user>/workspace/ 下建一个 buildroot 目录,把源码放进去。别放桌面或下载目录,路径里不要有中文和空格,否则交叉编译时可能出怪问题。
# 克隆最新版
git clone git://git.buildroot.net/buildroot
cd buildroot

# 或者下载稳定版(以 2023.02 为例)
wget https://buildroot.org/downloads/buildroot-2023.02.tar.gz
tar -xzf buildroot-2023.02.tar.gz
cd buildroot-2023.02

解压完,先别急着 make。咱们先看看里面都有什么。

2.2 顶层目录结构概览

执行 ls -l,你会看到一堆文件和文件夹。我第一次看的时候也懵,东西太多了。其实核心的就那么几个,我帮你梳理一下。

buildroot/
├── arch/          # 架构相关的配置和脚本
├── board/         # 板级支持包(关键!)
├── boot/          # 引导加载程序(uboot、grub等)
├── configs/       # 默认配置文件(关键!)
├── docs/          # 文档
├── fs/            # 文件系统生成逻辑
├── linux/         # Linux 内核相关的构建逻辑
├── output/        # 编译输出目录(第一次 make 后生成)
├── package/       # 所有软件包的构建规则(关键!)
├── support/       # 辅助脚本和工具
├── toolchain/     # 工具链相关(关键!)
├── Makefile       # 顶层 Makefile
└── Config.in      # 顶层配置菜单

嗯,这里要注意:output/ 一开始不存在,你执行完 make 才会生成。所有编译产物、临时文件、最终镜像都在里面。

核心原则: 你只需要关注 board/、configs/、package/、toolchain/ 这四个目录。其他目录大部分时间不用动。

为什么会这样?因为 Buildroot 的设计哲学是「配置驱动」。你通过 make menuconfig 选好配置,Buildroot 自动去 package/ 里找对应的构建规则,去 board/ 里找板级补丁和脚本,去 toolchain/ 里找工具链配置。你不需要手写 Makefile。

2.3 关键子目录详解

2.3.1 board/ —— 板级支持的核心

这个目录存放的是「板子级别的定制内容」。每个支持的开发板或产品,在这里都有一个子目录。

board/
├── raspberrypi/
│   ├── config.txt
│   ├── cmdline.txt
│   └── post-image.sh
├── beaglebone/
│   ├── uEnv.txt
│   └── post-build.sh
└── qemu/
    ├── aarch64-virt/
    └── ...

我在项目中遇到过一个问题:用默认配置编译出来的镜像,在自研板子上起不来。后来发现是 board/ 下的设备树文件没加对。说白了,board/ 就是你的板子身份证,里面放的是:

  • 设备树文件(.dts/.dtb)
  • 引导参数(cmdline.txt、config.txt)
  • 分区表
  • 后处理脚本(post-build.sh、post-image.sh)
我曾经踩过的坑: 有一次我修改了内核配置,但忘了更新 board 下的设备树,结果网卡驱动死活加载不上。排查了两天才发现是设备树里中断号没对上。所以记住:改硬件配置,一定要同步更新 board 下的文件。

2.3.2 configs/ —— 一键配置的入口

这个目录里全是 xxx_defconfig 文件。每个文件对应一个完整的 Buildroot 配置。你执行 make raspberrypi3_defconfig,Buildroot 就会读取 configs/raspberrypi3_defconfig,自动设置好架构、工具链、内核版本、软件包列表等所有选项。

configs/
├── raspberrypi3_defconfig
├── beaglebone_defconfig
├── qemu_aarch64_virt_defconfig
├── stm32mp157c_dk2_defconfig
└── ...

你想想看,如果没有这些 defconfig,你每次都要手动选几百个配置项,那得多痛苦。所以我的建议是:

  • 先找一个和你板子最接近的 defconfig 作为起点
  • 执行 make xxx_defconfig 加载
  • 再用 make menuconfig 微调
  • 最后 make savedefconfig 保存你自己的配置
小技巧: 如果你做产品,建议把最终调好的 defconfig 提交到 git 里。这样团队其他人拉下来直接 make 就能复现,省去沟通成本。

2.3.3 package/ —— 软件包的大本营

这是 Buildroot 里最大的目录,没有之一。每个软件包(busybox、openssl、dropbear、ffmpeg……)在这里都有一个子目录。

package/
├── busybox/
│   ├── Config.in
│   ├── busybox.mk
│   └── S01busybox
├── openssl/
│   ├── Config.in
│   ├── openssl.mk
│   └── ...
└── ...

每个软件包目录里通常包含三个核心文件:

文件 作用
Config.in 菜单配置项,决定这个包是否被选中、有哪些可选功能
<包名>.mk 构建规则,告诉 Buildroot 怎么下载、配置、编译、安装这个包
S<数字><服务名> 可选的启动脚本,放在 /etc/init.d/ 里

我记得刚开始看 busybox.mk 时,觉得变量名又多又乱。后来发现套路很固定:

# 典型的 .mk 文件结构
BUSYBOX_VERSION = 1.36.0
BUSYBOX_SOURCE = busybox-$(BUSYBOX_VERSION).tar.bz2
BUSYBOX_SITE = https://busybox.net/downloads
BUSYBOX_LICENSE = GPL-2.0

define BUSYBOX_BUILD_CMDS
    $(MAKE) -C $(@D) $(BUSYBOX_MAKE_FLAGS)
endef

define BUSYBOX_INSTALL_TARGET_CMDS
    $(MAKE) -C $(@D) install
endef

$(eval $(generic-package))

说白了,就是定义版本、下载地址、构建命令、安装命令,最后用 generic-package 或 autotools-package 等宏来注册。你如果想往系统里加一个自己的小程序,照着这个模板写一个 .mk 文件就行。

2.3.4 toolchain/ —— 工具链的配置中心

工具链是交叉编译的基础。这个目录里放的是工具链相关的配置逻辑和构建规则。

toolchain/
├── Config.in          # 工具链配置菜单
├── toolchain.mk       # 工具链构建规则
├── toolchain-external/ # 外部工具链支持
└── toolchain-buildroot/ # Buildroot 内部构建的工具链

在 make menuconfig 的 Toolchain 菜单里,你可以选择:

  • 使用外部工具链:比如 ARM 官方提供的 Linaro 工具链,或者芯片厂商提供的工具链
  • 让 Buildroot 自己构建:它会下载 gcc、binutils、glibc/musl 等源码,从头编译一套工具链
我的建议: 刚开始学习时,直接用 Buildroot 内部构建工具链,省事。做产品时,我倾向于使用芯片厂商提供的外部工具链,因为经过充分验证,稳定性更好。

2.4 知识体系结构图

下面这张图帮你把四个关键目录的关系理清楚:

Buildroot 关键目录协作关系 Buildroot 构建系统 board/ 板级配置、设备树、脚本 configs/ 默认配置 defconfig package/ 软件包构建规则 toolchain/ 工具链配置 💡 协作流程 1. 从 configs/ 加载 defconfig → 2. 根据配置从 package/ 拉取软件包 → 3. 使用 toolchain/ 指定的工具链编译 → 4. 结合 board/ 的板级文件生成最终镜像

2.5 动手实践:浏览你的 Buildroot 目录

光看不行,你得自己走一遍。我建议你按下面的步骤来:

  1. 打开终端,进入 Buildroot 源码目录
  2. 执行 ls -l 看看顶层结构
  3. 进入 board/,看看有哪些板子,挑一个你熟悉的进去看看
  4. 进入 configs/,找一个 defconfig 用 cat 查看内容
  5. 进入 package/,看看 busybox/ 目录里的三个文件
  6. 进入 toolchain/,看看 Config.in 里的选项
一个小练习: 执行 make raspberrypi3_defconfig,然后 make menuconfig,看看 Toolchain 菜单里当前选的是什么工具链。再退出,执行 cat .config | grep BR2_TOOLCHAIN,看看实际配置项是什么。这样你就能把菜单和配置文件对应起来了。