編輯:關於android開發
從執行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
4.import-products函數
133 define import-products 134 $(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 := full PRODUCT_DEVICE := generic PRODUCT_BRAND := Android PRODUCT_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-name 181 $(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等都會經歷這個重復的環境初始化過程。
Android實戰技巧之四十六:用patch更新Android Studio 公司機器上的Android Studio很時髦,每次都會准時接收到官方穩定版的推送。目前最新
聯系人的側邊字母索引ListView 將手機通訊錄姓名通過首字母排序。,listview通訊錄 1 package com.lixu.l
讓服務器iis支持.apk文件下載的設置方法,iis.apk隨著智能手機的普及,越來越多的人使用手機上網,很多網站也應手機上網的需要推出了網站客戶端,.apk文件就是安卓
Android Studio:Failed to resolve ***,androidresolve更換電腦後,也更新了所有的SDK的tool,仍然報錯:Failed