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 的路徑、flags, lex 、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.

arrow
arrow
    全站熱搜

    BB 發表在 痞客邦 留言(0) 人氣()