Android Build系列专题【篇五:构建系统build.prop生成机制】
Android Build系列专题【篇一:开发环境搭建】
https://blog.csdn.net/qq_27672101/article/details/118227738Android Build系列专题【篇二:AOSP编译流程】
https://blog.csdn.net/qq_27672101/article/details/113767664Android Build系列专题【篇三:平台编译流程】
https://blog.csdn.net/qq_27672101/article/details/153254875Android Build系列专题【篇四:编译文件相关语法】
https://blog.csdn.net/qq_27672101/article/details/153255058Android Build系列专题【篇五:构建系统主入口文件build/core/makefile】
https://blog.csdn.net/qq_27672101/article/details/154239576
这里我们主要介绍一下android构建系统的主入口文件build/core/makefile,它承担着整个编译的启动和调度工作。该文件作为构建系统的起点,负责初始化编译环境并包含所有必要的子模块文件。具体功能包括:
- 版本检查:确保使用的 make 版本符合要求(通常需要 3.81 或更高)
- 环境设置:定义 BUILD_SYSTEM 等关键环境变量
- 核心配置:包含 config.mk、definitions.mk 等基础定义文件
- 目标管理:根据 MAKECMDGOALS 和 TARGET_BUILD_VARIANT 设置不同的编译目标
- 模块调度:协调整个构建系统的执行流程
Android构建系统采用模块化设计,位于build/core/目录下,由makefile和多个mk文件组成。makefile作为启动入口,main.mk作为核心流程文件,通过包含关系组织起整个构建框架。由于整个流程过于复杂,这里只记录我跟读过的一些模块。
再阅读本篇之前,建议先看看Android Build系列专题【篇四:编译文件相关语法】
android编译构建中,需要生成默认的系统属性的配置,即init进程的系统属性服务线程,解析的bu众多xxx/build.prop文件,并读取解析这些文件中的键值对,并加载到系统属性服务,这个时候,我们才可以通过getprop进行属性获取。那么xxx/build.prop是如何生成的呢?这里就来探究一下这套机制。
一、Kati构建方式之sysprop.mk

sysprop.mk文件在build/make/core/Makefile文件中直接include包含编译进去。sysprop.mk的主要目的就是为各个分区创建默认的build.prop文件,build.prop文件在init进程中的属性服务线程里面有去读取build.prop文件并把该文件中的键值对加载到内存中。由此系统属性才能被正式使用。
1、build-properties函数
build-properties函数主要目的是用来为各个分区创建build.prop文件,其定义如下:
# la.qssi16/build/core/sysprop.mk
# 函数功能:为各个分区partition创建etc/build.prop文件 Rule for generating <partition>/[etc/]build.prop file
# $(1): 分区名称,通常参数为system/product/vendor/odm
# $(2): 输出路径,通常为product/etc/build.prop
# $(3): 输入属性文件路径,此文件的内容通常为键值对直接输出到$(2)中, path to the input *.prop files. The contents of the files are directly emitted to the output
# $(4): 包含键值对格式属性的变量名列表,这些键值对直接输出到$(2)中, list of variable names each of which contains name=value pairs
# $(5): 可选的要强制移除的属性名列表,可以移除$3和$4的一些键值对,optional list of prop names to force remove from the output. Properties from both $(3) and (4) are affected
# $(6): 可选的要追加到文件末尾的文件列表,optional list of files to append at the end. The content of each file is emitted to the output
# $(7): 可选的跳过公共属性生成的标志,optional flag to skip common properties generation
# 函数名称:build-properties
define build-properties
# 流程1:把输出文件安装到系统中,即product/etc/build.prop安装到系统中生效能过被init进程解读
ALL_DEFAULT_INSTALLED_MODULES += $(2)
# 流程2:$4指定的键值对直接输出到product/etc/build.prop文件中
$(eval # Properties can be assigned using `prop ?= value` or `prop = value` syntax.)
$(eval # Eliminate spaces around the ?= and = separators.)
$(foreach name,$(strip $(4)),\
$(eval _temp := $$(call collapse-pairs,$$($(name)),?=))\
$(eval _resolved_$(name) := $$(call collapse-pairs,$$(_temp),=))\
)
$(eval # Implement the legacy behavior when BUILD_BROKEN_DUP_SYSPROP is on.)
$(eval # Optional assignments are all converted to normal assignments and)
$(eval # when their duplicates the first one wins)
$(if $(filter true,$(BUILD_BROKEN_DUP_SYSPROP)),\
$(foreach name,$(strip $(4)),\
$(eval _temp := $$(subst ?=,=,$$(_resolved_$(name))))\
$(eval _resolved_$(name) := $$(call uniq-pairs-by-first-component,$$(_resolved_$(name)),=))\
)\
$(eval _option := --allow-dup)\
)
# 流程3:清空或者创建输出文件,即通过touch指令创建product/etc/build.prop文件
$(2): $(POST_PROCESS_PROPS) $(INTERNAL_BUILD_ID_MAKEFILE) $(3) $(6) $(BUILT_KERNEL_VERSION_FILE_FOR_UFFD_GC)
$(hide) echo Building $$@
$(hide) mkdir -p $$(dir $$@)
$(hide) rm -f $$@ && touch $$@
# 流程4:如果$7不是true,调用generate-common-build-props函数,生成通用键值对到product/etc/build.prop文件中
ifneq ($(strip $(7)), true)
$(hide) $$(call generate-common-build-props,$(call to-lower,$(strip $(1))),$$@)
endif
# 流程5:遍历所有输入属性文件,添加分隔符和注释并输出到product/etc/build.prop文件中
# Make and Soong use different intermediate files to build vendor/build.prop.
# Although the sysprop contents are same, the absolute paths of android-info.prop are different.
# Print the filename for the intermediate files (files in OUT_DIR).
# This helps with validating mk->soong migration of android partitions.
$(hide) $(foreach file,$(strip $(3)),\
if [ -f "$(file)" ]; then\
echo "" >> $$@;\
echo "####################################" >> $$@;\
$(if $(filter $(OUT_DIR)/%,$(file)), \
echo "# from $(notdir $(file))" >> $$@;\
,\
echo "# from $(file)" >> $$@;\
)\
echo "####################################" >> $$@;\
cat $(file) >> $$@;\
fi;)
$(hide) $(foreach name,$(strip $(4)),\
echo "" >> $$@;\
echo "####################################" >> $$@;\
echo "# from variable $(name)" >> $$@;\
echo "####################################" >> $$@;\
$$(foreach line,$$(_resolved_$(name)),\
echo "$$(line)" >> $$@;\
)\
)
# 流程6:追加SDK版本等信息和文件结束符
$(hide) $(POST_PROCESS_PROPS) $$(_option) \
--sdk-version $(PLATFORM_SDK_VERSION) \
--kernel-version-file-for-uffd-gc "$(BUILT_KERNEL_VERSION_FILE_FOR_UFFD_GC)" \
$$@ $(5)
$(hide) $(foreach file,$(strip $(6)),\
if [ -f "$(file)" ]; then\
cat $(file) >> $$@;\
fi;)
$(hide) echo "# end of file" >> $$@
$(call declare-1p-target,$(2))
endef
函数功能:为各个分区partition创建etc/build.prop文件
- $(1): 分区名称,通常参数为system/product/vendor/odm
- $(2): 输出路径,通常为product/etc/build.prop
- $(3): 输入属性文件路径,此文件的内容通常为键值对直接输出到$(2)中, path to the input *.prop files. The contents of the files are directly emitted to the output
- $(4): 包含键值对格式属性的变量名列表,这些键值对直接输出到$(2)中, list of variable names each of which contains name=value pairs
- $(5): 可选的要强制移除的属性名列表,可以移除$3和$4的一些键值对,optional list of prop names to force remove from the output. Properties from both $(3) and (4) are affected
- $(6): 可选的要追加到文件末尾的文件列表,optional list of files to append at the end. The content of each file is emitted to the output
- $(7): 可选的跳过公共属性生成的标志,optional flag to skip common properties generation
函数名称:build-properties
- 流程1:把输出文件安装到系统中,即product/etc/build.prop安装到系统中生效能过被init进程解读
- 流程2:$4指定的键值对直接输出到product/etc/build.prop文件中
- 流程3:清空或者创建输出文件,即通过touch指令创建product/etc/build.prop文件
- 流程4:如果$7不是true,调用generate-common-build-props函数,生成通用键值对到product/etc/build.prop文件中
- 流程5:遍历所有输入属性文件,添加分隔符和注释并输出到product/etc/build.prop文件中
- 流程6:追加SDK版本等信息和文件结束符
2、A14如何通过build-properties创建etc/build.prop默认文件?
1)system分区

2)vendor分区

3)product分区

4)odm和其他分区

3、Kati构建方式总结
如上清一色的代码,这里发现有几个共同点,build-properties函数的目的是,根据一些(输入参数)规则来进行构建build.prop文件作为输出。这里分别介绍几个:
1)TARGET_XXX_PROP
TARGET_SYSTEM_PROP、TARGET_VENDOR_PROP、TARGET_PRODUCT_PROP、TARGET_ODM_PROP这几个值,如果他们存在,就作为第三个参数传递进去,我们来看看这些变量的值都是些撒?

原来如此,高通项目中这里在device目录下进行了指定,即可以把需要配置的属性写到device/xxx/system.prop文件内,编译后就默认生效。
PS:这个需要注意一下,其他几个变量TARGET_PRODUCT_PROP我没有看到有哪里进行指定,具体项目具体分析,具体平台具体分析,具体基线具体分析,只要锁定这个变量准没错
2)$(TARGET_DEVICE_DIR)/xxx.prop
$(TARGET_DEVICE_DIR)/system|vendor|product|odm.prop,如果他们存在,就作为第三个参数传递键,这里的TARGET_DEVICE_DIR目录是什么呢?

从这段逻辑中,TARGET_DEVICE_DIR 会被设置为 找到的 BoardConfig.mk 文件所在目录的路径,即如果找到的是 vendor/samsung/universal9820/BoardConfig.mk,那么 TARGET_DEVICE_DIR 就是 vendor/samsung/universal982
PS:因为比较深,用的比较少,我基本上没见过,同样具体平台具体分析
3)ADDITIONAL_XXX_PROPERTIES
ADDITIONAL_SYSTEM_PROPERTIES、ADDITIONAL_VENDOR_PROPERTIES、ADDITIONAL_PRODUCT_PROPERTIES、ADDITIONAL_ODM_PROPERTIES如果他们存在,就作为第四个参数传递键对,作为输入参数,即会被kati构建系统编译进去。

PS:这几个变量其实在A16上面已经被废弃了,如果有定义会直接编译报错
4)PRODUCT_XXX_PROPERTIES
PRODUCT_SYSTEM_DEFAULT_PROPERTIES、PRODUCT_SYSTEM_PROPERTIES、PRODUCT_VENDOR_PROPERTIES、PRODUCT_ODM_PROPERTIES、PRODUCT_PRODUCT_PROPERTIES、PRODUCT_SYSTEM_EXT_PROPERTIES如果他们的值存在,就作为第四个参数传递键值对,即会被kati构建系统编译进去。
PS:这就是我们常用的那些宏变量,即在mk中进行配置属性的常用手段,这里的逻辑还进行了vendor/system分区隔离
4)XXX_PROPERTY_OVERRIDES
这里只找到了PRODUCT_DEFAULT_PROPERTY_OVERRIDES和PRODUCT_PROPERTY_OVERRIDES,如果他们的值存在,就作为第四个参数传递键值对,即会被kati构建系统编译进去。
PS:这就是我们常用的那些宏变量,即在mk中进行覆盖配置属性的手段
6)gen_from_buildinfo_sh
自定义sh脚本来作为输出参数,通常手段就是通过echo语法来输入键值对,这种方式可读性不是很高,作为第四个参数传递进去,在A14 system就有一个很好的例子:

PS:这种方式可读性太低了,看的一脸懵逼,好在A16中默认删掉了这段代码
7)INSTALLED_XXX_BUILD_PROP_TARGET := $(TARGET_OUT_XXX)/etc/build.prop
这里就是build-properties函数的输出参数,即根据前文中A-F的输入参数,最终整理输出到xxx/out/etc/buid.prop文件,我们可以在编译out目录下进行查看,也可以在手机的xxx/etc.build.prop文件中进行查看。

二、Soong构建方式
1)A16如何通过build-properties创建etc/build.prop默认文件?
A16对这块内容有所变更,主要是针对system/product/odm等分区的build.prop创建方式有变化,从代码来看vendor分区还是按照之前
A vendor分区

B system & product & odm分区
# la.qssi16/build/core/sysprop.mk
# -----------------------------------------------------------------
# system/build.prop
#
# system/build.prop is built by Soong. See system-build.prop module in
# build/soong/Android.bp.
INSTALLED_BUILD_PROP_TARGET := $(TARGET_OUT)/build.prop

如上system/product/odm分区并没有在mk文件中调用build-properties函数进行创建build.prop文件,而是定义了输出路径,然后备注See system-build.prop module in build/soong/Android.bp.
Android 16 在构建系统上继续强化了 Soong 的作用。10 在您之前分析的 Android 14 中,我们看到了详细的 Makefile 规则来生成 build.prop 文件,但在这里,我们看到的是对 Soong 构建系统的引用,这表明:
Soong 主导:system/build.prop 的生成已从传统的 Makefile 规则迁移到 Soong 构建系统。
模块化定义:具体的生成规则现在定义在 build/soong/Android.bp 文件中的 system-build.prop 模块。
C sysprop.mk日志打印
为了更好的解读sysprop.mk的编译流程,我添加日志如下:

日志输出如下:

打开out/target/product/qssi_64/product/etc/build.prop文件:

里面的内容输出和本章介绍的build-properties函数逻辑基本一致。
更多推荐



所有评论(0)