3、基础配置:make menuconfig 入门

Buildroot 的配置,说白了就是通过一个菜单界面,告诉系统你要给谁编译、用什么工具链、最终生成什么。这个菜单界面就是 make menuconfig。我第一次用的时候也觉得不就是个配置界面嘛,但后来发现,这里面的门道,直接决定了你根文件系统能不能跑起来。

核心思路:配置的本质是定义「目标平台 + 构建策略 + 工具链来源」。这三者定下来,剩下的就是选包。

3.1 make menuconfig 操作与结构

在 Buildroot 根目录下执行:

$ make menuconfig

你会看到一个基于 kconfig 的蓝白界面。上下键移动,回车进入子菜单,空格或 Y 键选中,N 键排除,M 键编译为模块(如果支持)。

我个人习惯先按 / 键搜索某个配置项,比如搜 busybox,能直接定位到它在哪个菜单下。这个功能在包多的时候特别有用。

小技巧:按 Z 键可以显示所有隐藏选项(那些被依赖关系隐藏的)。调试时经常用到。

整个配置界面分为几个顶层菜单:

  • Target options — 目标架构、CPU、浮点等
  • Build options — 编译目录、下载缓存、并行数等
  • Toolchain — 工具链类型、C库、内核头文件等
  • System configuration — 主机名、密码、初始化系统等
  • Kernel — Linux 内核配置
  • Target packages — 你要装进根文件系统的所有软件包
  • Filesystem images — 最终输出什么格式(ext4、squashfs、tar 等)

嗯,这里要注意:Target options 和 Toolchain 是基础中的基础。这两项配错了,后面全白搭。

3.2 Target options 配置

这个菜单决定了你的根文件系统跑在什么硬件上。我见过有人拿 ARM 配置编译出来的镜像烧到 x86 板子上,折腾了两天才发现是架构选错了。

配置项 说明 常见值
Target Architecture 目标 CPU 架构 ARM (little endian)、ARM64、x86_64、RISC-V 64
Target Architecture Variant CPU 具体型号或内核变体 cortex-a7、cortex-a53、nehalem、rocket
Target ABI 应用程序二进制接口 EABI、EABIhf(硬浮点)
Floating point strategy 浮点运算策略 VFPv4-D16、NEON、软件浮点
Target Binary Format 可执行文件格式 ELF(几乎都是这个)

举个例子,如果你用的是全志 H3 芯片(Cortex-A7),配置应该是:

Target Architecture: ARM (little endian)
Target Architecture Variant: cortex-a7
Target ABI: EABIhf
Floating point strategy: VFPv4-D16

我曾经在一个项目里,板子是 Cortex-A7,但默认选了 generic ARM,结果编译出来的系统性能差得离谱。后来发现是编译器没生成针对 cortex-a7 的指令调度。你想想看,这种坑多冤枉。

注意:浮点策略选错了,轻则性能下降,重则程序跑飞。硬浮点(EABIhf)和软浮点(EABI)的二进制不兼容。如果你的板子有硬件 FPU,一定要选硬浮点。

3.3 Build options 配置

这个菜单控制的是「怎么编译」,而不是「编译什么」。我刚开始学的时候经常忽略这里,直到磁盘被占满才回头来看。

配置项 说明 建议值
Build output directory 编译输出目录 默认 output/,可改为 build/ 或绝对路径
Download directory 源码包缓存目录 建议统一为 ~/buildroot_dl,多个项目共享
Number of jobs to run simultaneously 并行编译线程数 CPU 核心数 + 1(比如 4 核设 5)
Enable compiler cache 启用 ccache 加速 强烈建议开启
Enable package remaking 允许重新编译单个包 建议开启,调试时有用

我个人习惯把 Download directory 设成一个共享目录。这样我同时维护三四个项目时,不用每个项目都下载一遍 Linux 内核源码包,省了几十 G 的磁盘空间。

还有 Enable compiler cache,说白了就是 ccache。第一次编译慢,第二次改了一行代码再编译,只重新编译改动的文件,其他用缓存。我试过,全量编译从 40 分钟降到 5 分钟。

建议:把 Number of jobs 设成 CPU 核心数 + 1。设太大反而会因为上下文切换变慢。我一般 8 核机器设 9。

3.4 Toolchain 配置

工具链是编译器的集合。Buildroot 支持四种方式:

  • Buildroot 内部工具链 — 自己编译 gcc、binutils、glibc。灵活但慢。
  • 外部工具链(预编译) — 下载现成的,比如 Linaro、ARM 官方、Bootlin。快,推荐。
  • 系统工具链(本地) — 用你 PC 上的 gcc。只能编译同架构,不常用。
  • 自定义工具链 — 自己用 crosstool-NG 生成的。高级玩法。

我大部分项目都用 外部预编译工具链。为什么呢?省时间。Buildroot 自己编译一个完整的 gcc 工具链,在性能一般的机器上要半小时以上。而下载 Linaro 的 ARM 工具链,解压即用。

配置项 说明 推荐值
Toolchain type 工具链来源 External toolchain
Toolchain 具体工具链名称 Linaro ARM 2021.07 或 Bootlin 2022.02
Kernel Headers 内核头文件版本 与你目标内核版本匹配或略低
C library C 运行库 glibc(通用)、musl(嵌入式)、uclibc(极小)

关键:Kernel Headers 版本必须 ≤ 你实际运行的内核版本。比如你的板子跑 Linux 5.10,内核头文件可以选 5.10 或 5.4,但不能选 6.1。否则编译出来的程序调用新内核才有的系统调用,在老内核上会报错。

关于 C 库的选择,我个人的经验是:

  • glibc — 功能最全,兼容性最好。适合存储大、性能要求高的场景。
  • musl — 体积小、安全。我最近几个 IoT 项目都用它。静态链接时特别香。
  • uclibc — 极简,但维护不太活跃了。除非你 flash 只有 4MB,否则不建议。

我曾经在一个 32MB flash 的板子上,用 glibc 编译出来的 busybox 占 1.2MB,换成 musl 后只有 400KB。你想想看,省下来的空间能多放一个 Web 服务器。

3.5 配置流程与依赖关系

下面这张图展示了配置的先后顺序和依赖关系。我每次新建项目都按这个流程走一遍,基本不会漏。

Buildroot 基础配置流程 Buildroot 基础配置流程 1. Target options 2. Toolchain 3. Build options 4. System configuration 5. Target packages ⚠️ 配置顺序很重要 先定架构,再选工具链 工具链决定 C 库和 ABI 最后选包,避免依赖冲突 🔁 常见依赖关系 架构 → 工具链 ABI 工具链 → C 库选择 C 库 → 包兼容性 内核头文件 → 系统调用

这张图里,Target options 是起点。架构定了,工具链才能选。工具链定了,C 库和 ABI 就定了。然后才是系统配置和选包。我见过有人先选了一堆包,回头发现架构不对,全部重来。嗯,按这个顺序走,省心。

3.6 保存与验证配置

配置完成后,按 F6 保存,默认写入 .config 文件。你也可以用 make savedefconfig 生成一个精简版的 defconfig,只包含非默认值的选项。这个文件适合放到版本控制里。

$ make savedefconfig
$ cat defconfig
BR2_arm=y
BR2_cortex_a7=y
BR2_ARM_EABIHF=y
BR2_TOOLCHAIN_EXTERNAL=y
BR2_TOOLCHAIN_EXTERNAL_LINARO_ARM=y

我个人习惯把 defconfig 提交到 Git,每次编译前执行 make defconfig 恢复配置。这样团队协作时,每个人拿到的配置完全一致。

验证方法:执行 make show-targets 可以列出所有将要编译的包。如果列表里出现了你不认识的包,说明某个依赖被自动选中了。这时候回头检查一下配置。