Blade和其他构建工具有什么不同
大部分人都至少接触过不止一种构建工具,比如make,autotools。而我们开发了Blade,为什么那么多现成的工具不用,而又再造了一个轮子,相对于传统的make等工具,Blade的好处在又哪里呢?你的项目是否适合用Blade来构建,
以前的文档都是冷冰的介绍,今天本文将从作者和开发人员以及项目代码维护者的角度回答这些问题。
Blade总的来说要解决这些问题:
真正环境下的C++软件的开发,往往有数十人甚至数百个开发人员,源代码有成千上万个文件,百万甚至千万行。如何高效而安全地构建这些代码?
为了保证代码质量,我们还需要Codereview,代码提交流程,自动检测工具,单元测试,持续集成等现代化的开发流程,如何保证这些流程被实施?
Blade就是为这样的项目而生的。
下面是我分析的Blade的特点:
[构建规则简单]
Blade的构建规则很简单,是说明性而非指令性的,只要描述出源文件以及依赖即可,不需要描述如何构建。我比较过gyp和cmake的构建规则,都不如blade的简洁。
因为描述的是需要什么而不是怎么做,因此不需要开发人员掌握gcc的命令行,更无需记忆make的哪些奇奇怪怪的自动变量,大幅度降低使用门槛。
Blade还直接支持编译 protobuf,lex, yacc, swig 等,不需要自己写构建命令和规则。
[自动依赖分析和传递]
用过Make的都知道,所有的依赖关系要自己维护。我们都知道C/C++语言中的头文件是个很麻烦的事情,
在手工维护的make的依赖规则中,一般只写出.o文件对.c文件的依赖,这样当.c文件所包含的头文件变化时,
不会自动构建,这时候往往是需要做一次make clean然后重新编译,用make维护增量构建的意义大减。
即使写了对头文件的依赖,但是头文件里还会包含头文件,对于这些间接包含的头文件,是多到无法写出的。
而Blade自动分析头文件依赖关系,构建受影响的代码。头文件变化时,所有直接和间接包含它的源文件都会
被自动找出来,进行构建。而不受影响的源文件则无需重复构建,真正实现了增量构建。对于链接也是一样。
对于大的项目,我们往往分成多个库来构建,而且库之间还会有依赖关系,如果用了一个库,在用make的时候,
我们需要在命令行把它依赖的库都列出来,一个都不能少,而且顺序还不能错,否则都会导致链接错误。
更麻烦的是,假如某个库的实现变了,不再增加了一个新的依赖,那么所以用到这个库的地方都需要修改加上这个依赖。
Blade只需要开发人员写出直接依赖,而库的间接依赖是自动分析出来的,构建时也会自动检查所依赖的库是否需要重新构建。
[提高代码可读性]
既然Blade的构建理念是把整个项目看作一个有机的整体,那么头文件和库文件都在这个项目中有唯一的位置,天然不会重复,不怕重名。我多次经历或者见过头文件或者库文件重名,每次都浪费大量的时间。
Blade提倡从项目根目录开始定位文件和库,彻底避免了这样的问题。在这样方式组织代码的项目工作越久,就越能体会到Blade提倡的#include 从根开始写是在保护你而不是在故意为难你,并开始喜欢这种组织方式。
[构建速度优化]
除了上面所说的依赖关系维护消除了clean使得只需要增量构建外,Blade还开启了并行构建,默认多个进程同时构建,提高构建速度。
对于make也不是不可以并行构建,但是由于依赖关系的负责性,更容易出错。
为了进一步提高构建速度,Blade还支持ccache缓存构建结果和distcc分布式构建。
[易用性]
持续集成是代码质量的有效保证。通过持续集成,使代码持续处于可构建状态,大幅度减少了错误,提高了发布和部署的效率。
在做发布和持续集成时,我们常需要一次构建所有的目标,有时候还需要涉及32位64位等多个平台。
用make时一般的做法是用递归make,在上层的makefile里描述出有哪些子目录,并层层递归。这样的缺点是,
底层目录改动需要修改上层的Makefile,再加上库的依赖不能传递,使得makefile维护的大项目经常处于无法完整成功构建的状态。
Blade支持一下子构建整个目录树,并不需要写额外的描述。
对于递归make,两个目录有依赖关系时,依赖者就无法单独构建,需要跑到上层目录,先构建依赖,再构建自己才行。否则可能会用到旧的库。
Blade在代码树的任意子目录下都能构建,其依赖会被自动找出来构建,不多不少,确保正确性。
Blade内置 debug/release 两种构建类型,32/64位两种目标平台。
Blade的构建进度显示被大幅度简化为做了什么而不是在怎么做,减少了make中默认显示出的完整命令行对视觉的干扰。
为了更醒目地发现问题,构建过程中的警告和错误信息是用彩色高亮现实的,一眼就能看到错误提示行。
Blade的命令行接口类似svn,由一系列子命令,目标名和参数组成,简单好记忆,还支持bash风格的命令行补全,按tab键自动补全命令行。
[方便部署]
在我看来动态库就是灾难,见过不少依赖dlopen加载的库/框架,有的还支持热卸载,甚至想在同一个进程中加载不同版本的两个库来做对比测试,这样的项目无不bug不断,开发人员痛苦不堪。
因此Blade提倡静态链接,默认甚至把libstdc++和libgcc都静态链接到了可执行文件。发布时一个可执行文件就搞定(可能还需要一些配置文件,数据文件等)。省时省心。
[测试支持]
单元测试是代码质量的重要保证,可以把大量的低级错误消灭在萌芽状态,并提高代码的可维护性,降低开发成本。
用make的时候,一般是写一些可执行文件类型的目标,构建出来后,在人工运行它,没有任何机制保证这些测试会被运行。
如果测试写了不运行就等于白写,Blade直接支持类型为测试的目标类型,只需要描述哪些目标是是测试即可。Blade支持命令行批量执行这些测试。
因此运行测试可以由开发人员主动进行,也可以通过开发流程工具,在代码发起review或者提交前运行,以及持续集成时运行,使得测试真正做起来。
为了提高测试效率,自动支持多个测试进程并发运行,支持增量测试(自动跳过最后一次是成功且没有新的变化的测试程序)。
为了检查内存泄露,测试集成 gperftools,自动检测测试程序的内存泄露,使得大部分内存泄露可以在单元测试时发现。
最后总结一下,Blade是为了减轻大规模C++项目的维护成本,提高开发效率和质量而生的现代化构建工具。
Blade和其他构建工具有什么不同的更多相关文章
- Google软件构建工具Bazel原理及使用方法介绍
近期,Google开源了强大的自动化构建工具Bazel. 正好博主近期在使用china版的Bazel--腾讯自主开发的Blade,所以准备跟大家分享一下Google Bazel这个分布式构建系统的原理 ...
- Gulp:自动化构建工具
一.介绍: gulp是一个基于流的构建工具,可以自动执行指定的任务,简洁且高效 二.优点: 开发环境下,想要能够按模块组织代码,监听实时变化 css/js预编译,postcss等方案,浏览器前缀自动补 ...
- 前端构建工具之gulp(一)「图片压缩」
前端构建工具之gulp(一)「图片压缩」 已经很久没有写过博客了,现下终于事情少了,开始写博吧 今天网站要做一些优化:图片压缩,资源合并等 以前一直使用百度的FIS工具,但是FIS还没有提供图片压缩的 ...
- 前端构建工具之gulp_常用插件
gulp常用插件的使用 今天来看看一下gulp的常用插件的使用 就像gruntjs需要一个Gruntfile.js文件一样,gulp也需要一个文件作为它的主文件,在gulp中这个文件叫做gulpfil ...
- 前端构建工具的用法—grunt、gulp、browserify、webpack
随着前端项目的飞速发展,项目越来越大.文件越来越多,前端工程化的工具也越来越多.下面介绍目前最流行的四种构建工具——grunt.gulp.browserify.webpack 所有的构建工具都是基于N ...
- Google软件构建工具Bazel FAQ
Google软件构建工具Bazel FAQ 本文是我的翻译,原文在这里.欢迎转载,转载请注名本文作者和原始链接 注:如果想了解Bazel的原理,可以看看我之前翻译的Google Blaze原理及使用方 ...
- 为什么google bazel构建工具流行不起来
作者Jack47 转载请保留作者和原文出处 之前博主写了系列文章Google软件构建工具Bazel原理及使用方法介绍.最近使用了一段时间后,觉得这个东西不是一种通用的构建工具,很难对接到情况复杂的大的 ...
- 前端构建工具gulpjs的使用介绍及技巧
gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也非常简单,学习起来很容易,而且gulpjs使用的是nodejs中stream来读取和操作数据,其速 ...
- gulp自动化构建工具
gulp 自动化构建工具,实时监控.代码合并.压缩... http://www.gulpjs.com.cn/ 中文网 http://gulpjs.com/plugins/ 英文网 ...
随机推荐
- 浅谈C++ 异常处理的语义和性能
异常处理是个十分深奥的主题,这里只是浅论其对C++性能的影响. 在VC++中,有多个异常处理模式,三个最重要: No exception handling (无异常处理) C++ only (C++语 ...
- Python正则表达式+自创口诀
重新学习了Python正则表达式,看了一些很好的学习博客,向大家推荐这个. 感谢作者@AstralWind 博客地址:http://www.cnblogs.com/huxi/archive/2010/ ...
- 50 Pow(x, n)(求x的n次方Medium)
题目意思:x为double,n为int,求x的n次方 思路分析:直接求,注意临界条件 class Solution { public: double myPow(double x, int n) { ...
- Python新手学习基础之函数-lambda函数
lambda函数 在Python里除了用def定义函数外,还有一种匿名函数,也就是标题所示的lambda函数,它是指一类无需定义标识符(函数名)的函数或子程序. lambda函数的使用语法如下: la ...
- maven3.0
Maven入门教程 1.1. 介绍.环境配置 1.1.1. Maven介绍 Maven是一个采用纯Java编写的开源项目管理工具, Maven采用了一种被称之为Project Object Model ...
- 去除win8.1这台电脑中的6个库文件夹
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace,备份之后删除 wi ...
- Andoird 监听开机广播和关机广播
需求:有时候,我们需要自己的程序在开机后自动运行;在关机时,记录一些信息到文件中. 一.开机广播监听Android系统启动完成后会自动发出启动完成广播(android.intent.action.BO ...
- windows环境下VS2013编译openSSL
openssl版本:1.0.2h 编译器:MSVC (VS2013) 需要准备工具:perl. windows环境的perl下载请戳这里:http://www.activestate.com/acti ...
- POJ1789 Truck History(prim)
题目链接. 分析: 最大的敌人果然不是别人,就是她(英语). 每种代表车型的串,他们的distance就是串中不同字符的个数,要求算出所有串的distance's 最小 sum. AC代码如下: #i ...
- [Java] 继承中,父类被覆盖的成员变量、方法的可访问性
在 Java 的继承机制里,在子类内部,可以访问父类被覆盖的变量和方法:在子类外部,可以访问父类的被覆盖变量,但是不能访问父类的被覆盖方法. 父类中被覆盖的方法不能在外部被方法,这是出于封装的考虑. ...