摘要:Ninja具体干了什么?

阅读本文大约需要花费16分钟。

文章首发微信公众号:IngresGe

专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢!

欢迎关注我的公众号!

[Android取经之路] 的源码都基于Android-Q(10.0) 进行分析

[Android取经之路] 系列文章:

《系统启动篇》

  1. Android系统架构
  2. Android是怎么启动的
  3. Android 10.0系统启动之init进程
  4. Android10.0系统启动之Zygote进程
  5. Android 10.0 系统启动之SystemServer进程
  6. Android 10.0 系统服务之ActivityMnagerService
  7. Android10.0系统启动之Launcher(桌面)启动流程
  8. Android10.0应用进程创建过程以及Zygote的fork流程
  9. Android 10.0 PackageManagerService(一)工作原理及启动流程
  10. Android 10.0 PackageManagerService(二)权限扫描
  11. Android 10.0 PackageManagerService(三)APK扫描
  12. Android 10.0 PackageManagerService(四)APK安装流程

《日志系统篇》

  1. Android10.0 日志系统分析(一)-logd、logcat 指令说明、分类和属性
  2. Android10.0 日志系统分析(二)-logd、logcat架构分析及日志系统初始化
  3. Android10.0 日志系统分析(三)-logd、logcat读写日志源码分析
  4. Android10.0 日志系统分析(四)-selinux、kernel日志在logd中的实现​

《Binder通信原理》

  1. Android10.0 Binder通信原理(一)Binder、HwBinder、VndBinder概要
  2. Android10.0 Binder通信原理(二)-Binder入门篇
  3. Android10.0 Binder通信原理(三)-ServiceManager篇
  4. Android10.0 Binder通信原理(四)-Native-C\C++实例分析
  5. Android10.0 Binder通信原理(五)-Binder驱动分析
  6. Android10.0 Binder通信原理(六)-Binder数据如何完成定向打击
  7. Android10.0 Binder通信原理(七)-Framework binder示例
  8. Android10.0 Binder通信原理(八)-Framework层分析
  9. Android10.0 Binder通信原理(九)-AIDL Binder示例
  10. Android10.0 Binder通信原理(十)-AIDL原理分析-Proxy-Stub设计模式
  11. Android10.0 Binder通信原理(十一)-Binder总结

  《HwBinder通信原理》

  1. HwBinder入门篇-Android10.0 HwBinder通信原理(一)
  2. HIDL详解-Android10.0 HwBinder通信原理(二)
  3. HIDL示例-C++服务创建Client验证-Android10.0 HwBinder通信原理(三)
  4. HIDL示例-JAVA服务创建-Client验证-Android10.0 HwBinder通信原理(四)
  5. HwServiceManager篇-Android10.0 HwBinder通信原理(五)
  6. Native层HIDL服务的注册原理-Android10.0 HwBinder通信原理(六)
  7. Native层HIDL服务的获取原理-Android10.0 HwBinder通信原理(七)
  8. JAVA层HIDL服务的注册原理-Android10.0 HwBinder通信原理(八)
  9. JAVA层HIDL服务的获取原理-Android10.0 HwBinder通信原理(九)
  10. HwBinder驱动篇-Android10.0 HwBinder通信原理(十)
  11. HwBinder原理总结-Android10.0 HwBinder通信原理(十一)

《编译原理》

  1. 编译系统入门篇-Android10.0编译系统(一)
  2. 编译环境初始化-Android10.0编译系统(二)
  3. make编译过程-Android10.0编译系统(三)
  4. Image打包流程-Android10.0编译系统(四)
  5. Kati详解-Android10.0编译系统(五)
  6. Blueprint简介-Android10.0编译系统(六)
  7. Blueprint代码详细分析-Android10.0编译系统(七)
  8. Android.bp 语法浅析-Android10.0编译系统(八)

1 概述

在 Android 7.0 之前,Android 编译系统使用 GNU Make 描述和shell来构建编译规则,模块定义都使用Android.mk进行定义,Android.mk的本质就是Makefile,但是随着Android的工程越来越大,模块越来越多,Makefile组织的项目编译时间越来越长。这样下去Google工程师觉得不行,得要优化。

因此,在Android7.0开始,Google采用ninja来代取代之前使用的make,由于之前的Android.mk数据实在巨大,因此Google加入了一个kati工具,用于将Android.mk转换成ninja的构建规则文件buildxxx.ninja,再使用ninja来进行构建工作。

ninja的网址:https://ninja-build.org

编译速度快了一些,但是既然要干, 那就干个大的,最终目标要把make都取代,于是从Android8.0开始,Google为了进一步淘汰Makefile,因此引入了Android.bp文件来替换之前的Android.mk。

Android.bp只是一个纯粹的配置文件,不包括分支、循环语句等控制流程,本质上就是一个json配置文件。Android.bp  通过Blueprint+soong转换成ninja的构建规则文件build.ninja,再使用ninja来进行构建工作。

Android10.0上,mk和bp编译的列表可以从 \out\.module_paths中的Android.bp.list、Android.mk.list中看到,Android10.0还有400多个mk文件没有被替换完,Google任重道远。

    Android编译演进过程:

1)Android7.0之前 使用GNU Make

2)Android7.0 引入ninja、kati、Android.bp和soong构建系统

3)Android8.0 默认打开Android.bp

4)Android9.0 强制使用Android.bp

Google在 Android 7.0之后,引入了Soong构建系统,旨在取代make,它利用 Kati GNU Make 克隆工具和 Ninja 构建系统组件来加速 Android 的构建。

Make 构建系统得到了广泛的支持和使用,但在 Android 层面变得缓慢、容易出错、无法扩展且难以测试。Soong 构建系统正好提供了 Android build 所需的灵活性。

Ninja是一个注重速度的小型构建系统。它与其他构建系统在两个主要方面不同:它被设计为使其输入文件由更高级别的构建系统生成,并且被设计为尽可能快地运行构建。

Android系统的编译历程:

2 Make与ninja的对比

在传统的C/C++项目中,通常采用make系统使用Makefile来进行整个项目的编译构建,Makefile指定的编译依赖规则会使编译流程简单,但是make的依赖大而且复杂,在大型项目编译时,使用的模块越来越多,Makefile组织的项目编译时间越来越长,这个对于编译效率来说是一个极大的浪费。

Ninja是由Google员工Evan Martin 开发的小型构建系统。Ninja注重速度,它在两个主要方面与其他构建系统有所不同:Ninja被设计为使其输入文件由更高级别的构建系统生成,并且其被设计为尽可能快地运行构建。

本质上,Ninja旨在替换Make,这在执行增量(或无操作)构建时很慢。这可能会大大降低开发人员在大型项目上的工作速度,例如Google Chrome将40,000个输入文件编译为单个可执行文件。实际上,谷歌浏览器是忍者的主要用户和动机。它也用于构建Android ,并且被大多数从事LLVM的开发人员所使用。

与Make相比,Ninja缺少诸如字符串操作之类的功能,因为Ninja生成文件不是要手工编写的。相反,应使用“生成生成器”生成Ninja生成文件。Gyp,CMake,Meson和gn 是流行的构建管理软件工具,它们支持为Ninja创建构建文件。

Ninja开发时,认为make由以下几点导致编译慢:

  • 隐式规则,make包含很多默认

  • 变量计算,比如编译参与应该如何计算出来

  • 依赖对象计算

ninja相对于make增加了下面这些功能:

  • 如果构建命令发生变化,那么这个构建也会重新执行。

  • 所依赖的目录在构建之前都已经创建了,如果不是这样的话,我们执行命令之前都要去生成目录。

  • 每条构建规则,除了执行命令之外,还允许有一个描述,真正执行打印这个描述而不是实际执行命令。

  • 每条规则的输出都是buffered的,也就是说并行编译,输入内容不会被搅和在一起。

针对这点所以基本上可以认为ninja就是make的最最精简版。

Make编译使用的文件名为Makefile、makefile或者以.make、.mk结尾的文件,Ninja的文件名一般为build.ninja或者以.ninja结尾的文件。

3 ninja的用法

3.1 ninja代码位置

Android自带ninja,ninja路径:

prebuilts/build-tools/darwin-x86/bin/ninja
prebuilts/build-tools/linux-x86/bin/ninja
prebuilts/build-tools/linux-x86/asan/bin/ninja

3.2 命令的用法

执行ninja -h 后,可以得到ninja的使用帮助说明

我们在编译时,常用的是-t参数。我们执行一下ninja -t list会得到相应的指令说明:

例如 ninja -t clean 用来清除编译中间文件,相比make clean减少了研发人员的开发过程。

指令说明:

ninja subtools:browse        # 在浏览器中浏览依赖关系图。(默认会在 8080 端口启动一个基于python的http服务)
clean         # 清除构建生成的文件
commands      # 罗列重新构建制定目标所需的所有命令
deps          # 显示存储在deps日志中的依赖关系
graph         # 为指定目标生成 graphviz dot 文件。#  如 ninja -t graph all |dot -Tpng -ograph.png
query         # 显示一个路径的inputs/outputs
targets       # 通过DAG中rule或depth罗列target
compdb        # dump JSON兼容的数据库到标准输出
recompact     # 重新紧凑化ninja内部数据结构

4 ninja的实践

4.1 下载ninja

下载地址:

git clone https://github.com/ninja-build/ninja.git

4.2 编译ninja

cd ninja
./configure.py --bootstrap #在ninja目录中执行

4.3 安装ninja

编译结束后,会在ninja目录中生成ninja的可执行程序ninja。可以直接将ninja程序拷贝到/usr/bin中。cp ./ninja /usr/bin #在ninja目录中执行

现在就可以在任意位置使用ninja了。

4.4 ninja实践

1)mkdir test

2)vim test/main.c

填入代码内容:

#include <stdio.h>
#include <stdlib.h>
int main() {printf("This is my first Ninja Project!\n");return 0;
}

3)配置build.ninja

vim build.ninja

填入内容:

cc = g++
cflags = -Wallrule cccommand = gcc $cflags -c $in -o $outdescription = compile .ccbuild foo.o: cc foo.c

4)编译:

cd test
ninja

5 ninja编译流程

5.1 AOSP编译过程

5.2.ninja生成过程

在编译过程中,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

最终由ninja -t out/combined-aosp_arm.ninja来完成最终的编译

out/combined-aosp_arm.ninja内容如下所示:

builddir = out
pool local_pooldepth = 42
build _kati_always_build_: phony
subninja out/build-aosp_arm.ninja
subninja out/build-aosp_arm-package.ninja
subninja out/soong/build.ninja

6 总结

Ninja的诞生,主要是为了提升编译速度,Ninja中去除了变量的计算,没有默认规则, 依赖必须显式声明,从而提升编译速度。基本上可以认为ninja就是make的最最精简版。

参考:

《The Ninja build system》

《Ninja 构建系统》

Ninja简介-Android10.0编译系统(九)相关推荐

  1. Blueprint简介-Android10.0编译系统(六)

    摘要:Android.bp由Blueprint进行解析翻译,最终通过soong build编译成ninja文件,那么Blueprint是什么呢? 阅读本文大约需要花费10分钟. 文章首发微信公众号:I ...

  2. Ninja提升编译速度的方法-Android10.0编译系统(十)

    摘要:如何通过Ninja来提升Android编译速度 阅读本文大约需要花费10分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢 ...

  3. 编译系统总结篇-Android10.0编译系统(十一)

    摘要:Android10.0编译系统总结 阅读本文大约需要花费20分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢! 欢迎关 ...

  4. Android.bp 语法浅析-Android10.0编译系统(八)

    摘要:Blueprint解析Android.bp到ninja的代码流程时如何走的? 阅读本文大约需要花费18分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Andro ...

  5. Blueprint代码详细分析-Android10.0编译系统(七)

    摘要:Blueprint解析Android.bp到ninja的代码流程时如何走的? 阅读本文大约需要花费18分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Andro ...

  6. Kati详解-Android10.0编译系统(五)

    摘要:本节主要来讲解Kati把Makefile编译成build-xxx.ninja,那么Kati是什么? 是如何工作的呢? 阅读本文大约需要花费24分钟. 文章首发微信公众号:IngresGe 专注于 ...

  7. Image打包流程-Android10.0编译系统(四)

    摘要:本节主要来进行Android10.0 Image打包流程,理解system.img是如何打包的 阅读本文大约需要花费28分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源 ...

  8. make编译过程-Android10.0编译系统(三)

    摘要:本节主要来进行Android10.0 编译系统的make过程 阅读本文大约需要花费29分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设计, ...

  9. Android10.0系统启动之Zygote进程-[Android取经之路]

    [Android取经之路] 的源码都基于Android-Q(10.0) 进行分析 [Android取经之路] 系列文章: <系统启动篇> Android系统架构 Android是怎么启动的 ...

最新文章

  1. 零基础入门学习Python(17)-函数的参数
  2. NB-IOT来了,物联网时代才真正来临
  3. mega_[MEGA DEAL]带有Kotlin捆绑包的完整Android Oreo(95%折扣)
  4. http三次握手四次挥手详解
  5. ruby + phantomjs 自动化测试 - GA
  6. python编程教程if_Python编程:从入门到实践——【作业】——第五章(if语句)...
  7. 常用python分析数据包pipinstallnumpy_安装numpy和matplotlib时,pip依赖关系解析失败
  8. [实践系列]Promises/A+规范
  9. 某合资源网4.5主题 完美无错版 emlog模板
  10. dell服务器linux密码,Dell服务器忘记idrac密码,如何在不重启服务器的情况下重置密码?...
  11. Intel 64/x86_64/IA-32/x86处理器基本执行环境 (1) - 32位执行环境概述
  12. 5G让万物互联成为可能 大连接时代谋划物联网
  13. python3多进程写时拷贝_python利用进程池,多进程拷贝文件
  14. 给页面title添加图标
  15. iOS 中input隐藏输入光标
  16. 北京市小汽车摇号程序的反编译、算法及存在的问题浅析
  17. Linux C/C++ 调试的那些“歪门邪道”
  18. 树展示 移动端_一种手机端树形数据结构的展现方法与流程
  19. 从被遗忘到牛市龙头,一文梳理ETH 2020爆发逻辑
  20. 全新全球电竞赛事--世界超级联赛WSL发布首项赛事计划

热门文章

  1. CUD学习-查看电脑block数量与如何分配给程序
  2. spring mvc mysql配置_spring mvc配置数据库连接
  3. qstringlist格式怎么写到txt_进阶能力 | 一招解决TXT电子书乱码问题
  4. Omad群组部署、依赖部署一键解决
  5. 【Interfacenavigation】用RecyclerView创建一个列表(4)
  6. Zookeeper的功能以及工作原理
  7. java对象的强引用,软引用,弱引用和虚引用
  8. GNS3与SecureCRT关联问题
  9. 数据类型,运算符和表达式03 - 零基础入门学习C语言04
  10. win下配置cmder