Introducing qbs

Over the years we have developed a kind of a love-hate relationship towards qmake. It does its job but also has its quirks and is widely considered unmaintainable. The blog post [TMQB] contains a wish list for a qmake replacement. We have considered the various tools on the market, but none satisfied us - see for example [WNCM]. So some time ago we have initiated an internal project to try some of the ideas. This is the outcome of it: the Qt Build Suite, aka qbs (pronounced as "Cubes").

It is not qmake

Unlike qmake, qbs is not tied to the Qt version, and it generates a proper build graph (dependency graph) from the high-level project description in the project file. Also, classical makefile generators like qmake and CMake create makefiles and leave the execution of the actual build commands to tools like make or ninja. Qbs on the other hand fills the role of a parallel make and directly calls the compiler, linker and other tools, pretty much like SCons and Ant do.

Declarative Language

The language of qbs is a simplified version of QML, providing an IDE-friendly representation of software projects. Still it provides the freedom of writing all kinds of JavaScript expressions on the right-hand-side of property bindings. A project file editor could know how to edit file lists that are pure string array literals. For more complicated constructs it would fall back to opening the project file in a text editor.


files: ["foo.h", "foo.cpp", "main.cpp"]              // editable from IDE
files: generateFileList().concat(['extra.cpp'])      // only editable in your text editor

For most use cases it should be possible to write IDE-friendly project files. But if you need more power, you are free to unleash all your l33t JavaScript skillz.

Now let's have a look at the obligatory "Hello World" example:

// helloworld.qbp
import qbs.base 1.0

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

The import statement enables us to use items like "Application". We are giving our application the name "HelloWorld" and adding a C++ source file to it.

A thorough walk-through of the language can be found in the documentation under "language introduction".

Extensible

Dealing with code generators or resource compilers is something you really want to avoid in qmake. In qbs you can easily write rules to transform files of a certain type to files of another type. One can either call processes that do the transformation externally (e.g., rcc) or directly execute the transformation in JavaScript. This simplified example demonstrates how to turn the .pluginspec.in files of the Qt Creator source tree to .pluginspec files.

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;
    }
}

Fast incremental builds

Qbs sees the project as whole and thus does not need to fork itself for subdirectories. Even if only a part of the project is built, the whole build graph is taken into consideration. The problems of recursive make (see [RMCH]) are no more.

This also has the consequence that incremental builds are much faster than with make. I have modified the benchmark generator script from [QPBS] and added qbs support. The following results were obtained from incremental builds of a project with 200 libraries, 50 classes per library, 30 lib-internal includes per file and 10 lib-external includes per file.

On my machine, doing an incremental build without any changed files with make takes

real 0m4.076s
user 0m2.556s
sys 0m1.952s

doing the same with qbs

real 0m0.843s
user 0m0.724s
sys 0m0.112s

Build Instructions

Enough talk. Where do I get it? How to build it?


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

Please read the docs, esp. the part "configuring qbs". You can find them online here. Then you can start playing around with the example projects in qbs/tests/manual. If you are more in search of a real-world project, you can find qbs project files for Qt Creator right here.

The project is open for contributions. Please see "Setting up Gerrit" on the Qt Project's wiki for instructions. The URL of the gerrit remote is <Gerrit/Jira username>@codereview.qt-project.org:qt-labs/qbs.
The project's mailinglist can be found at http://lists.qt-project.org/mailman/listinfo/qbs

Outlook

The state of this project is experimental. It is meant as a playground for different build tool concepts. Qmake will still be around for a long time, and nobody will force you to use qbs or any other build tool - though of course we will probably try to push qbs for Qt's own build system at some point.

Users of common meta build tools like CMake or the GNU Autotools may have noticed that a crucial part is missing if qbs is meant to seriously compete in the cross-platform build tool market: adapting to the host environment, aka configure checks. For the time being it is still necessary to use an external configure script to generate a JSON file for qbs' use, but that is of course not meant to be the long-term solution. The idea is to make configure tests usable like other modules. Their implementation will of course not be purely declarative, but will contain some JavaScript code.

There is plenty to do! For a non-exhaustive list of ideas, see our issue tracker (once our admins configure public access to the product).

References

[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


Blog Topics:

Comments