一.概述

在 Android 7.0 之前,Android 编译系统使用 GNU Make 描述和shell来构建编译规则,模块定义都使用Android.mk进行定义,Android.mk的本质就是Makefile,但是随着Android的工程越来越大,模块越来越多,Makefile组织的项目编译时间越来越长。因此,在Android7.0开始,Google采用ninja来代取代之前使用的make,由于之前的Android.mk数据实在巨大,因此Google加入了一个kati工具,用于将Android.mk转换成ninja的构建规则文件buildxxx.ninja,再使用ninja来进行构建工作。最终目标要把make都取代,于是从Android8.0开始,Google为了进一步淘汰Makefile,因此引入了Android.bp文件来替换之前的Android.mk。Android.bp只是一个纯粹的配置文件,不包括分支、循环语句等控制流程,本质上就是一个json配置文件。Android.bp 通过Blueprint+soong转换成ninja的构建规则文件build.ninja,再使用ninja来进行构建工作。这些文件之间的关系,如下图所示:

  • kati是把Android.mk转换成ninja file。
  • soong是把Android.bp转换成ninja file。
  • Android.bp是jason形式组织的文件,将来逐步取代Android.mk
  • 后续没有Android.mk,kati将会消失。
  • ninja是同make编译构建系统一样,来替换make的,速度快。
  • blueprint是一个处理Android.bp相关语法的库文件。

如下图为Android编译系统的演进:

谷歌官网的的Soong 构建系统介绍

二.编译流程

以Android10为例

2.1 编译构成

Android的编译目录在/build 中,目录结构如下:



这个目录中可以看到core文件夹被link到了make/core,envsetup.sh被link到make/envsetup.sh,这主要是为了对使用者屏蔽切换编译系统的差异。

这里重点看四个文件夹:blueprint、kati、make、soong

  1. blueprint:用于处理Android.bp,编译生成*.ninja文件,用于做ninja的处理
  2. kati:用于处理Android.mk,编译生成*.ninja文件,用于做ninja的处理
  3. make:文件夹还是原始的make那一套流程,比如envsetup.sh
  4. soong:构建系统,核心编译为soong_ui.bash

Soong编译系统家族成员及各自关系如下图所示:



在编译过程中,Android.bp会被收集到out/soong/build.ninja.d,blueprint以此为基础,生成out/soong/build.ninja

Android.mk会由kati/ckati生成为out/build-aosp_arm.ninja

两个ninja文件会被整合进入out/combined-aosp_arm.ninja

2.2 编译步骤

三.编译环境初始化

3.1 envsetup说明

编译的第一步需要初始化一下环境变量。这是由envsetup.sh完成的,这里的envsetup.sh被link到了 build/make/envsetup.sh。

envsetup.sh 主要做了下面几个事情:

在source build/envsetup.sh后,输入hmm可以看到envsetup支持的一些接口:

命令 说明
lunch lunch <product_name>-<build_variant>选择<product_name>作为要构建的产品,<build_variant>作为要构建的变体,并将这些选择存储在环境中,以便后续调用“m”等读取。
tapas 交互方式:tapas [ ...] [arm/x86/mips/arm64/x86_64/mips64] [eng/userdebug/user]
croot 将目录更改到树的顶部或其子目录。
m 编译整个源码,可以不用切换到根目录
mm 编译当前目录下的源码,不包含他们的依赖模块
mmm 编译指定目录下的所有模块,不包含他们的依赖模块 例如:mmm dir/:target1,target2.
mma 编译当前目录下的源码,包含他们的依赖模块
mmma 编译指定目录下的所模块,包含他们的依赖模块
provision 具有所有必需分区的闪存设备。选项将传递给fastboot。
cgrep 对系统本地所有的C/C++ 文件执行grep命令
ggrep 对系统本地所有的Gradle文件执行grep命令
jgrep 对系统本地所有的Java文件执行grep命令
resgrep 对系统本地所有的res目录下的xml文件执行grep命令
mangrep 对系统本地所有的AndroidManifest.xml文件执行grep命令
mgrep 对系统本地所有的Makefiles文件执行grep命令
sepgrep 对系统本地所有的sepolicy文件执行grep命令
sgrep 对系统本地所有的source文件执行grep命令
godir 根据godir后的参数文件名在整个目录下查找,并且切换目录
allmod 列出所有模块
gomod 转到包含模块的目录
pathmod 获取包含模块的目录
refreshmod 刷新allmod/gomod的模块列表

3.2 Lunch说明

环境变量初始化完成后,我们需要选择一个编译目标。lunch 主要作用是根据用户输入或者选择的产品名来设置与具体产品相关的环境变量。

3.3 Make说明

执行完lunch命令后,就可以使用make命令来执行编译Build。

Android10.0上是通过soong执行编译构建,这里执行make命令时,main.mk文件把一些环境变量和目标都配置好后,会执行envsetup.sh中的make()进行编译。

如果找到“build/soong/soong_ui.bash”,就使用soong_ui.bash 来进行编译,否则使用原始的make命令进行编译。

四.总结

Android10.0中,mk文件通过kati\ckati编译生成 build-aosp_arm.ninja, bp文件通过blueprint-soong解析编译生成为build.ninja ,这些ninja文件会合并成combined-aosp_arm.ninja,最终通过ninja工具进行最终的编译。

参考:https://blog.csdn.net/yiranfeng/article/details/109082489?spm=1001.2014.3001.5501

Android编译系统的更多相关文章

  1. Android编译系统详解(一)

    ++++++++++++++++++++++++++++++++++++++++++ 本文系本站原创,欢迎转载! 转载请注明出处: http://blog.csdn.net/mr_raptor/art ...

  2. 深入浅出 - Android系统移植与平台开发(十)- Android编译系统与定制Android平台系统(瘋耔修改篇二)

    第四章.Android编译系统与定制Android平台系统 4.1Android编译系统 Android的源码由几十万个文件构成,这些文件之间有的相互依赖,有的又相互独立,它们按功能或类型又被放到不同 ...

  3. 【转】Android编译系统详解(三)——编译流程详解

    原文网址:http://www.cloudchou.com/android/post-276.html 本文原创作者:Cloud Chou. 欢迎转载,请注明出处和本文链接 1.概述 编译Androi ...

  4. Android编译系统入门(二)

    Android.mk的使用方法 在上一篇Android编译系统入门(一)中我们只要介绍了Android系统使用make命令默认编译的依赖树是droid,而droid是一个伪目标,它有两个先决条件dro ...

  5. Android编译系统中的Android.bp【转】

    本文转载自: 转自:http://note.qidong.name/2017/08/android-blueprint/ Android编译系统中的Android.bp.Blueprint与Soong ...

  6. Android编译系统(Android.mk文件详解)

    [Android-NDK(Native Development Kit)  docs文档] NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成a ...

  7. Android 编译系统的组成

    Android 和 Linux 的编译系统都是通过 Makefile 工具来组织编译源代码的. Makefile 工具用来解释和执行 Makefile 文件,在 Makefile 文件里定义好工程源代 ...

  8. Android编译系统入门(一)

    做过Android平台开发的朋友对make,mm或make clean命令应该很熟悉,但也许大家只是熟知这些命令的作用却不知道这些命令底下有些什么原理?那么今天我就带着大家推开Android编译系统的 ...

  9. Android编译系统简要介绍【转】

    本文转载自:http://blog.csdn.net/luoshengyang/article/details/18466779 在Android源码环境中,我们开发好一个模块后,再写一个Androi ...

  10. Android编译系统参考手册

    build/core/clear_vars.mk Clear out values of all variables used by rule templates 清除LOCAL变量,每个模块的And ...

随机推荐

  1. [Spring 6.0源码解析] @Configuration注解源码解析

    Spring 6.0源码解析之@Configuration 首先写一个启动代码: public class ConfigurationAnnotationTest { private static f ...

  2. AT_abc270_g [ABC270G] Sequence in mod P 题解

    题目传送门 前置知识 大步小步算法 解法 递推式为 \(x_{n}=(ax_{n-1}+b) \bmod p\),发现可以统一消去 \(\bmod p\) ,只在最后参与计算.以下过程省去模运算. 当 ...

  3. 【CSS】如何复原被隐藏的滚动条?记一个看似简单的样式问题所引发的一系列思考

    壹 ❀ 引 故事的起因是这样的,某一个同事在封装了一个TableList组件,用于做表格视图渲染,但出于研发经验考虑上,他可能觉得表格若出滚动条可能会引发某些不可预估的小问题(毕竟一个基础组件会被用于 ...

  4. CF1850H The Third Letter

    题目链接 题解 知识点:贪心,图论建模. 考虑对约束 a b d 建边 \(a \mathop{\to}\limits^d b\) 与 \(b \mathop{\to}\limits^{-d} a\) ...

  5. NC19987 [HAOI2012]ROAD

    题目链接 题目 题目描述 C国有n座城市,城市之间通过m条单向道路连接.一条路径被称为最短路,当且仅当不存在从它的起点到终点的另外一条路径总长度比它小.两条最短路不同,当且仅当它们包含的道路序列不同. ...

  6. Python 中isinstance的用法

    isinstance()函数用来判断一个对象是否是一个已知的类型.isinstance(object, classinfo) 类似 type().isinstance() 与 type() 区别: t ...

  7. C语言,结构体成员的地址

    先回顾一个基础的知识,不同类型的数据在16位,32位,64位的机器分别占用多少字节. 类型 16位机器(字节) 32位机器(字节) 64位机器(字节) char 1 1 1 short 2 2 2 i ...

  8. Android上的日志

    Android的日志机制和普通的Java项目有一些不一样, 这里记录一下 安卓内建的Log 安卓应用类型(在build.gradle里定义 android {...})的模块, 可以直接引用内建的an ...

  9. col命令

    col命令 在很多UNIX说明文件里,都有RLF控制字符,当我们把说明文件的内容输出成纯文本文件时,控制字符会变成乱码,col命令则能有效滤除这些控制字符. 语法 col [options] 参数 - ...

  10. KQL笔记

    KQL: {'query': {'bool': {'must': [{'match': {'Sql': 'insert'}}, {'match': {'PolicyName.keyword': 'd8 ...