gn命令
前言
当软件规模逐渐增加,这时可能有几十个源代码文件,而且有了模块划分,有的要编译成静态库,有的要编译成动态库,最后链接成可执行代码,这时命令行方式就捉襟见肘,需要一个构建系统。
常见的构建系统有GNU Make。需要注意的是,构建系统并不是取代gcc这样的工具链,而是定义编译规则,最终还是会调用工具链编译代码。
编写GNU Makefile将是一件繁琐和乏味的事情,而且极容易出错。这时就出现了生成Makefile的工具,比如cmake、AutoMake等等,这种构建系统称作元构建系统(meta build system)。在Linux上软件仓库的概念还没有普及的时候,通常我们安装软件的步骤是:
./configure
make
make install
第一步就是调用AutoTool工具,根据系统环境(Linux的版本众多,软件安装情况也不一样),生成GNU Makefile。
几年前的chromium开源项目采用的是GYP(Generate Your Projects)构建系统,这也是一种元构建系统。
软件工程师根据GYP规则编写构建工程文件(通常以gyp, gypi为后缀),GYP工具根据gyp文件生成GNU Makefile。
接着chromium项目又整出了Ninja构建系统,但这个Ninja并不是用来取代GYP的,而是取代GNU make的,据谷歌官方的说法是速度有了好几倍的提升。
对于我们开发者而言,不需要去深入了解Ninja或GNU Makefile这样构建系统,因为这只是一种中间输出,所以ninja的出现,与我们关系不大,原来怎么写gyp,现在还是怎么写,只是构建命令稍微做了改变。GN文件相当于gyp文件的下一代,和GYP差别不大,但是总体上比原来的GYP文件更清晰。
GN构建系统
GN是一种元构建系统,生成Ninja构建文件(Ninja build files),相较GYP而言,具有如下优点:
可读性更好,更容易编写和维护。
速度更快,谷歌官方给的数据是20倍的速度提升。
修改GN文件后,执行ninja构建时会自动更新Ninja构建文件。
更简单的模块依赖,提供了public_deps, data_deps等,在GYP中,只有一种目标依赖,导致依赖关系错综复杂,容易引入不必要的模块依赖。
提供了更好的工具查询模块依赖图谱。这在GYP构建系统中是一个噩梦,要查一个目标依赖哪些模块或者一个模块被哪些目标依赖几乎是不可能的。
更好的调试支持。在GN中,只需要一条print语句就可以解决。
从命令行运行gn,这实际上是depot_tools下的一个脚本,所以需要确保depot_tools路径包含在环境变量$PATH中。
配置一个构建
在GN中,采用了更灵活的方式,你随便指定一个目录,比如为了测试,定义一个test输出目录,可以采用如下的命令: gn gen out/test
GN命令
gn args <out_dir>: Display or configure arguments declared by the build.
gn check <out_dir>: Check header dependencies.
gn clean <out_dir>: Cleans the output directory.
gn desc <out_dir> <target_name> [<what to display>]: Show lots of insightful information about a target or config.
gn format [--dump-tree] [--in-place] [--stdin] BUILD.gn: Format .gn file.
gn gen <out_dir>: Generate ninja files.
gn help: Does what you think.
gn ls <build dir> [<label_pattern>]*: List matching targets.
gn path <out_dir> <target_one> <target_two>: Find paths between two targets.
gn refs <out_dir> (<label_pattern>|<file>)*: Find stuff referencing a target or file.
注:想要看懂.gn文件,务必看上面的文档!
整体构建流程
- 在当前目录中查找.gn 文件,然后沿着目录树向上走,直到找到.gn文件所在目录为止。将此目录设置为“source root”并解析此文件以查找构建配置文件的名称。
- 执行构建配置文件(这是默认的工具链)。
- 将BUILD.gn文件加载到根目录中。
- 递归加载BUILD.gn其他目录以解析所有当前依赖项。如果在指定位置找不到BUILD文件,GN将查看tools/gn/secondary中的相应位置。
- 解决目标的依赖关系后,将.ninja文件写入磁盘。
- 解决所有目标后,写出根build.ninja文件。
Ninja 构建系统
https://blog.csdn.net/yujiawang/article/details/72627121
一些好用的ninja命令: 在浏览器中查看编译Target的编译依赖图(此命令会启动一个web server服务): ninja -t browse --port=8000 --no-browser mytarget