6、产品配置与 BoardConfig:产品定义文件(product.mk)、BoardConfig.mk 配置、设备树概念
好,咱们今天聊聊 Android Build 系统里最核心的两个配置文件——product.mk 和 BoardConfig.mk。还有那个听起来很玄乎的「设备树」概念。
说实话,我刚入行那会儿,看到一堆 .mk 文件就头大。后来踩了几个坑才明白,这两兄弟分工特别明确:一个管「软件长什么样」,一个管「硬件怎么跑」。
6.1 product.mk:产品定义文件
product.mk 说白了就是告诉编译系统:你要做一个什么样的手机/平板/电视。
它定义的是「产品级」的属性。比如:
- 产品叫什么名字(PRODUCT_NAME)
- 包含哪些应用(PRODUCT_PACKAGES)
- 系统属性(PRODUCT_PROPERTY_OVERRIDES)
- 语言、时区等默认配置
我习惯把 product.mk 想象成一张「购物清单」——你要往系统里装什么,全写在这里。
一个典型的 product.mk 长这样:
# 产品名称
PRODUCT_NAME := my_device
# 品牌和型号
PRODUCT_BRAND := MyBrand
PRODUCT_MODEL := MyPhoneX
# 要打包的应用
PRODUCT_PACKAGES += \
MyLauncher \
MySettings \
MyCamera
# 系统属性
PRODUCT_PROPERTY_OVERRIDES += \
ro.product.manufacturer=MyBrand \
ro.build.version.sdk=34
# 默认语言
PRODUCT_LOCALES := zh_CN en_US
嗯,这里要注意:PRODUCT_NAME 必须唯一。我见过有人把两个产品写成同一个名字,结果编译出来的镜像完全乱套了。
6.2 BoardConfig.mk:硬件配置
BoardConfig.mk 管的是「硬件层面」的东西。它告诉编译系统:你的板子用什么 CPU?内存多大?分区怎么分?
说白了,product.mk 决定「装什么软件」,BoardConfig.mk 决定「硬件怎么支持这些软件」。
我个人习惯:把 BoardConfig.mk 放在 device/<厂商>/<设备名>/ 目录下,和 product.mk 做邻居。这样找起来方便。
来看一个实际例子:
# 芯片架构
TARGET_ARCH := arm64
TARGET_ARCH_VARIANT := armv8-a
TARGET_CPU_VARIANT := cortex-a75
# 分区大小(单位:字节)
BOARD_BOOTIMAGE_PARTITION_SIZE := 67108864
BOARD_SYSTEMIMAGE_PARTITION_SIZE := 2147483648
BOARD_USERDATAIMAGE_PARTITION_SIZE := 5368709120
# 内核相关
TARGET_NO_KERNEL := false
BOARD_KERNEL_CMDLINE := console=ttyS0,115200
# 是否使用 A/B 分区
AB_OTA_UPDATES := true
这里有个坑,我曾经踩过:分区大小写错了,编译出来的镜像刷进去直接变砖。所以每次改 BoardConfig.mk,我都会反复检查分区数值。
6.3 设备树概念
设备树(Device Tree)是 Android 从 Linux 内核继承过来的概念。它用文本文件描述硬件信息,编译成 .dtb 文件后给内核用。
为什么要用设备树?
- 同一个内核可以支持不同硬件
- 硬件信息不用写死在代码里
- 改硬件配置只需要改 .dts 文件
你想想看,如果没有设备树,每换一个屏幕型号就得改内核代码,那得多麻烦?
注意:设备树文件(.dts)和 BoardConfig.mk 是两回事。BoardConfig.mk 是给 Android Build 系统看的,设备树是给 Linux 内核看的。它们描述的是同一个硬件,但视角不同。
一个简单的设备树片段:
/dts-v1/;
/ {
model = "MyDevice";
compatible = "mycompany,mydevice";
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x40000000>; // 1GB RAM
};
chosen {
bootargs = "console=ttyS0,115200";
};
};
嗯,这里要记住:设备树里的 reg 属性,第一个是基地址,第二个是大小。我刚开始写的时候经常搞反,结果内核死活找不到内存。
6.4 三者的关系
我用一张图来展示它们之间的关系:
从图上可以看得很清楚:product.mk 和 BoardConfig.mk 是 Android Build 系统的左右手,而设备树是它们和内核之间的桥梁。
6.5 实际项目中的经验
我在做某个平板项目时,遇到过这么个问题:
产品经理说「我们要支持 1080p 屏幕」,我就在 product.mk 里加了屏幕分辨率属性。结果刷机后发现,系统确实显示 1080p 了,但触摸屏完全没反应。
查了半天才发现,BoardConfig.mk 里忘了配置触摸屏的 I2C 地址。而设备树里虽然有触摸屏节点,但 BoardConfig.mk 没告诉内核去加载对应的驱动。
这个教训让我养成了一个习惯:改 product.mk 之前,先检查 BoardConfig.mk 是否配套。就像换轮胎之前,得先确认轮毂尺寸对不对。
避坑指南:我曾经在 BoardConfig.mk 里写错了分区大小,导致 OTA 升级总是失败。后来我写了个脚本,每次编译前自动校验分区数值是否合理。建议你也这么做。
6.6 小结
今天的内容其实就三个核心点:
- product.mk:定义产品软件配置,相当于「菜单」
- BoardConfig.mk:定义硬件配置,相当于「厨房设备」
- 设备树:描述硬件细节给内核看,相当于「食材清单」
这三者配合好了,编译出来的系统才能正常跑起来。少一个,或者配错了,轻则功能异常,重则直接变砖。
嗯,下一节我们会深入看看 Android.mk 和 Android.bp 的写法,那是真正开始「写代码」的地方了。