Android编译系统分析之envsetup.sh

已开通新的博客,后续文字都会发到新博客

http://www.0xfree.top


我们用几个问题来解释这篇文章要讨论的内容

为什么用\cd 而不用cd

在android原代码的提交中,我们发现了这个解释:

Use “\cd” to disable alias temporarily.

使用\cd 来临时屏蔽alias别名

具体作用如下示例:

function mycd()
{
    echo "in mycd"
    cd $@
}
alias cd='mycd'

function cproj()
{
    pwd
    \cd .. 或者 cd ..
    pwd
}

cproj()

我们执行这个脚本,前者将会打印:

/home/foree/bin
/home/foree

后者将会打印:

/home/foree/bin
in mycd
/home/foree

android 如何定位TOP目录

循环递归,查找build/core/envsetup.mk这个路径下文件是否存在

function gettop
{
local TOPFILE=build/core/envsetup.mk
if [ -n "$TOP" -a -f "$TOP/$TOPFILE" ] ; then
	# The following circumlocution ensures we remove symlinks from TOP.
	(cd $TOP; PWD= /bin/pwd)
else
	if [ -f $TOPFILE ] ; then
        # The following circumlocution (repeated below as well) ensures
        # that we record the true directory name and not one that is
        # faked up with symlink names.
        PWD= /bin/pwd
	else
        local HERE=$PWD
        T=
        while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
        \cd ..
        T=`PWD= /bin/pwd -P`
        done
        \cd $HERE
        if [ -f "$T/$TOPFILE" ]; then
             echo $T
        fi
     fi
fi
}

关于shell脚本中命令太长的多行写法

adb shell ps \
| tr -d '\r' \
| sed -e 1d -e 's/^[^ ]* *\([0-9]*\).* \([^ ]*\)$/\1 \2/'

如何进入到指定关键字的目录,并选择符合条件中的一个

function godir () {
if [[ -z "$1" ]]; then
	echo "Usage: godir <regex>"
	return
fi
T=$(gettop)
if [[ ! -f $T/filelist ]]; then
    echo -n "Creating index..."
    (\cd $T; find . -wholename ./out -prune -o -wholename ./.repo -prune -o -type f > filelist)
    echo " Done"
    echo ""
fi

local lines

lines=($(\grep "$1" $T/filelist | sed -e 's/\/[^/]*$//' | sort | uniq))
if [[ ${#lines[@]} = 0 ]]; then
    echo "Not found"
    return
fi

local pathname
local choice

if [[ ${#lines[@]} > 1 ]]; then
    while [[ -z "$pathname" ]]; do
        local index=1
        local line
        for line in ${lines[@]}; do
        printf "%6s %s\n" "[$index]" $line
        index=$(($index + 1))
    done

    echo
    echo -n "Select one: "

    unset choice
    read choice

    if [[ $choice -gt ${#lines[@]} || $choice -lt 1 ]]; then
        echo "Invalid choice"
        continue
    fi

    pathname=${lines[$(($choice-1))]}
    done
else
	pathname=${lines[0]}
fi

\cd $T/$pathname

}

envsetup.sh的作用

export 一些函数,像如:

function lunch()

function _lunch()

function gettop

function getdriver()

function m()

function findmakefile()

function mm()

function mmm()

function mma()

function mmma()

function croot()

function cproj()

function pid()

以上这些就是咱们平时使用的croot,lunch,mm这些函数的来源,

然后在脚本的最后,需要判断一下当前环境的shell是否为bash,对于非bash来说,例如zsh,因为与bash的语法有微小差别,因此使用一些命令会出错,例如,lunch之后,如果直接选择数字,而不是类型,可能会导致lunch一个错误的机型

if [ "x$SHELL" != "x/bin/bash" ]; then
case `ps -o command -p $$` in
bash)
;;
*)
echo "WARNING: Only bash is supported, use of other shell would lead to erroneous results"
;;
esac
fi

然后最后,再查找device和vendor目录下vendorsetup.sh文件,目录层级最深为4层,我们可以以vendor_device-TAG的方式加入变量,通过add_lunch_combo加到Lunch的选择项中。

# Execute the contents of any vendorsetup.sh files we can find.
for f in `test -d device && find -L device -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null` \
`test -d vendor && find -L vendor -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null`
do
echo "including $f"
. $f
done

我们来看看通过lunch启动都干了些什么(可以通过cat build/envsetup.sh|sed -n ‘/function lunch/,/^}/p’ 打印函数)

function lunch()
{
local answer

if [ "$1" ] ; then
	answer=$1
else
	print_lunch_menu
	echo -n "Which would you like? [aosp_arm-eng] "
	read answer
fi

local selection=
if [ -z "$answer" ]
then
	selection=aosp_arm-eng
elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
then
	if [ $answer -le ${#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" ]
then
	echo
	echo "Invalid lunch combo: $answer"
	return 1
fi

export TARGET_BUILD_APPS=
local product=$(echo -n $selection | sed -e "s/-.*$//")
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

local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//")
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_BUILD_TYPE=release

echo
set_stuff_for_environment
printconfig
}

如上:主要关注点在于4个正则表达式

  1. elif (echo -n a n s w e r g r e p q e &quot; [ 0 9 ] [ 0 9 ] answer | grep -q -e &quot;^[0-9][0-9]* ")
  2. elif (echo -n KaTeX parse error: Double superscript at position 24: … grep -q -e "^[^̲\-][^\-]*-[^\-]…")
  3. local product=$(echo -n s e l e c t i o n s e d e &quot; s / . selection | sed -e &quot;s/-.* //")
  4. local variant=$(echo -n $selection | sed -e “s/[-]*-//”)

第一个是查找1-2位数的正则表达式
第二个是匹配vendor_product-eng这样格式的选择项
第三个用来提取-前边的关键字,例如meizu_m76-eng中的meizu_m76
第四个用来提取variant变量,就是eng,userdebug,user这几个变量

我们从这里可以看出,vendorsetup.sh中写出符合标准格式的combo,然后在lunch的时候导出

接下来我们进入lunch的世界

Android编译系统之lunch分析

猜你喜欢

转载自blog.csdn.net/beijing2008lm/article/details/84672856
今日推荐