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)
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保存你自己的配置
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 等源码,从头编译一套工具链
2.4 知识体系结构图
下面这张图帮你把四个关键目录的关系理清楚:
2.5 动手实践:浏览你的 Buildroot 目录
光看不行,你得自己走一遍。我建议你按下面的步骤来:
- 打开终端,进入 Buildroot 源码目录
- 执行
ls -l看看顶层结构 - 进入
board/,看看有哪些板子,挑一个你熟悉的进去看看 - 进入
configs/,找一个 defconfig 用cat查看内容 - 进入
package/,看看busybox/目录里的三个文件 - 进入
toolchain/,看看Config.in里的选项
make raspberrypi3_defconfig,然后 make menuconfig,看看 Toolchain 菜单里当前选的是什么工具链。再退出,执行 cat .config | grep BR2_TOOLCHAIN,看看实际配置项是什么。这样你就能把菜单和配置文件对应起来了。