4. 配置系统入门
Buildroot 的构建结果几乎完全由配置决定:选择哪个架构、用哪套工具链、编哪些包、生成什么格式的根文件系统,全部记录在配置里。理解配置系统,是掌握 Buildroot 的第一道门槛。本节围绕四个问题展开:用什么界面改配置、如何用 defconfig 固化配置、配置项分成哪几类、配置如何保存与加载。
一、核心原理:Kconfig 与 .config
Buildroot 的配置系统沿用 Linux 内核的 Kconfig 机制。源码树中散布着大量 Config.in 文件,它们用 Kconfig 语法声明配置项:名称、类型(bool、string、int、choice)、默认值、依赖 depends on、反向依赖 select、提示文字与帮助信息。配置工具读取这些声明,生成一个可交互的界面,最终把用户的选择写成一个纯文本文件 .config。
关键点在于:.config 是配置的“唯一事实来源”。构建时,Buildroot 读取 .config,再结合各包的 .mk 文件决定编译行为。因此,只要保存了 .config,就保存了整个构建的“配方”。
二、make menuconfig:交互式配置入口
最常用的配置命令是:
cd buildroot
make menuconfig
它基于 ncurses 提供终端菜单界面,操作方式与内核 menuconfig 一致:方向键移动,Enter 进入子菜单或切换选项,Y 选中、N 取消、M 在 Buildroot 中通常不适用(Buildroot 不做模块化),/ 搜索配置项,? 查看帮助,Esc Esc 返回,退出时提示保存。
除 menuconfig 外,还有几个入口值得知道:
make nconfig:更现代的界面,支持鼠标与更好的搜索。make xconfig:图形界面,需要 Qt 环境。make gconfig:GTK 图形界面。make oldconfig:不交互,用现有.config补齐新增项,适合升级 Buildroot 版本后使用。make olddefconfig:新增项一律取默认值,自动化场景常用。
搜索功能非常实用。例如不确定串口控制台配置在哪,可在 menuconfig 中按 / 输入 BR2_TARGET_GENERIC_GETTY_PORT,界面会显示它的路径、当前值和依赖关系。
三、defconfig:把配置固化成文件
手工在 menuconfig 里点选的结果只存在于本地 .config,无法直接进版本库、也无法复现。Buildroot 的解法是 defconfig:一个精简的、只记录“非默认值”的配置文件,通常放在 configs/ 目录下,命名形如 xxx_defconfig。
使用方式:
# 加载已有 defconfig 生成 .config
make qemu_aarch64_virt_defconfig
# 基于当前 .config 反向生成精简 defconfig
make savedefconfig
# 结果在 buildroot/defconfig,可复制到 configs/ 下管理
savedefconfig 会剔除所有等于默认值的项,只保留真正被改动的配置,因此文件短、可读、diff 友好。这正是 Buildroot 官方维护上百个开发板配置的方式。
make <board>_defconfig → make menuconfig 微调 → make savedefconfig → 把 defconfig 提交到自己的仓库。这样任何同事一条命令即可复现你的配置。
四、配置项分类
menuconfig 顶层菜单本身就是一份分类地图。理解分类有助于快速定位配置项。
| 顶层菜单 | 作用 | 典型配置项 |
|---|---|---|
| Target options | 目标架构与 ABI | BR2_arm、BR2_aarch64、BR2_ARM_EABIHF |
| Build options | 构建行为与下载 | BR2_DL_DIR、BR2_JLEVEL、BR2_PRIMARY_SITE |
| Toolchain | 工具链来源与 C 库 | BR2_TOOLCHAIN_BUILDROOT、BR2_TOOLCHAIN_EXTERNAL、BR2_TOOLCHAIN_BUILDROOT_GLIBC |
| System configuration | 主机名、登录、设备节点 | BR2_TARGET_GENERIC_HOSTNAME、BR2_TARGET_GENERIC_GETTY_PORT、BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_DEVTMPFS |
| Kernel | 内核版本与配置 | BR2_LINUX_KERNEL、BR2_LINUX_KERNEL_DEFCONFIG、BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE |
| Target packages | 用户空间软件包 | BR2_PACKAGE_BUSYBOX、BR2_PACKAGE_OPENSSH、BR2_PACKAGE_PYTHON3 |
| Filesystem images | 根文件系统格式 | BR2_TARGET_ROOTFS_EXT2、BR2_TARGET_ROOTFS_SQUASHFS、BR2_TARGET_ROOTFS_UBIFS |
| Bootloaders | 引导程序 | BR2_TARGET_UBOOT、BR2_TARGET_UBOOT_BOARD_DEFCONFIG |
| Host utilities | 宿主机工具 | BR2_PACKAGE_HOST_GENIMAGE、BR2_PACKAGE_HOST_DOSFSTOOLS |
| Legacy config options | 已废弃项 | 仅用于兼容旧配置 |
从依赖角度看,配置项还可分为三类:独立项(如主机名,随时可改)、依赖项(如某包依赖 BR2_TOOLCHAIN_HAS_THREADS,不满足则不可见)、被选中项(由 select 自动打开,如选 Python3 会自动带上若干库)。当某个选项“找不到”时,多半是依赖未满足,用 / 搜索即可看到它被谁依赖。
五、保存与加载配置
配置的保存与加载围绕 .config 与 defconfig 两个文件展开:
- 保存:menuconfig 退出时写入
.config;make savedefconfig生成精简版defconfig。 - 加载:
make <name>_defconfig从configs/<name>_defconfig生成.config;也可用make BR2_DEFCONFIG=path/to/my_defconfig defconfig指定任意路径。 - 备份:直接复制
.config或 defconfig 到仓库;.config完整但冗长,defconfig 精简但依赖默认值。 - 复用:把 defconfig 放入
configs/,即可像官方板级配置一样用make xxx_defconfig调用。
.config 而不备份 defconfig,升级 Buildroot 后旧 .config 可能因选项改名而失效;反之只备份 defconfig,若默认值随版本变化,重建结果可能与当初不一致。量产项目建议两者都归档,并记录 Buildroot 版本号。
六、案例与复盘
场景:为一块 AArch64 开发板定制镜像,要求串口控制台为 ttyS0、主机名 prod-board、包含 openssh、根文件系统为 ext2。
make qemu_aarch64_virt_defconfig
make menuconfig
# System configuration -> hostname = prod-board
# System configuration -> getty port = ttyS0
# Target packages -> Networking -> openssh
# Filesystem images -> ext2/3/4 root filesystem
make savedefconfig
cp defconfig configs/prod_board_defconfig
make prod_board_defconfig # 验证可复现
复盘要点:一是先选一个最接近的官方 defconfig 作为起点,比从零配置快得多;二是每次改完都跑一次 savedefconfig,避免 .config 与 defconfig 长期脱节;三是遇到选项灰显或消失,先用 / 搜索确认依赖,而不是反复翻菜单。