概述
一套系统代码,需要衍生出很多产品,而产品之间的差异点可以通过产品进行区分。这样,我们在编译时进行区分。编译的基本方式为:
1.source build/envsetup.sh
2.lunch + 产品名
这里,重点介绍添加产品名的原理
核心配置文件
AndroidProducts.mk
BoardConfig.mk
vendorsetup.sh //通过AndroidProducts.mk的引入,可去掉
product.mk //名称自定义
重点介绍:
AndroidProducts.mk
1.目的:指定产品的配置文件,同时,也可以将产品名添加到lunch选型中。
2.实现:
PRODUCT_MAKEFILES --- 指定配置文件,例如引入product.mk,如下:
PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/common.mk
COMMON_LUNCH_CHOICES --- 添加产品名到lunch中,例如:
COMMON_LUNCH_CHOICES := \
full_tb8788m1_64_wifi-eng \
full_tb8788m1_64_wifi-userdebug \
full_tb8788m1_64_wifi-user
BoardConfig.mk
1.目的:产品涉及的硬件相关配置,例如架构、分区等等
vendorsetup.sh
1.目的:可将产品名导入lunch
2.实现:
add_lunch_combo rk3288-user
add_lunch_combo rk3288-userdebug
注:
add_lunch_combo 是build/envsetup.sh中定义的方法
product.mk
1.目的:产品涉及的软件相关配置,例如集成哪些软件(app等等)、软件涉及配置文件等等。
2.实现:
以下信息必加:
PRODUCT_NAME := rk3288
PRODUCT_DEVICE := rk3288
PRODUCT_BRAND := Android
PRODUCT_MODEL := rk3288
PRODUCT_MANUFACTURER := rockchip
(PRODUCT_NAME和PRODUCT_DEVICE保持一致,同时,跟产品名一样)
原理介绍
注:源码来自7.1
1.AndroidProducts.mk怎么被自动加载?
a.build/core/product.mk定义AndroidProducts.mk。关注get-all-product-makefiles
注:从代码根目录device/vendor/product中目录寻找AndroidProducts.mk
# Search for AndroidProducts.mks in the given dir.
# $(1): the path to the dir //寻找最深为6层的文件目录中的AndroidProducts.mk
define _search-android-products-files-in-dir
$(sort $(shell test -d $(1) && find -L $(1) \
-maxdepth 6 \
-name .git -prune \
-o -name AndroidProducts.mk -print))
endef
#
# Returns the list of all AndroidProducts.mk files.
# $(call ) isn't necessary. //寻找所有的AndroidProducts.mk 寻找目录为device/vendor/product
#
define _find-android-products-files
$(foreach d, device vendor product,$(call _search-android-products-files-in-dir,$(d))) \
$(SRC_TARGET_DIR)/product/AndroidProducts.mk
endef
#
# Returns the sorted concatenation of PRODUCT_MAKEFILES
# variables set in the given AndroidProducts.mk files.
# $(1): the list of AndroidProducts.mk files.
#
define get-product-makefiles
$(sort \
$(foreach f,$(1), \
$(eval PRODUCT_MAKEFILES :=) \
$(eval LOCAL_DIR := $(patsubst %/,%,$(dir $(f)))) \
$(eval include $(f)) \
$(PRODUCT_MAKEFILES) \
) \
$(eval PRODUCT_MAKEFILES :=) \
$(eval LOCAL_DIR :=) \
)
endef
#
# Returns the sorted concatenation of all PRODUCT_MAKEFILES
# variables set in all AndroidProducts.mk files.
# $(call ) isn't necessary. //获取所有的AndroidProducts.mk列表
#
define get-all-product-makefiles
$(call get-product-makefiles,$(_find-android-products-files))
endef
b.build/core/product_config.mk使用AndroidProducts.mk。关注current_product_makefile
注:AndroidProducts.mk 关联TARGET_PRODUCT
ifneq ($(strip $(TARGET_BUILD_APPS)),)
# An unbundled app build needs only the core product makefiles.
all_product_configs := $(call get-product-makefiles,\
$(SRC_TARGET_DIR)/product/AndroidProducts.mk)
else
# Read in all of the product definitions specified by the AndroidProducts.mk
# files in the tree. //获取全部的AndroidProducts.mk文件
all_product_configs := $(get-all-product-makefiles)
endif
//采用当前配置current_product_makefile
//还是采用所有的配置all_product_makefiles
//特别注意:AndroidProducts.mk 关联TARGET_PRODUCT
# Find the product config makefile for the current product.
# all_product_configs consists items like:
# <product_name>:<path_to_the_product_makefile>
# or just <path_to_the_product_makefile> in case the product name is the
# same as the base filename of the product config makefile.
current_product_makefile :=
all_product_makefiles :=
$(foreach f, $(all_product_configs),\
$(eval _cpm_words := $(subst :,$(space),$(f)))\
$(eval _cpm_word1 := $(word 1,$(_cpm_words)))\
$(eval _cpm_word2 := $(word 2,$(_cpm_words)))\
$(if $(_cpm_word2),\
$(eval all_product_makefiles += $(_cpm_word2))\
$(if $(filter $(TARGET_PRODUCT),$(_cpm_word1)),\
$(eval current_product_makefile += $(_cpm_word2)),),\
$(eval all_product_makefiles += $(f))\
$(if $(filter $(TARGET_PRODUCT),$(basename $(notdir $(f)))),\
$(eval current_product_makefile += $(f)),)))
_cpm_words :=
_cpm_word1 :=
_cpm_word2 :=
current_product_makefile := $(strip $(current_product_makefile))
all_product_makefiles := $(strip $(all_product_makefiles))
load_all_product_makefiles :=
ifneq (,$(filter product-graph, $(MAKECMDGOALS)))
ifeq ($(ANDROID_PRODUCT_GRAPH),--all)
load_all_product_makefiles := true
endif
endif
ifneq (,$(filter dump-products,$(MAKECMDGOALS)))
ifeq ($(ANDROID_DUMP_PRODUCTS),all)
load_all_product_makefiles := true
endif
endif
ifeq ($(load_all_product_makefiles),true)
# Import all product makefiles.
$(call import-products, $(all_product_makefiles))
else
# Import just the current product.
ifndef current_product_makefile
$(error Can not locate config makefile for product "$(TARGET_PRODUCT)")
endif
ifneq (1,$(words $(current_product_makefile)))
$(error Product "$(TARGET_PRODUCT)" ambiguous: matches $(current_product_makefile))
endif
$(call import-products, $(current_product_makefile))
endif # Import all or just the current product makefile
c.build/core/main.mk调用到product_config.mk
build/core/main.mk --> build/core/config.mk -->
build/core/envsetup.mk --> build/core/product_config.mk
d.make编译就是从build/core/main.mk开始
2.BoardConfig.mk怎么被自动加载?
a.build/core/envsetup.mk使用BoardConfig.mk
注:从代码根目录device/vendor中目录寻找BoardConfig.mk
关联TARGET_DEVICE
build/core/envsetup.mk
# Boards may be defined under $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)
# or under vendor/*/$(TARGET_DEVICE). Search in both places, but
# make sure only one exists.
# Real boards should always be associated with an OEM vendor.
board_config_mk := \
$(strip $(sort $(wildcard \
$(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \
$(shell test -d device && find -L device -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \
$(shell test -d vendor && find -L vendor -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \
)))
ifeq ($(board_config_mk),)
$(error No config file found for TARGET_DEVICE $(TARGET_DEVICE))
endif
ifneq ($(words $(board_config_mk)),1)
$(error Multiple board config files for TARGET_DEVICE $(TARGET_DEVICE): $(board_config_mk))
endif
include $(board_config_mk)
特别注意
BoardConfig.mk 关联TARGET_DEVICE
b.build/core/main.mk调用envsetup.mk
build/core/main.mk --> build/core/envsetup.mk
具体实现
1.参考RK的系统代码:rk3288
device/rockchip/rk3288
AndroidProducts.mk
BoardConfig.mk
rk3288.mk
vendorsetup.sh
2.简单总结:
1.创建device/[company]/[product]
2.放置对应的文件即可
拓展
1.产品目录下自定义的system.prop怎么被自动编译到system/system.prop
直接放到device/[company]/[product]目录即可。
原理:
编译过程自动加载
build/core/Makefile
##特别注意,如果TARGET_SYSTEM_PROP被定义了,就无法自动加载了。需要在product.mk中定义以下即可
##例如,TARGET_SYSTEM_PROP += device/[company]/[product]/system.prop
ifdef TARGET_SYSTEM_PROP
system_prop_file := $(TARGET_SYSTEM_PROP)
else
system_prop_file := $(wildcard $(TARGET_DEVICE_DIR)/system.prop) #没有定义,就可以自动加载
endif
$(intermediate_system_build_prop): $(BUILDINFO_SH) $(INTERNAL_BUILD_ID_MAKEFILE) $(BUILD_SYSTEM)/version_defaults.mk $(system_prop_file) $(INSTALLED_ANDROID_INFO_TXT_TARGET)
@echo Target buildinfo: $@
@mkdir -p $(dir $@)
$(hide) echo > $@
ifneq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OEM_PROPERTIES),)
$(hide) echo "#" >> $@; \
echo "# PRODUCT_OEM_PROPERTIES" >> $@; \
echo "#" >> $@;
$(hide) $(foreach prop,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OEM_PROPERTIES), \
echo "import /oem/oem.prop $(prop)" >> $@;)
endif
$(hide) TARGET_BUILD_TYPE="$(TARGET_BUILD_VARIANT)" \
TARGET_BUILD_FLAVOR="$(TARGET_BUILD_FLAVOR)" \
TARGET_DEVICE="$(TARGET_DEVICE)" \
PRODUCT_NAME="$(TARGET_PRODUCT)" \
PRODUCT_BRAND="$(PRODUCT_BRAND)" \
PRODUCT_DEFAULT_LOCALE="$(call get-default-product-locale,$(PRODUCT_LOCALES))" \
PRODUCT_DEFAULT_WIFI_CHANNELS="$(PRODUCT_DEFAULT_WIFI_CHANNELS)" \
PRODUCT_MODEL="$(PRODUCT_MODEL)" \
PRODUCT_MANUFACTURER="$(PRODUCT_MANUFACTURER)" \
PRIVATE_BUILD_DESC="$(PRIVATE_BUILD_DESC)" \
BUILD_ID="$(BUILD_ID)" \
BUILD_DISPLAY_ID="$(BUILD_DISPLAY_ID)" \
DATE="$(DATE_FROM_FILE)" \
BUILD_NUMBER="$(BUILD_NUMBER_FROM_FILE)" \
BOARD_BUILD_SYSTEM_ROOT_IMAGE="$(BOARD_BUILD_SYSTEM_ROOT_IMAGE)" \
AB_OTA_UPDATER="$(AB_OTA_UPDATER)" \
PLATFORM_VERSION="$(PLATFORM_VERSION)" \
PLATFORM_SECURITY_PATCH="$(PLATFORM_SECURITY_PATCH)" \
PLATFORM_BASE_OS="$(PLATFORM_BASE_OS)" \
PLATFORM_SDK_VERSION="$(PLATFORM_SDK_VERSION)" \
PLATFORM_PREVIEW_SDK_VERSION="$(PLATFORM_PREVIEW_SDK_VERSION)" \
PLATFORM_VERSION_CODENAME="$(PLATFORM_VERSION_CODENAME)" \
PLATFORM_VERSION_ALL_CODENAMES="$(PLATFORM_VERSION_ALL_CODENAMES)" \
BUILD_VERSION_TAGS="$(BUILD_VERSION_TAGS)" \
TARGET_BOOTLOADER_BOARD_NAME="$(TARGET_BOOTLOADER_BOARD_NAME)" \
BUILD_FINGERPRINT="$(BUILD_FINGERPRINT_FROM_FILE)" \
$(if $(OEM_THUMBPRINT_PROPERTIES),BUILD_THUMBPRINT="$(BUILD_THUMBPRINT)") \
TARGET_BOARD_PLATFORM="$(TARGET_BOARD_PLATFORM)" \
TARGET_CPU_ABI_LIST="$(TARGET_CPU_ABI_LIST)" \
TARGET_CPU_ABI_LIST_32_BIT="$(TARGET_CPU_ABI_LIST_32_BIT)" \
TARGET_CPU_ABI_LIST_64_BIT="$(TARGET_CPU_ABI_LIST_64_BIT)" \
TARGET_CPU_ABI="$(TARGET_CPU_ABI)" \
TARGET_CPU_ABI2="$(TARGET_CPU_ABI2)" \
TARGET_AAPT_CHARACTERISTICS="$(TARGET_AAPT_CHARACTERISTICS)" \
bash $(BUILDINFO_SH) >> $@
$(hide) $(foreach file,$(system_prop_file), \
if [ -f "$(file)" ]; then \
echo "#" >> $@; \
echo Target buildinfo from: "$(file)"; \
echo "# from $(file)" >> $@; \
echo "#" >> $@; \
cat $(file) >> $@; \
fi;)
$(if $(ADDITIONAL_BUILD_PROPERTIES), \
$(hide) echo >> $@; \
echo "#" >> $@; \
echo "# ADDITIONAL_BUILD_PROPERTIES" >> $@; \
echo "#" >> $@; )
$(hide) $(foreach line,$(ADDITIONAL_BUILD_PROPERTIES), \
echo "$(line)" >> $@;)
$(hide) cat $(INSTALLED_ANDROID_INFO_TXT_TARGET) | grep 'require version-' | sed -e 's/require version-/ro.build.expect./g' >> $@
$(hide) build/tools/post_process_props.py $@ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_PROPERTY_BLACKLIST)
2.lunch + 产品名格式
BUILD-BUILDTYPE
BUILD 可以自定义为product
BUILDTYPE 是以下类型之一:
编译类型 使用情况
user 权限受限;适用于生产环境
userdebug 与“user”类似,但具有 root 权限和可调试性;是进行调试时的首选编译类型
eng 具有额外调试工具的开发配置
3.AndroidProducts.mk和BoardConfig.mk加载谁先谁后?
131 include $(BUILD_SYSTEM)/product_config.mk ### 先加载AndroidProducts.mk
132
133 build_variant := $(filter-out eng user userdebug,$(TARGET_BUILD_VARIANT))
134 ifneq ($(build_variant)-$(words $(TARGET_BUILD_VARIANT)),-1)
135 $(warning bad TARGET_BUILD_VARIANT: $(TARGET_BUILD_VARIANT))
136 $(error must be empty or one of: eng user userdebug)
137 endif
138
139 SDK_HOST_ARCH := x86
140
141 # Boards may be defined under $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)
142 # or under vendor/*/$(TARGET_DEVICE). Search in both places, but
143 # make sure only one exists.
144 # Real boards should always be associated with an OEM vendor.
145 board_config_mk := \ ### 再加载BoardConfig.mk
146 $(strip $(sort $(wildcard \
147 $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \
148 $(shell test -d device && find -L device -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \
149 $(shell test -d vendor && find -L vendor -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \
150 )))
参考学习
https://source.android.com/source/building
https://blog.csdn.net/daoshuti/article/details/108513784
http://qiushao.net/2019/11/19/Android%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E5%85%A5%E9%97%A8/2-%E6%B7%BB%E5%8A%A0product/
http://qiushao.net/2019/11/20/Android%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E5%85%A5%E9%97%A8/3-%E6%B7%BB%E5%8A%A0%E7%B3%BB%E7%BB%9F%E5%B1%9E%E6%80%A7/
网友评论