一、Android編譯步驟:
二、初始化編譯環境--source build/envsetup.sh
在build/envsetup.sh中主要完成了三件事。
添加編譯目標的代碼如下:
for f in `/bin/ls vendor/*/vendorsetup.sh vendor/*/*/vendorsetup.sh device/*/*/vendorsetup.sh 2> /dev/null`do echo "including $f" . $fdoneunset f
三、選擇編譯目標--lunch
通過lunch選擇編譯目標,函數定義如下:
function lunch(){
local answer
//如果調用lunch時帶參數就表示手動指定編譯目標,否則列印選擇編譯目標的菜單 if [ "$1" ] ; then answer=$1 else print_lunch_menu echo -n "Which would you like? [full-eng] " read answer fi local selection=
//如果沒有編譯目標預設為full-eng,否則如果answer是數字就將其轉換為對應的字串表示 if [ -z "$answer" ] then selection=full-eng elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$") then if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ] then selection=${LUNCH_MENU_CHOICES[$(($answer-1))]} fi elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$") then selection=$answer fi
//如果表示編譯目標的字串是空的表示非法選擇,錯誤返回 if [ -z "$selection" ] then echo echo "Invalid lunch combo: $answer" return 1 fi export TARGET_BUILD_APPS=
//檢測選擇的product是否合法(只要在相應目錄建立vendorsetup.sh並add_lunch_combo就可在lunch menu中顯示相應項,但如果不配置product相關資訊就會Invalid)
local product=$(echo -n $selection | sed -e "s/-.*$//") check_product $product if [ $? -ne 0 ] then echo echo "** Don't have a product spec for: '$product'" echo "** Do you have the right repo manifest?" product= fi
//從selection解析出product,variant local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//") check_variant $variant if [ $? -ne 0 ] then echo echo "** Invalid variant: '$variant'" echo "** Must be one of ${VARIANT_CHOICES[@]}" variant= fi if [ -z "$product" -o -z "$variant" ] then echo return 1 fi
//匯出TARGET_PRODECT,TARGET_BUILD_VARIANT與TARGET_BUILD_TYPE,比如若選擇的是full-eng,那麼TARGET_PRODUCT=full,TARGET_BUILD_VARIANT=eng export TARGET_PRODUCT=$product export TARGET_BUILD_VARIANT=$variant export TARGET_BUILD_TYPE=release echo set_stuff_for_environment printconfig}
四、編譯--make -j8
要make肯定有Makefile,Android根目錄的Makefile只是簡單地include進來了一個檔案:
1 ### DO NOT EDIT THIS FILE ### 2 include build/core/main.mk 3 ### DO NOT EDIT THIS FILE ###
而build/core/main.mk就比較複雜了,以下是main.mk的結構圖:
在main.mk中首先定義了預設編譯目標並做版本檢查,然後include config.mk。
在config.mk中定義了在Android.mk中編譯目標時會用到的常量
CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mkBUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mkBUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mkBUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mkBUILD_RAW_STATIC_LIBRARY := $(BUILD_SYSTEM)/raw_static_library.mkBUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mkBUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mkBUILD_RAW_EXECUTABLE:= $(BUILD_SYSTEM)/raw_executable.mkBUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mkBUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mkBUILD_PHONY_PACKAGE:= $(BUILD_SYSTEM)/phony_package.mkBUILD_HOST_PREBUILT:= $(BUILD_SYSTEM)/host_prebuilt.mkBUILD_PREBUILT:= $(BUILD_SYSTEM)/prebuilt.mkBUILD_MULTI_PREBUILT:= $(BUILD_SYSTEM)/multi_prebuilt.mkBUILD_JAVA_LIBRARY:= $(BUILD_SYSTEM)/java_library.mkBUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mkBUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mkBUILD_DROIDDOC:= $(BUILD_SYSTEM)/droiddoc.mkBUILD_COPY_HEADERS := $(BUILD_SYSTEM)/copy_headers.mkBUILD_NATIVE_TEST := $(BUILD_SYSTEM)/native_test.mkBUILD_HOST_NATIVE_TEST := $(BUILD_SYSTEM)/host_native_test.mk
然後include進來了/build/core/envsetup.sh,在envsetup.sh中定義了HOST_OS,OUT_DIR等環境變數,並通過include product_config.mk檢索所有Product,並做有效性檢查,然後根據lunch時選擇的Product設定TARGET_DEVICE。
然後在envsetup.sh中根據TARGET_DEVICE尋找BoardConfig.mk檔案進行Board相關配置,尋找KERNEL_HEADER,配置編譯工具鏈。
在definitions.mk中定義了all_makefiles_under等用來檢索檔案的函數。
根據TARGET_BUILD_VARIANT設定ro.secure等系統屬性,設定tags_to_install等變數。
接下來通過
subdir_makefiles := \ $(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git $(subdirs) Android.mk) include $(subdir_makefiles)
找到所有子目錄下的Android.mk檔案並include進來,這樣在Android.mk定義的LOCAL_PACKAGE_NAME與include $(BUILD_PACKAGE)就可以將相應的Android.mk中定義的目標包含進編譯模組中,在config.mk中有如下定義:
BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk
而package.mk又包含base_rules.mk將LOCAL_MODULE添加到ALL_MODULES中。
post_clean.mk是跟Resource Overlay相關,使們們不需要修改framework中原來的資源檔就可以定義framework-res.apk中的資源。
接下來include build/core/Makefile檔案,定義bootimage,systemimage等信賴目標,然後通過make編譯droid(預設)目標就可以編譯系統了。
Android採用檢索所有子目錄中的Android.mk將所有要編譯的模組收集起來的方式編譯系統,而不是進入到每個子目錄執行make,這樣就方便了我們添加自己的模組。