[Android源码浅析]一.编译系统(上)

本文需要的shell基础

一.编译命令

每次编译系统时,我们都会执行以下命令:

source build/envsetup.sh
lunch
make

我们就围绕着这3个命令来分析Android的编译系统

二.envsetup.sh

  • envsetup.sh主要做了两件事,定义函数和生成编译配置列表

1.定义函数

  • 这个没什么好说的,像我们平时常用到的mm、mmm、croot、godir等都是这里定义的

2.生成编译配置列表

  • 下面这段就是搜索device、vendor、product三个目录下最大深度为4的vendorsetup.sh
for f in `test -d device && find -L device -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort` \
         `test -d vendor && find -L vendor -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort` \
         `test -d product && find -L product -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort`
do
    echo "including $f"
    . $f
done
unset f
  • addcompletions,这里是调用了前面定义的函数addcompletions,我们看下这个函数做了什么
function addcompletions()
{
    local T dir f

    # Keep us from trying to run in something that isn't bash.
    if [ -z "${BASH_VERSION}" ]; then 
        return # bash版本字符串如果是空,return
    fi

    # Keep us from trying to run in bash that's too old.
    if [ ${BASH_VERSINFO[0]} -lt 3 ]; then
        return # bash版本<3,return
    fi

    dir="sdk/bash_completion"
    if [ -d ${dir} ]; then # 如果sdk/bash_completion存在且是一个目录
        for f in `/bin/ls ${dir}/[a-z]*.bash 2> /dev/null`; do # 遍历sdk/bash_completion目录下名字由小写字母组成后缀是bash的文件
            echo "including $f" # 引用这个文件
            . $f
        done
    fi
}

3.执行source build/envsetup.sh

  • 看下执行结果,与上面分析相符。这要是引用了两类文件vendorsetup.sh和*.bash
    在这里插入图片描述
  • 先看下vendorsetup.sh。我们用的是nexus6,那就看下device/moto/shamu/vendorsetup.sh
add_lunch_combo aosp_shamu-userdebug # 显然是lunch命令用到的,放到lunch说明
add_lunch_combo aosp_shamu-eng # 这个是我加的
  • 再看下adb.bash。bash的内容很长,可以看到熟悉的install、push、pull等等。其实bash脚本主要是为命令提供tab提示

三.lunch

  • lunch主要做了两件事,添加product-variant,设置各种环境变量。下面来分析下如果做的这两件事。

1.lunch命令格式

命令格式:
lunch <product_name>-<build_variant>

还记得add_lunch_combo aosp_shamu-userdebug吗?
add_lunch_combo是在envsetup.sh里定义的函数
aosp_shame就是product_name
userdebug就是build_variant

2.lunch中的重要函数

  • add_lunch_combo
function add_lunch_combo()
{
    local new_combo=$1 # new_combo=aosp_shamu-userdebug
    local c
    for c in ${LUNCH_MENU_CHOICES[@]} ; do # LUNCH_MENU_CHOICES[@]是获取数组LUNCH_MENU_CHOICES中的所有元素
        if [ "$new_combo" = "$c" ] ; then # 如果已经有了这个元素,就返回
            return
        fi
    done
    LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo) # 新增aosp_shamu-userdebug到LUNCH_MENU_CHOICES
}
  • build_build_var_cache
# Get all the build variables needed by this script in a single call to the build system.
function build_build_var_cache()
{
    T=$(gettop)
    # Grep out the variable names from the script.
    # 提取envsetup.sh的get_build_var的参数,nexus6提取到的是:
    # 2ND_TARGET_GCC_VERSION
    # ANDROID_BUILD_PATHS
    # print
    # report_config
    # TARGET_ARCH
    # TARGET_DEVICE
    # TARGET_GCC_VERSION
    cached_vars=`cat $T/build/envsetup.sh | tr '()' '  ' | awk '{for(i=1;i<=NF;i++) if($i~/get_build_var/) print $(i+1)}' | sort -u | tr '\n' ' '`
    # 提取envsetup.sh的get_abs_build_var的参数,nexus6提取到的是:
    # ANDROID_GCC_PREBUILTS
    # ANDROID_PREBUILTS
    # HOST_OUT
    # print
    # PRODUCT_OUT
    cached_abs_vars=`cat $T/build/envsetup.sh | tr '()' '  ' | awk '{for(i=1;i<=NF;i++) if($i~/get_abs_build_var/) print $(i+1)}' | sort -u | tr '\n' ' '`
    # Call the build system to dump the "<val>=<value>" pairs as a shell script.
    # make config.mk,得到cached_vars和cached_abs_vars各项的value
    # dump-many-vars是makefile的一个伪目标
    build_dicts_script=`\cd $T; CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
                        command make --no-print-directory -f build/core/config.mk \
                        dump-many-vars \
                        DUMP_MANY_VARS="$cached_vars" \
                        DUMP_MANY_ABS_VARS="$cached_abs_vars" \
                        DUMP_VAR_PREFIX="var_cache_" \
                        DUMP_ABS_VAR_PREFIX="abs_var_cache_"`
    local ret=$?
    if [ $ret -ne 0 ]
    then
        unset build_dicts_script
        return $ret
    fi
    # Excute the script to store the "<val>=<value>" pairs as shell variables.
    # 给各项参数赋值
    # var_cache_2ND_TARGET_GCC_VERSION=''
	# var_cache_ANDROID_BUILD_PATHS='/home/frezrik/nexus6/out/host/linux-x86/bin'
	# var_cache_print=''
	# var_cache_TARGET_ARCH='arm'
	# var_cache_TARGET_DEVICE='shamu'
	# var_cache_TARGET_GCC_VERSION='4.9'
	# var_cache_report_config=`echo '============================================'; echo 'PLATFORM_VERSION_CODENAME=REL'; echo 'PLATFORM_VERSION=7.1.1'; echo 'TARGET_PRODUCT=aosp_shamu'; echo 'TARGET_BUILD_VARIANT=eng'; echo 'TARGET_BUILD_TYPE=release'; echo 'TARGET_BUILD_APPS='; echo 'TARGET_ARCH=arm'; echo 'TARGET_ARCH_VARIANT=armv7-a-neon'; echo 'TARGET_CPU_VARIANT=krait'; echo 'TARGET_2ND_ARCH='; echo 'TARGET_2ND_ARCH_VARIANT='; echo 'TARGET_2ND_CPU_VARIANT='; echo 'HOST_ARCH=x86_64'; echo 'HOST_2ND_ARCH=x86'; echo 'HOST_OS=linux'; echo 'HOST_OS_EXTRA=Linux-4.4.0-177-generic-x86_64-with-Ubuntu-16.04-xenial'; echo 'HOST_CROSS_OS=windows'; echo 'HOST_CROSS_ARCH=x86'; echo 'HOST_CROSS_2ND_ARCH=x86_64'; echo 'HOST_BUILD_TYPE=release'; echo 'BUILD_ID=NGI77B'; echo 'OUT_DIR=out'; echo '============================================';`
	# abs_var_cache_ANDROID_GCC_PREBUILTS='/home/frezrik/nexus6/prebuilts/gcc/linux-x86'
	# abs_var_cache_ANDROID_PREBUILTS='/home/frezrik/nexus6/prebuilt/linux-x86'
	# abs_var_cache_HOST_OUT='/home/frezrik/nexus6/out/host/linux-x86'
	# abs_var_cache_PRODUCT_OUT='/home/frezrik/nexus6/out/target/product/shamu'
	# abs_var_cache_print=''
    eval "$build_dicts_script
    ret=$?
    unset build_dicts_script
    if [ $ret -ne 0 ]
    then
        return $ret
    fi
    BUILD_VAR_CACHE_READY="true" # get_build_var report_config
}
  • set_stuff_for_environment
function set_stuff_for_environment()
{
    settitle # 设置PROMPT_COMMAND,这个在源码里未搜到引用的位置
    set_java_home # 设置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'
    export ASAN_OPTIONS=detect_leaks=0
}
  • printconfig
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 # `echo '============================================'; echo 'PLATFORM_VERSION_CODENAME=REL'; echo 'PLATFORM_VERSION=7.1.1'; echo 'TARGET_PRODUCT=aosp_shamu'; echo 'TARGET_BUILD_VARIANT=eng'; echo 'TARGET_BUILD_TYPE=release'; echo 'TARGET_BUILD_APPS='; echo 'TARGET_ARCH=arm'; echo 'TARGET_ARCH_VARIANT=armv7-a-neon'; echo 'TARGET_CPU_VARIANT=krait'; echo 'TARGET_2ND_ARCH='; echo 'TARGET_2ND_ARCH_VARIANT='; echo 'TARGET_2ND_CPU_VARIANT='; echo 'HOST_ARCH=x86_64'; echo 'HOST_2ND_ARCH=x86'; echo 'HOST_OS=linux'; echo 'HOST_OS_EXTRA=Linux-4.4.0-177-generic-x86_64-with-Ubuntu-16.04-xenial'; echo 'HOST_CROSS_OS=windows'; echo 'HOST_CROSS_ARCH=x86'; echo 'HOST_CROSS_2ND_ARCH=x86_64'; echo 'HOST_BUILD_TYPE=release'; echo 'BUILD_ID=NGI77B'; echo 'OUT_DIR=out'; echo '============================================';`
}

3.lunch函数说明

function lunch()
{
    local answer

    if [ "$1" ] ; then
        answer=$1 # lunch后面带参数
    else
        print_lunch_menu # 打印add_lunch_combo中赋值的LUNCH_MENU_CHOICES
        echo -n "Which would you like? [aosp_shamu-eng] "
        read answer
    fi

    local selection=

    if [ -z "$answer" ]
    then
        selection=aosp_shamu-eng # 如果未输入,则使用缺省配置
    elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$") # 匹配数字
    then
        if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ] # ${#LUNCH_MENU_CHOICES[@]}是获取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" ] # 如果selection未被赋值
    then
        echo
        echo "Invalid lunch combo: $answer"
        return 1
    fi

    export TARGET_BUILD_APPS=

    local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//") # 将 product-variant的variant分离出来
    check_variant $variant # 只能是(user userdebug eng)
    if [ $? -ne 0 ]
    then
        echo
        echo "** Invalid variant: '$variant'"
        echo "** Must be one of ${VARIANT_CHOICES[@]}"
        variant=
    fi

    local product=$(echo -n $selection | sed -e "s/-.*$//") # 将 product-variant的product分离出来
    TARGET_PRODUCT=$product \
    TARGET_BUILD_VARIANT=$variant \
    build_build_var_cache
    if [ $? -ne 0 ]
    then
        echo
        echo "** Don't have a product spec for: '$product'"
        echo "** Do you have the right repo manifest?"
        product=
    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
    destroy_build_var_cache # 清除各项的值
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值