Android Donut Makefile分析 (build/envsetup.sh)

来源:互联网 发布:淘宝开店要两个银行卡 编辑:程序博客网 时间:2024/04/17 04:46
build/envsetup.sh 脚本主体部分看源代码之前需要了解代码分布和结构,分析Makefile应该是最好的方法。在Blog记录之以备以后查看,也供有兴趣朋友参考。在编译donut之前,需要运行cd ~/mydroid. build/envsetup.shlunch aosp_dream_us-engmakebuild/envsetup.sh 是编译android的入口。该shell脚本定义了一些函数,并设定了编译的环境变量。lunch aosp_dream_us-eng 配置用户需要编译的目标产品(target product)和变体(variant)。aosp_dream_us-eng 字符串包含了target product  和variant,它们用减号-隔开,aosp_dream_us是target product,eng是variant。variant 有三种选择user userdebug eng,可以从字面上看出其意义,但具体的差别还不是特别清楚,待后面分析之。lunch 的入口是让用户指定或者选择需要编译的target product 和 variant,出口是设定编译相关的环境变量。build/envsetup.sh 定义了很多函数,并且执行的脚本很分散,因此下面将所有的函数都删除掉了,剩余下脚本的主体,便于代码分析和走读。该主体主要做的事情是:1. 首先脚本设定了两个缺省的target product,一个是generic-eng,一个是simulator2. 运行所有vendor下的 vendorsetup.sh文件,在google官方的 donut源代码中,为vendor/aosp/vendorsetup.sh,内容如下:add_lunch_combo aosp_emulator_us-engadd_lunch_combo aosp_emulator_eu-engadd_lunch_combo aosp_dream_us-userdebugadd_lunch_combo aosp_dream_eu-userdebugadd_lunch_combo aosp_dream_us-engadd_lunch_combo aosp_dream_eu-engadd_lunch_combo aosp_sapphire_us-userdebugadd_lunch_combo aosp_sapphire_eu-userdebugadd_lunch_combo aosp_sapphire_us-engadd_lunch_combo aosp_sapphire_eu-eng可以看出,又添加了一些 和 aosp 相关的 target product 和 variant。下面是脚本主体,用蓝色添加了一下注释,便于阅读:# 定义了 variant的字符范围VARIANT_CHOICES=(user userdebug eng)# 如果是Linux环境,定义了几个和simulator相关的函数case `uname -s` in    Linux)        function choosesim()        {            echo "Build for the simulator or the device?"            echo "     1. Device"            echo "     2. Simulator"            echo            export TARGET_SIMULATOR=            local ANSWER            while [ -z $TARGET_SIMULATOR ]            do                echo -n "Which would you like? [1] "                if [ -z "$1" ] ; then                    read ANSWER                else                    echo $1                    ANSWER=$1                fi                case $ANSWER in                "")                    export TARGET_SIMULATOR=false                    ;;                1)                    export TARGET_SIMULATOR=false                    ;;                Device)                    export TARGET_SIMULATOR=false                    ;;                2)                    export TARGET_SIMULATOR=true                    ;;                Simulator)                    export TARGET_SIMULATOR=true                    ;;                *)                    echo                    echo "I didn't understand your response.  Please try again."                    echo                    ;;                esac                if [ -n "$1" ] ; then                    break                fi            done            set_stuff_for_environment        }        ;;    *)        function choosesim()        {            echo "Only device builds are supported for" `uname -s`            echo "     Forcing TARGET_SIMULATOR=false"            echo            if [ -z "$1" ]            then                echo -n "Press enter: "                read            fi            export TARGET_SIMULATOR=false            set_stuff_for_environment        }        ;;esac# 首先将 LUNCH_MENU_CHOICES 变量消除# Clear this variable.  It will be built up again when the vendorsetup.sh# files are included at the end of this file.unset LUNCH_MENU_CHOICES          # 当前 LUNCH_MENU_CHOICES = generic-eng# add the default one hereadd_lunch_combo generic-eng         # 当前 LUNCH_MENU_CHOICES = generic-eng simulator# if we're on linux, add the simulator.  There is a special case# in lunch to deal with the simulatorif [ "$(uname)" = "Linux" ] ; then        add_lunch_combo simulator       fi# 这里是MAC OS的环境,不考虑case `uname -s` in      Darwin)        function mgrep()        {            find -E . -type f -iregex '.*/(Makefile|Makefile\..*|.*\.make|.*\.mak|.*\.mk)' -print0 | xargs -0 grep --color -n "$@"        }        function treegrep()        {            find -E . -type f -iregex '.*\.(c|h|cpp|S|java|xml)' -print0 | xargs -0 grep --color -n -i "$@"        }        ;;    *)        function mgrep()        {            find . -regextype posix-egrep -iregex '(.*\/Makefile|.*\/Makefile\..*|.*\.make|.*\.mak|.*\.mk)' -type f -print0 | xargs -0 grep --color -n "$@"        }        function treegrep()        {            find . -regextype posix-egrep -iregex '.*\.(c|h|cpp|S|java|xml)' -type f -print0 | xargs -0 grep --color -n -i "$@"        }        ;;esac# 设定当前shell环境的数组下标从0开始还是1开始,并记录在 _arrayoffset# determine whether arrays are zero-based (bash) or one-based (zsh)_xarray=(a b c)if [ -z "${_xarray[${#_xarray[@]}]}" ]then    _arrayoffset=1else    _arrayoffset=0fiunset _xarray# 运行所有vendor下的 vendorsetup.sh文件#存在vendor/aosp/vendorsetup.sh当前 LUNCH_MENU_CHOICES = generic-eng simulator aosp_emulator_us-eng aosp_emulator_eu-eng aosp_dream_us-userdebug aosp_dream_eu-userdebug aosp_dream_us-eng aosp_dream_eu-eng aosp_sapphire_us-userdebug aosp_sapphire_eu-userdebug aosp_sapphire_us-eng aosp_sapphire_eu-eng# Execute the contents of any vendorsetup.sh files we can find.for f in `/bin/ls vendor/*/vendorsetup.sh vendor/*/build/vendorsetup.sh 2> /dev/null` do    echo "including $f"    . $fdoneunset f明天接下来看 lunch()函数


build/envsetup.sh 脚本分析(lunch函数)lunch函数提供了一个菜单,让开发人员选择需要编译的目标产品(target product)和变体(variant),并做一些检查,设置环境变量,并打印出主要的环境变量。直接运行lunch(必须先运行 build/envsetup.sh,让lunch函数驻留到环境变量中)ning@ning-desktop:~/donut-compare/mydroid$ lunchYou're building on Linuxgeneric-eng simulator aosp_emulator_us-eng aosp_emulator_eu-eng aosp_dream_us-userdebug aosp_dream_eu-userdebug aosp_dream_us-eng aosp_dream_eu-eng aosp_sapphire_us-userdebug aosp_sapphire_eu-userdebug aosp_sapphire_us-eng aosp_sapphire_eu-engLunch menu... pick a combo:     1. generic-eng     2. simulator     3. aosp_emulator_us-eng     4. aosp_emulator_eu-eng     5. aosp_dream_us-userdebug     6. aosp_dream_eu-userdebug     7. aosp_dream_us-eng     8. aosp_dream_eu-eng     9. aosp_sapphire_us-userdebug     10. aosp_sapphire_eu-userdebug     11. aosp_sapphire_us-eng     12. aosp_sapphire_eu-engWhich would you like? [generic-eng] 7============================================PLATFORM_VERSION_CODENAME=RELPLATFORM_VERSION=1.6TARGET_PRODUCT=aosp_dream_usTARGET_BUILD_VARIANT=engTARGET_SIMULATOR=falseTARGET_BUILD_TYPE=releaseTARGET_ARCH=armHOST_ARCH=x86HOST_OS=linuxHOST_BUILD_TYPE=releaseBUILD_ID=Donut============================================用户也可以直接输入参数,不使用菜单ning@ning-desktop:~/donut-compare/mydroid$ lunch aosp_dream_us-eng============================================PLATFORM_VERSION_CODENAME=RELPLATFORM_VERSION=1.6TARGET_PRODUCT=aosp_dream_usTARGET_BUILD_VARIANT=engTARGET_SIMULATOR=falseTARGET_BUILD_TYPE=releaseTARGET_ARCH=armHOST_ARCH=x86HOST_OS=linuxHOST_BUILD_TYPE=releaseBUILD_ID=Donut============================================下面是lunch函数源代码,用蓝色添加了一下注释,便于阅读:function lunch(){    local answer    if [ "$1" ] ; then       # lunch后面直接带参数        answer=$1    else       # lunch后面不带参数,则打印处所有的target product和variant菜单提供用户选择        print_lunch_menu           echo -n "Which would you like? [generic-eng] "        read answer    fi    local selection=    if [ -z "$answer" ]    then           # 如果用户在菜单中没有选择,直接回车,则为系统缺省的generic-eng        selection=generic-eng    elif [ "$answer" = "simulator" ]    then        # 如果是模拟器        selection=simulator    elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")    then        # 如果answer是选择菜单的数字,则获取该数字对应的字符串        if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ]        then            selection=${LUNCH_MENU_CHOICES[$(($answer-$_arrayoffset))]}        fi        # 如果 answer字符串匹配 *-*模式(*的开头不能为-)    elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$")    then        selection=$answer    fi    if [ -z "$selection" ]    then        echo        echo "Invalid lunch combo: $answer"        return 1    fi    # special case the simulator    if [ "$selection" = "simulator" ]    then        # 模拟器模式        export TARGET_PRODUCT=sim        export TARGET_BUILD_VARIANT=eng        export TARGET_SIMULATOR=true        export TARGET_BUILD_TYPE=debug    else        # 将 product-variant模式种的product分离出来        local product=$(echo -n $selection | sed -e "s/-.*$//")        # 检查之,调用关系 check_product()->get_build_var()->build/core/config.mk比较罗嗦,不展开了        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        # 将 product-variant模式种的variant分离出来        local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//")        # 检查之,看看是否在 (user userdebug eng) 范围内        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_SIMULATOR=false        export TARGET_BUILD_TYPE=release    fi # !simulator    echo    # 设置到环境变量,比较多,不再一一列出,最 简单的方法 set >env.txt 可获得    set_stuff_for_environment    # 打印一些主要的变量, 调用关系 printconfig()->get_build_var()->build/core/config.mk->build/core/envsetup.mk 比较罗嗦,不展开了    printconfig}
原文链接:http://www.lupaworld.com/home.php?mod=space&uid=131820&do=blog&id=149463

原创粉丝点击