当前位置: 代码迷 >> Android >> Android系统编译环境初步化时Product产品的import-nodes过程
  详细解决方案

Android系统编译环境初步化时Product产品的import-nodes过程

热度:62   发布时间:2016-04-24 12:03:08.0
Android系统编译环境初始化时Product产品的import-nodes过程

从执行make -f config,mk文件开始,config,mk作为当前的makefile文件,将会被make解析,一般make解析Makefile文件流程首先是加载其中include的各种其他mk文件,同时在加载的过程中会初始化自定义的变量,类似于预编译,在完成各种初始化后,确定目标以及依赖关系,最终执行目标输出动作。

在config.mk中存在多个需要include的mk文件,这里关注product相关的envsteup.mk

在envsteup.mk从又会include product_config.mk,开始提取目前系统中所配置的product相关型号。

1. product import入口

$(call import-products, $(call get-all-product-makefiles))

可以看到该变量由一个宏定义来实现,位于之前include的product.mk文件中。

 59 define get-all-product-makefiles 60 $(call get-product-makefiles,$(_find-android-products-files)) 61 endef

在Makefile文件中可使用define来定义一个函数,亦或者可以理解为一个宏,如果在调用自定义的函数时需要传入参数,则一般需要使用call函数来间接调用函数名的方式,否则可以直接以函数名的方式来直接调用(一般无该同名变量时,以函数方式处理),如上所述调用get-all-product-makefiles。


2. get-all-product-makefiles

get-all-product-makefiles的处理过程也类似,先是调用_find-android-products-files函数,该函数的目的是遍历系统中所有的AndroidProduct.mk文件,并把结果以空格分隔的变量形式作为返回值返回

30 define _find-android-products-files 31 $(shell test -d device && find -L device -maxdepth 6 -name AndroidProducts.m    k) \ 32   $(shell test -d vendor && find vendor -maxdepth 6 -name AndroidProducts.mk    ) \ 33   $(SRC_TARGET_DIR)/product/AndroidProducts.mk 34 endef


3 get-product-makefiles处理AndroidProducts.mk,后者以$(1)作为参数输入

 41 define get-product-makefiles 42 $(sort \ 43   $(foreach f,$(1), \ 44     $(eval PRODUCT_MAKEFILES :=) \ 45     $(eval LOCAL_DIR := $(patsubst %/,%,$(dir $(f)))) \ 46     $(eval include $(f)) \ 47     $(PRODUCT_MAKEFILES) \ 48    ) \ 49   $(eval PRODUCT_MAKEFILES :=) \ 50   $(eval LOCAL_DIR :=) \ 51  ) 52 endef 53 
这个函数大致处理是for循环f即为之前find到的AndroidProduct,mk,也将其作为mk文件include,提取其中带有PRODUCT_MAKEFILES的变量,将每个AndroidProduct.mk

提取出的PRODUCT_MAKEFILES作为文件返回。

最终该函数处理后的返回值结构大致如下,可以看到结果大致是定义了Product相关的mk相关于系统顶层目录所在的相对路径:

build/target/product/core.mk 
build/target/product/full.mk.PRODUCT_NAME := full

build/target/product/full_x86.mk build/target/product/generic.mk build/target/product/generic_x86.mk build/target/product/large_emu_hw.mk build/target/product/sdk.mk build/target/product/sdk_x86.mk build/target/product/vbox_x86.mk device/asus/grouper/full_grouper.mk device/generic/armv7-a-neon/mini_armv7a_neon.mk device/generic/armv7-a/mini_armv7a.mk device/moto/stingray/full_stingray.mk device/moto/stingray/generic_stingray.mk device/moto/stingray/stingray_emu.mk device/moto/wingray/full_wingray.mk device/sample/products/sample_addon.mk device/samsung/crespo/full_crespo.mk device/samsung/crespo4g/full_crespo4g.mk device/samsung/maguro/full_maguro.mk device/samsung/toro/full_toro.mk device/samsung/tuna/full_tuna.mk device/ti/panda/full_panda.mk

4.import-products函数

133 define import-products134 $(info ssssssssssssss$(PRODUCTS)!!!!!!!!!!)\135 $(call import-nodes,PRODUCTS,$(1),$(_product_var_list))\136 $(info ccccccccccccc$(PRODUCTS)a----------aaa)137 endef
在这里$(1)代表上述3中函数处理的返回值,是一些列带有product定义的mk文件。通过import-nodes对这个返回值进行处理:

244 $(if \245   $(foreach _in,$(2), \246     $(eval _node_import_context := _nic.$(1).[[$(_in)]]) \247     $(if $(_include_stack),$(eval $(error ASSERTION FAILED: _include_stack \248                 should be empty here: $(_include_stack))),) \249     $(eval _include_stack := ) \250     $(call _import-nodes-inner,$(_node_import_context),$(_in),$(3)) \251     $(call move-var-list,$(_node_import_context).$(_in),$(1).$(_in),$(3)) \252     $(eval _node_import_context :=) \253     $(eval $(1) := $($(1)) $(_in)) \254     $(if $(_include_stack),$(eval $(error ASSERTION FAILED: _include_stack \255                 should be empty here: $(_include_stack))),) \256    ) \257 ,)258 endef
该函数的处理较为复杂,但大致的含义是根据每个mk文件所在路径,找到后将每个mk文件中定义的变量字段,如:

PRODUCT_NAME := fullPRODUCT_DEVICE := genericPRODUCT_BRAND := AndroidPRODUCT_MODEL := Full Android on Emulator
经过处理转换为全新的变量,类似如下:

PRODUCT.build/target/product/full.mk.PRODUCT_NAEM := full

此外还有一点需要注意的时,执行完该函数后相关的输入参数$(2)将会返回并保存到一个全新的变量PRODUCTS.

该变量再后续进行target product check时,最终确定TARGET_DEVICE时,需要经过如下步骤:

INTERNAL_PRODUCT := $(call resolve-short-product-name, $(TARGET_PRODUCT))

在调用resolve-short-product-name(前一博文有说明),会逐一提取这个变量中的mk文件路径并再组成一个变量名

PRODUCT.build/target/product/full.mk.PRODUCT_NAEM
如下:

180 define _resolve-short-product-name181   $(eval pn := $(strip $(1)))182   $(eval p := \183       $(foreach p,$(PRODUCTS), \184           $(if $(filter $(pn),$(PRODUCTS.$(p).PRODUCT_NAME)), \185             $(p) \186        )) \187    )188   $(eval p := $(sort $(p)))189   $(if $(filter 1,$(words $(p))), \190     $(p), \191     $(if $(filter 0,$(words $(p))), \192       $(error No matches for product "$(pn)"), \193       $(error Product "$(pn)" ambiguous: matches $(p)) \194     ) \
这里传入的pn值即为我们选择的TARGET_PRODUCT,只有在所有的mk中找到PRODUCT_NAME和TARGET_PRODUCT相一致时,我们lunch选择的产品才是合理的,整个系统编译环境的初始化才算正常。为后续的make/mm打下基础,并确保这是正常的,因为后面make、mm等都会经历这个重复的环境初始化过程。






  相关解决方案