Android Makefile 的流程 (non recursive make)




  • 始化相關變數



  • 偵測編譯環境和目標環境



  • 決定目標 product



  • 讀取 product 的設定



  • 讀取 product 所指定之目標平台架構設定




    • 選擇 toolchain



    • 指定編譯參數 (*-.mk)




  • 清除輸出目錄



  • 設定/檢查版本編號



  • 讀取所有 BoardConfig.mk 檔案



  • 讀取所有 module 的設定



  • 根據設定,產生必需的 rule



  • 產生 image



以上的主要流程都是由 build/core/main.mk 所安排。


3.1.始化和偵測


Android Makefile 參照關係是這樣的


Makefile -> build/core/main.mk -> build/core/config.mk -> build/core/envsetup.mk -> build/core/product_config.mk


build/core/config.mk 所進行。 build/core/envsetup.mk 檢查 developer 的設定 (buildspec.mk) ,並檢查執行環境,以決定輸出目錄、項目。


build/core/config.mk 本身還依據參數,決定解譯時的相關參數。像是 compiler 的路徑、flagslex yacc 的路徑參數等。


關於 product 的相關設定,則是由 build/core/product_config.mk 所處理,使用 build/core/product.mk 提供之 macro 載入。根據 AndroidProduct.mk 的內容, product_config.mk 決定了




  • PRODUCT_TAGS



  • OTA_PUBLIC_KEYS



  • PRODUCT_POLICY



  • ......









Product 設定的讀取



呼叫build/core/product.mk中定義的函數get-all-product-makefiles ,來搜尋整個vendor 的子目錄,找到vendor下所有的AndroidProducts.mk, 不同子目錄下的AndroidProducts.mk 中定義了不同的PRODUCT_NAME, PRODUCT_DEVICE 資訊(我們也可以通過打開build/core/product_config.mk 中的#$(dump-products) 語句使主控台編譯的時候輸出所有product 資訊 , 接著build/core/product_config.mk 呼叫resolve-short-product-name TARGET_PRODUCT符合AndroidProducts.mk 中定義的PRODUCT_DEVICE 賦值給TARGET_DEVICE


Module 設定的讀取


Module 是指 native code 的軟體元件,而 Java application 則被稱為 package build/core/definitions.mk 定義 module/package 相關 macro ,讀取、檢查 module/package 定義檔;分散 source tree 各處的 Android.mk 檔案。 build/core/main.mk 使用 find 指令,在這些子目錄下找出所有 Android.mk ,並將路徑存在 subdir_makefiles 變數裡。最後,include 這些檔案。


這些 Android.mk include 定義成變數 BUILD_SHARED_LIBRARY BUILD_PACKAGE 等,和其目的相配的 makefile。這些 makefile 會變 Android.mk 定義之內容,存成 ALL_MODULES.Android.mk>. 形式。

例如;
Android.mk
定義了 LOCAL_MODULE_SUFFIX ,變會存成 ALL_MODULES.Android.mk>.LOCAL_MODULE_SUFFIX 。而 Android.mk 路徑,會存於 ALL_MODULES 變數裡。


Search Android.mk 的路徑,基本上會是整個 source tree 。但會依特定的 goal ,選擇性只找尋特定目錄。例如 SDK 只需特定目錄下的 Android.mk


Board Level 設定


和目標平台主板相關之設定,例如使用了什麼裝置、driver 等,或是是否需要編譯 bootloader kernel 等,都是在 BoardConfig.mk 裡設定。同樣,每張主板可以有不同設定,存在不同目錄下的 BoardConfig.mk ,以 find 尋找如下檔案:




  • build/target/board/$(TARGET_DEVICE)/BoardConfig.mk



  • vendor/*/$(TARGET_DEVICE)/BoardConfig.mk



board_config_mk := \
$(strip $(wildcard \
$(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \
vendor/*/$(TARGET_DEVICE)/BoardConfig.mk \
))
include $(board_config_mk)





TARGET_DEVICE product 所定義,因此同一個 BoardConfig.mk 可被多個 product 所使用。一個 TARGET_DEVICE ,通常只有一個 BoardConfig.mk BoardConfig.mk 會被直接 include building system name space 裡。因此,一些 module enable/disable ,可以在 BoardConfig.mk 以對映不同的主板。


另外在這裡TARGET_DEVICE 巨集也決定了TARGET_DEVICE_DIR,因為TARGET_DEVICE_DIR 取的是上面提到的BoardConfig.mk 的路徑。


TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))


當然Android Ob目標輸出也是由TARGET_DEVICE決定,見build/core/envsetup.mk


TARGET_OUT_ROOT_release := $(OUT_DIR)/target
TARGET_OUT_ROOT_debug := $(DEBUG_OUT_DIR)/target
TARGET_OUT_ROOT := $(TARGET_OUT_ROOT_$(TARGET_BUILD_TYPE))
TARGET_PRODUCT_OUT_ROOT := $(TARGET_OUT_ROOT)/product
PRODUCT_OUT := $(TARGET_PRODUCT_OUT_ROOT)/$(TARGET_DEVICE)


Rules


module 的定義檔 Android.mk 裡,可定義 module tag LOCAL_MODULE_TAGS,以分類這些 module。每一個 product 可以指定需要的 tag (PRODUCT_TAGS),使 building system 只編譯標示這些 tag module。在 build/core/main.mk 裡,所有標示特定 tag module 收集為 ALL_DEFAULT_INSTALLED_MODULES ,並 include build/core/Makefile 處理。


build/core/Makefile 為這些 module 產生 rule ,並使產生 image goal depend on 這些 rule ,使這些 module 被編譯。


再回到build/core/main.mk編譯系統接著做的一個件事情是,遍歷所有字目錄,找到所有Android.mk檔案,並將這些Android.mk檔案include 進來

#
# Typical build; include any Android.mk files we can find.
#
subdir_makefiles := \
$(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git $(subdirs) Android.mk)
include $(subdir_makefiles)


我們再來看其中的


./build/target/board/Android.mk


,對了它參照


include $(TARGET_DEVICE_DIR)/AndroidBoard.mk


由上面TARGET_DEVICE_DIR的定義,這下又進入了vendor TARGET_DEVICE指向的目錄了,這個mk檔案中定義了特定Product需要編譯和安裝app script.

立你斯 發表在 痞客邦 留言(2) 人氣()