Android编译流程

Android编译流程

一、编译流程

google已经给出了android的原生编译流程:source build/envsetup.sh加载命令初始化环境、lunch选择平台、make执行编译命令。

 

1、初始化编译环境

进入android源代码根目录执行命令source build/envsetup.sh即可初始化编译环境。如下日志:

 

 

其实该过程从source命令就可以看出主要是执行了envsetup.sh脚本且加载环境变量到当前终端。脚本envsetup.sh中其实定义了很多函数(省略)

source build/envsetup.sh执行之后,为当前终端加载了上面的这些函数,之后可以在该终端执行这些命令(函数名)来执行这些函数的内容,最后调用函数source_vendorsetup加载其他目录(device vendor product)下的vendorsetup.sh脚本。注意,该命令只在当前终端生效,如果未生效那么lunch和mm等命令是无法使用的。

2、选择编译平台

在Android根目录下执行lunch命令来选择当前编译平台,该命令可以直接跟上参数,也可以让其显示菜单让我们选择,如下:

 

 

3、开始编译

最后就可以执行make或者mm等命令进行编译了,但他们的流程可能有些不一样。因为按照linux的makefile机制,make命令其实直接执行了当前目录下的makefile脚本,但是linux并没有mm或者mma等这些命令,根据下面的代码可以知道android 7.0之后采用了独有的soong编译系统直接执行了当前目录下的android.mk或者android.bp脚本。(注意android.mk一直存在,android编译系统对makefile做的一层封装)

二、Soong工具

随着android工程越来越大,包含的module越来越多,以makefile(包括android.mk)组织的项目编译花费的时间越来越多。谷歌在7.0开始引入了ninja进行编译系统的组织,相对于make来说ninja在大的项目管理中速度和并行方面有突出的优势,因此谷歌采用了ninja来取代之前使用的make。但是现有的android项目还是由makefile组织,因此谷歌引入了kati(后来被称为soong)将makefile(包括android.mk)翻译成ninja文件。

 

Android 7.0开始逐步引入kati soong(未正式使用默认关闭,需要USE_SOONG=true手动开启),将makefile文件和Android.mk文件转化成ninja文件,使用ninja文件对编译系统进行管理。

 

Android 8.0开始引入了Android.bp文件来替代之前的Android.mk文件。Android.bp只是纯粹的配置文件(类似json),不包括分支、循环等流程控制(如果想要进行分支循环控制可自己写go来完成),因此Android.bp文件被转化成ninja文件的效率远远高于Android.mk文件。

 

Android 9.0开始强制使用Android.bp来代替Android.mk。

1、Soong工作原理

Soong源代码路径位于/android/build/soong/,从第一章的内容了解到目前的Android代码编译命令make(包括mm等命令)都基本上使用的该目录下的soong_ui.bash来进行代码编译。主要涉及到如下流程:

 

Android.mk转换成ninja文件:soong_ui.bash将指定目录下的所有Android.mk(包括makefile)文件转换成out/build-<product_name>.ninja文件

Android.bp转换成ninja文件:soong_ui.bash将指定目录下所有的Android.bp文件也转换成out/soong/build.ninja文件

组合nijia文件:soong_ui.bash还会生成一个较小的out/combined-<product_name>.ninja文件,负责把二者组合起来作为执行入口

Soong根据nijia来控制源码编译

 

 

2、转换关系

通过Kati工具将Android.mk和makefile文件转换成ninja格式的文件

 

通过Buleprint工具解析Android.bp文件,在通过Soong将被解析后的Android.bp转换成ninja格式的文件

 

通过androidmk工具可以直接将没有分支和循环流程控制的Android.mk文件转换成Android.bp文件(一般开发者可能会用到该工具)

 

相关术语:

Ninja:ninja是一个编译框架,会根据相应的ninja格式的配置文件进行编译,但是ninja文件一般不会手动修改,而是通过将Android.bp文件转换成ninja格文件来编译

Android.mk:Android.mk其本质是执行envsetup.sh之后,编译系统对makefile进行了一层封装,让开发者更加简单的使用makefile。因此可直接把他当成makefile看待

Kati:kati是专为Android开发的一个基于Golang和C++的工具,主要功能是把Android中的Android.mk文件转换成Ninja文件

Android.bp:Android.bp的出现就是为了替换Android.mk文件。bp跟mk文件不同,它是纯粹的配置,没有分支、循环等流程控制,不能做算数逻辑运算。如果需要控制逻辑,那么只能通过Go语言编写

Soong:Soong类似于之前的Makefile编译系统的核心,负责提供Android.bp语义解析,并将之转换成Ninja文件。Soong还会编译生成一个androidmk命令,用于将Android.mk文件转换为Android.bp文件,不过这个转换功能仅限于没有分支、循环等流程控制的Android.mk才有效

Blueprint:Blueprint是生成、解析Android.bp的工具,是Soong的一部分。Soong负责Android编译而设计的工具,而Blueprint只是解析文件格式,Soong解析内容的具体含义。Blueprint和Soong都是由Golang写的项目,从Android 7.0,prebuilts/go/目录下新增Golang所需的运行环境,在编译时使用

androidmk:androidmk是Soong提供的一套可直接通过命令的方式将一个android.mk生成一个对应的android.bp。通常开发者需要手动替换Android.mk的时候用到

三、make流程

在android源码根目录输入make命令之后,将以树结构的方式编译整个工程所有子目录,这里只介绍一下从make是如何走到我们lunch选择的平台mk。

 

1、编译开端main.mk

根据前面两章的内容我们应该很容易知道,在进行模块编译的时候执行mm其实就是执行了当前目录下的android.mk或者android.bp文件里面的指定的内容。那么在根目录下执行make其本质还是执行的根目录下面的makefile文件(跟linux一模一样)。根目录下的Android.bp内容是空,makefile直接指向了build/make/core/main.mk文件,如下

main.mk根据名称也知道是我们编译执行的主函数,当然其比较复杂,我们比较感兴趣大概流程如下三步:

  • 导入build/make/core/config.mk进行环境变量或重要参数的配置(比如常用的CLEAR_VARS、BUILD_PACKAGE)

 

导入build/make/core/definitions.mk也定义了一些其他变量(比如常用的my-dir、all-subdir-makefiles、all-subdir-java-files)

定义了一系列规则,规则的目标就是编译要生成的目标文件(比如单独编译某个分区可以直接使用make vendorimage、make xxximage)

2、编译配置config.mk

config.mk定义了很多变量,这些变量对应某个mk文件并有对应的逻辑功能,例如CLEAR_VARS其实就是对应执行clear_vars.mk脚本,如下代码:


posted @ 2022-06-17 15:08  include_chen  阅读(1107)  评论(0编辑  收藏  举报