编译cubieboard android 源码过程详解之(三):lunch

时间:2021-02-01 04:37:23

阅读本文前请先阅读

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吃完了,真难消化,编写这些脚本的大神真叫人佩服啊!!!