Android SDK中关于BoardConfig.mk的宏定义继承和覆盖规则
在新建产品lunch的时候,如果在这两个BoardConfig.mk文件都定义了一个宏,但是变量不一样,谁生效? 比如下面这两个?
device/rockchip/rk356x/rk3568_caigong/BoardConfig.mk
device/rockchip/rk356x/BoardConfig.mk
这是一个非常好的问题,它触及了 Android 构建系统(Soong)的核心机制:变量覆盖和继承。
先说结论
最终生效的是 device/rockchip/rk356x/rk3568_caigong/BoardConfig.mk 中定义的宏。
换句话说,更具体(Specific)的设备配置会覆盖更通用(Generic)的平台配置。
详细解释
在 Android 的构建系统中,当您使用 lunch 命令选择了一个特定的目标(例如 lunch atk_dlrk3568-userdebug)时,构建系统会按一个特定的顺序来包含(include)各种 *.mk 文件。
这个过程可以理解为一种 “继承”和“覆盖” 的机制:
通用平台配置:device/rockchip/rk356x/BoardConfig.mk
这个文件包含了 所有基于 RK356x 芯片的平台 的通用配置。
它定义了对于任何使用 RK3568、RK3566 等芯片的开发板都适用的默认设置。
它首先被包含(include),具体设备配置:device/rockchip/rk356x/rk3568_caigong/BoardConfig.mk
这个文件是针对 【rk3568_caigong】这款特定开发板 的配置。
它通常会继承(include)通用的平台配置,然后对其进行定制和覆盖。
它在通用平台配置之后被包含。
关键的覆盖机制是:在 Makefile 中,后定义的变量会覆盖先前的同名变量。
因此,加载顺序是:
包含 …/rk356x/BoardConfig.mk (设置变量 X = 通用值)
包含 …/rk3568_caigong/BoardConfig.mk (重新设置变量 X = 专用值,覆盖了上一步的“通用值”)
最终,在整个构建过程中,变量 X 的值就是 ATK_DLRK3568/BoardConfig.mk 中设置的“专用值”。
如何验证?—— 实际查看构建过程
可以通过以下方法亲自验证这个结论:
方法一:查看 lunch 后的变量值
初始化环境并选择您的目标:
bash
source build/envsetup.sh
lunch atk_dlrk3568-userdebug # 请替换为您的确切目标名称
使用 get_build_var 命令来打印出您关心的那个宏(变量)的值:
bash
get_build_var YOUR_VARIABLE_NAME
这个命令会返回最终生效的值,它肯定来自 rk3568_caigong/BoardConfig.mk。
方法二:检查继承关系(阅读代码)
打开 device/rockchip/rk356x/rk3568_caigong/BoardConfig.mk 文件,在文件的开头,您会看到这样一行代码:
这行代码意味着它继承了通用配置
include device/rockchip/rk356x/BoardConfig.mk
然后是针对本设备的覆盖和新增配置
YOUR_VARIABLE := your_specific_value
这行 include 指令明确地建立了继承关系:先加载通用配置,然后再用当前文件中的定义去覆盖它。
为什么会这样设计?
这种设计模式非常合理和强大:
1、避免重复:芯片供应商(如 Rockchip)可以在 rk356x/BoardConfig.mk 中提供一套标准配置,所有采用该芯片的设备都不需要重复编写这些代码。
2、易于定制:设备制造商(如caigong)只需要在自家的 BoardConfig.mk 中编写差异化部分即可,例如:
不同的分区大小 (BOARD_SYSTEMIMAGE_PARTITION_SIZE)
不同的内核命令行参数 (BOARD_KERNEL_CMDLINE)
启用或禁用某些功能 (BOARD_HAVE_BLUETOOTH)
添加设备特有的特性
3、维护清晰:当需要更新通用配置时,只需修改一个文件,所有设备都会受益。设备特有的问题则在各自的目录下解决,互不干扰。