给内核添加一份 .c 文件并不会让它自动参与构建。Kconfig 负责描述功能选项、依赖、帮助文本和可见性;配置工具据此生成 .config 与自动生成头文件;Kbuild Makefile 再依据 CONFIG_* 的值选择将对象编入内核、构建为模块或完全跳过。三层必须同时接通,才能解释“menuconfig 里能看到但代码没编”“模块没有生成”“符号依赖为什么消失”。
Kconfig 表达的是可选性和依赖
bool 只能是 y/n,适合必须内建或关闭的功能;tristate 可为 y/m/n,允许构建成模块。depends on 表达用户必须先满足的前置条件;select 会强制打开另一个符号,因此应谨慎使用,避免绕开该符号自身依赖导致不完整配置。
1 | # Makefile:CONFIG_VENDOR_SENSOR=y -> vendor_sensor.o 进内核 |
Kbuild 还会处理目录递归、复合对象、模块信息和链接顺序。新增驱动目录时,既要让父级 Kconfig source 到子 Kconfig,也要让父级 Makefile 进入子目录;只接其中一边都会造成看似诡异的结果。
一条可重复的配置工作流
从已知 defconfig 开始,使用 make menuconfig 或 nconfig 修改,随后运行 make olddefconfig 让新选项获得合理默认值,最后用 make savedefconfig 保存最小差异。不要只复制完整 .config 却不记录内核版本和工具链;选项名、依赖和默认值会随版本改变。
1 | make <board>_defconfig |
构建后检查 vmlinux/模块目录、modinfo 和目标机 dmesg。若是模块,确认 CONFIG_MODULES、依赖模块、安装路径、模块签名与目标内核版本一致;“编过了”不代表目标机能加载。
配置是产品接口的一部分
内核配置决定驱动、文件系统、网络、安全和调试能力,应该与 DTS、Bootloader 参数、rootfs 模块和 CI 一起版本化。为量产关闭调试选项之前,先保留可诊断的替代路径;为缩小镜像删除功能之前,确认恢复、OTA 和现场故障处理不依赖它。Kconfig 不是一个菜单,而是内核能力和产品约束的正式声明。
参考:Kconfig Language · Kbuild