目录:

Ninja简介

make 的 3 个特性

举例说明Ninja 的用法

如何向构建工具 Ninja 描述构建图

后记

鸿蒙系统的编译构建是基于 Gn 和 Ninja 完成的,那么 Gn 和 Ninjia 有什么关系呢?具体又是如何工作的呢?想必大多数热衷于应用开发的同学都还没有深究过,那么今天就借此机会带着大家扒一扒 Gn 和 Ninja。

我们先来说说 Ninja 吧!

Ninja 是借由 Google Chrome 项目而诞生的一个构建工具,它的诞生目标是为了速度。换句话说,在 Google Chrome 项目的开发过程中,开发者们认为同类型的其它构建工具不给力,所以才会考虑重新开发更高效的工具。要说同类型,那么不得不提构建界的老大哥 make !make 即 GNU Make,一个用于决定如何使用命令完成最终目标构建的程序。

在这里强调 make 的 3 个特性:

  1. make 只是一个通用程序,它不知道如何具体的完成目标的构建工作
  2. make 需要 makefile 中的描述来决定目标构建的具体方案
  3. make 需要借助其它工具(如:gcc)才能执行方案,最终完成工作

这是不是跑题了!不是说好的讨论 Ninja 吗?怎么扯到 make 上去了?!

因为 Ninja 可以看作是一个更好的 make !而大多数同学都熟悉 make ,所以通过对比 make 学习 Ninja 是一个非常好的选择!上述关于 make 的 3 个特性对于 Ninjia 同样适用(理论上,make 有的 Ninjia 都有,并且更好!)。那么,是不是得先学习 make 再学习 Ninja 呢?我觉得倒也不是!毕竟我们最终还是在鸿蒙上做应用开发,编译构建系统只需要大体了解即可。

接下来通过一个简单的例子向大家展示 Ninja 的用法!

test.c 是一个简单的 Hello World 程序,用于打印一个字符串和头文件 test.h 中常量 CONST 的值。

根据 C 程序的编译方式可知:

  1. 在预处理阶段 test.h 中的代码直接嵌入test.c 中(头文件 .h 最终成为源文件 .c 的一部分)
  2. test.c 编译后得到目标文件 test.o
  3. test.o 链接后得到最终的可执行程序  test.out

各个文件在编译过程中有明显的上下游关系,即:上游文件影响或者产生下游文件。

上图即描述了编译过程,同时也反映了这样一个事实:任何一个文件被改动时只可能影响下游文件,而不会影响上游文件。如:test.c 被修改了,那么可能导致编译得到 test.o 发生改变,进而导致最终的可执行程序 test.out 改变。因此,当 test.c 被修改时,那么应该重新触发编译和链接这两个动作。

看到这里,有同学可能存在这样的疑问:怎么知道文件已经被修改了并触发相应动作呢?

其实很简单,可以根据文件修改时间判断呀!目前几乎主流的文件系统都会记录文件被修改的时间,所以结合文件的上下游关系可知:上游文件被修改的时间应该总是 小于等于 下游文件被修改的时间。这样,只需要遍历一次上面的构建图就可以知道执行哪些动作产生最终可执行程序了。

接下来思考这样一个问题:如何向构建工具 Ninja 描述构建图?

Ninja 的本质是一种通用程序。既然是程序,那么擅长的必然是处理结构化文本!因此,可以用结构化文本(Ninja脚本)来描述构建图。

下面直接上代码!

解读:

1. Ninja 脚本中的 build 语句描述构建图中的一个文件上下游关系。如:build test.o cc test.c 指明 test.o 由 test.c 通过规则 cc 而构建,test.c 在构建图中位于 test.o 的上游,从 test.c 到 test.o 需要执行的动作通过规则 cc 定义。Ninja 通过判断上下游文件的修改时间决定是否执行规则中定义的动作。多个 build 语句共同描述一个编译构建图。

2. Ninja 脚本中通过 rule 定义规则描述构建图中需要执行的动作。如:规则 cc 所定义的具体动作是  gcc -c in -oin−oout ,其中 in 指代上游文件,in指代上游文件,out 指代下游文件。对于 build test.o cc test.c 而言,最终执行的动作为:gcc -c test.c -o test.o 。

3. 由 C 语言及其编译方式可知:当源文件包含的头文件改动时,源文件需要重新编译。因此,在构建图中头文件顺理成章的成为了源文件的上游文件,需要考虑的仅仅是如何定义 rule 最终触发编译动作。这里使用的技巧是通过命令 touh 更新源文件的修改时间,于是可定义 rule dp 的执行动作为 touch $out。这样 build test.c : dp test.h 的意思就很清楚了:当 test.h 被修改时,执行 touch test.c 更新修改时间,进而触发重新编译。

4. default test.out  指明默认构建的目标是 test.out,即: ninja 执行当前脚本时默认编译构建的是 test.out。

理解了 Ninja 脚本的基本构成后就可以通过实验进一步体会了!

1. 将上面的脚本另存为文件,并重命名为 build.ninja,且与 test.c 和 test.h 位于同一目录下

2. 打开命令行定位到源码目录,执行 ninja > log.txt

通过编译输出(log.txt)以及 test.out 的运行结果可知目标构建成功。

后记:

这只是一个 Ninja 的入门级介绍,更多的细节大家可以参考附件中的手册。同时,文中的示例代码也可以在附件中下载。大家可以自己动手修改源码(比如:修改 test.h 中 CONST 的值)然后自行编译体会 Ninja 的用法。

Enjoy it!

作者:唐佐林

想了解更多内容,请访问: 51CTO和华为官方战略合作共建的鸿蒙技术社区https://harmonyos.51cto.com

浅析鸿蒙中的 Gn 与 Ninja(一)的更多相关文章

  1. WebRTC编译系统之GYP,gn和ninja

    GN(Generate Ninja)来生成构建脚本,使用 ninja 来构建. gn 的介绍在这里:https://www.chromium.org/developers/gn-build-confi ...

  2. 浅析Java中的final关键字

    浅析Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ...

  3. 浅析mongodb中group分组

    这篇文章主要介绍了浅析mongodb中group分组的实现方法及示例,非常的简单实用,有需要的小伙伴可以参考下. group做的聚合有些复杂.先选定分组所依据的键,此后MongoDB就会将集合依据选定 ...

  4. 浅析py-faster-rcnn中不同版本caffe的安装及其对应不同版本cudnn的解决方案

    浅析py-faster-rcnn中不同版本caffe的安装及其对应不同版本cudnn的解决方案 本文是截止目前为止最强攻略,按照本文方法基本可以无压力应对caffe和Ross B. Girshick的 ...

  5. 浅析JS中的模块规范(CommonJS,AMD,CMD)////////////////////////zzzzzz

    浅析JS中的模块规范(CommonJS,AMD,CMD)   如果你听过js模块化这个东西,那么你就应该听过或CommonJS或AMD甚至是CMD这些规范咯,我也听过,但之前也真的是听听而已.     ...

  6. 浅析Java中的访问权限控制

    浅析Java中的访问权限控制 今天我们来一起了解一下Java语言中的访问权限控制.在讨论访问权限控制之前,先来讨论一下为何需要访问权限控制.考虑两个场景: 场景1:工程师A编写了一个类ClassA,但 ...

  7. [转载]浅析Java中的final关键字

    浅析Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ...

  8. 浅析 JavaScript 中的 函数 currying 柯里化

    原文:浅析 JavaScript 中的 函数 currying 柯里化 何为Curry化/柯里化? curry化来源与数学家 Haskell Curry的名字 (编程语言 Haskell也是以他的名字 ...

  9. 浅析 JavaScript 中的 函数 uncurrying 反柯里化

    柯里化 柯里化又称部分求值,其含义是给函数分步传递参数,每次传递参数后部分应用参数,并返回一个更具体的函数接受剩下的参数,这中间可嵌套多层这样的接受部分参数函数,直至返回最后结果. 因此柯里化的过程是 ...

随机推荐

  1. openstack高可用集群17-openstack集成Ceph准备

    Openstack集成Ceph准备 Openstack环境中,数据存储可分为临时性存储与永久性存储. 临时性存储:主要由本地文件系统提供,并主要用于nova虚拟机的本地系统与临时数据盘,以及存储gla ...

  2. 项目1_001_涉及知识点(Django任务追踪平台)

  3. C#中使用NPOI提示(找到的程序集清单定义与程序集引用不匹配)

    问题 找到的程序集清单定义与程序集引用不匹配. (异常来自 HRESULT:0x80131040) 描述 使用NPOI导出word文档,需要C#的解压缩类,所以引用了ICSharpCode.Sharp ...

  4. 写一个nginx.conf方便用于下载某个网页的所有资源

    写一个nginx.conf方便用于下载某个网页的所有资源 worker_processes 1; events { worker_connections 1024; } http { include ...

  5. 安装篇六:安装PHP(7.2.29版本)

    准备环境,下载依赖软件 # No1:在前面安装好的基础上,关闭iptables.selinux # No2:安装依赖包 yum install zlib-devel bzip2-devel -y &l ...

  6. EXCEL2010分成多个窗口的,解决单个窗口显示多个文档的弊病

    本操作需要修改注册表,请在修改之前导出要修改的项目以备份. 1.定位到[HKEY_CLASSES_ROOT\Excel.Sheet.12\shell\Open],导出保存.展开Open,将ddeexe ...

  7. 1.自定义view入门

    1.继承自view 系统提供的view 如 TextView .ImageView 都是继承自view的: 2.自定义一个TextView 通过自定义一个TextView 来熟悉继承自view 的自定 ...

  8. Python-对比参考目录查找多个文件夹中不同的文件

    改完文件名称后,Dr.he 发现分别保存5个状态的jpg 文件的文件夹出现缺少文件的情况.为了让他少熬夜查找缺失文件,结合网友分享的脚本,写了查找以下代码,满足他的需求,也以防自己忘记.以下代码能解决 ...

  9. 容器编排系统K8s之ConfigMap、Secret资源

    前文我们了解了k8s上的pv/pvc/sc资源的使用和相关说明,回顾请参考:https://www.cnblogs.com/qiuhom-1874/p/14188621.html:今天我们主要来聊一下 ...

  10. 卷积神经网络CNN-学习1

    卷积神经网络CNN-学习1 十年磨一剑,霜刃未曾试. 简介:卷积神经网络CNN学习. CNN中文视频学习链接:卷积神经网络工作原理视频-中文版 CNN英语原文学习链接:卷积神经网络工作原理视频-英文版 ...