qbs介绍

作者:Zhen Zeng | Feb 21, 2012 12:32:05 PM

原文链接:JörgIntroducing qbs

多年来我们对qmake产生了一种爱恨交织的感情。一方面它确实能工作,另一方面它也有一些怪癖,因此被广泛地认为无法维护下去了。博文 [TMQB] 包含了一个有希望取代qmake的方法的列表。我们研究了市面上的各种各样的工具,但是没有一个能符合我们的需求 - 详见 [WNCM] 。所以不久之前我们启动了一个内部项目用以实验一些新的想法,成果就是:Qt编译套件,qbs(读作 "Qubes")

它不是qmake

和qmake不一样,qbs没有绑定Qt版本,它从项目文件的高级项目描述中生成一个正确的编译表(依赖表)。同样,传统的MakeFile生成工具比如qmake和CMake生成了makefile文件,然后将实际的命令留给make或者ninja这样的工具去执行。Qbs的另一方面就是充当了并行生成与直接调用编译器、连接器以及其他工具的角色,非常像SCons和Ant做的事情。

Declarative语言

qbs的语法是一个简化版本的qml,提供了对IDE友好的软件项目的展示。它同样提供了自由使用任何JavaScript表达式进行属性绑定的支持。项目文件编辑器能够理解如何对纯字符串数组文字进行处理。对于更复杂的结构,项目文件编辑器能够“回滚”,使用文本编辑器打开项目文件。

files: ["foo.h", "foo.cpp", "main.cpp"]              // 可从 IDE 编辑
files: generateFileList().concat(["extra.cpp"]) // 只能在文本编辑器中处理

对于大多数应用场景来说,可以编写对IDE友好的的项目文件。如果你需要更多的控制,你也可以自由的释放你高超的JavaScript技巧。
现在我们来看一个必须的“Hello World”项目:

// helloworld.qbp
import qbs.base 1.0

CppApplication {
name: "HelloWorld"
files: "main.cpp"
}

import语句使我们可以使用类似“Application”一样的项目,我们给项目起名为“Hello World”,并添加了一个C++源文件。

语言的详细部分说明在文档的“语言介绍”中。

可扩展性

在 qmke中进行代码生成与资源编译相关操作是大家想尽量避免的。而在qbs里,你可以很容易地编写一些规则来将一种特定类型的文件转换为另外一种。qbs既可以调用一个外部工具(例如:rcc)来进行转换操作,也可以直接用内含的JavaScript来转换。下面是一个简单的例子,演示了如何将Qt Creator源码树的.pluginspec.in文件转换为.pluginspec文件。

Rule {
...
prepare: {
var cmd = new JavaScriptCommand();
cmd.description = "generating " + FileInfo.fileName(output.fileName);
cmd.qtcreator_version = product.module.qtcreator_version;
cmd.sourceCode = function() {
var inf = new TextFile(input.fileName);
var all = inf.readAll();
all = all.replace(new RegExp('\$\$QTCREATOR_VERSION(?!w)', 'g'), qtcreator_version);
var file = new TextFile(output.fileName, TextFile.WriteOnly);
file.write(all);
file.close();
}
return cmd;
}
}

快速增量编译

qbs将项目视为整体因此不会为它划分成子项目。就算是只编译项目的一部分,整个编译图表都会纳入考虑范围当中。不会再出现循环生成的问题了(参见: [RMCH])。

采用这种方式还有一个好处就是可以使得增量编译的速度比生成操作要快得多。我修改了来自[QPBS]的基准生成脚本,添加了qbs的支持。下述的测试结果来自一个增量编译的项目,项目包含了200个库,每个库50个类,每个文件有50个库内包含以及10个库外包含。

在我的机器上,进行没有修改任何生成文件的增量编译操作耗时:
实际 0m4.076s
用户 0m2.556s
系统 0m1.952s
qbs 下同样操作耗时:
实际 0m0.843s
用户 0m0.724s
系统 0m0.112s

编译说明

说得够多了。我如何能获取它?怎么编译它?

git clone git://gitorious.org/qt-labs/qbs.git
cd qbs
qmake -r qbs.pro
make
make docs

请先阅读文档,尤其是“配置qbs”部分。在线版本可以访问这里。然后你就可以开始试试/qbs/tests/manual下面的例子了。如果需要一个现实点的项目例子,可以在这里找到为Qt Creator而写的qbs项目文件。

qbs项目欢迎贡献者,参考Qt-Project 词条中的“Setting up Gerrit”。gerrit远程地址是 <Gerrit/Jira>@codereview.qt-project.org:qt-labs/qbs 。

qbs项目的邮件列表是: http://lists.qt-project.org/mailman/listinfo/qbs

前景

这是一个试验性质的项目,用来试验不同编译工具概念。qmake仍然会存在很长一段时间,并且没人会强迫谁去使用qbs,或者其它任何编译工具。尽管在某些时候我们肯定会尝试将qbs作为Qt自身的编译系统来使用。

通用元编译工具,比如CMake或者GNU Autotools的用户也许注意到了,严谨来说,qbs与跨平台编译工具相比有一个关键部分的缺失:适应宿主环境,就是所谓的配置检查。当前,qbs仍然需要一个外部的配置脚本来生成一个JSON格式的文件,从而能被qbs调用。但是这终究不是一个长久的解决方法。关键点在于使配置测试像其他模块一样可用。其实现当然不止包括了Declarative,还包含了一些JavaScript代码。

目前还有很多需要做的工作!非完整的想法列表可以通过我们的缺陷跟踪器查看(当我们的管理员将这个项目设为公众开放的时候)。

引用

[RMCH] Peter Miller (1998), “Recursive Make Considered Harmful”, AUUGN Journal of AUUG Inc., 19(1), pp. 14-25
[TMQB] Marius Storm-Olsen (2009), “To make, or not to make – QMake and beyond”, http://labs.qt.nokia.com/2009/10/12/to-make-or-not-to-make-qmake-and-beyond/
[WNCM] http://lists.qt.nokia.com/pipermail/qt5-feedback/2011-June/000494.html
[QPBS] Noel Llopis (2005), “The Quest for the Perfect Build System”, http://gamesfromwithin.com/the-quest-for-the-perfect-build-system