当前位置:阳光沙滩 >Android > 查看文章

AOSP-android开源项目编译过程

前一篇文章AOSP-Android系统定制下载系统源码我们完成了android系统源代码的下载和编译,接下来我们就分析一下编译的过程。

看这篇文章之前,最好会shell脚本的语法,这样子看代码也不吃力。

1.了解android的编译系统

在昨天我们下载的源码里头,我们直接调用几个命令,就可以编译系统了。以后我们修改了源代码,也是直接使用命令编译即可。也就是说,在昨天我们下载的android源代码中,就包含了android的编译系统。英文是build system,这里的build我们也可以理解为构建,索性我们就翻译为构建系统吧。

Android build system是用来编译android系统的,生成SDK,也包括文档。主要由*.mk、python脚本以及一些shell脚本组成。

1、我们昨天编译的时候,首先使用了

source build/envsetup.sh

这句话前面已经解析过了,就是把envsetup.sh里的脚本载入到系统环境中,这样子就可以直接使用里面的命令了。envsetup.sh这个其实就是shell脚本。sh就是shell的意思。

我们可以看看这个脚本里写了一些什么东西:

function hmm() {
cat <<EOF
Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:
- lunch:   lunch <product_name>-<build_variant>
- tapas:   tapas [<App1> <App2> ...] [arm|x86|mips|armv5|arm64|x86_64|mips64] [eng|userdebug|user]
- 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, but not their dependencies.
- mmm:     Builds all of the modules in the supplied directories, but not their dependencies.
           To limit the modules being built use the syntax: mmm dir/:target1,target2.
- mma:     Builds all of the modules in the current directory, and their dependencies.
- mmma:    Builds all of the modules in the supplied directories, and their dependencies.
- cgrep:   Greps on all local C/C++ files.
- ggrep:   Greps on all local Gradle files.
- jgrep:   Greps on all local Java files.
- resgrep: Greps on all local res/*.xml files.
- sgrep:   Greps on all local source 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 "/^[ \t]*function /s/function \([a-z_]*\).*/\1/p" | sort | uniq`; do
      A="$A $i"
    done
    echo $A
}

如果你source build/envsetup.sh以后,再执行hmm,则会有以上的帮助内容输出:

Untitled6

这些帮助内容什么意思呢?我们解释一下常用的吧!

lunch:就是载入你要编译的项目。参数可以是项目编号或者项目名称

croot:这个就是切换回系统代码的根目录。这个我经常用到。

假设我们的项目是android5.1这个文件夹,那么我们的源码根目录则是android5.1这里

我们有可能在系统源码里的子文件夹里,如果我们要切回到根目录就是cd ../../..n个../

可以直接使用croot就回去了,就是这个意思

mm、mmm: 这个后面我们会常用到,也不用去记,用得多就知道了。先混个脸熟吧。

2、我们lunch完以后,就开编了。

make -j40

make也是一个命令,就是开始编译系统了。-j就是job的意思,而这里的40根据自己硬件的情况写即可。

google官方推荐是CPU线程的2倍。

2.代码分析

接下来, 我们结合代码进行分析。source build/envsetup.sh这个就是把这个shell载入到系统环境中,这样子,我们才有后面的lunch,make这些命令。

2.1.shell脚本

我们打开envsetup.sh文件,找到lunch的方法:

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
}

这就是lunch方法的代码了:

首先是判断有没有参数,其实我们直接lunch 参数 这种形式也是可以的。但是我们为了看有哪些选项,所以就直接lunch,没有输入参数。而看代码,我们可以知道,判断参数内容没有的时候,就输出选项菜单。

    local answer

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

print_lunch_menu就是输出选项菜单

2018-09-26_122629

这就是print_lunch_menu输出的结果了。

然后判断用户输入的内容是否匹配,检查完以后


    set_stuff_for_environment
    printconfig

调用了这两个方法

第一个就是设置环境内容

第二个方法是输出配置信息:

2018-09-26_122842

所以,如果你想要看配置信息,直接printconfig即可看到。

看完了lunch以后,我们看看make方法

function make()
{
    local start_time=$(date +"%s")
    $(get_make_command) "$@"
    local ret=$?
    local end_time=$(date +"%s")
    local tdiff=$(($end_time-$start_time))
    local hours=$(($tdiff / 3600 ))
    local mins=$((($tdiff % 3600) / 60))
    local secs=$(($tdiff % 60))
    echo
    if [ $ret -eq 0 ] ; then
        echo -n -e "#### make completed successfully "
    else
        echo -n -e "#### make failed to build some targets "
    fi
    if [ $hours -gt 0 ] ; then
        printf "(%02g:%02g:%02g (hh:mm:ss))" $hours $mins $secs
    elif [ $mins -gt 0 ] ; then
        printf "(%02g:%02g (mm:ss))" $mins $secs
    elif [ $secs -gt 0 ] ; then
        printf "(%s seconds)" $secs
    fi
    echo -e " ####"
    echo
    return $ret
}

make方法的代码很少,其实都调用到别的地方去了。

以上代码,主要是对编译时间 做了一个记录和计算。以及判断编译结果,输出编译结果。

编译成功了,还是失败了。

那编译的实际代码在哪里呢?这句:

    $(get_make_command) "$@"

也就是说,调用了get_make_command这个方法:

function get_make_command()
{
  echo command make
}

echo 也就是输出,对吧!

command make是什么呢?

其实是执行make命令,那什么前面要加command呢?因为我们的shell脚本也有make方法呀,所以调用make的话,会调用shell里的方法发,而使用command make则是调用系统里的make命令。

我们可以看看make的说明:

huangyk@cneeds-PowerEdge-T430:/code/huangyk/android5.1code$ make -h
Usage: make [options] [target] ...
Options:
  -b, -m                      Ignored for compatibility.
  -B, --always-make           Unconditionally make all targets.
  -C DIRECTORY, --directory=DIRECTORY
                              Change to DIRECTORY before doing anything.
  -d                          Print lots of debugging information.
  --debug[=FLAGS]             Print various types of debugging information.
  -e, --environment-overrides
                              Environment variables override makefiles.
  -f FILE, --file=FILE, --makefile=FILE
                              Read FILE as a makefile.
  -h, --help                  Print this message and exit.
  -i, --ignore-errors         Ignore errors from commands.
  -I DIRECTORY, --include-dir=DIRECTORY
                              Search DIRECTORY for included makefiles.
  -j [N], --jobs[=N]          Allow N jobs at once; infinite jobs with no arg.
  -k, --keep-going            Keep going when some targets can't be made.
  -l [N], --load-average[=N], --max-load[=N]
                              Don't start multiple jobs unless load is below N.
  -L, --check-symlink-times   Use the latest mtime between symlinks and target.
  -n, --just-print, --dry-run, --recon
                              Don't actually run any commands; just print them.
  -o FILE, --old-file=FILE, --assume-old=FILE
                              Consider FILE to be very old and don't remake it.
  -p, --print-data-base       Print make's internal database.
  -q, --question              Run no commands; exit status says if up to date.
  -r, --no-builtin-rules      Disable the built-in implicit rules.
  -R, --no-builtin-variables  Disable the built-in variable settings.
  -s, --silent, --quiet       Don't echo commands.
  -S, --no-keep-going, --stop
                              Turns off -k.
  -t, --touch                 Touch targets instead of remaking them.
  -v, --version               Print the version number of make and exit.
  -w, --print-directory       Print the current directory.
  --no-print-directory        Turn off -w, even if it was turned on implicitly.
  -W FILE, --what-if=FILE, --new-file=FILE, --assume-new=FILE
                              Consider FILE to be infinitely new.
  --warn-undefined-variables  Warn when an undefined variable is referenced.

This program built for x86_64-pc-linux-gnu
Report bugs to <bug-make@gnu.org>
huangyk@cneeds-PowerEdge-T430:/code/huangyk/android5.1code$

我们可以看到熟悉的-j,Allow N jobs at once; infinite jobs with no arg.

到这里就开始去make了!

2.2.make

make是一个很庞大的构建系统,相关的文档看这里

https://www.gnu.org/software/make/manual/make.html

同学们不需要学会整个make构建系统的原理,但是要会编写Android.mk文件。

我们在平时开发的时候,在修改系统的时候,就要修改Android.mk文件了,比如说编译一个apk,编译c++文件,修改一些内容以后重新编译,解决资源冲突的问题..等等.

其他的内容,我们后面接着分析吧。

这篇文章我们先到这里结束了,感谢您的阅读!欢迎分享转载,请保留本文地址,感谢!

7K
为您推荐
各种观点