設定檔
Android building system包括幾種重要的設定檔,
- Android .mk
- AndroidProducts.mk
- target_<os>-.mk, host_-.mk and -.mk
- BoardConfig.mk
- buildspec.mk
Android .mk是module和package的設定檔,每個module/package的目錄下都會有一個Android.mk。所謂的module是指系統的native code ,相對於用Java寫成的Android application稱爲package。
AndroidProducts.mk 則設定product 配置。product 即特定系統版本,透過編譯不同product ,產生不同軟體配置內容,安裝不同的application。Product 可視爲特定專案,產生特定規格系統。
BoardConfig.mk 是爲product 主板做設定,像是driver 選擇、 設定。*-.mk 則是針對選擇的作業系統和CPU 架構,進行相關設定。
buildspec.mk 是位於source 根目錄下,爲進行編譯者所做之額外設定。例如,可在此選擇要產生的product 、平臺、額外的module/package 等。
參數
build/envsetup.sh實作一個mm指令,以編譯單一module,不需編譯整個source tree。ONE_SHOT_MAKEFILE這個makefile變數/參數就是用以實作這個功能。使用方法是在執行make時,將該變數指定爲module的Android .mk。
- make ONE_SHOT_MAKEFILE=
透過定義CREATE_MODULE_INFO_FILE , building system 會將所有module 資訊列在$(PRODUCT_OUT)/module-info.txt 檔案裏。
- make CREATE_MODULE_INFO_FILE=true
設定BUILD_TINY_ANDROID=true , building system 產生一個簡單的image , 以測試硬體的可用度。此功能用於移植的早期階段,以快速bring up 。
HOST_BUILD_TYPE 和TARGET_BUILD_TYPE 指定building system 產生binary 的目的爲debug 或release 。透過設定此二變數,能產生包含debug information 的binry 。
- debug
- release
這些參數,也可設於buildspec.mk 裏,以避免開發過程不斷的重新指定。
Goals
一般編輯整個Android系統,就是使用droid這個goal。droid會產生一個完整的系統,包括bootloader、kernel、系統程式、模組和應用程式。
showcommands 和droid 功能相同,但droid 在編譯過程不顯示所使用的指令。透過showcommands 這個goal, building system 顯示過程中每一個步驟的詳細指令。
Makefile 的流程
- 初始化相關變數
- 偵測編譯環境和目標環境
- 決定目標product
- 讀取product 的設定
- 讀取product 所指定之目標平臺架構設定
- 選擇toolchain
- 指定編譯參數(*-.mk)
- 清除輸出目錄
- 設定/檢查版本編號
- 讀取所有BoardConfig.mk 檔案
- 讀取所有module 的設定
- 根據設定,產生必需的rule
- 產生image
以上的主要流程都是由build/core/main.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 設定的讀取
Android product的設定來自於build/target/product/AndroidProduct.mk和vendor子目錄下的AndroidProduct.mk 。building system透過find指令,找出所有可能的AndroidProduct.mk。AndroidProduct.mk裏定義PRODUCT_MAKEFILES變數,列舉所有實際定義product的makefile。這些makefile各自定義獨立的product 。product相關參數,存成PRODUCTS..形式的變數。並將makefile 路徑存在PRODUCTS 變數。因此,透過PRODUCTS 能取得所有的product 路徑/名稱, 並透過PRODUCTS.. 形式的變數取得內容。
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.<path of="" Android.mk>.形式。例如, Android .mk定義了LOCAL_MODULE_SUFFIX ,變會存成ALL_MODULES.<path of="" 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
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 被編譯。
結論
Android的building system其實不是那麼複雜。在瞭解之後,也不是那麼難修改。但, GNU make的一些語法,所building system使用一些不是那麼直覺的用法,使的building system較難了解。但,花點心思就能克服。