当前位置: 首页 > 科技观察

鸿蒙Gn和Ninja简析(一)

时间:2023-03-21 00:42:10 科技观察

更多内容请访问:与华为官方共建的鸿蒙技术社区https://harmonyos.51cto.com/#zz鸿蒙系统的编译搭建是基于Gn和Ninja,那么Gn和Ninja是什么关系呢?它是如何工作的?想必大部分热衷于应用开发的同学都没有研究过,那么今天就借此机会带大家来扒一扒Gn和Ninja。先说忍者吧!Ninja是一个脱胎于GoogleChrome项目的构建工具,它的诞生就是以速度为目标的。也就是说,在谷歌浏览器项目的开发过程中,开发者认为其他同类型的构建工具效果不佳,因此他们考虑重新开发更高效的工具。要说同类型,那就不得不提make这个建筑界的老大哥了!Make即GNUMake,一个用来决定如何使用命令来完成最终目标构建的程序。这里强调make的三个特点:make只是一个通用程序,它不知道具体如何完成目标构建工作make需要makefile中的描述来确定目标构建的具体方案make需要其他工具(如as:gcc)才能执行计划,最终完成工作。这不是题外话吗!讨论忍者不好吗?它是如何参与make的?!因为Ninja也算是比较好的制作了!而且大部分同学都熟悉make,所以通过make来学习Ninja是非常不错的选择!make的以上三个特性同样适用于Ninja(理论上有些make有Ninja,更好!)。那么,是不是一定要先学make再学Ninja呢?我不这么认为!毕竟我们还是在鸿蒙上做应用开发,对编译构建系统有一个大概的了解就可以了。接下来我就通过一个简单的例子来给大家展示一下Ninja的用法!test.c是一个简单的HelloWorld程序,用于打印头文件test.h中的字符串和常量CONST的值。根据C程序的编译方式可知,在预处理阶段,test.h中的代码直接嵌入到test.c中(头文件.h最终成为源文件.c的一部分),编译test.c后得到目标文件test.otest。o链接后得到最终的可执行程序test.out。每个文件在编译过程中都有明显的上下游关系,即上游文件影响或生成下游文件。上图描述了编译过程,同时也反映了一个事实,即任何一个文件发生变化时,可能只影响下游文件,而不会影响上游文件。例如修改test.c,可能会导致编译后的test.o发生变化,进而导致最终的可执行程序test.out发生变化。因此,当test.c被修改时,编译和链接这两个动作应该重新触发。看到这里,可能有同学会有这样的疑惑:怎么知道文件被修改并触发了相应的动作呢?其实很简单,根据文件修改时间判断即可!目前几乎主流的文件系统都会记录文件被修改的时间,所以结合文件的上下游关系可以看出,上游文件被修改的时间应该总是小于等于下游文件被修改的时间。这样,只需要遍历一次上述构造图,就知道要执行哪些动作,才能生成最终的可执行程序。接下来思考这样一个问题:如何向构造工具Ninja描述构造图?Ninja的本质是一个通用程序。既然是程序,就一定擅长处理结构化文本!因此,可以使用结构化文本(Ninja脚本)来描述构造图。直接上代码吧!解读:1.Ninja脚本中的build语句描述了一个文件在构建图中的上下游关系。例如:buildtest.occtest.c表示test.o是由test.c通过规则cc构建的,test.c在构建图中位于test.o的上游,要执行的动作来自test.c到test.o由规则cc定义。Ninja通过判断上下游文件的修改时间来决定是否执行规则中定义的动作。多个构建语句一起描述了一个已编译的构建图。2.在Ninja脚本中,通过规则定义规则来描述构造图中需要执行的动作。例如:规则cc定义的具体动作是gcc-c$in-o$out,其中$in指的是上游文件,$out指的是下游文件。对于buildtest.occtest.c,最后的执行动作是:gcc-ctest.c-otest.o。3、从C语言及其编译方式可以看出,当源文件中包含的头文件发生变化时,需要重新编译源文件。因此,构建图中的头文件自然成为了源文件的上游文件,唯一需要考虑的就是如何定义最终触发编译动作的规则。这里使用的技巧是通过命令touh来更新源文件的修改时间,所以规则dp的执行动作可以定义为touch$out。这样,buildtest.c:dptest.h的意思就很明确了:当test.h被修改时,执行touchtest.c更新修改时间,然后触发重新编译。4.defaulttest.out表示默认构建目标为test.out,即:ninja在执行当前脚本时,默认编译构建test.out。了解了Ninja脚本的基本构成后,可以通过实验进一步体会!1.将上述脚本另存为文件,重命名为build.ninja,与test.c和test.h在同一目录下2.打开命令进入源代码目录,执行ninja>日志.txt。通过编译输出(log.txt)和test.out的运行结果可以知道target构建成功。后记:这只是Ninja的入门级介绍。更多详细信息,您可以参考附件中的手册。同时,文章中的示例代码也可以在附件中下载。可以自行修改源码(例如:修改test.h中CONST的值),然后自行编译,体验Ninja的用法。享受它的版权!?由作者和鸿蒙技术社区共同拥有。如需转载请注明出处,否则将追究法律责任。了解更多请访问:与华为官方共建鸿蒙科技社区https://harmonyos.51cto.com/#zz