Android编译系统环境初始化过程分析.docx

上传人:b****5 文档编号:29818991 上传时间:2023-07-27 格式:DOCX 页数:35 大小:49.25KB
下载 相关 举报
Android编译系统环境初始化过程分析.docx_第1页
第1页 / 共35页
Android编译系统环境初始化过程分析.docx_第2页
第2页 / 共35页
Android编译系统环境初始化过程分析.docx_第3页
第3页 / 共35页
Android编译系统环境初始化过程分析.docx_第4页
第4页 / 共35页
Android编译系统环境初始化过程分析.docx_第5页
第5页 / 共35页
点击查看更多>>
下载资源
资源描述

Android编译系统环境初始化过程分析.docx

《Android编译系统环境初始化过程分析.docx》由会员分享,可在线阅读,更多相关《Android编译系统环境初始化过程分析.docx(35页珍藏版)》请在冰豆网上搜索。

Android编译系统环境初始化过程分析.docx

Android编译系统环境初始化过程分析

Android编译系统环境初始化过程分析

Android源代码在编译之前,要先对编译环境进行初始化,其中最主要就是指定编译的类型和目标设备的型号。

Android的编译类型主要有eng、userdebug和user三种,而支持的目标设备型号则是不确定的,它们由当前的源码配置情况所决定。

为了确定源码支持的所有目标设备型号,Android编译系统在初始化的过程中,需要在特定的目录中加载特定的配置文件。

接下来本文就对上述的初始化过程进行详细分析。

对Android编译环境进行初始化很简单,分为两步。

第一步是打开一个终端,并且将build/envsetup.sh加载到该终端中:

[html]viewplaincopy在CODE上查看代码片派生到我的代码片

$../build/envsetup.sh

includingdevice/asus/grouper/vendorsetup.sh

includingdevice/asus/tilapia/vendorsetup.sh

includingdevice/generic/armv7-a-neon/vendorsetup.sh

includingdevice/generic/armv7-a/vendorsetup.sh

includingdevice/generic/mips/vendorsetup.sh

includingdevice/generic/x86/vendorsetup.sh

includingdevice/lge/mako/vendorsetup.sh

includingdevice/samsung/maguro/vendorsetup.sh

includingdevice/samsung/manta/vendorsetup.sh

includingdevice/samsung/toroplus/vendorsetup.sh

includingdevice/samsung/toro/vendorsetup.sh

includingdevice/ti/panda/vendorsetup.sh

includingsdk/bash_completion/adb.bash

从命令的输出可以知道,文件build/envsetup.sh在加载的过程中,又会在device目录中寻找那些名称为vendorsetup.sh的文件,并且也将它们加载到当前终端来。

另外,在sdk/bash_completion目录下的adb.bash文件也会加载到当前终端来,它是用来实现adb命令的bashcompletion功能的。

也就是说,加载了该文件之后,我们在运行adb相关的命令的时候,通过按tab键就可以帮助我们自动完成命令的输入。

关于bashcompletion的知识,可以参考官方文档:

第二步是执行命令lunch,如下所示:

[html]viewplaincopy在CODE上查看代码片派生到我的代码片

$lunch

You'rebuildingonLinux

Lunchmenu...pickacombo:

1.full-eng

2.full_x86-eng

3.vbox_x86-eng

4.full_mips-eng

5.full_grouper-userdebug

6.full_tilapia-userdebug

7.mini_armv7a_neon-userdebug

8.mini_armv7a-userdebug

9.mini_mips-userdebug

10.mini_x86-userdebug

11.full_mako-userdebug

12.full_maguro-userdebug

13.full_manta-userdebug

14.full_toroplus-userdebug

15.full_toro-userdebug

16.full_panda-userdebug

Whichwouldyoulike?

[full-eng]

我们看到lunch命令输出了一个Lunch菜单,该菜单列出了当前Android源码支持的所有设备型号及其编译类型。

例如,第一项“full-eng”表示的设备“full”即为模拟器,并且编译类型为“eng”即为工程机。

当我们选定了一个Lunch菜单项序号(1-16)之后,按回车键,就可以完成Android编译环境的初始化过程。

例如,我们选择1,可以看到以下输出:

[html]viewplaincopy在CODE上查看代码片派生到我的代码片

Whichwouldyoulike?

[full-eng]1

============================================

PLATFORM_VERSION_CODENAME=REL

PLATFORM_VERSION=4.2

TARGET_PRODUCT=full

TARGET_BUILD_VARIANT=eng

TARGET_BUILD_TYPE=release

TARGET_BUILD_APPS=

TARGET_ARCH=arm

TARGET_ARCH_VARIANT=armv7-a

HOST_ARCH=x86

HOST_OS=linux

HOST_OS_EXTRA=Linux-3.8.0-31-generic-x86_64-with-Ubuntu-13.04-raring

HOST_BUILD_TYPE=release

BUILD_ID=JOP40C

OUT_DIR=out

============================================

我们可以看到,lunch命令帮我们设置好了很多环境变量。

通过设置这些环境变量,就配置好了Android编译环境。

通过图1我们就可以直观地看到Android编译环境初始化完成后,我们所获得的东西:

总体来说,Android编译环境初始化完成之后,获得了以下三样东西:

1.将vendor和device目录下的vendorsetup.sh文件加载到了当前终端;

2.新增了lunch、m、mm和mmm等命令;

3.通过执行lunch命令设置好了TARGET_PRODUCT、TARGET_BUILD_VARIANT、TARGET_BUILD_TYPE和TARGET_BUILD_APPS等环境变量。

接下来我们就主要分析build/envsetup.sh文件的加载过程以及lunch命令的执行过程。

一.文件build/envsetup.sh的加载过程

文件build/envsetup.sh是一个bashshell脚本,从它里面定义的函数hmm可以知道,它提供了lunch、m、mm和mmm等命令供我们初始化编译环境或者编译Android源码。

函数hmm的实现如下所示:

[plain]viewplaincopy在CODE上查看代码片派生到我的代码片

functionhmm(){

cat<

Invoke".build/envsetup.sh"fromyourshelltoaddthefollowingfunctionstoyourenvironment:

-lunch:

lunch-

-tapas:

tapas[...][arm|x86|mips][eng|userdebug|user]

-croot:

Changesdirectorytothetopofthetree.

-m:

Makesfromthetopofthetree.

-mm:

Buildsallofthemodulesinthecurrentdirectory.

-mmm:

Buildsallofthemodulesinthesupplieddirectories.

-cgrep:

GrepsonalllocalC/C++files.

-jgrep:

GrepsonalllocalJavafiles.

-resgrep:

Grepsonalllocalres/*.xmlfiles.

-godir:

Gotothedirectorycontainingafile.

Lookatthesourcetoviewmorefunctions.Thecompletelistis:

EOF

T=$(gettop)

localA

A=""

foriin`cat$T/build/envsetup.sh|sed-n"/^function/s/function[a-z_]*.*/\1/p"|sort`;do

A="$A$i"

done

echo$A

}

我们在当前终端中执行hmm命令即可以看到函数hmm的完整输出。

函数hmm主要完成三个工作:

1.调用另外一个函数gettop获得Android源码的根目录T。

2.通过cat命令显示一个HereDocument,说明$T/build/envsetup.sh文件加载到当前终端后所提供的主要命令。

3.通过sed命令解析$T/build/envsetup.sh文件,并且获得在里面定义的所有函数的名称,这些函数名称就是$T/build/envsetup.sh文件加载到当前终端后提供的所有命令。

注意,sed命令是一个强大的文本分析工具,它以行为单位为执行文本替换、删除、新增和选取等操作。

函数hmm通过执行以下的sed命令来获得在$T/build/envsetup.sh文件定义的函数的名称:

[plain]viewplaincopy在CODE上查看代码片派生到我的代码片

sed-n"/^function/s/function[a-z_]*.*/\1/p"

它表示对所有以“function”开头的行,如果紧接在“function”后面的字符串仅由字母a-z和下横线(_)组成,那么就将这个字符串提取出来。

这正好就对应于shell脚本里面函数的定义。

文件build/envsetup.sh除了定义一堆函数之外,还有一个重要的代码段,如下所示:

[plain]viewplaincopy在CODE上查看代码片派生到我的代码片

#Executethecontentsofanyvendorsetup.shfileswecanfind.

forfin`/bin/lsvendor/*/vendorsetup.shvendor/*/*/vendorsetup.shdevice/*/*/vendorsetup.sh2>/dev/null`

do

echo"including$f"

.$f

done

unsetf

这个for循环遍历vendor目录下的一级子目录和二级子目录以及device目录下的二级子目录中的vendorsetup.sh文件,并且通过source命令(.)将它们加载当前终端来。

vendor和device相应子目录下的vendorsetup.sh文件的实现很简单,它们主要就是添加相应的设备型号及其编译类型支持到Lunch菜单中去。

例如,device/samsung/maguro目录下的vendorsetup.sh文件的实现如下所示:

[plain]viewplaincopy在CODE上查看代码片派生到我的代码片

add_lunch_combofull_maguro-userdebug

它调用函数add_lunch_combo添加一个名称为“full_maguro-userdebug”的菜单项到Lunch菜单去。

函数add_lunch_combo定义在build/envsetup.sh文件中,它的实现如下所示:

[plain]viewplaincopy在CODE上查看代码片派生到我的代码片

functionadd_lunch_combo()

{

localnew_combo=$1

localc

forcin${LUNCH_MENU_CHOICES[@]};do

if["$new_combo"="$c"];then

return

fi

done

LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]}$new_combo)

}

传递给函数add_lunch_combo的参数保存在位置参数$1中,接着又保存在一个本地变量new_combo中,用来表示一个要即将要添加的Lunch菜单项。

函数首先是在数组LUNCH_MENU_CHOICES中检查要添加的菜单项是否已经存在。

只有在不存在的情况下,才会将它添加到数组LUNCH_MENU_CHOICES中去。

注意,${LUNCH_MENU_CHOICES[@]}表示数组LUNCH_MENU_CHOICES的所有元素。

数组LUNCH_MENU_CHOICES是定义在文件build/envsetup.sh的一个全局变量,当文件build/envsetup.sh被加载的时候,这个数组会被初始化为化full-eng、full_x86-eng、vbox_x86-eng和full_mips-eng,如下所示:

[plain]viewplaincopy在CODE上查看代码片派生到我的代码片

#addthedefaultonehere

add_lunch_combofull-eng

add_lunch_combofull_x86-eng

add_lunch_combovbox_x86-eng

add_lunch_combofull_mips-eng

这样当文件build/envsetup.sh加载完成之后,数组LUNCH_MENU_CHOICES就包含了当前源码支持的所有设备型号及其编译类型,于是当接下来我们执行lunch命令的时候,就可以通过数组LUNCH_MENU_CHOICES看到一个完整的Lunch藤蔓。

二.lunch命令的执行过程

lunch命令实际上是定义在文件build/envsetup.sh的一个函数,它的实现如下所示:

[plain]viewplaincopy在CODE上查看代码片派生到我的代码片

functionlunch()

{

localanswer

if["$1"];then

answer=$1

else

print_lunch_menu

echo-n"Whichwouldyoulike?

[full-eng]"

readanswer

fi

localselection=

if[-z"$answer"]

then

selection=full-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"Invalidlunchcombo:

$answer"

return1

fi

exportTARGET_BUILD_APPS=

localproduct=$(echo-n$selection|sed-e"s/-.*$//")

check_product$product

if[$?

-ne0]

then

echo

echo"**Don'thaveaproductspecfor:

'$product'"

echo"**Doyouhavetherightrepomanifest?

"

product=

fi

localvariant=$(echo-n$selection|sed-e"s/^[^\-]*-//")

check_variant$variant

if[$?

-ne0]

then

echo

echo"**Invalidvariant:

'$variant'"

echo"**Mustbeoneof${VARIANT_CHOICES[@]}"

variant=

fi

if[-z"$product"-o-z"$variant"]

then

echo

return1

fi

exportTARGET_PRODUCT=$product

exportTARGET_BUILD_VARIANT=$variant

exportTARGET_BUILD_TYPE=release

echo

set_stuff_for_environment

printconfig

}

函数lunch的执行逻辑如下所示:

1.检查是否带有参数,即位置参数$1是否等于空。

如果不等于空的话,就表明带有参数,并且该参数是用来指定要编译的设备型号及其编译类型的。

如果等于空的话,那么就调用另外一个函数print_lunch_menu来显示Lunch菜单项,并且通过调用read函数来等待用户输入。

无论通过何种方式,最终变量answer的值就保存了用户所指定的备型号及其编译类型。

2.对变量answer的值的合法性进行检查。

如果等于空的话,就将它设置为默认值“full-eng”。

如果不等于空的话,就分为三种情况考虑。

第一种情况是值为数字,那么就需要确保该数字的大小不能超过Lunch菜单项的个数。

在这种情况下,会将输入的数字索引到数组LUNCH_MENU_CHOICES中去,以便获得一个用来表示设备型号及其编译类型的文本。

第二种情况是非数字文本,那么就需要确保该文本符合-的形式,其中表示设备型号,而表示编译类型。

第三种情况是除了前面两种情况之外的所有情况,这是非法的。

经过合法性检查后,变量selection代表了用户所指定的备型号及其编译类型,如果它的值是非法的,即它的值等于空,那么函数lunch就不往下执行了。

3.接下来是解析变量selection的值,也就是通过sed命令将它的值提取出来,并且分别保存在变量product和variant中。

提取出来的product和variant值有可能是不合法的,因此需要进一步通过调用函数check_product和check_variant来检查。

一旦检查失败,也就是函数check_product和check_variant的返回值$?

等于非0,那么函数lunch就不往下执行了。

4.通过以上合法性检查之后,就将变量product和variant的值保存在环境变量TARGET_PRODUCT和TARGET_BUILD_VARIANT中。

此外,另外一个环境变量TARGET_BUILD_TYPE的值会被设置为"release",表示此次编译是一个release版本的编译。

另外,前面还有一个环境变量TARGET_BUILD_APPS,它的值被函数lunch设置为空,用来表示此次编译是对整个系统进行编译。

如果环境变量TARGET_BUILD_APPS的值不等于空,那么就表示此次编译是只对某些APP模块进行编译,而这些APP模块就是由环境变量TARGET_BUILD_APPS来指定的。

5.调用函数set_stuff_for_environment来配置环境,例如设置JavaSDK路径和交叉编译工具路径等。

6.调用函数printfconfig来显示已经配置好的编译环境参数。

在上述执行过程中,函数check_product、check_variant和printconfig是比较关键的,因此接下来我们就继续分析它们的实现。

函数check_product定义在文件build/envsetup.sh中,它的实现如下所示:

[plain]viewplaincopy在CODE上查看代码片派生到我的代码片

#checktoseeifthesuppliedproductisonewecanbuild

functioncheck_product()

{

T=$(gettop)

if[!

"$T"];then

echo"Couldn'tlocatethetopofthetree.TrysettingTOP.">&2

return

fi

CALLED_FROM_SETUP=trueBUILD_SYSTEM=build/core\

TARGET_PRODUCT=$1\

TARGET_BUILD_VARIANT=\

TARGET_BUILD_TYPE=\

TARGET_BUILD_APPS=\

get_build_varTARGET_DEVICE>/dev/null

#hidesuccessfulanswers,butallowtheerrorstoshow

}

函数gettop用来返回Android源代码工程的根目录。

函数check_product需要在Android源代码工程根目录或者子目录下调用。

否则的话,函数check_product就出错返回。

接下来函数check_product设置几个环境变量,其中最重要的是前面三个CALLED_FROM_SETUP、BUILD_SYSTEM和TARGET_PRODUCT。

环境变量CALLED_FROM_SETUP的值等于true表示接下来执行的make命令是用来初始化Android编译环境的。

环境变量BUILD_SYSTEM用来指定Android编译系统的核心目录,它的值被设置为build/core。

环境变量TARGET_PRODU

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 学科竞赛

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1