概述
Android build系統(tǒng)主要的邏輯都包含在Make文件,另外還包括各種shell和 python腳本,Build樹可以理解為給Android源碼的編譯構(gòu)建了一整套規(guī)則。
框架
1.結(jié)構(gòu)
1.Build核心模塊

圖1中Build源碼文件定義了整個Build系統(tǒng)的框架,其他所有的Make文件都是基于這個構(gòu)建環(huán)境編寫出來并成功編譯。Build的核心文件都在/build/core/下。
2.針對產(chǎn)品的Build模塊

圖2中是針對某個產(chǎn)品類型的Make文件,一般都在device目錄下,根據(jù)產(chǎn)品類型有一組完整的Build模塊,比如hisillicon為硬件廠商定義的產(chǎn)品build樹,與Android核心build模塊一起構(gòu)建build系統(tǒng)。
3.針對單獨模塊的Build

單獨模塊的Build是依賴Android核心Build模塊的,所以在單獨模塊編譯時需要有如下操作:


單獨模塊的編譯以Android.mk文件為核心,也是大多數(shù)開發(fā)者最熟悉的Build模塊。
2.Build樹分析
1.編譯前準(zhǔn)備
編譯前執(zhí)行的第一條命令source ./build/envsetup.sh,初始化了各種環(huán)境變量以及Shell函數(shù):




lunch函數(shù)實際則指定了編譯的目標(biāo)設(shè)備:

2.開始編譯
Build編譯系統(tǒng)的入口是根目錄下的一個最簡單的MakeFIle,僅僅只有一行代碼:

在源碼根目錄調(diào)用make命令時,make命令最先讀取這個文件。雖然這個文件只有一行代碼,把/build/core/main.mk包含進(jìn)來,但是這個操作引入了整個Build系統(tǒng)。


| 文件名 | 作用 |
|---|---|
| main.mk | 最主要的 Make 文件,該文件中首先將對編譯環(huán)境進(jìn)行檢查,同時引入其他的 Make 文件 |
| help.mk | 包含了名稱為 help 的 Make 目標(biāo)的定義,該目標(biāo)將列出主要的 Make 目標(biāo)及其說明 |
| pathmap.mk | 將許多頭文件的路徑通過名值對的方式定義為映射表,并提供 include-path-for 函數(shù)來獲取。例如,通過$(call include-path-for, frameworks-native)便可以獲取到 framework 本地代碼需要的頭文件路徑 |
| envsetup.mk | 配置 Build 系統(tǒng)需要的環(huán)境變量,例如:TARGET_PRODUCT,TARGET_BUILD_VARIANT,HOST_OS,HOST_ARCH 等。當(dāng)前編譯的主機(jī)平臺信息(例如操作系統(tǒng),CPU 類型等信息)就是在這個文件中確定的。另外,該文件中還指定了各種編譯結(jié)果的輸出路徑 |
| combo/select.mk | 根據(jù)當(dāng)前編譯器的平臺選擇平臺相關(guān)的 Make 文件 |
| dumpvar.mk | 在 Build 開始之前,顯示此次 Build 的配置信息 |
| config.mk | 整個 Build 系統(tǒng)的配置文件,最重要的 Make 文件之一。該文件中主要包含以下內(nèi)容:定義了許多的常量來負(fù)責(zé)不同類型模塊的編譯。定義編譯器參數(shù)以及常見文件后綴,例如 .zip,.jar.apk。根據(jù) BoardConfig.mk 文件,配置產(chǎn)品相關(guān)的參數(shù)。設(shè)置一些常用工具的路徑,例如 flex,e2fsck,dx |
| definitions.mk | 最重要的 Make 文件之一,在其中定義了大量的函數(shù)。這些函數(shù)都是 Build 系統(tǒng)的其他文件將用到的。例如:my-dir,all-subdir-makefiles,find-subdir-files,sign-package 等,關(guān)于這些函數(shù)的說明請參見每個函數(shù)的代碼注釋 |
| distdir.mk | 針對 dist 目標(biāo)的定義。dist 目標(biāo)用來拷貝文件到指定路徑。 |
| dex_preopt.mk | 針對啟動 jar 包的預(yù)先優(yōu)化 |
| pdk_config.mk | 顧名思義,針對 pdk(Platform Developement Kit)的配置文件 |
| post_clean.mk | 在前一次 Build 的基礎(chǔ)上檢查當(dāng)前 Build 的配置,并執(zhí)行必要清理工作。 |
| host_static_library.mk | 定義了如何編譯主機(jī)上的靜態(tài)庫 |
| host_shared_library.mk | 定義了如何編譯主機(jī)上的共享庫 |
| static_library.mk | 定義了如何編譯設(shè)備上的靜態(tài)庫 |
| shared_library.mk | 定義了如何編譯設(shè)備上的共享庫 |
| executable.mk | 定義了如何編譯設(shè)備上的可執(zhí)行文件 |
| host_executable.mk | 定義了如何編譯主機(jī)上的可執(zhí)行文件 |
| package.mk | 定義了如何編譯 APK 文件 |
| prebuilt.mk | 定義了如何處理一個已經(jīng)編譯好的文件 ( 例如 Jar 包 ) |
| multi_prebuilt.mk | 定義了如何處理一個或多個已編譯文件,該文件的實現(xiàn)依賴 prebuilt.mk |
| host_prebuilt.mk | 處理一個或多個主機(jī)上使用的已編譯文件,該文件的實現(xiàn)依賴 multi_prebuilt.mk |
| java_library.mk | 定義了如何編譯設(shè)備上的共享 Java 庫 |
| static_java_library.mk | 定義了如何編譯設(shè)備上的靜態(tài) Java 庫 |
| host_java_library.mk | 定義了如何編譯主機(jī)上的共享 Java 庫 |
Android Build系統(tǒng)包含了編譯的所有規(guī)則:
make bigfish -j8會匹配到以下聲明,并開始makefile編譯

為了方便模塊編譯,Build系統(tǒng)還設(shè)置了很多編譯環(huán)境。單獨編譯一個模塊時,需要配置變量后才能執(zhí)行編譯:
| TAG | 作用 |
|---|---|
| LOCAL_SRC_FILES | 當(dāng)前模塊包含的所有源代碼文件 |
| LOCAL_MODULE | 當(dāng)前模塊的名稱,這個名稱應(yīng)當(dāng)是唯一的,模塊間的依賴關(guān)系就是通過這個名稱來引用的 |
| LOCAL_C_INCLUDES | C 或 C++ 語言需要的頭文件的路徑 |
| LOCAL_STATIC_LIBRARIES | 當(dāng)前模塊在靜態(tài)鏈接時需要的庫的名稱 |
| LOCAL_SHARED_LIBRARIES | 當(dāng)前模塊在運行時依賴的動態(tài)庫的名稱 |
| LOCAL_CFLAGS | 提供給 C/C++ 編譯器的額外編譯參數(shù) |
| LOCAL_JAVA_LIBRARIES | 當(dāng)前模塊依賴的 Java 共享庫 |
| LOCAL_STATIC_JAVA_LIBRARIES | 當(dāng)前模塊依賴的 Java 靜態(tài)庫 |
| LOCAL_PACKAGE_NAME | 當(dāng)前 APK 應(yīng)用的名稱 |
| LOCAL_CERTIFICATE | 簽署當(dāng)前應(yīng)用的證書名稱 |
在Android Build系統(tǒng)中聲明了很多編譯類型:Java 庫,C/C++ 庫,APK 應(yīng)用,以及可執(zhí)行文件等,并且Java 或者 C/C++ 庫還可以分為靜態(tài)的或者動態(tài)的,庫或可執(zhí)行文件既可能是針對設(shè)備的也可能是針對主機(jī)的或者模擬器的,不同的模塊的編譯聲明和方法是不一樣的,在config.mk中聲明了模塊類型,如下:
| TAG | Action |
|---|---|
| BUILD_HOST_STATIC_LIBRARY | 編譯靜態(tài)庫(適用與主機(jī)) |
| BUILD_HOST_SHARED_LIBRARY | 編譯動態(tài)庫(適用與主機(jī)) |
| BUILD_HOST_EXECUTABLE | 編譯可執(zhí)行程序(適用與主機(jī)) |
| BUILD_HOST_PREBUILT | 預(yù)編譯(適用與主機(jī)) |
| BUILD_HOST_JAVA_LIBRARY | 編譯java包(適用與主機(jī)) |
| BUILD_JAVA_LIBRARY | 編譯java包 |
| BUILD_STATIC_JAVA_LIBRARY | 編譯java靜態(tài)包 |
| BUILD_STATIC_LIBRARY | 編譯靜態(tài)庫 |
| BUILD_SHARED_LIBRARY | 編譯動態(tài)庫 |
| BUILD_EXECUTABLE | 編譯可執(zhí)行程序 |
| BUILD_PACKAGE | 編譯apk |
| BUILD_PREBUILT | 預(yù)編譯(針對單個預(yù)編譯文件) |
| BUILD_MULTI_PREBUILT | 預(yù)編譯(針對多個預(yù)編譯文件) |
在Android源碼中,為了把一個模塊添加到Build系統(tǒng)中,每個模塊都需要編寫一個專門的Android.mk文件,Build系統(tǒng)會查找到所有目錄下的Android.mk,并根據(jù)Android.mk文件編譯出指定的目標(biāo)文件。