强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

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

特性BuildrootYocto
复杂度
学习曲线平缓陡峭
构建速度
包管理简单复杂
适用场景小型系统大型系统
文件系统BusyBoxBusyBox / 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 基本配置

10.3.1 启动 menuconfig

# 打开配置界面
$ 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 ArchitectureVariant
Raspberry Pi 2/3ARM (little endian)cortex-a7 / cortex-a53
Raspberry Pi 4ARM (little endian)cortex-a72
BeagleBoneARM (little endian)cortex-a8
x86 PCx86_64(Generic)
MIPS 路由器MIPS (big endian)24Kc

Toolchain(工具链)

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 librarymusl体积小,静态链接友好
C libraryglibc功能完整,兼容性好
C libraryuClibc-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 构建系统
menuconfigKconfig 配置界面
rootfs_overlay覆盖 rootfs 的文件
交叉编译在 x86 上构建 ARM 二进制
QEMU系统仿真测试工具
预定义配置make xxx_defconfig

扩展阅读


上一章: 第 9 章 — 系统工具
下一章: 第 11 章 — Docker 中使用