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


0 0
原创粉丝点击