build/envsetup.sh 脚本主体部分 看源代码之前需要了解代码分布和结构,分析Makefile应该是最好的方法。在Blog记录之以备以后查看,也供有兴趣朋友参考。 在编译donut之前,需要运行 cd ~/mydroid . build/envsetup.sh lunch aosp_dream_us-eng make build/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,一个是simulator 2. 运行所有vendor下的 vendorsetup.sh文件,在google官方的 donut源代码中,为vendor/aosp/vendorsetup.sh,内容如下: add_lunch_combo aosp_emulator_us-eng add_lunch_combo aosp_emulator_eu-eng add_lunch_combo aosp_dream_us-userdebug add_lunch_combo aosp_dream_eu-userdebug add_lunch_combo aosp_dream_us-eng add_lunch_combo aosp_dream_eu-eng add_lunch_combo aosp_sapphire_us-userdebug add_lunch_combo aosp_sapphire_eu-userdebug add_lunch_combo aosp_sapphire_us-eng add_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 here add_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 simulator if [ "$(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=1 else _arrayoffset=0 fi unset _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" . $f done unset f 明天接下来看 lunch()函数
build/envsetup.sh 脚本分析(lunch函数) lunch函数提供了一个菜单,让开发人员选择需要编译的目标产品(target product)和变体(variant),并做一些检查,设置环境变量,并打印出主要的环境变量。 直接运行lunch(必须先运行 build/envsetup.sh,让lunch函数驻留到环境变量中) ning@ning-desktop:~/donut-compare/mydroid$ lunch You're building on Linux 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 Lunch 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-eng Which would you like? [generic-eng] 7 ============================================ PLATFORM_VERSION_CODENAME=REL PLATFORM_VERSION=1.6 TARGET_PRODUCT=aosp_dream_us TARGET_BUILD_VARIANT=eng TARGET_SIMULATOR=false TARGET_BUILD_TYPE=release TARGET_ARCH=arm HOST_ARCH=x86 HOST_OS=linux HOST_BUILD_TYPE=release BUILD_ID=Donut ============================================ 用户也可以直接输入参数,不使用菜单 ning@ning-desktop:~/donut-compare/mydroid$ lunch aosp_dream_us-eng ============================================ PLATFORM_VERSION_CODENAME=REL PLATFORM_VERSION=1.6 TARGET_PRODUCT=aosp_dream_us TARGET_BUILD_VARIANT=eng TARGET_SIMULATOR=false TARGET_BUILD_TYPE=release TARGET_ARCH=arm HOST_ARCH=x86 HOST_OS=linux HOST_BUILD_TYPE=release BUILD_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