3、配置Buildroot:make menuconfig详解、Target options配置、Build options配置、Toolchain配置
好,咱们接着往下走。上一章我们把Buildroot源码拉下来了,也试了试默认配置的编译。但说实话,那个默认配置基本就是个空壳子,啥也跑不起来。真正的活儿,全在配置这一步。
今天我就带你手把手过一遍 make menuconfig 的四个核心板块:Target options、Build options、Toolchain。这四个地方要是配错了,后面编译出来不是跑不起来,就是根本编不过。我在项目里踩过的坑,今天一并告诉你。
3.1 make menuconfig 界面概览
执行 make menuconfig 后,你会看到一个蓝底白字的菜单界面。嗯,跟Linux内核的配置界面长得一模一样,毕竟它们用的是同一套工具——kconfig。
这个界面里,从上到下大概有十几个菜单项。但咱们今天只讲前三个最关键的:
- Target options —— 目标硬件平台
- Build options —— 编译行为控制
- Toolchain —— 交叉编译工具链
剩下的那些(System configuration、Kernel、Target packages等)后面章节会逐个展开。别急,一口吃不成胖子。
3.2 Target options 配置
这个菜单说白了就是告诉Buildroot:你的目标板子长什么样?CPU是什么架构?用哪种浮点运算?
我见过不少新手上来就瞎选,结果编出来的内核跑都跑不起来。咱们一项一项看。
3.2.1 Target Architecture
这里选CPU架构。常见的有:
- ARM (little endian) —— 绝大多数ARM板子选这个
- ARM64 (little endian) —— 比如树莓派3/4的64位模式
- i386 / x86_64 —— PC或工控机
- RISC-V 64-bit —— 新出的开源架构,我最近在玩
举个例子,如果你用的是全志H3芯片(比如香橙派Zero),那就选 ARM (little endian)。别选错了,选成big endian的话,后面所有二进制都跑不了。
3.2.2 Target Architecture Variant
这个更细了。同样是ARM,还分cortex-A7、cortex-A53、cortex-M4等等。选错了,编译器生成的指令集可能不兼容。
我记得有一次,客户拿了个全志V3s的板子,我默认选了cortex-A7,结果编出来的内核在启动时卡在 Uncompressing Linux... 就不动了。查了半天,发现V3s其实是cortex-A7,但它的浮点单元是VFPv4,而我选的变体默认用了不同的浮点模型。嗯,这就是细节。
cat /proc/cpuinfo 看。实在不行,选最通用的 generic ARM,性能差一点但至少能跑。
3.2.3 Target ABI
ABI(Application Binary Interface)决定了函数调用时参数怎么传、寄存器怎么用。ARM平台下常见两种:
- EABI —— 老版本,兼容性好
- EABIhf —— 硬浮点,性能更好
我个人建议:只要你的CPU支持硬浮点(比如cortex-A系列),就选EABIhf。性能差距很明显,尤其是做音视频处理的时候。
3.2.4 Floating point strategy
这里选浮点策略。选项有:
- VFPv2 / VFPv3 / VFPv4 —— 不同版本的向量浮点单元
- NEON —— SIMD指令集,做多媒体加速用的
- Soft float —— 软件模拟浮点,慢但兼容
怎么选?看芯片。比如全志H3支持VFPv4和NEON,那就两个都勾上。如果选了NEON但编译器发现CPU不支持,编译会报错。所以还是那句话:查手册。
3.3 Build options 配置
这个菜单控制的是Buildroot怎么编译、编译成什么样。说白了就是编译器的行为开关。
3.3.1 Build type
这里有两个选项:
- Static —— 所有库都静态链接,生成的可执行文件大,但部署简单
- Shared —— 动态链接,体积小,但需要带一堆.so文件
我个人的经验:开发调试阶段用shared,方便替换库。产品发布时如果空间紧张,可以考虑static。但要注意,有些库(比如glibc)不支持纯静态链接,选了static可能会编译失败。
3.3.2 Debug mode
这个选项会往编译命令里加 -g 标志,生成调试符号。好处是出问题了可以用gdb调试,坏处是编译出来的东西体积大好几倍。
我建议:开发板调试时打开,正式发布时关掉。别像我以前那样,给客户交付一个200MB的根文件系统,里面一半都是调试符号……客户差点没骂娘。
3.3.3 Optimization level
这里选优化等级:
| 选项 | 说明 | 适用场景 |
|---|---|---|
| -O0 | 不优化,编译最快 | 调试阶段 |
| -O1 | 基本优化 | 一般调试 |
| -O2 | 常用优化,性能好 | 正式发布 |
| -Os | 优化体积 | 存储紧张 |
我一般用 -O2。除非板子Flash特别小(比如4MB),才会考虑 -Os。但要注意,-Os 有时会牺牲性能,实时性要求高的场景慎用。
3.4 Toolchain 配置
工具链配置是整个Buildroot里最容易出问题的地方。说白了,工具链就是交叉编译器、链接器、库的集合。选错了,后面所有包都编不过。
3.4.1 Toolchain type
这里有两个主流选项:
- Buildroot toolchain —— 让Buildroot自己编译一套工具链
- External toolchain —— 使用系统预装的或第三方提供的工具链
怎么选?
- 如果你从头开始做系统,选 Buildroot toolchain。它完全可控,但编译时间会长一些(第一次要编gcc、glibc,得半小时到一小时)。
- 如果你已经有现成的工具链(比如Linaro提供的),选 External toolchain。省时间,但要注意版本匹配。
我个人的习惯:项目初期用External toolchain快速验证,等系统稳定了再切回Buildroot toolchain做最终发布。这样既快又稳。
3.4.2 Toolchain configuration(Buildroot toolchain)
如果你选了Buildroot toolchain,下面会多出一堆子选项:
- Kernel headers —— 选跟目标内核版本匹配的头文件。比如你内核用5.10,这里就选5.10.x。不匹配的话,编译某些驱动会报错。
- C library —— 可选glibc、uClibc-ng、musl。glibc功能最全但体积大,musl轻量但兼容性稍差。嵌入式场景我推荐glibc,除非你Flash特别小。
- GCC compiler version —— 选gcc版本。我一般选最新的稳定版,但要注意有些老内核不支持太新的gcc。比如Linux 4.9用gcc 12可能会编译不过。
Custom kernel headers 然后随便填个版本号。我曾经图省事填了个4.19,结果内核头文件跟实际内核差了三个大版本,编译出来的glibc在运行时疯狂报 FATAL: kernel too old。折腾了两天才发现是头文件版本不匹配。
3.4.3 External toolchain(外部工具链)
如果你选External toolchain,需要指定工具链的路径和前缀。比如:
Toolchain path: /opt/arm-gcc-linaro-7.5.0
Toolchain prefix: arm-linux-gnueabihf-
这里要注意:
- 路径要写绝对路径,别用相对路径
- 前缀要带最后的横杠
- - 工具链的架构必须跟Target options里选的一致,否则编译会报
unknown architecture
我记得有一次,我用了Linaro的aarch64工具链,但Target options里选了ARM(32位)。结果编译内核时报了一堆 unsupported relocation type 错误。嗯,这就是架构不匹配的典型症状。
3.5 本章知识体系图
下面这张图帮你理清今天讲的四个配置模块之间的关系:
3.6 配置保存与验证
配完之后,按 Exit 退出,系统会问你是否保存。选 Yes,配置会写入 .config 文件。
我建议你顺手备份一份:
cp .config config_myboard_v1
这样万一改乱了,还能恢复。别问我为什么知道要备份……有一次我不小心按了 Load 加载了默认配置,一整天的心血全没了。
grep -E "^BR2_ARCH|^BR2_TOOLCHAIN|^BR2_GCC" .config 快速查看关键配置项。如果看到 BR2_arm=y 和 BR2_GCC_VERSION_12_X=y,说明架构和gcc版本都配上了。
好了,这一章的内容就到这儿。配置这块儿,说白了就是「选对参数,别手滑」。下一章我们会进入真正的编译环节,看看Buildroot是怎么把这几千个包一个个编出来的。