现在的位置: 首页 > 移动开发 > 正文

Android学习之envsetup.sh

2019年09月05日 移动开发 ⁄ 共 4928字 ⁄ 字号 评论关闭

Android 开发之envsetup.sh

    1,基本概述

      Android源码下载之后一般编译之前都需要source环境变量build/envsetup.sh。脚本主要是一些基本函数,和配置编译工具和路径等。

    export PATH=$PWD/bootable/bootloader/uboot-imx/tools:$PATH

    export ARCH=arm

    export CROSS_COMPILE=$PWD/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi-

然后就是查找一些vendorsetup.sh文件并执行:

for f in `/bin/ls vendor/*/vendorsetup.sh vendor/*/*/vendorsetup.sh device/*/*/vendorsetup.sh 2 >/dev/null`

do

     echo "including $f"

     . $f

done

 

unset f

 

2,函数介绍

       下面主要介绍5个常用函数:

     1)gettop

 

function gettop
{
	local TOPFILE=build/core/envsetup.mk
	if [ -n "$TOP" -a -f "$TOP/TOPFILE" ] ; then
		echo $TOP
	else
		if [ -f $TOPFILE ] ; then
			PWD= /bin/pwd
		else
			local HERE=$PWD
			T=
			while [ \( ! (\ -f $TOPFILE \) \) -a \( $PWD != "/" \) ] ; do
				cd .. > /dev/null
				T=`PWD= /bin/pwd`
			done
			cd $HERE > /dev/null
			if [ -f "$T/TOPFILE" ] ; then
				echo $T
			fi
		fi
	fi
}

这个函数主要是获取Android源码的根目录,根据根目录下的build/core/envsetup.mk文件来判断的。

注意:调用这个函数的时候有个要求:就是你必须在源码根目录的子目录中,如果你处在根目录的上级目录则调用失败,因为这个函数是通过不停的调用cd ..命令,然后通过文件build/core/envsetup.mk来判断源码根目录的。

     
2)help

 

function help()
{
cat <<EOF
Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:
- croot:   Changes directory to the top of the tree.
- m:       Makes from the top of the tree.
- mm:      Builds all of the modules in the current directory.
- mmm:     Builds all of the modules in the supplied directories.
- cgrep:   Greps on all local C/C++ files.
- jgrep:   Greps on all local Java files.
- resgrep: Greps on all local res/*.xml files.
- godir:   Go to the directory containing a file.

Look at the source to view more functions. The complete list is:
EOF
    T=$(gettop)
    local A
    A=""
    for i in `cat $T/build/envsetup.sh | sed -n "/^function /s/function \([a-z_]*\).*/\1/p" | sort`; do
      A="$A $i"
    done
    echo $A
}

帮助函数,cat $T/build/envsetup.sh | sed -n "/^function /s/function \([a-z_]*\).*/\1/p" | sort 这句脚本主要是获取envsetup.sh里面的以function开头的函数,并将函数名打印出来。

     3)m

 m函数就是从源码根目录下开始编译。

function m()
{
    T=$(gettop)
    if [ "$T" ]; then
        make -C $T $@
    else
        echo "Couldn't locate the top of the tree.  Try setting TOP."
    fi
}

其中make -C $T $@ 就是在源码根目录下执行:make 后面的$@就是执行m命令时后面携带的参数。

注意:bash中$@和$*都表示参数,但是$*表示的是所有参数用一个双引号""括起来,而$@表示多个参数分别用""括起来。
$*为"1 2 3"(一起被引号包住)
$@为"1" "2" "3"(分别被包住)

     4)mm

 mm函数是编译当前目录下的所有模块。

function mm()
{
    # If we're sitting in the root of the build tree, just do a
    # normal make.
    if [ -f build/core/envsetup.mk -a -f Makefile ]; then
        make $@
    else
        # Find the closest Android.mk file.
        T=$(gettop)
        local M=$(findmakefile)
        # Remove the path to top as the makefilepath needs to be relative
        local M=`echo $M|sed 's:'$T'/::'`
        if [ ! "$T" ]; then
            echo "Couldn't locate the top of the tree.  Try setting TOP."
        elif [ ! "$M" ]; then
            echo "Couldn't locate a makefile from the current directory."
        else
            ONE_SHOT_MAKEFILE=$M make -C $T all_modules $@
        fi
    fi
}

如果当前处在源码根目录下,且存在Makefile文件,直接执行make $@命令。

如果不是在源码根目录下:循环调用cd .. 调用findmakefile函数查找Android.mk文件,直到根目录,将Android.mk文件的绝对路径返回给M.

如找到了:M=/home/admin/android/frameworks/base/Android.mk,调用: local M=`echo $M|sed 's}'$T'/}}'`这句就是将源码根目录/home/admin/android/去掉,取得相对目录后,M=frameworks/base/Android.mk

最后执行:ONE_SHOT_MAKEFILE=frameworks/base/android.mk make -C /home/admin/android all_modules

相当于make -C /home/admin/android all_modules  ONE_SHOT_MAKEFILE=frameworks/base/android.mk

 

接下来会调用到:源码根目录下的Makefile中,我们发现内容是include  build/core/main.mk,即走到了build/core/main.mk文件中。后面就设计到Makefile的问题,我们后面会分析。现在只需要知道mm命令是怎么调用makefile里面去就行。

     5)mmm

mmm 命令就是从指定目录下开始编译所有模块

function mmm()
{
    T=$(gettop)
    if [ "$T" ]; then
        local MAKEFILE=
        local ARGS=
        local DIR TO_CHOP
        local DASH_ARGS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^-.*$/')
        local DIRS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^[^-].*$/')
        for DIR in $DIRS ; do
            DIR=`echo $DIR | sed -e 's:/$::'`
            if [ -f $DIR/Android.mk ]; then
                TO_CHOP=`(cd -P -- $T && pwd -P) | wc -c | tr -d ' '`
                TO_CHOP=`expr $TO_CHOP + 1`
                START=`PWD= /bin/pwd`
                MFILE=`echo $START | cut -c${TO_CHOP}-`
                if [ "$MFILE" = "" ] ; then
                    MFILE=$DIR/Android.mk
                else
                    MFILE=$MFILE/$DIR/Android.mk
                fi
                MAKEFILE="$MAKEFILE $MFILE"
            else
                if [ "$DIR" = snod ]; then
                    ARGS="$ARGS snod"
                elif [ "$DIR" = showcommands ]; then
                    ARGS="$ARGS showcommands"
                elif [ "$DIR" = dist ]; then
                    ARGS="$ARGS dist"
                elif [ "$DIR" = incrementaljavac ]; then
                    ARGS="$ARGS incrementaljavac"
                else
                    echo "No Android.mk in $DIR."
                    return 1
                fi
            fi
        done
        ONE_SHOT_MAKEFILE="$MAKEFILE" make -C $T $DASH_ARGS all_modules $ARGS
    else
        echo "Couldn't locate the top of the tree.  Try setting TOP."
    fi
}

最后mmm函数:首先T=$(gettop)获取源码根目录,

 

local DASH_ARGS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^-.*$/') 根据mmm后面的参数获取以空格隔开,以-开头的字符串

如:mmm -B frameworks/ 则DASH_ARGS = -B

 

local DIRS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^[^-].*$/') 表示根据mmm后面参数获取以空格隔开,不以-开头的字符串。

如:DIRS=frameworks/base/

 

for DIR in $DIRS ; do

DIR=`echo $DIR | sed -e 's:/$::'` 去掉DIR结尾的/,DIR=frameworks/base

if [ -f $DIR/Android.mk ] ;then

TO_CHOP=`(cd -P -- $T && pwd -P) | wc -c | tr -d ' '`

上面这句命令是:跳到源码根目录,pwd -P打印出来,获取到字符串长度如:/home/admin/androids TO_CHOP就是20

TO_CHOP=`expr $TO_CHOP + 1`

START=`PWD= /bin/pwd`

MFILE=`echo $START | cut -c${TO_CHOP}-`

这句话命令是:获取当前目录字符串,去掉前面21个字符,如:当前目录为/home/admin/androids,则MFILE=""

  if [ "$MFILE" = "" ] ; then

这里进行判断当前目录是否就是源码目录,如果是的话,MFILE为空,所以MFILe=frameworks/base/Android.mk

     MFILE=$DIR/Android.mk

  else

否则:MFILE=$MFILE/frameworks/base/Android.mk

总之:就是把当前目录的前面源码根目录去了,然后加上后面mmm -B **参数部分相对的目录,最后加上Android.mk就是,最后Android.mk文件的相对路径。

    MFILE=$MFILE/$DIR/Android.mk

   fi

  MAKEFILE=$MAKEFILE $MFILE

else

done

ONE_SHOT_MAKEFILE="MAKEFILE" make -C $T $DASH_ARGS all_modules $ARGS

相当于:make -C /home/admin/android -B all_modules    ONE_SHOT_MAKEFILE=frameworks/base/Android.mk

抱歉!评论已关闭.