chromium中的GN构建系统

chromium中的GN构建系统
原创云水木石 最后发布于2017-06-23 17:16:35 阅读数 6924 收藏
展开
阅读最新的chromium源码,发现项目的构建系统已经从GYP全面切换到GN了。在软件开发中,经常有人忠告:不要重复造轮子。但谷歌可不管这个,造的轮子一个接一个,谁叫人家牛呢?chromiumi项目为啥要折腾构建系统呢?因为谷歌chrome浏览器追求一个字:快。不仅浏览器的速度要快,构建系统也要追求快。

构建系统简介
在探讨chromium的最新GN构建系统之前,回顾一下软件开发中的构建系统。构建系统的需求是随着软件规模的增大而提出的。如果只是做软件编程训练,通常代码量比较小,编写的源代码只有几个文件。比如你编写了一段代码放入helloworld.c文件中,要编译这段代码,只需要执行以下命令:

gcc helloworld.c
1
当软件规模逐渐增加,这时可能有几十个源代码文件,而且有了模块划分,有的要编译成静态库,有的要编译成动态库,最后链接成可执行代码,这时命令行方式就捉襟见肘,需要一个构建系统。常见的构建系统有GNU Make。需要注意的是,构建系统并不是取代gcc这样的工具链,而是定义编译规则,最终还是会调用工具链编译代码。

当软件规模进一步扩大,特别是有多平台支持需求的时候,编写GNU Makefile将是一件繁琐和乏味的事情,而且极容易出错。这时就出现了生成Makefile的工具,比如cmake、AutoMake等等,这种构建系统称作元构建系统(meta build system)。在Linux上软件仓库的概念还没有普及的时候,通常我们安装软件的步骤是:

./configure
make
make install
1
2
3
第一步就是调用AutoTool工具,根据系统环境(Linux的版本众多,软件安装情况也不一样),生成GNU Makefile。

Chromium中的构建系统
在我几年前接触chromium开源项目的时候,chromium采用的是GYP(Generate Your Projects)构建系统,这也是一种元构建系统。软件工程师根据GYP规则编写构建工程文件(通常以gyp, gypi为后缀),GYP工具根据gyp文件生成GNU Makefile。接着chromium项目又整出了Ninja构建系统,但这个Ninja并不是用来取代GYP的,而是取代GNU make的,据谷歌官方的说法是速度有了好几倍的提升。对于我们开发者而言,不需要去深入了解Ninja或GNU Makefile这样构建系统,因为这只是一种中间输出,所以ninja的出现,与我们关系不大,原来怎么写gyp,现在还是怎么写,只是构建命令稍微做了改变。

最近再看chromium的源码,发现里面熟悉的GYP文件都不见了,取而代之的是GN文件(以gn和gni为文件名后缀),瞬时感觉一夜回到解放前。然而稍微研究了一个GN文件,还是那些熟悉的模块、依赖、条件等等元素,和GYP差别不大,而且总体上比原来的GYP文件更清晰。

GN构建系统
GN是一种元构建系统,生成Ninja构建文件(Ninja build files),相较GYP而言,具有如下优点:

可读性更好,更容易编写和维护。
速度更快,谷歌官方给的数据是20倍的速度提升。
修改GN文件后,执行ninja构建时会自动更新Ninja构建文件。以前用GYP的时候就有过修改了GYP,而忘记使用gyp命令重新生成Ninja构建文件的尴尬。
更简单的模块依赖,提供了public_deps, data_deps等,在GYP中,只有一种目标依赖,导致依赖关系错综复杂,容易引入不必要的模块依赖。
提供了更好的工具查询模块依赖图谱。这在GYP构建系统中是一个噩梦,要查一个目标依赖哪些模块或者一个模块被哪些目标依赖几乎是不可能的。
更好的调试支持。为了打印GYP中的变量值,我以前还专门写过一篇博文<<如何打印gyp构建系统中的变量值>>,在GN中,只需要一条print语句就可以解决。
快速入门
运行GN
从命令行运行gn,这实际上是depot_tools下的一个脚本,所以需要确保depot_tools路径包含在环境变量$PATH中。

配置一个构建
在GYP中,有两个特定的目录Debug和Release目录,分别用于生成Debug版本和Release版本。在GN中,采用了更灵活的方式,你随便指定一个目录,比如为了测试,定义一个test输出目录,可以采用如下的命令:

gn gen out/test
1
那要是我要分别构建Debug版本和Release版本怎么办?GN通过传递参数来解决。也就是说,现在光通过输出目录是无法确定到底是Debug版本和Release版本,而要取决于传递的构建参数。

传递构建参数
将上面的命令稍微修改一下,即可设置构建参数:

gn args out/test
1
您可以使用下面的命令列出可用的构建参数和它们的缺省值:

gn args --list out/test
1
我在chromium源码下运行,参数如此之多,要翻好几屏,所以不需要记住所有的参数,只需知道几个比较常用的参数:

is_component_build = true
is_debug = false
1
2
前面一个参数决定是否分动态库build,现在chrome for android包含了build出了几十个so,就是这么来的,好处是节约修改代码后的构建时间。后面一个参数决定是build Debug版本还是Release版本。

从编写代码到build
编写代码,比如代码文件为test/hello_world.cc
编写GN文件,比如放在和上面代码同一目录下。

executable("hello_world") {
sources = [
"hello_world.cc",
]
}
1
2
3
4
5
打开源码根目录下的BUILD.gn,加入对上述目标的依赖:

group("root") {
deps = [
...
"//url",
"//test:hello_world",
]
}
1
2
3
4
5
6
7
这里//代表源码根目录。

构建

gn gen out/Default
ninja -C out/Default hello_world
out/Default/hello_world
1
2
3
调试
打印

static_library("hello") {
...
print(configs)
}
1
2
3
4
可以打印这个目标的配置信息。

查看目标信息

gn desc out/Default //test:hello_world
1
这会列出很多详细的信息,包括配置参数、目标依赖,通过更复杂的命令参数,你还可以查看某个宏定义是在哪个目标定义,目标依赖的树结构,比如:

gn desc out/Default //base:base_i18n deps --tree
1
更多参数的说明可以使用gn help desc查看。

总结
因为还没有编写复杂的GN文件,所以对GN的优缺点还体会不深,不过对于GYP的几个深有感受的痛点:
- 多层嵌套,导致GYP文件难以阅读和修改,想想chromium下的build/common.gypi这个文件有多恐怖
- 打印支持
- 对于复杂的依赖缺少有效的手段去定位和排查

这在GN上得到了完美的解决,就冲这这一点,也要为谷歌点赞。虽然是重复发明轮子,但轮子比原来的好用啊!

参考文档
What is GN?
GN Quick Start guide
————————————————
版权声明:本文为CSDN博主「云水木石」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/mogoweb/article/details/73650218

原文地址:https://www.cnblogs.com/bigben0123/p/12558003.html

时间: 2024-10-03 17:59:22

chromium中的GN构建系统的相关文章

【Chromium中文文档】Profile架构(看看谷歌家的重构)

进程模型 转载请注明出处:https://ahangchen.gitbooks.io/chromium_doc_zh/content/zh//General_Architecture/Profile_Architecture.html 全书地址 Chromium中文文档 for https://www.chromium.org/developers/design-documents 持续更新ing,欢迎star gitbook地址:https://ahangchen.gitbooks.io/ch

Chromium on Android: Android在系统Chromium为了实现主消息循环分析

总结:刚开始接触一个Chromium on Android时间.很好奇Chromium主消息循环是如何整合Android应用. 为Android计划,一旦启动,主线程将具有Java消息层循环处理系统事件,如用户输入事件,而Chromium为,己还有一套消息循环的实现,这个实现有哪些特点.又将怎样无缝整合到Android Java层的消息循环中去,正是本文所要讨论的话题. 原创文章系列.转载请注明原始出处为http://blog.csdn.net/hongbomin/article/details

[Gradle] 在 Eclipse 下利用 gradle 构建系统

转载自:http://www.ibm.com/developerworks/cn/opensource/os-cn-gradle/ 构建系统时候常常要用到 Ant, Maven 等工具,对于初学者来说,它们还是过于复杂,上手还是需要时间的.本文将向读者介绍一种全新的构建项目的方式 gradle,它简单.上手快,能大大节省项目的时间和成本. 在 eclipse 下利用 gradle 构建系统 基本开发环境 操作系统:本教程使用的为 Windows Vista Enterprise, 如果您的系统是

CMake命令:CMake构建系统的骨架

CMake命令:CMake构建系统的骨架 80个命令(转载自http://www.cnblogs.com/coderfenghc/archive/2012/06/16/CMake_ch_01.html#2996205) CMD#1: add_custom_command为生成的构建系统添加一条自定义的构建规则. add_custom_command命令有两种主要的功能:第一种是为了生成输出文件,添加一条自定义命令. add_custom_command(OUTPUT output1 [outpu

Blade - 腾讯开源的构建系统 c/c++编译环境

typhoon-blade Blade is an advanced building system developed with python, majorly for C/C++ Blade 是一个现代构建系统,期望的目标是强大而好用,把程序员从构建的繁琐中解放出来. Blade主要定位于linux下的大型C++项目,密切配合研发流程,比如单元测试,持续集成,覆盖率统计等.但像unix下的文本过滤程序一样,保持相对的独立性,可以单独运行.目前重点支持i386/x86_64 Linux,未来可

基于Jenkins的自动构建系统开发_android总结

持续集成相关理论 1.1 极限编程的概述 1.1.1 极限编程的产生 2001年,为了解决许多公司的软件团队陷入不断增长的过程泥潭,一批业界专家一起概括出了一些可以让软件开发团队具有快速工作.响应变化能力的价值观和原则,他们称自己为敏捷联盟.敏捷开发过程的方法很多,主要有:SCRUM,Crystal,特征驱动软件开发(Feature Driven Development,简称FDD),自适应软件开发(Adaptive Software Development,简称ASD),以及最重要的极限编程(

打造一个全命令行的Android构建系统

IDE都是给小白程序猿的,大牛级别的程序猿一定是命令行控,终端控,你看大牛都是使用vim,emacs 就一切搞定" 这话说的尽管有些绝对.可是也不无道理.做开发这行要想效率高,自己主动化还真是缺少不了命令行工具,由于仅仅有命令行才是最佳的人机交互工具. 事实上IDE也是底层也是调用命令行工具而已,仅仅只是给普通开发人员呈现一个更友好的开发界面. 这里可不是宣扬让大家放弃IDE都改命令行,仅仅是每种事物都有他存在的理由,不管是编程语言还是工具都是一个原则 "没有最好的,仅仅有最合适的&q

进击的云安全! 让你轻松构建系统安全基线

安全基线是一个业务系统的最小安全保证,即该业务系统需要满足的最基本的安全要求.构造安全基线是系统安全工程的首要步骤,同时也是进行安全评估.发现和解决业务系统安全问题的先决条件. 从具体的内容来看,安全基线的内容主要分为三个方面:系统存在的安全漏洞.系统配置的脆弱性.系统状态的监控,这是必须满足的最小要求组成.因而在传统的环境下,即使是一个有经验的安全运维人员,完成一个系统的安全基线(加固系统环境和应用环境)平均花费的时间也要在30分钟到40分钟左右. 并且在构建的整个过程中,运维人员还将面临以下

使用maven多模块来构建系统时,spring初始化报错的问题

最近在实验maven结构的maven工程时,碰到一个问题,springbean总是初始化失败: Related cause: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userMapper' defined in file [D:\workspace\mavenweb\mavenweb-webapp\src\main\webapp\WEB-INF