GN和Ninja的构建流程
OpenHarmony的编译构建也以GN和 Ninja为主。同时,由于OpenHarmony兼容 Linux 内核,并且包含了大量的第三方开源库,所以也大量使用了CMake和 make。根据产品配置,编译生成对应的镜像包。编译脚本会依次调用preloader->loader->gn->ninja。其中gn和ninja这两步操作分别对应“
OpenHarmony的编译构建也以GN和 Ninja为主。同时,由于OpenHarmony兼容 Linux 内核,并且包含了大量的第三方开源库,所以也大量使用了CMake和 make。
根据产品配置,编译生成对应的镜像包。编译脚本会依次调用preloader->loader->gn->ninja。其中gn和ninja这两步操作分别对应“ gn cmd args”和“ ninja cmd args”两个命令的执行流程。这两个命令的执行流程合在一起构成了完整的GN和 Ninja构建流程。
“ gn cmd args”命令的具体流程包含如下6个步骤:
1. 在当前目录中查找构建入口. gn文件。
如果当前目录中没有. gn文件,就沿着目录树向上一级目录查找,直到找到. gn文件为止。
找到. gn文件后,会把. gn文件的所在目录设置为默认的 source root(即 root="/:")。解析这个. gn文件, 并根据文件中的 buildconfig的描述, 找到对应的编译配置文件(即BUILDCONFIG. gn)。如果. gn文件内还配置了 root,则将. gn文件内配置的 root作为默认的 source root。
如果直到文件系统的根目录“/”下都找不到. gn文件, 则会报错。编译失败。
2.运行 BUILDCONFIG. gn 文件,根据它的配置来设置一些全局变量和默认的编译工具链。
这里设置的全局变量和参数默认会对整个构建过程的所有文件都有效。
3. 加载 source root 目录下的BUILD. gn文件。
如果在. gn文件内没有重新配置 root路径,则默认加载“//BUILD. gn”;如果在. gn文件内重新配置了 root路径, 那加载 root指定的BUILD. gn文件。
4. 开始递归评估依赖关系, 根据依赖关系加载指定路径下的BUILD. gn文件。
如果在依赖目标指定的路径下找不到匹配的BUILD. gn文件, 就会去. gn文件中配置的“ secondary _ source”描述的路径下查找。如果还是找不到匹配的BUILD. gn, 就会报“缺少依赖目标”的错误。编译失败。
5. 在递归评估构建目标依赖关系的过程中,每解决一个构建目标的依赖关系,就生成对应目标的. ninja文件。
6. 当所有构建目标的依赖关系都解决掉之后,会生成一个 build. ninja文件。
此外,根据 The Ninja build system文档的描述,“ ninja cmd args”操作就是:
运行 Ninja程序, 默认会在当前目录下查找 build. ninja文件, 根据它描述的规则,调用编译工具去编译所有的过期目标。
冷知识:GN和Ninja构建工具的由来
Google的 Chromium 开源项目最早采用GYP ( Generate Your Projects) 工具来实现项目的自动化构建。工程师根据GYP 的规则编写构建. gyp文件(类似于脚本), 然后GYP工具根据. gyp文件生成 Makefile, 再通过 make 去执行 Makefile, 最终调用编译工具链来编译整个项目。这里的GYP工具和. gyp文件,就类似于前面提到的 CMake和CMakeList。
Chromium项目的工程师 Evan Martin认为 Makefile 描述的编译规则复杂晦涩, 而且 make工具的编译效率低下,于是自己开发出了一个 Ninja构建工具去取代 make,并用. ninja文件取代了 Makefile 文件。 Ninja非常注重构建速度,它的语法很简单,完全没有分支、循环等流程控制语句,关于如何编译代码的策略描述也非常少,而且在便利性和速度产生冲突时,优先选择速度。GYP后来发展成GN( Generate Ninja), GN与 Ninja一起组成的构建系统开始应用在 Android 7.0版本上。随后,越来越多的项目也开始使用GN和 Ninja进行项目构建, GN和 Ninja逐渐成为一种非常流行的构建系统。
注: 以上分享的内容部分源自于梁开祝老师所著的《沉浸式剖析OpenHarmony源代码》,也有部分自己的学习理解。
更多推荐
所有评论(0)