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

BusyBox 搭建 mini rootfs 完全指南 / 第 2 章:编译安装

第 2 章:编译安装

2.1 获取源码

2.1.1 官方下载

# 下载最新稳定版(以 1.36.1 为例)
$ wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2

# 解压
$ tar xjf busybox-1.36.1.tar.bz2
$ cd busybox-1.36.1

# 查看目录结构
$ ls
applets/   configs/   docs/     libbb/    scripts/  TODO
archival/  console/   editors/  libpwdgrp/  loginutils/  shell/    util-linux/
AUTHORS    coreutils/ examples/ Makefile     miscutils/   sysklogd
CHANGES    debianutils/ include/  Makefile.flags  networking/  testsuite/

2.1.2 Git 克隆

# 克隆仓库
$ git clone https://git.busybox.net/busybox
$ cd busybox

# 查看标签
$ git tag | grep "^[0-9]" | tail -10
1_35_0
1_36_0
1_36_1

# 切换到稳定版
$ git checkout 1_36_1

2.1.3 源码目录结构

busybox-1.36.1/
├── applets/           # Applet 注册和调度
│   ├── busybox.c      # 主入口
│   └── applet_tables.c
├── archival/          # 压缩归档工具(tar, gzip 等)
├── console-tools/     # 控制台工具
├── coreutils/         # 核心工具(ls, cat, cp 等)
├── debianutils/       # Debian 特有工具
├── docs/              # 文档
├── editors/           # 编辑器(vi, sed, awk 等)
├── e2fsprogs/         # ext2/3/4 工具
├── findutils/         # 查找工具(find, xargs 等)
├── include/           # 头文件
├── init/              # init 系统
├── libbb/             # 共享库函数
├── libpwdgrp/         # 用户/组相关库
├── loginutils/        # 登录相关工具
├── mailutils/         # 邮件工具
├── miscutils/         # 杂项工具
├── modutils/          # 内核模块工具
├── networking/        # 网络工具
├── printutils/        # 打印工具
├── procps/            # 进程工具(ps, top 等)
├── runit/             # runit 集成
├── selinux/           # SELinux 工具
├── shell/             # Shell(ash 等)
├── sysklogd/          # 系统日志
├── testsuite/         # 测试套件
├── util-linux/        # Linux 系统工具
├── Makefile           # 主 Makefile
├── Makefile.flags     # 编译标志
└── Config.in          # menuconfig 主配置

2.2 基本编译

2.2.1 最简编译流程

# 安装编译依赖(Ubuntu/Debian)
$ sudo apt install -y build-essential gcc make

# 清理(首次编译不需要)
$ make clean

# 使用默认配置
$ make defconfig

# 编译(使用所有 CPU 核心)
$ make -j$(nproc)

# 编译结果
$ ls -lh busybox
-rwxr-xr-x 1 user user 2.1M Jan 1 00:00 busybox

# 验证
$ ./busybox --help
BusyBox v1.36.1 (...) multi-call binary.

2.2.2 编译选项详解

# make 常用目标
$ make help              # 查看所有 make 目标
$ make defconfig         # 默认配置
$ make allnoconfig       # 全部禁用(最精简)
$ make allyesconfig      # 全部启用
$ make randconfig        # 随机配置(测试用)
$ make oldconfig         # 基于旧 .config 更新
$ make menuconfig        # 交互式配置界面
$ make silentoldconfig   # 静默更新配置

# 环境变量
$ make CC=gcc            # 指定编译器
$ make CROSS_COMPILE=arm-linux-gnueabihf-  # 交叉编译前缀
$ make EXTRA_CFLAGS="-O2 -g"  # 额外编译标志

2.2.3 安装到系统

# 安装到指定目录
$ make CONFIG_PREFIX=./_install install

# 查看安装结果
$ ls -la _install/
total 12
drwxr-xr-x 4 user user 4096 Jan  1 00:00 .
drwxr-xr-x 6 user user 4096 Jan  1 00:00 ..
drwxr-xr-x 2 user user 4096 Jan  1 00:00 bin
lrwxrwxrwx 1 user user   11 Jan  1 00:00 linuxrc -> bin/busybox
drwxr-xr-x 2 user user 4096 Jan  1 00:00 sbin
drwxr-xr-x 4 user user 4096 Jan  1 00:00 usr

$ ls _install/bin/ | head -10
addgroup    cat        dnsdomainname  fgrep      kill     mount    sh
adduser     chattr     echo           find       link     mountpoint  sleep
ash         chgrp      ed             fsync      linuxrc  mv       stty
busybox     chmod      egrep          grep       ln       netstat  ...

2.3 静态编译

静态编译是构建 mini rootfs 的关键步骤,它将所有依赖库编译进单一二进制文件。

2.3.1 为什么需要静态编译

对比项动态链接静态链接
二进制大小较小(需动态库)较大(包含库代码)
依赖需要 glibc/musl无外部依赖
部署需复制 .so 文件单一文件即可运行
启动速度需加载动态库直接执行
安全性可替换系统库独立,无法篡改库

2.3.2 使用 glibc 静态编译

# 启用静态编译
$ make menuconfig
# 进入 Settings → Build Options → [*] Build BusyBox as a static binary (no shared libs)

# 或直接修改 .config
$ sed -i 's/# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .config

# 编译
$ make -j$(nproc)

# 验证静态链接
$ file busybox
busybox: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, ...

$ ldd busybox
    not a dynamic executable

2.3.3 使用 musl 静态编译(推荐)

musl libc 是专为静态链接设计的轻量级 C 库,生成的二进制更小:

# 安装 musl 工具链
$ sudo apt install -y musl-tools

# 使用 musl 编译器
$ make clean
$ make CC=musl-gcc CONFIG_PREFIX=./_install_static -j$(nproc)

# 或在 menuconfig 中设置
# Settings → Build Options → (musl-gcc) Path to musl-gcc

# 验证
$ ls -lh busybox
-rwxr-xr-x 1 user user 960K Jan  1 00:00 busybox    # 通常比 glibc 版本小 30-50%

$ file busybox
busybox: ELF 64-bit LSB executable, statically linked, with debug_info, stripped

2.3.4 体积优化编译

# 编译优化选项
$ make menuconfig

在 menuconfig 中启用以下选项:

Settings --->
  Build Options --->
    [*] Build BusyBox as a static binary (no shared libs)
    [*] Strip binary (减少二进制大小)
    (-Os) CFLAGS (优化级别,-Os 为体积优化)
    [*] Use -fwhole-program (进一步优化)
# 编译并 strip
$ make -j$(nproc)
$ strip busybox
$ ls -lh busybox
-rwxr-xr-x 1 user user 847K Jan  1 00:00 busybox

2.3.5 大小对比

配置大小(x86_64)
glibc 动态链接~700KB(不含 .so)
glibc 静态链接~2.1MB
musl 静态链接~960KB
musl 静态 + strip~847KB
musl 静态 + strip + -Os~780KB
所有 Applet 启用~3.5MB
最小 Applet 集~200KB

2.4 交叉编译

交叉编译用于为目标架构(如 ARM、MIPS)生成二进制,是嵌入式开发的必备技能。

2.4.1 ARM 交叉编译

# 安装 ARM 交叉编译工具链
$ sudo apt install -y gcc-arm-linux-gnueabihf

# 验证工具链
$ arm-linux-gnueabihf-gcc --version
arm-linux-gnueabihf-gcc (Ubuntu ...) 11.4.0

# 清理并配置
$ make clean
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- defconfig

# 启用静态编译
$ sed -i 's/# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .config

# 编译
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j$(nproc)

# 验证
$ file busybox
busybox: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, ...

# 使用 QEMU 测试
$ sudo apt install -y qemu-user-static
$ qemu-arm-static ./busybox --help

2.4.2 AArch64 交叉编译

# 安装工具链
$ sudo apt install -y gcc-aarch64-linux-gnu

# 编译
$ make clean
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig
$ sed -i 's/# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .config
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc)

# 验证
$ file busybox
busybox: ELF 64-bit LSB executable, ARM aarch64, ...

# QEMU 测试
$ qemu-aarch64-static ./busybox --help

2.4.3 MIPS 交叉编译

# 安装工具链
$ sudo apt install -y gcc-mips-linux-gnu

# 编译(大端)
$ make clean
$ make ARCH=mips CROSS_COMPILE=mips-linux-gnu- defconfig
$ sed -i 's/# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .config
$ make ARCH=mips CROSS_COMPILE=mips-linux-gnu- -j$(nproc)

# 小端 MIPS
$ make ARCH=mipsel CROSS_COMPILE=mipsel-linux-gnu- defconfig
$ make ARCH=mipsel CROSS_COMPILE=mipsel-linux-gnu- -j$(nproc)

2.4.4 RISC-V 交叉编译

# 安装工具链
$ sudo apt install -y gcc-riscv64-linux-gnu

# 编译
$ make clean
$ make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- defconfig
$ sed -i 's/# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .config
$ make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- -j$(nproc)

# QEMU 测试
$ qemu-riscv64-static ./busybox --help

2.4.5 交叉编译配置表

目标架构ARCH 值CROSS_COMPILE 前缀QEMU
ARM 32-bitarmarm-linux-gnueabihf-qemu-arm-static
ARM 64-bit (AArch64)arm64aarch64-linux-gnu-qemu-aarch64-static
MIPS 大端mipsmips-linux-gnu-qemu-mips-static
MIPS 小端mipselmipsel-linux-gnu-qemu-mipsel-static
RISC-V 64riscvriscv64-linux-gnu-qemu-riscv64-static
x86i386i686-linux-gnu-qemu-i386-static
PowerPCpowerpcpowerpc-linux-gnu-qemu-ppc-static

2.5 menuconfig 配置详解

2.5.1 启动配置界面

$ make menuconfig

界面操作:

  • 上下箭头: 移动光标
  • 回车/空格: 进入子菜单/切换选项
  • Y: 启用选项
  • N: 禁用选项
  • M: 编译为模块(BusyBox 不常用)
  • ?: 帮助信息
  • **/****: 搜索
  • Esc: 返回上级

2.5.2 关键配置项

Settings(全局设置)

Settings --->
  --- Build Options
  [*] Build BusyBox as a static binary (no shared libs)   # 静态编译
  [*] Build with Large File Support (for accessing files > 2 GB)
  ()  Cross Compiler prefix                                # 交叉编译前缀
  (-Os) Additional CFLAGS                                  # 编译优化
  [*] Produce a binary suitable for debugger
  --- Installation Options
  (/usr) BusyBox installation prefix                       # 安装前缀

Archival Utilities(归档工具)

Archival Utilities --->
  [*] ar
  [*] bzip2
  [*] cpio
  [*] dpkg
  [*] gzip
  [*] tar
      [*] Enable long options (tar)
      [*] Support extraction from bzip2 compressed archives
      [*] Support extraction from xz compressed archives
  [*] unzip
  [*] xz

Coreutils(核心工具)

Coreutils --->
  [*] cat
  [*] chgrp
  [*] chmod
  [*] chown
  [*] cp
  [*] cut
  [*] date
  [*] dd
  [*] df
  [*] echo
  [*] head
  [*] ln
  [*] ls
  [*] md5sum
  [*] mkdir
  [*] mv
  [*] pwd
  [*] rm
  [*] sort
  [*] tail
  [*] touch
  [*] wc

Networking Utilities(网络工具)

Networking Utilities --->
  [*] ifconfig
  [*] ip
  [*] nc
  [*] netstat
  [*] nslookup
  [*] ping
  [*] route
  [*] wget
  [*] udhcpc (DHCP client)
  [*] ntpd
  [*] telnet
  [*] telnetd
  [*] tftp

Shells(Shell 配置)

Shells --->
  [*] ash
      [*] ash built-in commands
      [*]   Enable job control
      [*]   Alias support
      [*]   Standalone shell (reads busybox.conf)
  [*] hush
  [*] msh (deprecated)

Init Utilities(初始化)

Linux Init Utilities --->
  [*] init
      [*] Support reading an inittab file
      [*] Support running init from within an initrd/initramfs
  [*] poweroff
  [*] reboot
  [*] halt

2.5.3 搜索配置项

在 menuconfig 界面按 / 键可以搜索:

Search (CONFIG_...): grep
  Symbol: FGREP [n]
  Prompt: fgrep
    Defined at coreutils/Config.in:19
    Depends on: FEATURE_FANCY_GREP [=y]
    Location:
      -> Coreutils
        -> grep
  Symbol: GREP [y]
  Prompt: grep
    Defined at findutils/Config.in:6
    Location:
      -> File/Console Utilities

2.5.4 预定义配置

BusyBox 提供多个预定义配置文件:

# 查看可用配置
$ ls configs/
2net_defconfig        minimal_defconfig      ...
android_defconfig     musl_defconfig
...

# 使用特定配置
$ cp configs/minimal_defconfig .config
$ make oldconfig    # 应用并更新
$ make -j$(nproc)

2.6 编译问题排查

2.6.1 常见编译错误

# 错误:缺少头文件
fatal error: ncurses.h: No such file or directory
# 解决:
$ sudo apt install -y libncurses5-dev libncursesw5-dev

# 错误:缺少库
/usr/bin/ld: cannot find -lc
# 解决(静态编译时):
$ sudo apt install -y libc6-dev

# 错误:交叉编译找不到工具链
/bin/sh: 1: arm-linux-gnueabihf-gcc: not found
# 解决:
$ sudo apt install -y gcc-arm-linux-gnueabihf

2.6.2 调试编译问题

# 显示详细编译命令
$ make V=1

# 查看依赖关系
$ make V=2

# 只编译特定目标
$ make applets/busybox.o

# 查看编译标志
$ make show-targets

2.6.3 清理编译产物

# 清理编译产物(保留 .config)
$ make clean

# 完全清理(包括 .config)
$ make distclean

# 清理安装目录
$ rm -rf _install

2.7 自动化编译脚本

#!/bin/bash
# build_busybox.sh - BusyBox 自动化编译脚本

set -e

BUSYBOX_VERSION="1.36.1"
INSTALL_DIR="$(pwd)/_install"
ARCH="${1:-x86_64}"

# 配置架构和工具链
case "$ARCH" in
    x86_64)
        CROSS_COMPILE=""
        KARCH=""
        ;;
    arm)
        CROSS_COMPILE="arm-linux-gnueabihf-"
        KARCH="arm"
        ;;
    aarch64)
        CROSS_COMPILE="aarch64-linux-gnu-"
        KARCH="arm64"
        ;;
    *)
        echo "Unsupported architecture: $ARCH"
        exit 1
        ;;
esac

# 下载源码
if [ ! -d "busybox-${BUSYBOX_VERSION}" ]; then
    wget "https://busybox.net/downloads/busybox-${BUSYBOX_VERSION}.tar.bz2"
    tar xjf "busybox-${BUSYBOX_VERSION}.tar.bz2"
fi

cd "busybox-${BUSYBOX_VERSION}"

# 配置
make clean || true
make ARCH=$KARCH CROSS_COMPILE=$CROSS_COMPILE defconfig

# 启用静态编译
sed -i 's/# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .config
sed -i 's/CONFIG_TC=y/# CONFIG_TC is not set/' .config

# 编译
make ARCH=$KARCH CROSS_COMPILE=$CROSS_COMPILE -j$(nproc)

# 安装
rm -rf "$INSTALL_DIR"
make ARCH=$KARCH CROSS_COMPILE=$CROSS_COMPILE \
    CONFIG_PREFIX="$INSTALL_DIR" install

# 统计
echo "Build complete!"
echo "Binary size: $(ls -lh busybox | awk '{print $5}')"
echo "Install dir: $INSTALL_DIR"
echo "Installed symlinks: $(find $INSTALL_DIR -type l | wc -l)"

2.8 本章小结

步骤命令说明
下载源码wget && tar从官网下载并解压
默认配置make defconfig使用默认配置
自定义配置make menuconfig交互式配置界面
启用静态编译设置 CONFIG_STATIC=y无需外部依赖库
编译make -j$(nproc)并行编译
安装make CONFIG_PREFIX=./_install install安装到指定目录
交叉编译设置 CROSS_COMPILE=为目标架构编译

扩展阅读


上一章: 第 1 章 — BusyBox 概述
下一章: 第 3 章 — 基本用法