先整體看一下Android源碼的整個編譯流程,后面會針對每個過程都做了什么來詳細講解一下。
一、源碼編譯過程
- 清空out目錄
make clobber
- 初始化參數(shù)設置
source build/envsetup.sh
- lunch選擇平臺
$ lunch
You're building on Darwin
Lunch menu... pick a combo:
1. aosp_arm-eng
2. aosp_arm64-eng
3. aosp_mips-eng
4. aosp_mips64-eng
5. aosp_x86-eng
6. aosp_x86_64-eng
7. aosp_car_arm-userdebug
8. aosp_car_arm64-userdebug
9. aosp_car_x86-userdebug
10. aosp_car_x86_64-userdebug
11. mini_emulator_arm64-userdebug
12. m_e_arm-userdebug
13. m_e_mips-userdebug
14. m_e_mips64-eng
15. mini_emulator_x86-userdebug
16. mini_emulator_x86_64-userdebug
17. uml-userdebug
......
- 編譯
make -j4
二、參數(shù)初始化(envsetp.sh)
envsetp.sh主要做了兩件事情:加載編譯命令、加載平臺信息。
- 加載編譯命令
function hmm() {
cat <<EOF
Run "m help" for help with the build system itself.
Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:
- lunch: lunch <product_name>-<build_variant>
Selects <product_name> as the product to build, and <build_variant> as the variant to
build, and stores those selections in the environment to be read by subsequent
invocations of 'm' etc.
- tapas: tapas [<App1> <App2> ...] [arm|x86|mips|arm64|x86_64|mips64] [eng|userdebug|user]
- croot: Changes directory to the top of the tree.
- m: Makes from the top of the tree.
- mm: Builds all of the modules in the current directory, but not their dependencies.
- mmm: Builds all of the modules in the supplied directories, but not their dependencies.
To limit the modules being built use the syntax: mmm dir/:target1,target2.
- mma: Builds all of the modules in the current directory, and their dependencies.
- mmma: Builds all of the modules in the supplied directories, and their dependencies.
- provision: Flash device with all required partitions. Options will be passed on to fastboot.
- cgrep: Greps on all local C/C++ files.
- ggrep: Greps on all local Gradle files.
- jgrep: Greps on all local Java files.
- resgrep: Greps on all local res/*.xml files.
- mangrep: Greps on all local AndroidManifest.xml files.
- mgrep: Greps on all local Makefiles files.
- sepgrep: Greps on all local sepolicy files.
- sgrep: Greps on all local source files.
- godir: Go to the directory containing a file.
Environment options:
- SANITIZE_HOST: Set to 'true' to use ASAN for all host modules. Note that
ASAN_OPTIONS=detect_leaks=0 will be set by default until the
build is leak-check clean.
Look at the source to view more functions. The complete list is:
EOF
local T=$(gettop)
local A=""
local i
for i in `cat $T/build/envsetup.sh | sed -n "/^[[:blank:]]*function /s/function \([a-z_]*\).*/\1/p" | sort | uniq`; do
A="$A $i"
done
echo $A
}
腳本執(zhí)行完成后,會把上面的所有命令都加載到終端上,后面才能夠使用上面的這些命令,否則執(zhí)行上面的命令會提示-bash: ***: command not found
- 加載平臺信息
if [ "x$SHELL" != "x/bin/bash" ]; then
case `ps -o command -p $$` in
*bash*)
;;
*)
echo "WARNING: Only bash is supported, use of other shell would lead to erroneous results"
;;
esac
fi
# Execute the contents of any vendorsetup.sh files we can find.
for f in `test -d device && find -L device -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort` \
`test -d vendor && find -L vendor -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort` \
`test -d product && find -L product -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort`
do
從代碼中可以看到回去查找device、vendor、product下的vendorsetup.sh腳本并進行加載。
這里有一個需要注意的地方就是必須使用bash執(zhí)行envsetp.sh腳本。
三、lunch
先看一下lunch命令做了些什么
function lunch()
{
local answer
if [ "$1" ] ; then
answer=$1
else
print_lunch_menu
echo -n "Which would you like? [aosp_arm-eng] "
read answer
fi
......
}
如果lunch后面帶了參數(shù)繼續(xù)執(zhí)行,沒帶參數(shù)會調用print_lunch_menu去打印提示信息
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
}
平臺信息是從LUNCH_MENU_CHOICES變量中獲取并打印出來的,LUNCH_MENU_CHOICES變量是通過add_lunch_combo函數(shù)來進行設置的:
unset LUNCH_MENU_CHOICES
function add_lunch_combo()
{
local new_combo=$1
local c
for c in ${LUNCH_MENU_CHOICES[@]} ; do
if [ "$new_combo" = "$c" ] ; then
return
fi
done
LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo)
}
那add_lunch_combo是在什么時候調用的呢?還記得上一步中加載的vendorsetup.sh腳本嗎?
這里可以找一個vendorsetup.sh看一下他里面做了什么操作;
下面是device/generic/mini-emulator-arm64/vendorsetup.sh腳本的內容:
# This file is executed by build/envsetup.sh, and can use anything
# defined in envsetup.sh.
#
# In particular, you can add lunch options with the add_lunch_combo
# function: add_lunch_combo generic-eng
add_lunch_combo mini_emulator_x86-userdebug
當我們選擇完一個平臺后lunch會記錄下選擇的平臺,并做一系列的初始化操作,這樣就完成了環(huán)境變量的配置
Which would you like? [aosp_arm-eng] aosp_x86_64-eng
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=9 //android版本9.0
TARGET_PRODUCT=aosp_x86_64 //生成的目標
TARGET_BUILD_VARIANT=eng //eng版本
TARGET_BUILD_TYPE=release
TARGET_ARCH=x86_64
TARGET_ARCH_VARIANT=x86_64
TARGET_2ND_ARCH=x86
TARGET_2ND_ARCH_VARIANT=x86_64 // 工具鏈x86
HOST_ARCH=x86_64
HOST_2ND_ARCH=x86
HOST_OS=darwin
HOST_OS_EXTRA=Darwin-18.6.0-x86_64-10.14.5
HOST_BUILD_TYPE=release
BUILD_ID=PQ3B.190605.006
OUT_DIR=out
============================================
再看一下環(huán)境變量,會看到增加了很多Android相關的環(huán)境變量
$ export
declare -x ANDROID_BUILD_PATHS="/Volumes/M1/aosp/android9.0/out/soong/host/darwin-x86/bin:/Volumes/M1/aosp/android9.0/out/host/darwin-x86/bin:/Volumes/M1/aosp/android9.0/prebuilts/gcc/darwin-x86/x86/x86_64-linux-android-4.9/bin:/Volumes/M1/aosp/android9.0/development/scripts:/Volumes/M1/aosp/android9.0/prebuilts/devtools/tools:/Volumes/M1/aosp/android9.0/external/selinux/prebuilts/bin:/Volumes/M1/aosp/android9.0/prebuilts/android-emulator/darwin-x86_64:"
declare -x ANDROID_BUILD_TOP="/Volumes/M1/aosp/android9.0"
declare -x ANDROID_DEV_SCRIPTS="/Volumes/M1/aosp/android9.0/development/scripts:/Volumes/M1/aosp/android9.0/prebuilts/devtools/tools:/Volumes/M1/aosp/android9.0/external/selinux/prebuilts/bin"
declare -x ANDROID_EMULATOR_PREBUILTS="/Volumes/M1/aosp/android9.0/prebuilts/android-emulator/darwin-x86_64"
declare -x ANDROID_HOME="/Users/huangyoubin/Library/Android/sdk"
declare -x ANDROID_HOST_OUT="/Volumes/M1/aosp/android9.0/out/host/darwin-x86"
declare -x ANDROID_HOST_OUT_TESTCASES="/Volumes/M1/aosp/android9.0/out/host/darwin-x86/testcases"
declare -x ANDROID_JAVA_HOME="/Volumes/M1/aosp/android9.0/prebuilts/jdk/jdk9/darwin-x86"
declare -x ANDROID_JAVA_TOOLCHAIN="/Volumes/M1/aosp/android9.0/prebuilts/jdk/jdk9/darwin-x86/bin"
declare -x ANDROID_NDK="/Users/huangyoubin/Library/Android/sdk/ndk-bundle"
declare -x ANDROID_PRE_BUILD_PATHS="/Volumes/M1/aosp/android9.0/prebuilts/jdk/jdk9/darwin-x86/bin:"
declare -x ANDROID_PRODUCT_OUT="/Volumes/M1/aosp/android9.0/out/target/product/generic_x86_64"
declare -x ANDROID_TARGET_OUT_TESTCASES="/Volumes/M1/aosp/android9.0/out/target/product/generic_x86_64/testcases"
declare -x ANDROID_TOOLCHAIN="/Volumes/M1/aosp/android9.0/prebuilts/gcc/darwin-x86/x86/x86_64-linux-android-4.9/bin"
最后就可以使用make命令進行源碼編譯了