阅读本文前请先阅读
2014-02-26
这一步是选择要编译的产品。
2014-02-27
在文档中分析函数调用真的不是很方便,这里先试着用缩进表示函数的层次,缩进越多表示被调用的层级越深(很遗憾,插入的代码无法缩进显示)。因为有些代码片段只属于函数的一部分,所以在代码片段上都表明了所属的函数(红色背景,白色字体)。
lunch
function lunch() { local answer if [ "$1" ] ; then answer=$1 else print_lunch_menu echo -n "Which would you like? [full-eng] " read answer fi
如果我们调用lunch命令时传入了参数,就赋值给answer;否则就执行print_lunch_menu,并等待用户输入。
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:
1 local selection= 2 3 if [ -z "$answer" ] #如果没有输入 4 then 5 selection=full-eng #默认为 full-eng 6 elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$") #匹配字符串:以一个数字开头,后面是任意个数字 7 then 8 if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ] #如果数字数值小于或等于产品列表中产品数目 9 then 10 selection=${LUNCH_MENU_CHOICES[$(($answer-1))]} #选择对应的产品 11 fi 12 elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$") #匹配字符串:类似full-eng格式的字符串 13 then 14 selection=$answer 15 fi 16 17 if [ -z "$selection" ] #找不到对应的产品 18 then 19 echo 20 echo "Invalid lunch combo: $answer" 21 return 1 22 fi
这段代码功能是处理用户输入,用户可以输入数字,也可以输入产品名。$selection 变量最终存储产品名称。具体分析见代码注释。
lunch:
1 local product=$(echo -n $selection | sed -e "s/-.*$//") #去除字符串中以 ‘-’ 字符开头的部分,效果是:full-eng只剩下full,也就
#是产品名 2 check_product $product 3 if [ $? -ne 0 ] 4 then 5 echo 6 echo "** Don't have a product spec for: '$product'" 7 echo "** Do you have the right repo manifest?" 8 product= 9 fi 10 11 local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//") #去除字符串中不以'-'开头但以'-'结尾的部分,效果是full-eng #只剩下eng,也就是变种名 12 check_variant $variant 13 if [ $? -ne 0 ] 14 then 15 echo 16 echo "** Invalid variant: '$variant'" 17 echo "** Must be one of ${VARIANT_CHOICES[@]}" 18 variant= 19 fi 20 21 if [ -z "$product" -o -z "$variant" ] #判断是否有不满足条件的情况 22 then 23 echo 24 return 1 25 fi 26 27 export TARGET_PRODUCT=$product #导出产品名 full 28 export TARGET_BUILD_VARIANT=$variant #导出变种名 eng 29 export TARGET_BUILD_TYPE=release #导出类型为 release
以上代码根据用户最终的选择分析出产品名和变种名。
lunch:
1 set_stuff_for_environment
set_stuff_for_environment:
1 function set_stuff_for_environment() 2 { 3 settitle
settitle:
1 function settitle() 2 { 3 if [ "$STAY_OFF_MY_LAWN" = "" ]; then 4 local product=$TARGET_PRODUCT 5 local variant=$TARGET_BUILD_VARIANT 6 local apps=$TARGET_BUILD_APPS 7 if [ -z "$apps" ]; then 8 export PROMPT_COMMAND="echo -ne \"\033]0;[${product}-${variant}] ${USER}@${HOSTNAME}: ${PWD}\007\"" 9 else 10 export PROMPT_COMMAND="echo -ne \"\033]0;[$apps $variant] ${USER}@${HOSTNAME}: ${PWD}\007\"" 11 fi 12 fi 13 }
看来主要目的是设置 PROMPT_COMMAND 变量,但是还没发现是被什么地方调用的,暂且跳过(Todo)。
set_stuff_for_environment:
1 set_java_home
set_java_home:
1 function set_java_home() { 2 if [ ! "$JAVA_HOME" ]; then 3 case `uname -s` in 4 Darwin) 5 export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home 6 ;; 7 *) 8 export JAVA_HOME=/usr/lib/jvm/java-6-sun 9 ;; 10 esac 11 fi 12 }
设置JAVA_HOME环境变量
set_stuff_for_environment:
1 setpaths
setpaths:
1 function setpaths() 2 { 3 T=$(gettop) 4 if [ ! "$T" ]; then 5 echo "Couldn't locate the top of the tree. Try setting TOP." 6 return 7 fi
获取顶层目录:*/android
gettop
1 function gettop 2 { 3 local TOPFILE=build/core/envsetup.mk 4 if [ -n "$TOP" -a -f "$TOP/$TOPFILE" ] ; then #如果已经设置过TOP,并且当前目录存在文件 "build/core/envsetup.mk" 5 echo $TOP 6 else 7 if [ -f $TOPFILE ] ; then 8 # The following circumlocution (repeated below as well) ensures 9 # that we record the true directory name and not one that is 10 # faked up with symlink names. 11 PWD= /bin/pwd 12 else 13 # We redirect cd to /dev/null in case it's aliased to 14 # a command that prints something as a side-effect 15 # (like pushd) 16 local HERE=$PWD 17 T= 18 while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do #如果不存在$TOPFILE且还没到根目录 19 cd .. > /dev/null #返回到上层目录 20 T=`PWD= /bin/pwd` 21 done 22 cd $HERE > /dev/null 23 if [ -f "$T/$TOPFILE" ]; then 24 echo $T #返回顶层目录:*/android 25 fi 26 fi 27 fi 28 }
感觉分析这个函数有点难度,不过最终目的是找到包含“build/core/envsetup.mk”文件的目录,即安卓源码的根目录:*/android
setpaths:
1 # out with the old 2 if [ -n "$ANDROID_BUILD_PATHS" ] ; then 3 export PATH=${PATH/$ANDROID_BUILD_PATHS/} 4 fi 5 if [ -n "$ANDROID_PRE_BUILD_PATHS" ] ; then 6 export PATH=${PATH/$ANDROID_PRE_BUILD_PATHS/} 7 # strip trailing ':', if any 8 export PATH=${PATH/%:/} 9 fi
功能:如果之前在“PATH”中设置过“ANDROID_BUILD_PATHS”和“ANDROID_PRE_BUILD_PATHS”,则将其清除。
setpaths
1 # and in with the new 2 CODE_REVIEWS= 3 prebuiltdir=$(getprebuilt) #获取prebuild目录,实际上返回的是:android/prebuilt/linux-x86 4 5 # The gcc toolchain does not exists for windows/cygwin. In this case, do not reference it. 6 export ANDROID_EABI_TOOLCHAIN= 7 toolchaindir=toolchain/arm-linux-androideabi-4.4.x/bin 8 if [ -d "$prebuiltdir/$toolchaindir" ]; then 9 export ANDROID_EABI_TOOLCHAIN=$prebuiltdir/$toolchaindir 10 fi 11 12 export ARM_EABI_TOOLCHAIN= 13 toolchaindir=toolchain/arm-eabi-4.4.3/bin 14 if [ -d "$prebuiltdir/$toolchaindir" ]; then 15 export ARM_EABI_TOOLCHAIN=$prebuiltdir/$toolchaindir 16 fi 17 18 export ANDROID_TOOLCHAIN=$ANDROID_EABI_TOOLCHAIN 19 export ANDROID_QTOOLS=$T/development/emulator/qtools 20 export ANDROID_BUILD_PATHS=:$(get_build_var ANDROID_BUILD_PATHS):$ANDROID_QTOOLS:$ANDROID_TOOLCHAIN:$ARM_EABI_TOOLCHAIN$CODE_REVIEWS 21 export PATH=$PATH$ANDROID_BUILD_PATHS 22 23 unset ANDROID_JAVA_TOOLCHAIN 24 unset ANDROID_PRE_BUILD_PATHS 25 if [ -n "$JAVA_HOME" ]; then 26 export ANDROID_JAVA_TOOLCHAIN=$JAVA_HOME/bin 27 export ANDROID_PRE_BUILD_PATHS=$ANDROID_JAVA_TOOLCHAIN: 28 export PATH=$ANDROID_PRE_BUILD_PATHS$PATH 29 fi 30 31 unset ANDROID_PRODUCT_OUT 32 export ANDROID_PRODUCT_OUT=$(get_abs_build_var PRODUCT_OUT) 33 export OUT=$ANDROID_PRODUCT_OUT #获取产品最终文件输出目录 34 35 unset ANDROID_HOST_OUT 36 export ANDROID_HOST_OUT=$(get_abs_build_var HOST_OUT) 37 unset ANDROID_DEVICE_CONFIG 38 tdevice=$(get_build_var TARGET_DEVICE) 39 export DEVICE=$T/device/*/$tdevice
这段有难度,里面涉及到了makefile,暂时先不分析(TODO)。
set_stuff_for_environment
1 set_sequence_number
set_sequence_number
function set_sequence_number() { export BUILD_ENV_SEQUENCE_NUMBER=10 }
做什么用的,不知道。
set_stuff_for_environment
1 export ANDROID_BUILD_TOP=$(gettop) 2 }
终于完了。
lunch
1 printconfig 2 }
printconfig
1 function printconfig() 2 { 3 T=$(gettop) 4 if [ ! "$T" ]; then 5 echo "Couldn't locate the top of the tree. Try setting TOP." >&2 6 return 7 fi 8 get_build_var report_config #get_build_var report_config 参考 “android/build/core/dumpvar.mk" 9 }
通过make输出当前的配置。
lunch吃完了,真难消化,编写这些脚本的大神真叫人佩服啊!!!