AOSP编译系统初探(二)
来源:互联网 发布:国外大学网络课程证书 编辑:程序博客网 时间:2024/05/21 15:47
(二)编译的第二步是用lunch命令来选择一个编译目标以完成基本的编译信息配置,也可以通过带参数的lunch命令来直接选择一个编译目标。如果运行不带参数的lunch命令,终端输出如下:
$ lunchYou're building on LinuxLunch 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_manta-userdebug 8. aosp_deb-userdebug 9. aosp_grouper-userdebug 10. full_fugu-userdebug 11. aosp_fugu-userdebug 12. aosp_tilapia-userdebug 13. aosp_flo-userdebug 14. aosp_nx40x-userdebug 15. aosp_aries-userdebug 16. aosp_shamu-userdebug 17. mini_emulator_arm64-userdebug 18. mini_emulator_arm-userdebug 19. mini_emulator_x86-userdebug 20. mini_emulator_mips-userdebug 21. mini_emulator_x86_64-userdebug 22. aosp_mako-userdebug 23. aosp_hammerhead-userdebugWhich would you like? [aosp_arm-eng]然后输入一个序号来选择一个编译目标,或直接按【ENTER】来选择默认的选项。如果输入合法的话,终端输出如下。
============================================PLATFORM_VERSION_CODENAME=RELPLATFORM_VERSION=5.0.1TARGET_PRODUCT=aosp_armTARGET_BUILD_VARIANT=engTARGET_BUILD_TYPE=releaseTARGET_BUILD_APPS=TARGET_ARCH=armTARGET_ARCH_VARIANT=armv7-aTARGET_CPU_VARIANT=genericTARGET_2ND_ARCH=TARGET_2ND_ARCH_VARIANT=TARGET_2ND_CPU_VARIANT=HOST_ARCH=x86_64HOST_OS=linuxHOST_OS_EXTRA=Linux-3.13.0-43-generic-x86_64-with-Ubuntu-12.04-preciseHOST_BUILD_TYPE=releaseBUILD_ID=LRX22COUT_DIR=out============================================
可以看到运行完lunch之后,很多自定义变量便获得了与你选择的编译目标相对应的值。这是如何完成的呢?
lunch是定义在build/envsetup.sh中的一个脚本函数,内容如下。
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 local selection= if [ -z "$answer" ] then selection=aosp_arm-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= 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 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 export TARGET_PRODUCT=$product export TARGET_BUILD_VARIANT=$variant export TARGET_BUILD_TYPE=release echo set_stuff_for_environment printconfig}
下面分成几个部分来理解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命令,则将第一个参数赋值给answer;否则,调用print_lunch_menu函数在终端中显示在上一步中获得的所有编译目标,然后将从终端中获得的输入赋值给answer。print_lunch_menu也是定义在build/envsetup.sh中,内容如下。
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}这个函数还是比较简单的,主要部分是使用一个for循环来将上一步构造的LUNCH_NEMU_CHOICES数组中的每一项输出。
lunch函数的第二部分如下:
local selection= if [ -z "$answer" ] then selection=aosp_arm-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这一部分的逻辑是:如果answer为空,即不带参数调用lunch并且在lunch的输入中直接按【ENTER】,则将默认的编译目标aosp_arm-eng赋值给selection。当answer不为空,即带参数调用lunch或者不带参数调用lunch但之后的输入阶段确实输入了某些值时,如果answer是纯数字,那么在answer不超过LUNCH_MENU_CHOICES数组的项数时,将数组中第answer项赋值给selection;如果answer符合<producn>-<variant>的格式的话,就将answer直接赋值给selection。经过这些检测之后,如果selection仍为空,就中断运行,返回错误码。因为这意味着answer不符合正确的输入要求。
在这段代码执行之后,selection就是符合<product>-<variant>格式的变量。在AOSP的逻辑中<product>表示设备代号,而<variant>表示编译类型。<product>会影响之后的编译信息的配置,<variant>必须是eng、userdebug、user中的一个。
export TARGET_BUILD_APPS= 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 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_BUILD_APPS,然后通过调用check_product和check_variant两个函数来检测selection中的<product>和<variant>的合法性,如果有不合法的则中断程序运行,返回错误码。check_product和check_variant同样都定义于build/envsetup.sh文件中。check_variant的内容如下:
VARIANT_CHOICES=(user userdebug eng)# check to see if the supplied variant is validfunction check_variant(){ for v in ${VARIANT_CHOICES[@]} do if [ "$v" = "$1" ] then return 0 fi done return 1}函数的逻辑很简单,就是确认variant的值是否是eng、userdebug、user中的一个,分别代表工程测试版、用户调试版和最终用户版。不同的类型会影响编译过程中所用到的辅助调试工具。
check_product的内容如下:
# check to see if the supplied product is one we can buildfunction check_product(){ T=$(gettop) if [ ! "$T" ]; then echo "Couldn't locate the top of the tree. Try setting TOP." >&2 return fi TARGET_PRODUCT=$1 \ TARGET_BUILD_VARIANT= \ TARGET_BUILD_TYPE= \ TARGET_BUILD_APPS= \ get_build_var TARGET_DEVICE > /dev/null # hide successful answers, but allow the errors to show}函数gettop用来获得aosp根目录的绝对路径,如果当前处于aosp目录之外则gettop无返回值。从而通过if实现了检测是否处于aosp目录中的功能,即需要在aosp根目录或其子目录下执行lunch命令。gettop和check_product调用的另一个shell函数get_build_var都定义于build/envsetup.sh文件中。get_build_var函数的内容如下。
# Get the exact value of a build variable.function get_build_var(){ T=$(gettop) if [ ! "$T" ]; then echo "Couldn't locate the top of the tree. Try setting TOP." >&2 return fi (\cd $T; CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \ command make --no-print-directory -f build/core/config.mk dumpvar-$1)}可以看到get_build_var同样执行了一个对当前目录的检测。其中定义了两个变量CALLED_FROM_SETUP和BUILD_SYSTEM,前者值为true时表示此时为配置编译环境的阶段,会影响后一句make命令的执行过程。BUILD_SYSTEM指明编译配置文件的位置。get_build_var的核心指令为“make --no-print-directory -f build/core/config.mk dumpvar-$1”。对于check_product,$1值为TARGET_DEVICE,所以此时执行的实际为“make --no-print-directory -f build/core/config.mk dumpvar-TARGET_DEVICE”。aosp的编译系统主要由两部分组成,一个是shell脚本,另一个即是make系统。这里初次触及到make部分。
暂不探究aosp中的诸多MAKEFILE文件,继续看lunch函数的其余部分。
export TARGET_PRODUCT=$product export TARGET_BUILD_VARIANT=$variant export TARGET_BUILD_TYPE=release echo set_stuff_for_environment printconfig这里设定了三个环境变量,供之后的make环节使用。这里调用的两个shell函数set_stuff_for_environment和printconfig内容如下:
function set_stuff_for_environment(){ settitle set_java_home setpaths set_sequence_number export ANDROID_BUILD_TOP=$(gettop) # With this environment variable new GCC can apply colors to warnings/errors export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'}function printconfig(){ T=$(gettop) if [ ! "$T" ]; then echo "Couldn't locate the top of the tree. Try setting TOP." >&2 return fi get_build_var report_config}
可以看到printconfig同样调用了get_build_var函数,只是参数不同。而set_stuff_for_environment则在设定了两个环境变量外又调用了另外四个shell函数。下面分别分析这四个函数。
1. settitle
function settitle(){ if [ "$STAY_OFF_MY_LAWN" = "" ]; then local arch=$(gettargetarch) local product=$TARGET_PRODUCT local variant=$TARGET_BUILD_VARIANT local apps=$TARGET_BUILD_APPS if [ -z "$apps" ]; then export PROMPT_COMMAND="echo -ne \"\033]0;[${arch}-${product}-${variant}] ${USER}@${HOSTNAME}: ${PWD}\007\"" else export PROMPT_COMMAND="echo -ne \"\033]0;[$arch $apps $variant] ${USER}@${HOSTNAME}: ${PWD}\007\"" fi fi}settitle主要是设定一个环境变量PROMPT_COMMAND,唯一一个用到的函数gettargetarch内容为“get_build_var TARGET_ARCH”,同样也为获得由<product>和<variant>决定的其他编译参数。这个环境变量的作用需要在之后的使用中再来分析。
2. set_java_home
# Force JAVA_HOME to point to java 1.7 or java 1.6 if it isn't already set.## Note that the MacOS path for java 1.7 includes a minor revision number (sigh).# For some reason, installing the JDK doesn't make it show up in the# JavaVM.framework/Versions/1.7/ folder.function set_java_home() { # Clear the existing JAVA_HOME value if we set it ourselves, so that # we can reset it later, depending on the version of java the build # system needs. # # If we don't do this, the JAVA_HOME value set by the first call to # build/envsetup.sh will persist forever. if [ -n "$ANDROID_SET_JAVA_HOME" ]; then export JAVA_HOME="" fi if [ ! "$JAVA_HOME" ]; then if [ -n "$LEGACY_USE_JAVA6" ]; then case `uname -s` in Darwin) export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home ;; *) export JAVA_HOME=/usr/lib/jvm/java-6-sun ;; esac else case `uname -s` in Darwin) export JAVA_HOME=$(/usr/libexec/java_home -v 1.7) ;; *) export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64 ;; esac fi # Keep track of the fact that we set JAVA_HOME ourselves, so that # we can change it on the next envsetup.sh, if required. export ANDROID_SET_JAVA_HOME=true fi}从注释也可以看出来这个函数的功能就是配置JAVA_HOME这个环境变量,使其指向正确的目录,并设置一个新的环境变量ANDROID_SET_JAVA_HOME来记录是否执行了这个检测。
3. setpaths
setpaths的内容较长,并且调用了许多build/envsetup.sh中的其他函数,所以就不贴这些代码了。这个函数的功能主要是向PATH环境变量中增加AOSP目录下一些路径并且设定了许多和AOSP目录有关的环境变量。
4. set_sequence_number
这个函数只有一条语句:“export BUILD_ENV_SEQUENCE_NUMBER=10”。这个环境变量的作用暂时还不知道。
综上,lunch的作用就是获得之后的编译所针对的<product>和<variant>,检测它们的合法性,从各种配置文件中找到由这两个参数派生出来的其他编译参数并导出为各个环境变量。如下是lunch设置的环境变量和更改后的PATH环境变量:
ANDROID_DEV_SCRIPTS=/home/user/mnt/aosp/android-5.0.1_r1/development/scripts:/home/user/mnt/aosp/android-5.0.1_r1/prebuilts/devtools/toolsARM_EABI_TOOLCHAIN=/home/user/mnt/aosp/android-5.0.1_r1/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/binANDROID_PRE_BUILD_PATHS=/usr/lib/jvm/java-7-openjdk-amd64/bin:ANDROID_BUILD_TOP=/home/user/mnt/aosp/android-5.0.1_r1ANDROID_PRODUCT_OUT=/home/user/mnt/aosp/android-5.0.1_r1/out/target/product/genericANDROID_JAVA_TOOLCHAIN=/usr/lib/jvm/java-7-openjdk-amd64/binOUT=/home/user/mnt/aosp/android-5.0.1_r1/out/target/product/genericTARGET_BUILD_VARIANT=engBUILD_ENV_SEQUENCE_NUMBER=10ANDROID_BUILD_PATHS=/home/user/mnt/aosp/android-5.0.1_r1/out/host/linux-x86/bin:/home/user/mnt/aosp/android-5.0.1_r1/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin:/home/user/mnt/aosp/android-5.0.1_r1/prebuilts/gcc/linux-x86/:/home/user/mnt/aosp/android-5.0.1_r1/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin:/home/user/mnt/aosp/android-5.0.1_r1/development/scripts:/home/user/mnt/aosp/android-5.0.1_r1/prebuilts/devtools/tools:/home/user/mnt/aosp/android-5.0.1_r1/prebuilts/android-emulator/linux-x86_64:TARGET_BUILD_APPS=TARGET_BUILD_TYPE=releasePATH=/usr/lib/jvm/java-7-openjdk-amd64/bin:/home/user/mnt/aosp/android-5.0.1_r1/out/host/linux-x86/bin:/home/user/mnt/aosp/android-5.0.1_r1/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin:/home/user/mnt/aosp/android-5.0.1_r1/prebuilts/gcc/linux-x86/:/home/user/mnt/aosp/android-5.0.1_r1/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin:/home/user/mnt/aosp/android-5.0.1_r1/development/scripts:/home/user/mnt/aosp/android-5.0.1_r1/prebuilts/devtools/tools:/home/user/mnt/aosp/android-5.0.1_r1/prebuilts/android-emulator/linux-x86_64:/home/user/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/gamesJAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64ANDROID_TOOLCHAIN=/home/user/mnt/aosp/android-5.0.1_r1/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/binANDROID_TOOLCHAIN_2ND_ARCH=/home/user/mnt/aosp/android-5.0.1_r1/prebuilts/gcc/linux-x86/GCC_COLORS=error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01ANDROID_EMULATOR_PREBUILTS=/home/user/mnt/aosp/android-5.0.1_r1/prebuilts/android-emulator/linux-x86_64TARGET_GCC_VERSION=4.8PROMPT_COMMAND=echo -ne "\033]0;[arm-aosp_arm-eng] user@Aspire-4750: /home/user/mnt/aosp/android-5.0.1_r1\007"ANDROID_HOST_OUT=/home/user/mnt/aosp/android-5.0.1_r1/out/host/linux-x86ANDROID_SET_JAVA_HOME=trueTARGET_PRODUCT=aosp_arm
- AOSP编译系统初探(二)
- AOSP编译系统初探(一)
- 编译android源代码(aosp)
- AOSP编译
- Android6.0源码编译笔记(二)-利用国内镜像源同步AOSP源码
- ubuntu14.04 配置 AOSP(android open source project)android系统源码编译环境
- Android N AOSP:HWUI学习(二)
- MTK AOSP项目编译
- AOSP编译问题记录
- Sierra下编译Aosp
- [Android]Ubuntu编译AOSP
- AOSP build 系统简介
- 修改编译Nexus5x android7.0.1(N)版本内核(AOSP)
- Mac下Android源码(AOSP)编译环境搭建方法
- Android 编译系统 (二)
- Android 编译系统 (二)
- Android 编译系统 (二)
- Android 编译系统 (二)
- MFC ListControl的应用
- C++ 如何一次性获取用户输入并判断是否为数字?
- Android 4.4电源管理
- Reverse Integer [Easy]
- cximage 进行gif 背景透明处理
- AOSP编译系统初探(二)
- 第十七周 【OJ-问题 E: 重复字符串】
- 应用汇
- CSS
- hbase安装
- Linux中cut命令
- c++的某些操作符为什么要返回引用?为什么经常有书中说对于一些操作符我们要尊重内置类的操作符,所以要返回引用
- Android自定义发送本地广播
- java中的多线程