<一>配置過程分析:
jackie@jackie-host:~/svn/vimicro$ . ./build/envsetup.sh
including device/vimicro/vortex/vendorsetup.sh
------------------------------------------------------------------
build/envsetup.sh末尾有:
# Execute the contents of any vendorsetup.sh files we can find.
for f in `/bin/ls vendor/*/vendorsetup.sh vendor/*/build/vendorsetup.sh device/*/*/vendorsetup.sh 2> /dev/null`
do
echo "including $f"
. $f
done
unset f
------------------------------------------------------------------
device/vimicro/vortex/vendorsetup.sh:
add_lunch_combo generic_vortex-userdebug
add_lunch_combo full_vortex-userdebug //添加lunch項目
------------------------------------------------------------------
jackie@jackie-host:~/svn/vimicro$ lunch //配置lunch
You're building on Linux
Lunch menu... pick a combo:
1. generic-eng
2. simulator
3. generic_vortex-userdebug
4. full_vortex-userdebug
Which would you like? [generic-eng] 3
-------------------------------------------------------------------
function lunch()
{
local answer
if [ "$1" ] ; then
answer=$1
else
print_lunch_menu
//列印lunch列表
echo -n "Which would you like? [generic-eng] "
read answer
………………
# 將 product-variant模式種的product分離出來
# 將 product-variant模式種的variant分離出來
# 檢查之,看看是否在 (user userdebug eng) 範圍內
export TARGET_PRODUCT=$product
export TARGET_BUILD_VARIANT=$variant
export TARGET_SIMULATOR=false
export TARGET_BUILD_TYPE=release
printconfig
//列印一些主要的變數, 調用關係 printconfig()->get_build_var()->build/core/config.mk->build/core/envsetup.mk
}
function print_lunch_menu()
{
local uname=$(uname)
echo
echo "You're building on" $uname
echo
echo "Lunch menu... pick a combo:"
local i=1
local choice
for choice in ${LUNCH_MENU_CHOICES[@]}
do
echo " $i. $choice"
i=$(($i+1))
done
echo
}
-------------------------------------------------------------------
在build/core/envsetup.mk最末尾回顯:
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=2.3 //envsetup.mk->version_defaults.mk 定義了平台版本
TARGET_PRODUCT=generic_vortex
TARGET_BUILD_VARIANT=userdebug
TARGET_SIMULATOR=false //envsetup.mk:預設當為false時,TARGET_PRODUCT=generic
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS= //lunch->export TARGET_BUILD_APPS=
TARGET_ARCH=arm .
HOST_ARCH=x86 .
HOST_OS=linux .
HOST_BUILD_TYPE=release .
BUILD_ID=GRH55 //lunch->...->envsetup.mk有定義
============================================
以上在build/buildspec.mk.default 有預設宏定義
<二>Android編譯系統分析:
執行:make -j2
頂層目錄下的Makefile:
就只有一行:include build/core/main.mk
固實際是從main.mk開始編譯的。
《1》初始化參數設定:
在 main.mk 裡,簡單設定幾個主要編譯路徑的變數後,來到config.mk :
build/core/main.mk->config.mk
->(0)首先設定了源檔案的一系列路徑,包括標頭檔、庫檔案、服務、API 已經編譯工具的路徑。
例如:SRC_HEADERS := \ …… SRC_TARGET_DIR := $(TOPDIR)build/target 等。
->(1)讀取 buildspec.mk 的設定,在這裡我們可以加入自己的目標產品資訊:
直接編輯build/buildspec.mk.default並移到根目錄下; device/vimicro/vortex/buildspec.mk是 一樣的。
ifndef TARGET_PRODUCT
TARGET_PRODUCT:=generic_vortex
endif
《2》讀取Product設定:
->(2)接著進入envsetup.mk:
->version_defaults.mk 中具體定義平台版本
->product_config.mk:include $(BUILD_SYSTEM)/product.mk
get-all-product-makefiles
product.mk:define get-all-product-makefiles來遍曆整個vendor或device 的子目錄, 找到vendor或device目錄下所有的 AndroidProducts.mk, 不同子目錄下的“產品.mk” 中定義了不同的 PRODUCT_NAME, PRODUCT_DEVICE 等資訊
---------------------------------------------------------------------
device/vimicro/vortex/AndroidProducts.mk 包含所有具體“產品.mk”檔案
PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/generic_vortex.mk \
$(LOCAL_DIR)/full_vortex.mk
device/vimicro/vortex/generic_vortex.mk
$(call inherit-product, device/vimicro/vortex/device_vortex.mk)//device_vortex.mk:PRODUCT_COPY_FILES 批量拷貝!
$(call inherit-product, $(SRC_TARGET_DIR)/product/generic.mk)
PRODUCT_NAME := generic_vortex
PRODUCT_DEVICE := vortex //賦值為TARGET_DEVICE
PRODUCT_LOCALES += hdpi
---------------------------------------------------------------------
接著build/core/product_config.mk 會調用resolve-short-product-name 將TARGET_PRODUCT匹配的“產品.mk” 中定義的 PRODUCT_DEVICE 賦值給TARGET_DEVICE。
《3》讀取BoardConfig:
BoardConfig.mk是和目標平台主板相關的設定,例如使用了什麼裝置、driver 等,或是是否需要編譯bootloader 、kernel等,都是在 BoardConfig.mk 裡設定。同樣,每張主板可以有不同設定,存在不同目錄下的。
->(3)讀取BoardConfig:129 board_config_mk := \……$(SRC_TARGET_DIR)/board/ $(TARGET_DEVICE)/BoardConfig.mk \
device/*/$(TARGET_DEVICE)/BoardConfig.mk \
這裡的TARGET_DEVICE 就是 votex ,就是說為了定義我們自己的產品 votex. TARGET_DEVICE 宏也決定了TARGET_DEVICE_DIR, 因為TARGET_DEVICE_DIR 取的是上面提到的 BoardConfig.mk 的路徑。即device/vimicro/vortex/BoardConfig.mk
TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))
當然Android 的Ob目標輸出也是由TARGET_DEVICE決定,見build/core/envsetup.mk。
PRODUCT_OUT := $(TARGET_PRODUCT_OUT_ROOT)/$(TARGET_DEVICE)
《4》讀取所有Module:
->(4)讀取所以Moudule (definitions.mk )
結束全域變數配置後,回到main.mk ,馬上對編譯工具及版本進行檢查,錯誤便中斷編譯。
main.mk 160:include $(BUILD_SYSTEM)/definitions.mk包含檔案 definitions.mk 這裡面定義了許多變數和函數供main.mk 使用。
編譯系統接著做的一個件事情是,遍曆所有子目錄,找到所有Android.mk檔案,並將這些Android.mk檔案include 進來
#
# Include all of the makefiles in the system
#
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的定義,這下又進入了device目錄下TARGET_DEVICE指向的目錄了(device/vimicro/vortex/目錄),這個mk檔案中定義了特定Product需要編譯和安裝app 和 script.
我們在package/apps 下每個模組根目錄都能看到 Android.mk ,裡面會去定義當前本地模組的 Tag : LOCAL_MODULE_TAGS ,Android 會通過這個 Tag 來決定哪些本地模組會編譯進系統,通過 PRODUCT 和 LOCAL_MODULE_TAGS 來決定哪些應用程式套件會編譯進系統。 ( 前面說過,你也能通過buildspec.mk 來制定你要編譯進系統的模組 )
最後需要編譯的模組路徑打包到 ALL_DEFAULT_INSTALLED_MODULES:
《5》產生鏡像檔案images:
->(5)產生相應的rules,生存images:
所有需要配置的準備工作都已完成,下面該決定如何產生image 輸出檔案了,這一過程實際上在 build/core/Makefile 中處理的。這裡定義各種img 的產生方式,包括 ramdisk.img 、 userdata.img 、 system.img 、 update.zip 、 recover.img 等。 當Make include 所有的檔案,完成對所有 make 檔案的解析以後就會尋找產生 對應目標 的規則,依次產生它的依賴,直到所有滿足的模組被編譯好,然後使用相應的工具打包成相應的img 。
kernel/Android.mk
kernel/arch/arm/configs/vc0882_vortex_nand_defconfig ->kernel/.config
Makefile的主要流程:
以下主要流程都在build/core/main.mk 裡安排。
初始化相關的參數設定(buildspec.mk 、 envsetup.mk 、 config.mk)
檢測編譯環境和目標環境
決定目標product
讀取product 的配置資訊及目標平台資訊
讀取BoardConfig 的配置
讀取所有Module 的配置
根據配置產生必要的規則(build/core/Makefile)
產生image