Android 编译系统分析(二)
生活随笔
收集整理的這篇文章主要介紹了
Android 编译系统分析(二)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
把Android所有的Make文件分為4種:
1、For config
這類文件主要來配置product,board,以及根據(jù)你的Host和Target選擇相應(yīng)的工具以及設(shè)定相應(yīng)的通用編譯選項:
build/core/config.mk ? ? ? ? summary of config
build/core/envsetup.mk ? ?generate dir config and so on
build/target/product ? ? ? ? product config
build/target/board ? ? ? ? ? ?board config
build/core/combo ? ? ? ? ? ? ?build flags config?
這里解釋下這里的board和product。borad主要是涉及到硬件芯片的配置,比如是否提供硬件的某些功能,比如說GPU等等,或者芯片支持浮點運算等等。product是指針對當(dāng)前的芯片配置定義你將要生產(chǎn)產(chǎn)品的個性配置,主要是指APK方面的配置,哪些APK會包含在哪個product中, 哪些APK在當(dāng)前product中是不提供的。
config.mk是一個總括性的東西,它里面定義了各種module編譯所需要使用的HOST工具以及如何來編譯各種模塊,比如說 BUILT_PREBUILT就定義了如何來編譯預(yù)編譯模塊。
envsetup.mk主要會讀取由envsetup.sh寫入環(huán)境變量中的一些變量來配置 編譯過程中的輸出目錄,combo里面主要定義了各種Host和Target結(jié)合的編譯器和編譯選項。
2. Module Compile 這類文件主要定義了如何來處理Module的Android.mk,以及采用何種方式來生成目標(biāo)模塊,這些模塊生成規(guī)則都定義在config.mk里面,我們可以看看: CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk BUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mk BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk BUILD_RAW_STATIC_LIBRARY := $(BUILD_SYSTEM)/raw_static_library.mk BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk BUILD_RAW_EXECUTABLE:= $(BUILD_SYSTEM)/raw_executable.mk BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk BUILD_HOST_PREBUILT:= $(BUILD_SYSTEM)/host_prebuilt.mk BUILD_PREBUILT:= $(BUILD_SYSTEM)/prebuilt.mk BUILD_MULTI_PREBUILT:= $(BUILD_SYSTEM)/multi_prebuilt.mk BUILD_JAVA_LIBRARY:= $(BUILD_SYSTEM)/java_library.mk BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk BUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mk BUILD_DROIDDOC:= $(BUILD_SYSTEM)/droiddoc.mk BUILD_COPY_HEADERS := $(BUILD_SYSTEM)/copy_headers.mk BUILD_KEY_CHAR_MAP := $(BUILD_SYSTEM)/key_char_map.mk 除了CLEAR_VARS是清楚本地變量之外,其他所有的都對應(yīng)了一種模塊的生成規(guī)則,每一個本地模塊最后都會include其中的一種來生成目標(biāo)模 塊。大部分上面的.mk都會包含base_rules.mk,這是對模塊進(jìn)行處理的基礎(chǔ)文件,建議要寫本地模塊的都去看看,看明白了為什么 Android.mk要這么寫就會大致明白了。
3.Local Module 本地模塊的Makefile文件就是我們在Android里面幾乎上隨處可見的Android.mk ,Android進(jìn)行編譯的時候會通過下面的函數(shù)來 遍歷所有子目錄中的Android.mk,一旦找到就不會再往層子目錄繼續(xù)尋找(所有你的模塊定義的頂層Android.mk必須包含自己定義的子目錄中的Android.mk)。 subdir_makefiles += \ $(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git $(subdirs) Android.mk) 不同類型的本地模塊具有不同的語法,但基本上是相通的,只有個別變量的不同。 Android通過LOCAL_MODULE_TAGS來決定哪些本地模塊會不會編譯進(jìn)系統(tǒng),通過PRODUCT和LOCAL_MODULE_TAGS來決定哪些應(yīng)用包會編譯進(jìn)系統(tǒng)(默認(rèn)情況是只要設(shè)置為tests則不編譯進(jìn)系統(tǒng)),如果用戶不指定LOCAL_MODULE_TAGS,默認(rèn)它的值是user。此外用戶可以通過buildspec.mk來指定你需要編譯進(jìn)系統(tǒng)的模塊。 用戶也可以通過mm來編譯指定模塊,或者通過make clean-module_name來刪除指定模塊。
4.Package? 這主要指的是build/core/Makefile這個文件,它定義了生成各種img的方式,包括ramdisk.img ? userdata.img ?system.img ?update.zip ?recover.img等。我們可以看看這些img都是如何生成的,對應(yīng)著我們常用的幾個make goals:
在實際的過程中,我們也可以自己編輯out目錄下的生成文件,然后手工打包相應(yīng)生成相應(yīng)的img,最常用的是加入一些需要集成進(jìn)的prebuilt file。 所有的Makefile都通過build/core/main.mk這個文件組織在一起,它定義了一個默認(rèn)goals:droid,當(dāng)我們在TOP目錄下 敲Make實際上就等同于我們執(zhí)行make droid。當(dāng)Make include所有的文件,完成對所有make我文件的解析以后就會尋找生成droid的規(guī)則,依次生成它的依賴,直到所有滿足的模塊被編譯好,然后使用 相應(yīng)的工具打包成相應(yīng)的img。
基本上Android building system就是以這樣一種方式組織在一起的了,下面說一點閑散的東西。首先是如何來加快Android的編譯過程,因為每次Android都要遍歷所有 的Android.mk,不管是編譯整個工程還是只編譯某個模塊。所以可以將遍歷的結(jié)果保存下來,下次直接從文件讀就好了,但是這里容易出錯,所以一定要 確認(rèn)是否正確包含了所有的.mk,當(dāng)新加入文件的時候確認(rèn)將原來保存的文件刪除。下面是我寫的加快編譯的一個makefile,將下面的語句替換掉 main.mk中的相應(yīng)部分就可以了: FROM: subdir_makefiles += \ $(shell build/tools/findleaves.sh --prune="./out" $(subdirs) Android.mk) TO: ifneq ($(ONE_SHOT_MAKEFILE),) else ifneq ($(CASH_MK),true) subdir_makefiles += \ $(shell build/tools/findleaves.sh --prune="./out" $(subdirs) Android.mk) else subdir-makefiles-cash := $(shell cat build/subdir_mk_cash) ifeq ($(subdir-makefiles-cash),) $(warning No .mk cash ,create now !) subdir_makefiles += \ $(shell build/tools/findleaves.sh --prune="./out" $(subdirs) Android.mk) mk-to-file := $(shell echo $(subdir_makefiles) > build/subdir_mk_cash)? else $(warning Using cash mk !) subdir_makefiles := $(shell cat build/subdir_mk_cash) endif endif
endif 通過CASH_MK=true來打開快速編譯的功能,因為沒有對錯誤進(jìn)行檢測的操作,所以使用的時候一定要特別小心。
總起來說,Android的Makefile的引用關(guān)系是這樣的, Makfile-->build/core/main.mk-->build/core/config.mk--->build/core/envsetup.mk-->build/core/product_config.mk 在build/core/product_config.mk中編譯系統(tǒng)首先調(diào)用build/core/product.mk/中定義的函數(shù)get-all-product-makefiles來遍歷整個vendor的子目錄,找到vendor下所有的AndroidProduct.mk,不同子目錄下的AndroidProduct.mk中不同的PRODUCT_NAME,PRODUCT_DEVICE等信息(可以通過打開build/core/product_config.mk中的#$(dump-products)語句使控制臺編譯的時候輸出都有的product信息),接著build/core/product_config.mk會調(diào)用resolve-short-product-name將TARGET_PRODUCT匹配的的AndroidProduct.mk總定義的PRODUCT_DEVICE賦值給TARGET_DEVICE。 在回到build/core/config.mk, include $(TARGET_DEVICE)/BoardConfig.mk board_config_mk := \ $(strip $(wildcard \ $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \ device/*/$(TARGET_DEVICE)/BoardConfig.mk \ vendor/*/$(TARGET_DEVICE)/BoardConfig.mk \ )) ..... include $(board_config_mk) 而這個BoardConfig.mk決定了目標(biāo)系統(tǒng)的屬性,比如使用ALSA還是GENERIC_AUDIO等等,另外在這里TARGET_DEVICE宏也決定了TARGET_DEVICE_DIR,(TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk))))
當(dāng)然Android的obj目標(biāo)輸出也是由TARGET_DEVICE決定,見build/core/envsetup.mk。再回到build/core/main.mk,編譯系統(tǒng)接著做的一件事情是,遍歷所有的子目錄,找到所有的Android.mk文件,并將這些Android.mk文件include進(jìn)來: 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的定義可知,這下又進(jìn)入了vendor下TARGET_DEVICE指向的目錄了,這個mk文件中定義了特定Product需要編譯和安裝的app和script.
2. Module Compile 這類文件主要定義了如何來處理Module的Android.mk,以及采用何種方式來生成目標(biāo)模塊,這些模塊生成規(guī)則都定義在config.mk里面,我們可以看看: CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk BUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mk BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk BUILD_RAW_STATIC_LIBRARY := $(BUILD_SYSTEM)/raw_static_library.mk BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk BUILD_RAW_EXECUTABLE:= $(BUILD_SYSTEM)/raw_executable.mk BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk BUILD_HOST_PREBUILT:= $(BUILD_SYSTEM)/host_prebuilt.mk BUILD_PREBUILT:= $(BUILD_SYSTEM)/prebuilt.mk BUILD_MULTI_PREBUILT:= $(BUILD_SYSTEM)/multi_prebuilt.mk BUILD_JAVA_LIBRARY:= $(BUILD_SYSTEM)/java_library.mk BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk BUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mk BUILD_DROIDDOC:= $(BUILD_SYSTEM)/droiddoc.mk BUILD_COPY_HEADERS := $(BUILD_SYSTEM)/copy_headers.mk BUILD_KEY_CHAR_MAP := $(BUILD_SYSTEM)/key_char_map.mk 除了CLEAR_VARS是清楚本地變量之外,其他所有的都對應(yīng)了一種模塊的生成規(guī)則,每一個本地模塊最后都會include其中的一種來生成目標(biāo)模 塊。大部分上面的.mk都會包含base_rules.mk,這是對模塊進(jìn)行處理的基礎(chǔ)文件,建議要寫本地模塊的都去看看,看明白了為什么 Android.mk要這么寫就會大致明白了。
3.Local Module 本地模塊的Makefile文件就是我們在Android里面幾乎上隨處可見的Android.mk ,Android進(jìn)行編譯的時候會通過下面的函數(shù)來 遍歷所有子目錄中的Android.mk,一旦找到就不會再往層子目錄繼續(xù)尋找(所有你的模塊定義的頂層Android.mk必須包含自己定義的子目錄中的Android.mk)。 subdir_makefiles += \ $(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git $(subdirs) Android.mk) 不同類型的本地模塊具有不同的語法,但基本上是相通的,只有個別變量的不同。 Android通過LOCAL_MODULE_TAGS來決定哪些本地模塊會不會編譯進(jìn)系統(tǒng),通過PRODUCT和LOCAL_MODULE_TAGS來決定哪些應(yīng)用包會編譯進(jìn)系統(tǒng)(默認(rèn)情況是只要設(shè)置為tests則不編譯進(jìn)系統(tǒng)),如果用戶不指定LOCAL_MODULE_TAGS,默認(rèn)它的值是user。此外用戶可以通過buildspec.mk來指定你需要編譯進(jìn)系統(tǒng)的模塊。 用戶也可以通過mm來編譯指定模塊,或者通過make clean-module_name來刪除指定模塊。
4.Package? 這主要指的是build/core/Makefile這個文件,它定義了生成各種img的方式,包括ramdisk.img ? userdata.img ?system.img ?update.zip ?recover.img等。我們可以看看這些img都是如何生成的,對應(yīng)著我們常用的幾個make goals:
在實際的過程中,我們也可以自己編輯out目錄下的生成文件,然后手工打包相應(yīng)生成相應(yīng)的img,最常用的是加入一些需要集成進(jìn)的prebuilt file。 所有的Makefile都通過build/core/main.mk這個文件組織在一起,它定義了一個默認(rèn)goals:droid,當(dāng)我們在TOP目錄下 敲Make實際上就等同于我們執(zhí)行make droid。當(dāng)Make include所有的文件,完成對所有make我文件的解析以后就會尋找生成droid的規(guī)則,依次生成它的依賴,直到所有滿足的模塊被編譯好,然后使用 相應(yīng)的工具打包成相應(yīng)的img。
基本上Android building system就是以這樣一種方式組織在一起的了,下面說一點閑散的東西。首先是如何來加快Android的編譯過程,因為每次Android都要遍歷所有 的Android.mk,不管是編譯整個工程還是只編譯某個模塊。所以可以將遍歷的結(jié)果保存下來,下次直接從文件讀就好了,但是這里容易出錯,所以一定要 確認(rèn)是否正確包含了所有的.mk,當(dāng)新加入文件的時候確認(rèn)將原來保存的文件刪除。下面是我寫的加快編譯的一個makefile,將下面的語句替換掉 main.mk中的相應(yīng)部分就可以了: FROM: subdir_makefiles += \ $(shell build/tools/findleaves.sh --prune="./out" $(subdirs) Android.mk) TO: ifneq ($(ONE_SHOT_MAKEFILE),) else ifneq ($(CASH_MK),true) subdir_makefiles += \ $(shell build/tools/findleaves.sh --prune="./out" $(subdirs) Android.mk) else subdir-makefiles-cash := $(shell cat build/subdir_mk_cash) ifeq ($(subdir-makefiles-cash),) $(warning No .mk cash ,create now !) subdir_makefiles += \ $(shell build/tools/findleaves.sh --prune="./out" $(subdirs) Android.mk) mk-to-file := $(shell echo $(subdir_makefiles) > build/subdir_mk_cash)? else $(warning Using cash mk !) subdir_makefiles := $(shell cat build/subdir_mk_cash) endif endif
endif 通過CASH_MK=true來打開快速編譯的功能,因為沒有對錯誤進(jìn)行檢測的操作,所以使用的時候一定要特別小心。
總起來說,Android的Makefile的引用關(guān)系是這樣的, Makfile-->build/core/main.mk-->build/core/config.mk--->build/core/envsetup.mk-->build/core/product_config.mk 在build/core/product_config.mk中編譯系統(tǒng)首先調(diào)用build/core/product.mk/中定義的函數(shù)get-all-product-makefiles來遍歷整個vendor的子目錄,找到vendor下所有的AndroidProduct.mk,不同子目錄下的AndroidProduct.mk中不同的PRODUCT_NAME,PRODUCT_DEVICE等信息(可以通過打開build/core/product_config.mk中的#$(dump-products)語句使控制臺編譯的時候輸出都有的product信息),接著build/core/product_config.mk會調(diào)用resolve-short-product-name將TARGET_PRODUCT匹配的的AndroidProduct.mk總定義的PRODUCT_DEVICE賦值給TARGET_DEVICE。 在回到build/core/config.mk, include $(TARGET_DEVICE)/BoardConfig.mk board_config_mk := \ $(strip $(wildcard \ $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \ device/*/$(TARGET_DEVICE)/BoardConfig.mk \ vendor/*/$(TARGET_DEVICE)/BoardConfig.mk \ )) ..... include $(board_config_mk) 而這個BoardConfig.mk決定了目標(biāo)系統(tǒng)的屬性,比如使用ALSA還是GENERIC_AUDIO等等,另外在這里TARGET_DEVICE宏也決定了TARGET_DEVICE_DIR,(TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk))))
當(dāng)然Android的obj目標(biāo)輸出也是由TARGET_DEVICE決定,見build/core/envsetup.mk。再回到build/core/main.mk,編譯系統(tǒng)接著做的一件事情是,遍歷所有的子目錄,找到所有的Android.mk文件,并將這些Android.mk文件include進(jìn)來: 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的定義可知,這下又進(jìn)入了vendor下TARGET_DEVICE指向的目錄了,這個mk文件中定義了特定Product需要編譯和安裝的app和script.
總結(jié)
以上是生活随笔為你收集整理的Android 编译系统分析(二)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android 编译系统分析(一)
- 下一篇: Android 编译系统分析(三)