[Android/Linux] 实战记录:利用 Kconfig 精确控制 i.MX8MM 特定 DTB 的编译生成
在嵌入式 Android/Linux 开发中,我们经常遇到一套内核源码需要支持多个板卡(Board)的情况。默认情况下,NXP i.MX 系列的 Makefile 往往会一股脑地编译所有定义好的 .dtb 文件。
这不仅浪费编译时间,还可能导致在打包 dtbo.img 时引入不必要的设备树,甚至引发 avbtool 打包失败的问题。本文记录了如何通过修改 Kconfig 和 Makefile,实现只编译当前 Product 所需 DTB 的方法。
1. 问题背景
在基于 NXP i.MX8MM 平台的 Android 项目开发中(Target Product: myproduct_8mm),我们需要编译特定的设备树文件 ok8mm-myboard.dtb。
原始痛点:
arch/arm64/boot/dts/freescale/Makefile中硬编码了所有开发板的 dtb,导致编译产生大量无用文件。- 尝试在
defconfig中添加CONFIG_IMX8MM_MYBOARD_DTB=y,但编译后发现该配置被内核构建系统忽略(因为 Kconfig 中定义为隐藏变量)。 - 最终导致
out目录下缺少目标 dtb,后续的mkdtimg和avbtool步骤因找不到文件而失败。
2. 解决思路
要实现精确控制,我们需要打通以下三层逻辑:
- 定义开关 (Kconfig) :在内核配置菜单中添加新的布尔选项,且必须使其"可见"(Visible),以便接受外部
defconfig的赋值。 - 关联编译 (Makefile) :修改 DTS 的 Makefile,将具体的
.dtb文件与上述 Kconfig 选项绑定。 - 启用开关 (Defconfig) :在对应产品的配置文件中,将该选项置为
y。
3. 代码修改详解
3.1 修改 Kconfig.platforms
这是最关键的一步。为了让 defconfig 文件中的赋值生效,必须给 config 加上提示字符串(Prompt string) 。如果省略提示语,Kconfig 会将其视为内部隐藏变量,从而忽略 defconfig 中的 =y 设置。
文件路径: vendor/nxp-opensource/kernel_imx/arch/arm64/Kconfig.platforms
kconfig
config ARCH_FSL_IMX8MM
...
help
This enables support for Freescale i.MX8MM SOC.
# 新增以下内容
config IMX8MM_EVK_DTB
bool "Build ok8mm-evk DTB" <-- 关键:加上这行描述,使其变为可见选项
default n
depends on ARCH_FSL_IMX8MM
help
Build ok8mm-evk.dtb (set in defconfig for evk_8mm product).
config IMX8MM_MYBOARD_DTB
bool "Build ok8mm-myboard DTB" <-- 关键:加上这行描述
default n
depends on ARCH_FSL_IMX8MM
help
Build ok8mm-myboard.dtb (set in defconfig for myproduct_8mm product).
3.2 修改 DTS Makefile
将原本硬编码在 dtb-$(CONFIG_ARCH_FSL_IMX8MM) 列表中的特定板卡 dtb 移出,改为由新定义的变量控制。
文件路径: vendor/nxp-opensource/kernel_imx/arch/arm64/boot/dts/freescale/Makefile
makefile
# 从通用列表中移除特定的 dtb
dtb-$(CONFIG_ARCH_FSL_IMX8MM) += fsl-imx8mm-evk.dtb \
fsl-imx8mm-evk-root.dtb \
fsl-imx8mm-evk-revb.dtb \
fsl-imx8mm-evk-revb-rm67191.dtb \
fsl-imx8mm-ddr4-evk-rm67191.dtb
# ok8mm-evk.dtb \ <-- 移除
# ok8mm-myboard.dtb <-- 移除
# 单独控制特定 dtb 的编译
dtb-$(CONFIG_IMX8MM_EVK_DTB) += ok8mm-evk.dtb
dtb-$(CONFIG_IMX8MM_MYBOARD_DTB) += ok8mm-myboard.dtb
3.3 修改 Defconfig
最后,在各产品的配置文件中开启对应的开关。
针对自研产品 (myproduct_8mm):
文件路径: device/fsl/imx8m/myproduct_8mm/android_addition_defconfig
文件路径: vendor/nxp-opensource/kernel_imx/arch/arm64/configs/myproduct_defconfig
properties
CONFIG_CLD_HL_SDIO_CORE=y
+CONFIG_IMX8MM_MYBOARD_DTB=y <-- 开启 MyBoard DTB
针对官方 EVK 产品 (evk_8mm) / 通用配置:
文件路径: device/fsl/imx8m/evk_8mm/android_addition_defconfig
文件路径: vendor/nxp-opensource/kernel_imx/arch/arm64/configs/android_defconfig
properties
CONFIG_CLD_HL_SDIO_CORE=y
+CONFIG_IMX8MM_EVK_DTB=y <-- 开启 EVK DTB
4. 结果验证
4.1 验证 .config 配置生效
在编译开始后(或者执行完 merge_config.sh 后),检查最终生成的内核配置文件 .config,确认我们的配置是否被正确写入。
bash
grep "CONFIG_IMX8MM" out/target/product/myproduct_8mm/obj/KERNEL_OBJ/.config
预期输出:

properties
CONFIG_IMX8MM_EVK_DTB is not set
CONFIG_IMX8MM_MYBOARD_DTB=y <-- 确认此项为 y
如果这一步显示 is not set,说明 Kconfig 的定义可能有误(例如缺少 Prompt 提示语),或者 defconfig 没有被正确合并。
4.2 验证 DTB 文件生成
执行编译命令后,检查内核输出目录:
out/target/product/myproduct_8mm/obj/KERNEL_OBJ/arch/arm64/boot/dts/freescale/
- 修改前 :目录下包含
ok8mm-evk.dtb,ok8mm-myboard.dtb以及大量其他无关的 i.MX8MM dtb。 - 修改后 :针对
myproduct_8mm的编译,目录下只包含ok8mm-myboard.dtb(以及基础的 fsl dtb),不再生成ok8mm-evk.dtb。

这样不仅理清了依赖关系,还确保了后续 make dtboimage 和 avbtool 打包流程的准确性。
5. 总结
在修改 Kernel 配置时,容易陷入的一个误区是:以为在 defconfig 里写了 CONFIG_XXX=y 就万事大吉。实际上,如果 Kconfig 中定义的选项没有 Prompt 提示语(例如 bool "Description"),它就是"隐形"的,构建系统会忽略外部输入并强制将其重置为默认值(通常是 n)。
通过规范化 Kconfig 定义和 Makefile 引用,我们成功实现了对多产品形态下设备树生成的精确控制。