Android源码编译详解(二)

Android源码编译详解(一)

一、lunch命令

1、首先我们看看lunch命令执行之后出现了什么

Android源码编译详解(二)

出现了上述信息,就是等待我们选择编译的平台,这里所谓的平台说白了就是指我们所编译的系统适合运行在什么设备上,并且是user版本还是eng版本,又或者说是debug版本,我们确定版本之后,输入数字按回车就选择好了!

2、至于选哪个,需要根根据你的设备而定,又或者参考google给出的指定文档,这里不展开说明了!

3、这里要说的是user,eng,userdebug这里些版本所代表的,我们该怎么选?首先我们对三个不同类型进行简要说明:

user版本:user版本其实就是指可以发放到用户手上的版本了,就比如说我们平时正常的去手机店买手机的时候就是user版本了。

eng版本:这个版本是我们平时所说的工程机一般都是用这个版本,有时候这个版本的机子也会发给用户试用。

userdebug版本:这个是调试版本,开发人员调试的时候用这个版本即可,当然也可以直接用eng版本。
4、下面看下其他网友对这几个版本不同的总结:

Android源码编译详解(二)

在上面我们仅仅是知道我们执行胃lunch命令之后,弹出来那么一堆东西,但是我们并不知道这堆东西是怎么来的,又有什么用?我们不妨进入源码看下,源码编译的第一个阶段我们指导,envsetup.sh干的其中一件事就是定义了很多的函数,而这些函数之中,就有lunch,所以走进envsetup.sh中去看看吧!
二、lunch源码分析(平台列表如何来的)

1、首先我们看看执行lunch命令之后平台菜单是怎么来的,下面是lunch函数的部分源码:


-Android源码编译详解(二)

从代码中我们可以看到,当我们执行命令的时候可以有两种方式,第一种就是直接指定编译平台的话可以通过lunch xxx_xxx_eng这样的带参数的方式执行,这样会通过$1将第一个参数保存到answer中,第二中就是不带参数的,这里我们执行的是第二种,那么代码就会走到print_lunch_menu。

2、接下来我们看下print_lunch_menu源码:

Android源码编译详解(二)

可以看出,这个函数做的一件事就是遍历并打印编译平台列表,而遍历的对象就是LUNCH_MENU_CHOICES这个数组,我们接下来看下这个数组的数据是怎么来的

3、LUNCH_MENU_CHOICES数据来源:

Android源码编译详解(二)

在这段代码中,我们看到,程序通过不断的调用add_lunch_combo函数,添加默认的编译平台选项到LUNCH_MENU_CHOICES中,这就是我们在执行lunch命令后出现的平台列表的数据来源了!但是有信息的朋友可能就发现了,这里只不过给我们添加了6个默认值,可是我们从前面的打印出来的列表中看一看到有二十多个呢,其它的哪来的呢?

不知道大家还记不记得,我们讲android源码编译第一个阶段的时候envsetup.sh的做的其中一件事(不记得得可以回头看一眼android源码编译详解(一)),就是通过下面的代码加载了很多的vendorsetup.sh脚本:

Android源码编译详解(二)

之前我们并没有说这些脚本是用来干嘛的,那么现在我们看下这些脚本里面都有些什么内容:

Android源码编译详解(二)

怎么样?很惊喜吧,从代码中我们看到,只有add_lunch_combo aosp_deb-userdebug这句是有效的,有没有似曾相识的感觉?完全就是在通过add_lunch_combo函数给LUNCH_MENU_CHOICES添加数据嘛,,这下知道那么多平台列表是哪来的了吧?也就是说,当我们定制了自己的系统,我们只需要在vendor目录下创建对应的目录,并且创建我们所需的vendorsetup.sh脚本调用add_lunch_combo函数就可以添加我们对应平台的标识了!至于这个标识有什么用后面再给大家说明
 

三、继续lunch剩下的源码

Android源码编译详解(二)

Android源码编译详解(二)

上面的代码不算少,但是我们只需要关注这段代码做的下面三件事即可

1、检查answer合法性,并给selection赋值

我们首先看第一个判断if [ -z "$answer" ],表示如果用户没有输入任何东西直接回车的话,就会通过selection=aosp_arm-eng指定缺省的编译选项。

其实这里我们只需要关注 elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")这个判断即可,走入这个判断就证明我们有手动指定了编译选项,然后通过selection=${LUNCH_MENU_CHOICES[$(($answer-1))]}给selection赋值,做完了一系列的判断赋值之后通过 if [ -z "$selection" ]判断selection是否被赋值,如果没有则退出程序并通知。

2、按照 product-variant的格式拆分selection并做合法性校验

 这里我们先说明下,什么是product-variant,这里的product指的是我们的产品型号、而variant就是编译类型,以aosp_arm-eng为列,这里的product=aosp_arm,variant=eng;

那么上面的代码中,我们看到local product=$(echo -n $selection | sed -e "s/-.*$//")提取product,并通过check_product函数进行检验,同样的local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//")对variant进行了分离,然后通过check_variant函数进行校验,我们下校验的过程:
Android源码编译详解(二)

其实很简单,只不过是判断我们分离出来的variant是否在VARIANT_CHOICES中,如果在就证明是合法的,返回0,否则返回1,紧接着通过if [ $? -ne 0 ]判断,如果$?(上一个指令返回的值)不等于0就将variant置空并打印提示

3、设置环境变量

接下来我们看到,程序分别对下面几个环境遍历进行了的赋值处理。
    export TARGET_PRODUCT=$product

    export TARGET_BUILD_VARIANT=$variant
    export TARGET_BUILD_TYPE=release

其实这真个lunch的过程还设置了大量的环境变量,涉及到的函数有set_stuff_for_environment、printconfig等,这里就不细细展开,lunch说白了就是一个设置环境变量的过程,最后你会发现他做了那么多事,只为了最后的那一段环境变量而已,如图:
Android源码编译详解(二)

好了到这里我们第二阶段已经基本完成大体的分析(太过细节的东西我也不是非常了解),强调一点的是我这里是基于android6.0的脚本文件进行说明的,其它版本的脚本文件应该会有些小改变!