The import-nodes process of the Product during the initialization of the Android compiling environment
Starting from executing the make-f config and mk files, config and mk files will be parsed by make, in general, the Makefile parsing process of make is to first load various mk files including include, and at the same time, the custom variables will be initialized during the loading process, similar to pre-compilation. After Various initialization, determine the target and dependency, and finally execute the target output action.
Multiple mk files to be included exist in config. mk. Here we will focus on the product-related envsteup. mk
In envsteup. mk, the product-related model configured in the system is extracted from include product_config.mk.
1. product import entry
$(call import-products, $(call get-all-product-makefiles))
We can see that this variable is implemented by a macro definition, which is located in the product. mk file of the previous include.
59 define get-all-product-makefiles 60 $(call get-product-makefiles,$(_find-android-products-files)) 61 endef
In the Makefile file, define can be used to define a function, or it can be understood as a macro. If you need to input parameters when calling a custom function, generally, you need to use the call function to call the function name indirectly. Otherwise, you can call the function name directly (generally, if the variable with the same name is not present, it is processed as a function ), call get-all-product-makefiles as described above.
2. get-all-product-makefiles
The process of get-all-product-makefiles is similar. First, call the _ find-android-products-files function to traverse all androidproducts in the system. mk file, and return the results in the form of variables separated by spaces as return values
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 processes AndroidProducts. mk. The latter uses $ (1) as the parameter input.
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
This function roughly processes the for loop f, that is, the AndroidProduct and mk found previously, and uses it as the mk File include, extracts the variables with PRODUCT_MAKEFILES, and extracts each AndroidProduct. mk
The extracted PRODUCT_MAKEFILES are returned as files.
The final structure of the returned values after the function is processed is roughly as follows. The result is roughly the relative path of Product-related mk related to the system top-level directory:
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_h1_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/generator device/generic/armv7-a/mini_armv7a.mk device/moto/ stingray/full_stingray.mk device/moto/stingray/Starter device/moto/wingray/Starter 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 Function
133 define import-products134 $(info ssssssssssssss$(PRODUCTS)!!!!!!!!!!)\135 $(call import-nodes,PRODUCTS,$(1),$(_product_var_list))\136 $(info ccccccccccccc$(PRODUCTS)a----------aaa)137 endef
Here $ (1) represents the return value processed by the function in the preceding 3, which is a product-defined mk file in some columns. Use import-nodes to process the returned value:
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
The processing of this function is complicated, but the general meaning is to find the variable fields defined in each mk File Based on the path of each mk file, such:
PRODUCT_NAME := fullPRODUCT_DEVICE := genericPRODUCT_BRAND := AndroidPRODUCT_MODEL := Full Android on Emulator
The processed variable is converted to a new one, similar to the following:
PRODUCT.build/target/product/full.mk.PRODUCT_NAEM := full
In addition, after the function is executed, the input parameter $ (2) will be returned and saved to a brand new variable PRODUCTS.
When the variable is checked by target product, the following steps are required to determine TARGET_DEVICE:
INTERNAL_PRODUCT := $(call resolve-short-product-name, $(TARGET_PRODUCT))
When you call resolve-short-product-name (described in the previous blog), the mk file path in this variable is extracted one by one and a variable name is formed.
PRODUCT.build/target/product/full.mk.PRODUCT_NAEM
As follows:
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 ) \
The pn value passed in here is the TARGET_PRODUCT we selected. It is reasonable for the lunch product to be selected only when the PRODUCT_NAME and TARGET_PRODUCT are consistent among all mk products, the initialization of the entire system compilation environment is normal. It lays the foundation for future make/mm and ensures that this is normal, because later make and mm will all go through this repetitive environment initialization process.