4. Busybox 源码获取与配置:从 git 仓库拉取源码、make menuconfig 图形化配置、保存与加载配置
这一章我们正式动手。源码获取和配置,是整个嵌入式系统构建的起点。说白了,你得先把 Busybox 请到你的开发机上,然后告诉它:你要编译哪些命令、用哪种 C 库、目标架构是什么。
我见过不少新手,直接从网上下载一个压缩包就开始编译。结果呢?编译出来的东西要么跑不起来,要么缺这缺那。嗯,这里面的坑,我当年都踩过。
4.1 从 Git 仓库拉取源码
我个人习惯用 Git 管理所有嵌入式项目的源码。Busybox 的官方仓库在 git.busybox.net,当然你也可以用 GitHub 上的镜像。
先看看怎么拉取稳定版本:
# 拉取最新稳定分支(推荐)
git clone git://git.busybox.net/busybox
cd busybox
git checkout 1_36_stable
# 或者拉取特定版本标签
git clone https://github.com/mirror/busybox.git
cd busybox
git checkout 1_36_1
为什么要用稳定分支?我在项目中遇到过,用 master 分支编译出来的 Busybox,在某个老款 ARM 板子上跑着跑着就 segfault 了。后来查了半天,发现是 master 分支里一个实验性的补丁没合好。从那以后,我坚持用 _stable 分支或打了 tag 的版本。
拉取完成后,看看目录结构:
busybox/
├── applets/ # 各个命令的入口
├── archival/ # 压缩/解压工具(tar、gzip 等)
├── coreutils/ # 核心工具(cat、cp、mv 等)
├── libbb/ # Busybox 自己的基础库
├── networking/ # 网络工具(ping、ifconfig 等)
├── shell/ # shell 实现(ash、hush)
├── util-linux/ # Linux 工具(mount、fdisk 等)
├── Config.in # 顶层配置菜单
├── Makefile # 主 Makefile
└── .config # 配置文件(编译后生成)
你想想看,这么多目录,每个目录下又有几十个源文件。如果不用配置工具,手动去改 Makefile 来开关功能,那得累死。所以,我们需要图形化配置。
4.2 make menuconfig 图形化配置
在源码根目录下,直接执行:
make menuconfig
前提是你的系统装了 ncurses-dev 或 libncurses5-dev。没装的话,Debian/Ubuntu 上跑:
sudo apt install libncurses5-dev
然后你会看到一个蓝底白字的菜单界面。这个界面和 Linux 内核的 menuconfig 长得一模一样。为什么?因为它们用的是同一套配置框架——Kconfig。
核心概念: Busybox 的配置系统基于 Kconfig。每个功能模块都有一个 Config.in 文件,里面定义了该模块的配置选项。menuconfig 读取这些文件,生成一个树形菜单。你选中的选项,最终会写入 .config 文件。
进入 menuconfig 后,你会看到类似这样的结构:
Busybox Configuration
├── General Configuration # 通用配置(路径、调试等)
├── Archival Utilities # 归档工具
├── Coreutils # 核心工具
├── Console Utilities # 控制台工具
├── Debian Utilities # Debian 兼容工具
├── Editors # 编辑器(vi、sed 等)
├── Finding Utilities # 查找工具(grep、find 等)
├── Init Utilities # 初始化工具(init、halt 等)
├── Login/Password Management # 登录管理
├── Linux Module Utilities # 模块工具
├── Linux System Utilities # 系统工具
├── Miscellaneous Utilities # 杂项工具
├── Networking Utilities # 网络工具
├── Print Utilities # 打印工具
├── Mail Utilities # 邮件工具
├── Process Utilities # 进程工具
├── Shells # Shell 选择
├── System Logging Utilities # 日志工具
└── ...
操作方式很简单:
- 方向键:上下移动光标
- Enter:进入子菜单
- Y:选中(编译进 Busybox)
- N:不选
- M:编译为模块(Busybox 里很少用)
- ?:查看帮助
- 空格:循环切换 Y/N/M
- Esc + Esc:返回上一级
我记得第一次用 menuconfig 时,觉得这界面太古老了。但用久了你会发现,它其实非常高效。尤其是做嵌入式,你需要在几十个选项里快速定位某个工具。按 / 键可以搜索,输入 ping 就能直接跳到 ping 的配置项。
make allnoconfig 然后手动选了几个,结果编译出来的 Busybox 有 2MB 多,在只有 4MB Flash 的板子上根本放不下。嵌入式系统,寸土寸金,只选你需要的。
4.3 保存与加载配置
配置完成后,按 Esc + Esc 退出,menuconfig 会问你是否保存。选 Yes,配置就写入了 .config 文件。
但这里有个问题:.config 是编译产物,一般不会提交到 Git 仓库。那你怎么在不同项目之间复用配置?
Busybox 提供了几个命令来管理配置:
| 命令 | 作用 | 我常用的场景 |
|---|---|---|
make defconfig |
生成默认配置(大部分功能开启) | 快速开始,然后手动裁剪 |
make allnoconfig |
生成最小配置(所有功能关闭) | 从零开始,只选需要的 |
make allyesconfig |
生成全功能配置 | 测试编译环境是否正常 |
make savedefconfig |
将当前配置精简为最小差异文件 | 保存到 Git,方便版本管理 |
make oldconfig |
基于现有 .config 更新配置 | 升级 Busybox 版本后使用 |
我个人最推荐的做法是:
# 1. 先做最小配置
make allnoconfig
# 2. 用 menuconfig 手动选你需要的工具
make menuconfig
# 3. 保存精简配置
make savedefconfig
# 4. 把 defconfig 文件提交到 Git
cp defconfig configs/my_project_defconfig
git add configs/my_project_defconfig
git commit -m "add my project defconfig"
为什么要用 savedefconfig?因为 .config 文件很大,里面有很多默认值。而 defconfig 只保存你修改过的选项,文件小、易读、易维护。你想想看,一个 2000 行的 .config 和一个 50 行的 defconfig,哪个更适合放在 Git 里?
加载配置也很简单:
# 加载你保存的精简配置
make my_project_defconfig
# 或者直接复制
cp configs/my_project_defconfig .config
make oldconfig
这里有个细节:make my_project_defconfig 会自动把 configs/my_project_defconfig 展开为完整的 .config。而 make oldconfig 会检查当前 .config 是否有缺失的选项(比如你升级了 Busybox 版本,新增了一些配置项),并提示你选择。
.config 编译,结果新版本里某个工具改了依赖关系,编译报错。后来我养成了习惯:每次升级版本后,先 make oldconfig,把新增的选项确认一遍。
4.4 知识体系总览
这一章的内容,说白了就是三个步骤:拉源码、配选项、存配置。但背后的逻辑,我画了一张图帮你理清:
这张图把整个流程串起来了。你从左边开始,拉取源码,然后选择一种基础配置模板(defconfig / allnoconfig / allyesconfig),再用 menuconfig 手动微调,最后保存为 .config 或精简的 defconfig。
我个人强烈建议走 allnoconfig + 手动选择 这条路。虽然一开始多花点时间,但你对最终镜像里包含了什么、没包含什么,心里一清二楚。做嵌入式,控制力就是生产力。