BusyBox 搭建 mini rootfs 完全指南 / 第 10 章:Buildroot 集成
第 10 章:Buildroot 集成
10.1 Buildroot 概述
10.1.1 什么是 Buildroot
Buildroot 是一个简化嵌入式 Linux 系统构建的工具,它使用交叉编译工具链自动构建完整的根文件系统,包括内核、bootloader、BusyBox 和应用程序。
Buildroot 构建流程
┌─────────────────┐
│ Buildroot │
│ 配置系统 │
│ (.config) │
└──────┬──────────┘
│
├──→ 交叉编译工具链
│ (gcc, glibc/musl, binutils)
│
├──→ 内核 (linux)
│
├──→ Bootloader (U-Boot / Barebox)
│
├──→ BusyBox
│
├──→ 系统工具包
│ (dropbear, iptables, etc.)
│
└──→ rootfs 镜像
(ext4, squashfs, cpio, tar)
10.1.2 Buildroot vs Yocto
| 特性 | Buildroot | Yocto |
|---|
| 复杂度 | 低 | 高 |
| 学习曲线 | 平缓 | 陡峭 |
| 构建速度 | 快 | 慢 |
| 包管理 | 简单 | 复杂 |
| 适用场景 | 小型系统 | 大型系统 |
| 文件系统 | BusyBox | BusyBox / systemd |
| 配置系统 | Kconfig (menuconfig) | BitBake |
| 典型用途 | 路由器、IoT | 手机、汽车、机顶盒 |
10.2 安装 Buildroot
# 安装依赖
$ sudo apt install -y build-essential gcc g++ \
libncurses-dev git wget cpio python3 unzip \
bc rsync file
# 克隆 Buildroot
$ git clone https://github.com/buildroot/buildroot.git
$ cd buildroot
# 查看最新稳定版标签
$ git tag | grep "^[0-9]" | tail -5
2024.02
2024.02.1
2024.05
# 切换到稳定版
$ git checkout 2024.05
# 查看目录结构
$ ls
arch/ boot/ CHANGES configs/ docs/
fs/ linux/ Makefile package/ support/
board/ DEVELOPERS COPYING dl/ system/
toolchain/
10.3 基本配置
# 打开配置界面
$ make menuconfig
10.3.2 关键配置项
Target Architecture(目标架构)
Target options --->
Target Architecture (ARM (little endian)) --->
Target Binary Format (ELF) --->
Target Architecture Variant (cortex-A7) --->
Target ABI (EABIhf) --->
Floating point strategy (VFPv4) --->
常见架构配置:
| 目标平台 | Target Architecture | Variant |
|---|
| Raspberry Pi 2/3 | ARM (little endian) | cortex-a7 / cortex-a53 |
| Raspberry Pi 4 | ARM (little endian) | cortex-a72 |
| BeagleBone | ARM (little endian) | cortex-a8 |
| x86 PC | x86_64 | (Generic) |
| MIPS 路由器 | MIPS (big endian) | 24Kc |
Toolchain --->
Toolchain type (Buildroot toolchain) --->
C library (musl) --->
[*] Enable C++ support
[*] Enable MMU support
Kernel Headers (Linux 5.15.x) --->
Binutils Version (2.40) --->
GCC compiler Version (gcc 13.x) --->
| 选项 | 推荐 | 说明 |
|---|
| C library | musl | 体积小,静态链接友好 |
| C library | glibc | 功能完整,兼容性好 |
| C library | uClibc-ng | 最小,嵌入式专用 |
System Configuration(系统配置)
System configuration --->
(miniroot) System hostname
(Welcome to miniroot) System banner
Root password (root)
Init system (BusyBox) --->
/dev management (Dynamic using devtmpfs + mdev) --->
(serial console) Run a getty (login prompt) after boot --->
Filesystem Images(文件系统镜像)
Filesystem images --->
[*] ext2/3/4 root filesystem
ext2/3/4 variant (ext4) --->
[*] tar the root filesystem
[*] cpio the root filesystem (for use as an initial RAM filesystem)
[*] squashfs root filesystem
Target Packages(目标包)
Target packages --->
--- Audio and video applications
--- Compressors and decompressors
--- Debugging, profiling and benchmark
--- Development tools
--- Filesystem and flash utilities
--- Fonts, themes, skins
--- Games
--- Graphic libraries and applications
--- Hardware handling
--- Interpreter languages and scripting
--- Libraries
--- Mail
--- Miscellaneous
--- Networking applications
[*] bind (ISC utilities only)
[*] bridge-utils
[*] curl
[*] dhcpcd
[*] dnsmasq
[*] dropbear (SSH server)
[*] iptables
[*] lighttpd
[*] nginx
[*] openssh
[*] wget
--- Package managers
--- Real-Time
--- Security
--- Shell and utilities
--- System tools
--- Text editors and viewers
10.3.3 使用预定义配置
# 查看预定义配置
$ ls configs/
am335x_boneblack_defconfig
qemu_arm_vexpress_defconfig
qemu_x86_64_defconfig
raspberrypi3_defconfig
raspberrypi4_defconfig
...
# 使用 QEMU x86_64 配置
$ make qemu_x86_64_defconfig
# 自定义配置
$ make menuconfig
# 保存配置
$ make savedefconfig BR2_DEFCONFIG=configs/myboard_defconfig
10.4 构建系统
10.4.1 完整构建
# 完整构建(首次需要较长时间)
$ make
# 构建输出位置
$ ls output/images/
rootfs.ext4
rootfs.tar
rootfs.cpio.gz
rootfs.squashfs
bzImage # x86 内核
zImage # ARM 内核
10.4.2 分步构建
# 构建工具链
$ make toolchain
# 构建内核
$ make linux
# 构建 BusyBox
$ make busybox
# 构建 rootfs
$ make rootfs
# 构建特定包
$ make dropbear
$ make nginx
10.4.3 清理
# 清理特定包
$ make busybox-dirclean
$ make linux-dirclean
# 清理所有包(保留工具链)
$ make clean
# 完全清理(包括工具链)
$ make distclean
10.5 QEMU 测试
10.5.1 x86_64 测试
# 构建 x86_64 镜像
$ make qemu_x86_64_defconfig
$ make
# 使用 QEMU 启动
$ qemu-system-x86_64 \
-kernel output/images/bzImage \
-drive file=output/images/rootfs.ext4,format=raw \
-append "root=/dev/sda console=ttyS0" \
-nographic \
-m 512M
# 使用 cpio 方式启动
$ qemu-system-x86_64 \
-kernel output/images/bzImage \
-initrd output/images/rootfs.cpio.gz \
-append "console=ttyS0" \
-nographic \
-m 512M
10.5.2 ARM 测试
# 构建 ARM 镜像
$ make qemu_arm_vexpress_defconfig
$ make
# 使用 QEMU 启动
$ qemu-system-arm \
-M vexpress-a9 \
-kernel output/images/zImage \
-dtb output/images/vexpress-v2p-ca9.dtb \
-drive file=output/images/rootfs.ext4,if=sd \
-append "root=/dev/mmcblk0 console=ttyAMA0" \
-nographic \
-m 256M
10.6 自定义 BusyBox 配置
# 配置 BusyBox
$ make busybox-menuconfig
# 修改 BusyBox 源码(不推荐,但有时需要)
$ make busybox-extract
$ vi output/build/busybox-1.36.1/shell/ash.c
$ make busybox
# 自定义 BusyBox 配置文件
# 将配置文件放在 package/busybox/busybox.config
$ cp my_busybox.config package/busybox/busybox.config
10.7 添加自定义包
10.7.1 包目录结构
package/myapp/
├── Config.in # Kconfig 配置
├── myapp.mk # 构建脚本
└── myapp.hash # 源码校验(可选)
10.7.2 Config.in 示例
config BR2_PACKAGE_MYAPP
bool "myapp"
depends on BR2_TOOLCHAIN_HAS_THREADS
select BR2_PACKAGE_LIBFOO
help
My custom application for the embedded device.
https://example.com/myapp
comment "myapp needs a toolchain with threads"
depends on !BR2_TOOLCHAIN_HAS_THREADS
10.7.3 包构建脚本(myapp.mk)
################################################################################
#
# myapp
#
################################################################################
MYAPP_VERSION = 1.0.0
MYAPP_SITE = https://example.com/releases
MYAPP_SOURCE = myapp-$(MYAPP_VERSION).tar.gz
MYAPP_LICENSE = MIT
MYAPP_LICENSE_FILES = LICENSE
# 依赖
MYAPP_DEPENDENCIES = libfoo zlib
# 使用 cmake 构建
MYAPP_SUPPORTS_IN_SOURCE_BUILD = NO
# 自定义配置选项
MYAPP_CONF_OPTS = \
-DENABLE_FEATURE=ON \
-DWITH_SSL=ON
# 安装目标文件
define MYAPP_INSTALL_TARGET_CMDS
$(INSTALL) -D -m 0755 $(@D)/build/myapp $(TARGET_DIR)/usr/bin/myapp
$(INSTALL) -D -m 0644 $(@D)/myapp.conf $(TARGET_DIR)/etc/myapp.conf
endef
# 初始化脚本
define MYAPP_INSTALL_INIT_SYSV
$(INSTALL) -D -m 0755 $(MYAPP_PKGDIR)/S99myapp \
$(TARGET_DIR)/etc/init.d/S99myapp
endef
$(eval $(cmake-package))
# 或 $(eval $(autotools-package))
# 或 $(eval $(generic-package))
10.7.4 初始化脚本
#!/bin/sh
# package/myapp/S99myapp
DAEMON="/usr/bin/myapp"
PIDFILE="/var/run/myapp.pid"
case "$1" in
start)
echo "Starting myapp..."
start-stop-daemon -S -b -m -p "$PIDFILE" -x "$DAEMON"
;;
stop)
echo "Stopping myapp..."
start-stop-daemon -K -p "$PIDFILE"
;;
restart)
"$0" stop
sleep 1
"$0" start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac
exit 0
10.7.5 注册包
# package/Config.in 中添加
menu "My custom packages"
source "package/myapp/Config.in"
endmenu
10.8 Board Support
10.8.1 Board 目录结构
board/mycompany/myboard/
├── genimage.cfg # 镜像生成配置
├── post-build.sh # 构建后脚本
├── post-image.sh # 镜像后脚本
├── rootfs_overlay/ # rootfs 覆盖文件
│ ├── etc/
│ │ ├── network/
│ │ │ └── interfaces
│ │ └── fstab
│ └── usr/
│ └── bin/
│ └── myapp
└── linux.config # 内核配置(可选)
10.8.2 rootfs_overlay
# board/mycompany/myboard/rootfs_overlay/etc/network/interfaces
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
address 192.168.1.100
netmask 255.255.255.0
gateway 192.168.1.1
# board/mycompany/myboard/rootfs_overlay/etc/fstab
# <file system> <mount point> <type> <options> <dump> <pass>
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
/dev/mmcblk0p2 / ext4 ro,noatime 0 1
10.8.3 配置使用 board
System configuration --->
(board/mycompany/myboard/rootfs_overlay) Root filesystem overlay directories
(board/mycompany/myboard/post-build.sh) Custom scripts to run before creating filesystem images
(board/mycompany/myboard/post-image.sh) Custom scripts to run after creating images
10.9 交叉编译外部程序
# 使用 Buildroot 工具链编译外部程序
$ export PATH=$(pwd)/output/host/bin:$PATH
$ export CROSS_COMPILE=aarch64-linux-
$ export CC=${CROSS_COMPILE}gcc
$ export CXX=${CROSS_COMPILE}g++
# 编译程序
$ $CC -o myapp myapp.c -static
# 验证
$ file myapp
myapp: ELF 64-bit LSB executable, ARM aarch64, statically linked
10.10 构建产物
$ ls -lh output/images/
-rw-r--r-- 1 user user 50M rootfs.ext4
-rw-r--r-- 1 user user 12M rootfs.tar
-rw-r--r-- 1 user user 8.5M rootfs.cpio.gz
-rw-r--r-- 1 user user 6.2M rootfs.squashfs
-rw-r--r-- 1 user user 12M zImage
-rw-r--r-- 1 user user 50M sdcard.img # 可能由 post-image.sh 生成
# 目录结构
$ ls output/target/
bin/ dev/ etc/ lib/ linuxrc media/ mnt/ opt/
proc/ root/ run/ sbin/ sys/ tmp/ usr/ var/
10.11 最佳实践
10.11.1 版本控制
# 保存完整配置
$ make savedefconfig
$ cp defconfig configs/myproject_defconfig
# 提交到 Git
$ git add configs/myproject_defconfig
$ git commit -m "Add my project defconfig"
10.11.2 增量开发流程
# 1. 初始配置
$ make menuconfig
$ make savedefconfig
# 2. 构建
$ make
# 3. 测试(QEMU)
$ qemu-system-x86_64 ...
# 4. 修改配置或添加包
$ make menuconfig
# 5. 增量构建
$ make
# 6. 重新测试
10.12 本章小结
| 概念 | 说明 |
|---|
| Buildroot | 嵌入式 Linux 构建系统 |
| menuconfig | Kconfig 配置界面 |
| rootfs_overlay | 覆盖 rootfs 的文件 |
| 交叉编译 | 在 x86 上构建 ARM 二进制 |
| QEMU | 系统仿真测试工具 |
| 预定义配置 | make xxx_defconfig |
扩展阅读
上一章: 第 9 章 — 系统工具
下一章: 第 11 章 — Docker 中使用