4、配置Buildroot:make menuconfig详解——Target options、Build options、Toolchain、System configuration
好,咱们继续往下走。上一章我们把Buildroot的目录结构和下载流程捋了一遍,现在该动真格的了——执行make menuconfig,进入那个经典的蓝白配置界面。
说实话,我第一次打开这个界面时,看着满屏的选项也有点懵。但别怕,这玩意儿跟Linux内核的menuconfig一脉相承,你玩过内核配置的话,上手会很快。没玩过也没关系,我带你一个一个看。
核心思路:menuconfig里的选项,本质上是帮你回答三个问题——
1. 你的硬件长什么样?(Target options)
2. 你想怎么构建?(Build options)
3. 你用哪个编译器?(Toolchain)
4. 系统跑起来后长什么样?(System configuration)
4.1 Target options —— 告诉Buildroot你的硬件是谁
进入menuconfig后,第一项就是Target options。这里配置的是目标板子的CPU架构和特性。说白了,就是告诉Buildroot:「嘿,我要给这个芯片做系统,你按它的脾气来。」
我个人习惯先选Target Architecture。ARM、MIPS、x86、RISC-V……你板子用啥就选啥。比如我手头这块全志H3,那就是ARM架构。
接着是Target Architecture Variant,也就是具体的处理器型号。拿ARM来说,有Cortex-A7、A53、A72等等。选错了会怎样?轻则编译出来的程序跑不起来,重则内核直接panic。嗯,我当年就吃过这个亏——给A7的板子选了A53的优化选项,结果系统启动到一半就挂了,查了两天才发现是这里配错了。
| 选项 | 说明 | 常见值 |
|---|---|---|
| Target Architecture | 目标CPU架构 | ARM (little endian) |
| Target Architecture Variant | 具体处理器型号 | cortex-a7 |
| Target ABI | 应用程序二进制接口 | EABIhf(硬浮点) |
| Floating point strategy | 浮点运算策略 | VFPv4-D16 / NEON |
| ARM instruction set | ARM指令集 | ARM / Thumb2 |
小技巧:如果你不确定板子的浮点单元是什么,可以查芯片手册,或者直接看内核的defconfig文件。全志H3一般选VFPv4-D16 + NEON,性能最优。
还有一个容易忽略的选项——Target ABI。ARM平台有EABI和EABIhf两种。EABIhf是硬浮点ABI,浮点运算直接用硬件指令,速度快很多。如果你的芯片有硬件FPU,一定要选EABIhf。选成EABI的话,浮点运算会走软模拟,性能差一大截。
4.2 Build options —— 控制构建过程的「开关」
这部分不涉及硬件,纯粹是控制Buildroot怎么干活。我一般会先改Download dir,把源码包下载到独立目录,方便多个项目共享。毕竟一个Linux源码包就一百多兆,每个项目都下载一遍太浪费了。
Number of jobs to run simultaneously——并行编译线程数。这个我建议设成CPU核心数的1.5到2倍。比如4核CPU,设成6或8。设少了编译慢,设多了容易把机器搞死机。我自己的工作站是8核16线程,一般设12,稳得很。
还有一个好东西——Enable compiler cache。打开ccache后,第二次编译会快很多。尤其是你改了一点配置重新编译时,ccache能省下大量时间。我建议默认就打开,反正没坏处。
注意:如果你在调试过程中频繁修改配置并重新编译,建议把strip相关的选项关掉。strip会去掉调试符号,虽然能减小文件体积,但出了问题你连栈回溯都看不了。等最终发布时再打开strip不迟。
4.3 Toolchain —— 系统的「翻译官」
Toolchain就是交叉编译工具链。Buildroot支持两种方式:内置工具链和外部工具链。
内置工具链是Buildroot自己编译的,好处是版本可控、配置灵活。坏处是……第一次编译要等很久,因为要先把GCC、binutils、glibc全部编译一遍。我记得第一次编译内置工具链,喝了两杯咖啡还没完。
外部工具链则是用现成的,比如ARM官方的GCC、Linaro的工具链,或者你板子厂商提供的。我个人的建议是:新手用外部工具链,省时间;老手用内置工具链,可控性强。
选外部工具链时,要注意几个点:
- Toolchain path:工具链的安装路径,比如
/opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf - Toolchain prefix:交叉编译器的前缀,比如
arm-linux-gnueabihf- - External toolchain C library:必须和工具链实际使用的C库一致,选错了编译会报错
- Kernel headers:内核头文件版本,建议和你要编译的内核版本匹配
避坑指南:我曾经遇到过一个问题——外部工具链的glibc版本是2.28,但Buildroot默认选了2.27。结果编译出来的程序在板子上运行时报错「FATAL: kernel too old」。折腾了半天才发现是C库版本不匹配。所以,外部工具链的每个子选项都要和实际工具链严格对应,别想当然。
4.4 System configuration —— 给系统「化妆」
这部分配置的是系统启动后的样子。说白了,就是设置主机名、欢迎语、root密码、网络配置这些。
System hostname:你希望板子叫什么名字?我一般用项目名,比如my-iot-gateway。
System banner:登录时显示的欢迎信息。可以写点个性化的东西,比如项目名称、版本号、联系方式。我习惯在banner里加上编译时间,方便排查问题。
Root password:默认是空的。开发阶段可以留空,方便登录。但产品发布前一定要设密码,不然谁都能ssh进去,安全堪忧。
Network configuration:这里可以选DHCP自动获取IP,也可以设静态IP。开发板一般用DHCP方便,但如果是生产环境,建议用静态IP,避免IP变化导致服务不可用。
Init system:初始化系统。Buildroot支持BusyBox init、systemd、OpenRC等。我个人的经验是:资源受限的嵌入式设备用BusyBox init,轻量、简单、可靠;功能复杂的设备用systemd,虽然体积大一点,但服务管理、日志、定时任务这些功能很完善。
| 初始化系统 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| BusyBox init | 体积小、简单、启动快 | 功能少、无并行启动 | 资源受限的嵌入式设备 |
| systemd | 功能强大、并行启动、日志完善 | 体积大、依赖多 | 功能复杂的设备、服务器 |
| OpenRC | 介于两者之间、依赖清晰 | 社区较小 | Gentoo系用户 |
小建议:如果你是第一次用Buildroot,建议先选BusyBox init。等把整个流程跑通了,再尝试systemd。一口吃不成胖子,嵌入式开发尤其如此。
好了,这四个核心模块讲完了。你可能会问:「这么多选项,我怎么知道哪些该改、哪些保持默认?」我的回答是:先按最小配置跑起来。只改Target options里的架构和CPU型号,Build options里设一下并行线程数,Toolchain选内置或外部工具链,System configuration设个主机名和密码。其他保持默认,先编译出一个能启动的系统再说。
等系统跑起来了,再回头慢慢调优。比如打开ccache加速编译、换成systemd管理服务、调整浮点策略提升性能。嵌入式开发就是这样——先求能用,再求好用。
下一节,我们会进入make linux-menuconfig,配置Linux内核。那又是一个新世界,但有了今天的基础,你会觉得亲切很多。