美文网首页
Android集成编译之产品添加

Android集成编译之产品添加

作者: 锄禾豆 | 来源:发表于2022-01-28 07:55 被阅读0次

概述

一套系统代码,需要衍生出很多产品,而产品之间的差异点可以通过产品进行区分。这样,我们在编译时进行区分。编译的基本方式为:
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/

相关文章

网友评论

      本文标题:Android集成编译之产品添加

      本文链接:https://www.haomeiwen.com/subject/douthrtx.html