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.

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.

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

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.

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).

Are you considering some Visual Studio (2010) integration or project generator like qmake currently have?

We use qmake to compile our project under linux and mac using standard c++ toolchain and develop whole application with Visual Studio, Visual Assist and Incredibuild on Windows platform. Are there any simmilar plans with qbs?

@KarlNapf
The CMake developer asked the Qt developers what they would want from a declarative-type CMake input file which would be parsable by CMake and offered to devote resources to it. As far as I can tell, no-one took them up on the offer publicly.

Why not just adopt cmake? I like qmake for Qt projects, and cmake is not perfect, but do we really need another build system? Why not settle for a “standard” (and help improve that)? What about the maintenance burden?

Great to finally see an approach for a portable, declarative build system! I wonder if qbs would allow for building the dependency graph exclusively using declarative items and predicates, which could be defined (separately) in JavaScript. The imperative style of managing dependencies in CMake seems just so insanely ugly to me…

Things I like:
– Git style config (global/project local)
– No more msvc shell hell
– It also seems to be possible to extend qbs with git style subcommands. Could we also have “qbs fetch-dependencies”? (I remember Cornelius Schumacher proposing a “CPAN for Qt” or a qbs run-tests)?

What I miss/don’t understand:
– Would you mind having a ‘qmake -project done right’ which could be “qbs generate “, even if it duplicates Qt Creator project wizards?
– And maybe this is a bit premature but I understand that Qbs would not be dependent on a Qt version, but Qt is required for QBS. If later, Qt depends on Qbs, how would you solve that circular dependency?

A MSVC generator would be possible, since qbs has full control over everything. If you can ignore the lack of IDE integration for now, you can even use qbs with incredibuild (provided the correct xml file).

I hate to be negative towards a new approach in which clearly quite some energy was invested, but I’m also the opinion: Just adopt CMake.

Writing a buildsystem is a big task and a huge maintenance effort. Better use an existing buildsystem like CMake that has been used in production for many years. CMake works quite well in many areas, especially areas that QMake neglected like configure checks. I fear the chances of QBS also covering all these areas equally well are small. Qt should focus its developer time on its core competence, the Qt library, and not on writing and maintaining a build system.
As a developer, I don’t want to learn yet another build system language. Please, use some standard tool that the rest of the industry uses as well.

The most cited reason for not using CMake is the IDE integration. But then, look at KDevelop, which has its own CMake parser that works quite well, so things like seeing a list of targets in the sidebar work as expected. KDevelop can even add or remove files from within the GUI. Of course that works only in simple CMake files, but this article itself mentions that QBS is in a similar situation and can not do this on more involved constructs. The most important thing is that it works flawlessly for the average small project, and that can be done with both CMake and QBS.
I don’t see why QtCreator couldn’t have a similar parser, surely maintaining such a parser would be much less work than writing a build system from scratch.

For other shortcomings in CMake, go and fix them upstream. QBS’s advantage in incremental builds was mentioned. I never found that to be a particular problem in CMake, especially since there is “make target/fast” that avoids the dependency checks. Anyway, even that would be fixable with a new CMake generator and a make replacement, if really needed.

Please, go for CMake, a buildsystem wildly used that is working and successful. It is surely not perfect in every regard, but then, writing your own buildsystem will also have its flaws, and given that buildsystems are not a core competency of Qt, I expect the flaws to be much larger than in CMake in the end, for questionable gain.

Sorry for the negativity towards QBS. I am sure it will be way better than QMake, and I like some of the new ideas in there. In the end I strongly favor CMake though.

Currently ninja is the reference for speed. Have you compared the “incremental build without any changed files”
(is there a shorter name for this? “empty build”, “clean build”) with the times ninja needs?

So on my system qbs managed the initial build about than half the time it took qmake/make. That is impressive. The incremental build without changed files was slightly faster with qbs, but not as much the blog post made me expect.

Now it would be interesting to be able to compare the compile time of Qt Creator build with CMake… I would expect it to be similar to qmake, considering that CMake is ultimately also using make for the heavy lifting. But that is just speculation at this point.

I wouldn’t be surprised if the Makefiles generated by CMake take longer than those generated by qmake, since they contain the complete dependencies, whereas those generated by qmake contain only some dependencies.

Also, if the speed of make itself is the isse, since today cmake git supports the ninja build tool, which is a make replacement, and it’s main focus is to be faster than make.

Hi. I’m the guy who made most of KDevelop’s CMake support. I must say that it’s a __nightmare__ to support CMake from a language point of view. I had the luck that I could dedicate quite some time to create our support and make it work, but I don’t know if that’s something QtCreator people will want to do (and for that matter, any other IDE).

As I’ve said before, I like the idea of defining what to compile and provide code _only when needed_, in contrast to CMake where you’re programming everything, and you happen to invoke definitions, sometimes.

On the other hand, the world doesn’t need Yet Another Build System. In my opinion, one of the very reasons that QMake wasn’t used that much is that it felt too tied to Qt, and whenever you left the typical project structure you had to start making weird constructions. I consider that if QBS doesn’t want to be another QMake, it should be detached from Qt. I don’t know if that’s a goal yet, though. That is, how easy is it to use Boost in the project? What about KDE for instance? A very interesting feature would be to make it possible to use Find*.cmake/*Config.cmake scripts on QBS, which would be considerably easy to implement.

A good example of why I think this can be short-sighted can be seen on how in those examples we don’t see how to add include directories or linking to libraries. Is it assuming Qt? Is it assuming you only do “hello worlds”? Please don’t be condescending to us and remember that us developers we don’t like to be creative with our build tool, we want a just-works ™.

In any case I’ll be following the development closely and the KDevelop team will definitely help if we can and are welcome to.

@thomas: the idea of handling ide projects with a text editor as only way, not as option somehow reminds me of aesop’s “fox and grapes.” if it had been possible to make cmake palatable for an ide on someone would have done it for any of the ides out there. alas, it has not happened in the years gone by.

@Goodbye qmake: I would love a ‘qbs create-project’ command, to create a boiler-plate .qbs file. No reason why someone couldn’t do that.
The world is full of circular dependencies. Don’t forget is that we already have working systems, so lets use them.

@KarlNapf: Incremental builds: Take a look at the system part for each of the tools.
qbs: 0,18s at 99%
make 1,73s at 190%
Clearly make is putting a lot more strain on your system, and getting a worse result from it. The user part in qbs is proportionally a lot bigger than in make’s case, so we might have to look at how we use threads to perhaps walk the DAG to figure out what needs to be done, or optimize the loading/storing of the DAG. We have been contemplating mmapping the DAG and thus eliminate the load/store of the whole structure which is quite large. But, that would require rewriting the tools classes we use in qbs, so it is clearly something for later optimization.) I think it’s safe to say that there’s plenty of potential for improvement in qbs.

Now, think about other platforms; Windows for example. How do you think the incremental build comparison will fare there, between qbs and nmake?

@Aleix Pol: Have a look starting at line 117, here http://codereview.qt-project.org/#patch,unified,16019,3,qtcreator.qbp
You’ll quickly see usages of rpath, includePath, (other) product dependencies, targetOS conditions, etc. Just dig deeper into that patch-set to see other constructs, and to see how qbs is used for building all of Qt Creator (not such a small product anymore).

In other news…
I’m surprised that no one has yet mentioned how cool it is that qbs can actually build with multiple bintools in parallel (Well, it’s perhaps not trivial to find out, and Jörg didn’t mention it in the blog post. But say you have both MSVC and MinGW installed, qbs can build a product with both, in parallel. If you have GCC and ICC, same thing. That’s the under-documented purpose of the ‘qbs shell’ command, which will create you a shell with the properly setup environment for a given environment. Nifty, ey?

@Aleix Pol: Ah, I forgot. No, qbs has no magical knowledge about Qt at all, unlike qmake. The tool is designed to be toolkit-agnostic.
All of qbs’ knowledge of Qt is put into qbs/js files which you can find under /share/qbs/modules/qt.

I agree with most people here, why re-invent yet another build system ?
It seems you studied existing tools, though when i read your requirements and options, I can’t understand why you ruled out waf (http://code.google.com/p/waf/ ). You mention scons, which is outdated by far..

Alex: If qbs is really faster than other systems, shouldn’t it be straight forward to add a generator for qbs to cmake?

Peter: Not sure whether “-j 7″ is faster or not:-) “-j 6″ is not enough to get all the cores to 100%. I did not bother too much after that and went straight to “-j 12″. As long as the system does not start to swap everything should be fine and it does not for 12 jobs.

Marius: Yes, qbs seems to be taking less resources, but the time I have to wait for qbs is pretty similar to the time I have to wait for make (on my system and for Qt Creator). I don’t really care how hard my computer works, I care about the time I have to wait for it to finish:-)

The initial build is really impressive with qbs though: It keeps all my cores at 100% all the time. Note that my system was not idle, so 522% cpu is really great for my 6 core system. Qbs looks really promising for a build farm:-)

Oscar: I just did compare the qmake build process to the qbs build process (on linux by the way). It was just a quick test, using the one project that has qbs-support, comparing the new stuff to what was used before.

From there you can not really guess at how other systems will compare, not even cmake which is by default also using make for the actual build process: The makefiles are very different, so the time used to run them may differ widely, too.

I like the idea of another build tool It look easy to use and very flexible. Yes its far from finished, but its the first experimental version. So lets try it. Nobody forces you to drop your favorite build system. Im pretty sure, that you can still use it even if qbs will be one day the default qt build system.

Thomas@ Also qmake somehow was capable to do it, but you had to have a build folder for every platform, what I’m asking if I can build all these platforms at once (e.g. $ qbs build android abis=all — to build all supported abis for android (armv5,armv7 and x86) or $ qbs build android abis=armv5;armv7 — to build only armv5 and armv7).

We have used qmake for many years, and I don’t think qmake is ‘quirk’. I feel qmake’s code is quite understandable and very brief when I first saw it. Please don’t try to create a brand new dedicated language for everything. It’s too challenging and just waste of time. Yes, you can optimize the performance of making tools, but it’s not a good reason for changing user interface totally. I cannot understand the ‘quirk’ qbp code at all without reading dozens of pages of documents. It is too hard for you to create a beautiful language. Actually, there are thousands of languages in the world, but few of them are popularly accepted. Please remember, you are not GOD!

@jobs: It’s not a new language, it’s QML. If you every going to use Qt5, you are very likely going to touch QML. The language and internals of qmake is beyond repair really. The moment you touch anything, you break it. It would require a complete rearchitechture to bring it up to scratch, and even then you wouldn’t really be able to support expected capabilities like parallel cross-platform builds; and certainly not without breaking previous qmake code anyways.
Using a defined language, which is the same language we already use else where, was therefore the best option.

@BogDan Vatra: Yes, you can. qbs can build any number of build variations in parallel. If you can define an environment for a qbs build, qbs can build in it in parallel. Yes, it *does* rock.
You get giddy when you see it munch through a command line like
‘qbs debug platform:armv5 debug platform:armv7 release linux-gcc’
all in parallel

@KarlNapf: I agree, it doesn’t matter if the application uses more resources. I just pointed out that qbs spends much less time in the kernel than make, so it has a head start. I also pointed out that we have work to do in userland, and indicated a few things that can make dramatic cuts in our current userland time; such as optimizing the load/store of the DAG, which has probably the greatest impact on userland time for incremental untouched builds.

I still need to spend some time testing it, but my first impression is: not for me. While I can clearly see the advantage over qmake for qt projects, in a broader scope I don’t see any reason to create a new tool from scratch except for the fun factor

OTOH I think that properly generated non-recursive makefiles would easily match the performance for incremental builds.

@Oscar Morante: Fair enough. You don’t have to use it
Regarding non-recursive makefiles. I beg to differ. Unless you are *only* thinking about the Linux platform, then a big maybe. You would never find a tool that could generate that optimal Makefile(s) though, and still be a flexible tool, I’m sure.

@ary: Unfortunately, no.

@Pau Garcia i Quiles: qbs doesn’t generate anything (except an internal build graph, which you can dump ;)), it’s a build tool, not a meta build system like gyp, cmake, qmake. So no, it does not generate project files for Visual Studio, Eclipse, XCode, etc. There are several options here, non which are implemented yet. You can
a) Add qbs as a project file plugin for these tools. Both Visual Studio and Eclipse allows you to create plugins which could use QBS as a “native” project format. This is probably the optimal solution, and what qbs is built for. It’s supposed to be easily integrated into an IDE, and our primary target is to get it into Qt Creator.
b) You can write an “iterator” for qbs which will run through the DAG and create these project files as an output. Possibly you could even create these non-recursive makefiles Oscar has been talking about that way too

This is very interesting. Ignore all the qbs haters pushing CMake. CMake syntax is aweful. qmake was always cleaner, at least often cleaner, although it certainly has it’s problems. Build times are unnecessarly slow as you point out so if qbs can compile my code dramatically faster while retaining a clean syntax I can easily jump into and maintain I’m all for it. A few questions:

1) I currently use qmake to compile my rather large project. Rather then use one giant monothic .pro file I have .pri files in every directory. Thus .pri files often include other .pri files in subdirectories. The main .pro file includes the top level .pri files. It looks like you do the same thingon qbs like so, is this correct?

2) having to tell qbs what mode ot compile in each time is a little burdensome. I’d like to be able to store my preferred build settings (debug, release, targets, and other options honestly) into a .qbs file. I currently do this with a .pri file that my .pro file includes near the top. I then add variuos things to CONFIG like so:

Creating project files for those tools is a lot of work. Is Nokia really going to maintain this? Just take a look at all the effort Kitware puts into CMake. Who is going to maintain this? This is not like implementing a feature here and there: if you want qbs to become a generic build tool, you’ll quickly find there are almost as many use cases (and bugs) as users.

Creating a plugin for each tool is not realistic either, IMHO. There are many tools out there. Some of them only allow limited extensibility, others do not allow extensibility at all (case in point: Visual Studio Express)

I’m all in for a great build system but I’m not sure Nokia has evaluated how much effort maintaining a build tool requires.

@Marius#54 benchmark time! ^_^
I know that probably nobody around here wants to hear about this but… autotools are very flexible and can generate non-recursive makefiles.

Anyway, as I said I still need more testing to learn what qbs can do for me and form an opinion. Just sharing my thoughts here, no hate… I was just surprised that somebody else wants to start another build system from scratch.

@Will Stokes: We have talked about adding aliases, in the same way git has aliases. Then you can say that ‘awesomeness = debug platform:armv5 debug platform:armv7 release linux-gcc’ for example, and then a simpleqbs awesomeness
would be the same as writing qbs debug platform:armv5 debug platform:armv7 release linux-gcc.
This is not implemented yet, but would definitely be cool to have, and easy to implement. Contrib?

qbs picks up single qbs files in a directory, so you don’t have to specify it, unless you have multiple qbs files at the top-level; just like qmake.

@Pau Garcia i Quiles: Like I said, qbs is not meant to be a meta build tool. If people would want to use it as such, we would expect them to put in some effort in that direction. Remember that qbs is a fully open project, just like Qt, so contributions are encouraged and welcome! Adding b) is not on our schedule at all, but might be very interesting for people in the community. And no, it wouldn’t be *that* hard really. a) might be more reasonable, but probably more geared towards Digia, perhaps. (Remember that we have Qt Creator, which is our priority atm, which can also debug any Windows application too, both MSVC and MinGW based.)

But, I don’t think that there’s any point of having both a) + b). So, then maybe option b) is better to support also the community members using MSVC Express, as you’ve indicated. However, I don’t think either should be in scope right now. It’s still experimental, and lets ensure the tool can do the job well before one start churning out other back-ends.
Just to reiterate, there’s nothing in the tool which stops qbs from also working as a meta build system, and spit out project files for other build system, but it’s currently not the primary goal.

BogDan: building for multiple platforms in one go is one feature I totally forgot to mention in the post. The build environment is setup when calling the build tools, thus you don’t have to be in the right shell. Building for multiple platforms looks like this on the command line “qbs build debug platform:android-armv5 debug platform:android-armv7″. (Of course these platforms have to be configured first.)

Marius#36: We hope to add dbus support in a future version. But first we need to focus on printing T-Shirts using OpenGL.

Jobs: I object and claim that domain specific languages are a good thing. Also, the main part of qbs’ language is JavaScript, which is well-defined and not invented by us.

Amani: The MinGW build seems to be broken at the moment. Will fix that.

Will Stokes:
1) For Qt Creator we’ve written one .qbs file per product (plugins, static libs and application). These are referenced from the top-level .qbp project file.
You could also have everything in one big file, though I’d consider this harder to maintain and more likely to cause conflicts when collaborating with other people in one repo.
2) At the moment you cannot do that. We thought about something like adding command line aliases or a “qbs init” step, where you pass your build parameters and all subsequent builds in that directory would use that.
If you rename you project to myProject.qbp, then it will be automatically picked up in the current directory. The thought here is that a .qbp is a project file that can contain products and reference products, that are in separate .qbs files.

I’ve not said “hard”. I’ve said it’ll be a lot of work. It’s one of those tedious and time-intensive tasks with very little reward, and you need to keep up to pace with 3rd party tools, libraries, etc.

Jorg: Are you aware of Premake [1] build system? It also features simple declarative language for project configuration, but unlike qbs it is a meta build tool. It already has some support for Qt [2] and Qt Creator [3]. Last, but not least, it’s a well-established open source project (founded in 2003)

Some ideas in tup are planned as future features in qbs though, like the introspection of the outputs for automatic cleanup, for example; to ensure that interative builds are guaranteed to be as if you did a fresh top-level build. (See https://bugreports.qt-project.org/browse/QBS-22 for that task. Note that LD_PRELOAD will have to be reassessed, obviously)

@Pau Garcia i Quiles: Depends on how neatly you want the backends to be. You can get far and quickly by simply dumping most options just into the “Additional Options” field for each of the build utilities in the .vcproj/.vcxproj, for example.

@Marius Storm-Olsen: I’ve read it and I still don’t understand which point made you decide that Premake is not acceptable. It’s small, fast, simple, extensible, doesn’t have external dependencies. It’s easy to support multiple platforms with it and cross-compile. Also, it supports existing IDEs and tools (make, ninja is also planned).

Well, it doesn’t have some features mentioned in the original post “To make, or not to make – QMake and beyond”, but is it really easier to design new tool from scratch when it’s possible to improve existing one?

Re Aleix Pol:
> Hi. I’m the guy who made most of KDevelop’s CMake support. I must say that it’s a __nightmare__ to
> support CMake from a language point of view.

Of course it is. There is no standard for the CMake language, this is not like implementing a C or C++ parser or any other standardizes format.
You have to reimplement basically every feature, every bug and every bug fix of cmake in KDevelop.
We told you that it doesn’t make sense to do this.
Back then in 2007 I would have had time to extend cmake so that it generates everything you need for KDevelop, but you insisted on reimplementing cmake in KDevelop. I told you this won’t be fun. Those emails should still be in some mailing list archive.

@Pau: The scope of the task is known fairly well. Trolltech/Nokia has experience in maintaining buildsystems (qmake, qbuild, tmake), IDE integrations (VS, Eclipse), extending existing IDEs (Carbide.C++ for Eclipse) and creating an IDE from scratch (Qt Creator). The decision to create qbs was made with careful deliberation, by people having worked on IDEs, IDE integrations and buildsystems for years, including the maintainers of qmake.

Sounds promising. I definitely see the need for a build tool used within qtcreator but less for a generic build tool used outside.

Re Andre':
> The decision to create qbs was made with careful deliberation, by people having worked on IDEs, IDE integrations and buildsystems for
> years, including the maintainers of qmake.
After reading the post I have to disagree:
1) The author compares a recursive makefile generated by qmake with qbs and though draws a wrong conclusion -> make is slow
2) “Qbs sees the project as whole and thus does not need to fork itself for subdirectories.” again this is a result of a poorly crafted qmake makefile

Let me quote the cited paper: “Recursive Make Considered Harmful”
> How can it be possible that we have been misusing make for 20 years? How can it be possible that behavior previously ascribed to make’s
> limitations is in fact a result of misusing it?
qmake contributed to these 20 years of misuses. How to craft a better build system when one does not understand the fundamental issue with the current one? (no offense)

@Sane: Even if qmake could and would be enhanced to created perfectly optimized, super-fast non-recursive Makefiles the problem that qmake .pro files themselves are barely usable from an IDE’s point of view would remain. The driving force (at least for me) here is not the speed of the build (even if it is a nice side effect) but the possibility to have a proper IDE integration _without_ killing the manual/command line approach.

I like to be positive on everyones development, because we continuously need effort and new idea’s to keep Qt what is, and make it even better! But i rather like to see Qt integrating with an existing good build-tool like like CMake…

I use Qt for several years now, and i’m already using CMake most of the time, because it gives what i miss in qmake.

Could we not better put some effort in making CMake even better, en optimize the Qt-CMake integration than in again developing a new build-system?

If we choose CMake, we have less to learn, Less to support, become better friends with CMake, make KDE community happy, …

i wish qbs all the best, your doing great things, but i prefer CMake…

Couldn’t we make a poll about the future of qmake,qbs,CMake,… ? i really would like to sea everyones idea on this topic ?

CMake has serious issues as a language from the tooling point of view. These issues are imo not solvable without adding another declarative language on top of CMake. Is this realistic (I do not know)? But honestly I think this would mean reinventing QMake as something else.
Also I do not think there will ever be a build system to rule them all. Just accept that Qbs does exists and is a declarative and tooling friendly approach of the problem domain. Personally I think CMake and Qbs are different enough to coexist fine.

Again, why not CMake? Sure the macro-based syntax is a bit retro, but the core dependency model that CMake builds of the whole project is very sound in my experience. The internal representation is very flexible and allows any number of output generators to create build-system specific “project files” or Makefiles. E.g. Qt Creator already parses the CodeBlocks generator’s output to permit working with CMake projects.

I’m not keen on the QML/Javascript syntax but we need a replacement for qmake and while cmake is very mature and well supported, the syntax is horrible.

I actually like working with qmake for the most part. The syntax is clean and minimalist and the defaults work well to build projects quickly. But then I’ve not used it for massive projects like Creator where you have to include switch logic into the build system.

My *biggest* issue with qmake has always been the poor documentation. I’m convinced that it’s the lack of documentation and best practices that leads to unreadable hack solutions.

1) How does this handle dependency tracking? This is a pain in qmake. Library and file change dependencies have to be manually added and there is very little documentation to do this.

2) Does Qbs replace the need for manual command line scripts for installed library names and copying files? These have to be fine-tuned individually for every platform. I should not have to do this just to copy a file during after a build.

Danny:
1) In qbs you don’t have to manually add the file dependencies if you’re linking to a library.
2) Ideally, there is a set of JS functions that enable you to copy files etc. in a platform-independent way.
We already have functionality for reading / writing text files and file copying.

Re Joerg:
>I didn’t say that make itself is slow. Just that the classical recursive make approach is slow. Of course this particular issue could be fixed
> by generated on giant makefile.
Sorry Joerg, no need for a gigantic makefile and yes recursive make files are bad and slow no need for a proof =D. Hope you find some time to study make/makefiles, this will definitely help you to craft a good build system.

Andre’, as I wrote I see the need for a build system for qtcreator as an IDE not a generic one. In the end you can have a slow builds in any build system if you do not understand and craft them carefully.

Great, I even saw that you implemented the platform probing for mingw (I had to hack it into gcc’s specific_probe last time).

There remains one last problem with the toolchain install path. You are using the following code for the mingwPath:
mingwPath = QFileInfo(dir + “/..”).canonicalFilePath();
And then, you save the value to the config variable cpp/toolchainInstallPath. This means that cpp/toolchainInstallPath is C:Mingw32 for example. Then, when qbs is running on the project, it tries to start C:MinGW32/g++, which fails because g++ is in C:Mingw32bin. I don’t know what you are using the toolchainInstallPath for, but I fixed it by manually editing my platform config file.

I also saw in your code a lot of occurrences of something like:
path = somedir + “/” + other_part;
I think Qt could benefit from some of python path handling methods:
path = os.path.join(somedir, other_part)
This would create something like the following code, without the verbosity:
path = somedir + QDir::separator() + otherpart;

And there is also os.pathsep that is “;” for windows and “:” for unix. There doesn’t seem to have a Qt equivalent for this.

What about deployment. Building an executable or a dll is missing the final step.

I use QtCreator to build and test under Windows (jom) and Linux (gcc) (well debugging under Windows via cdb is …. another topic). But finally my software has to be packed into an installer.

For Windows I still use the deployment project in the MSVS IDE. It has nice dependecy resolving and an option to manually (drag and drop) additional needed files, supports merge modules, can add files to special folders…
So should I use a generated vs proj.file then to fill my deployment again ….?

Is there an option to produce deployment installers from this new build tool?

@Mathieu#96: the i/o library could indeed use some polishing. Care for a merge request? But remember, that some of these paths are exclusively forward slashes for performance reasons. We work _alot_ with pathes inside qbs, and converting them back/forth all the time is pretty expensive.

@Michael#97: Deployment will be solved in the long run, including extra files, etc. Installers are a different topic. It’s pretty hard to generate them from a build system, as everyone has different needs, different preferred installer frameworks, different ui ideas, etc…
However, qbs comes with a library that exposes all the relevant information needed to create your own tool for qbs->someInstaller builders.

There are a lot of build systems so it’s hard to believe none of them are good enough. I’m guessing the only reason not to use scons or waf is not to add python to the list of requirements for building? Because JS is so much better… riiight.

Thank you, this is great news. I am especially excited about the line:
import qbs.base 1.0
That means we can expect that a convenient build object, like CppApplication, will be available for everything and can be imported. Imagine building CORBA, Qt, OpenGl, web applications or just any application with specific build requirements will become easy because it will be sufficient to specify the tree of input objects. No more brittle build logic written in messy build script languages.
The build logic can be written in Qt/C++. I expect that there will be a big choice of contributed build objects and we can simply pick the objects which serve us best.

@Shawn#101: Focus in qbs (at least from the IDE point of view) is the declarative part. Build-in extensibility by some scripting language is also a “must”, for various reasons, but something users should not consiously notice in big parts of their project. I don’t think the actual choice of the scripting language matters as much as you indicate. One of the pro-JS reasons is that “it’s already there”, including the tight coupling to the declarative part. The QML tooling (parser, editor, …) has to be maintained anyway so this choice makes the “language part” of the build system fairly cheap. Also from a user perspective /not/ introducing yet-another-language into the mix already existing in Qt should rather lower the entrance barrier.

On the specific suggestion to use Python: I am certainly not a JS fan myself, and I am using Python in some extension of the Qt Creator debugger plugin (triggered by gdb’s choice to use it as extension language), so I am biased, even though not the way you probably expect: I rather like (the user side of) Python. But at the end of the day this is not about personal preferences but rather technical reasons.

@Michael: Does qbs really need to support making an installer? That seems like bloating it up. It’s a tool for compiling (and presumably on OSX creating the application bundle). Deploying is another task entirely and we’re better of not seeing qbs bloating in order to do that. Besides, on Windows there are other tools available like NSIS.

@Will Stokes#106: In my eyes the result of a build project is something that runs on other computers as the computer where it was build.

E.g. in visual studio the deployment project is part of my solution. A “build” the installer. So I guess it’s a matter of definition what building means in the software creation context. To build a house does not stop in creating the stones…

As you mention right the act of creating an installer to deploy software is not simple and but the outcome of a project in my eyes only is a program if the deployment is defined and executable via an installer package (.msi, .rpm, .deb, …).
So I have to define the environment that is needed for the program to work.

In my experience some of work creating a program has to do with defining the dependencies that lie outside of the source code (fonts, libraries, resources, default settings, ….)

There is a large intersection in dependencies for deployment and software building. Why not use these dependency information.
At least to create a tool that can convert the dependencies into an input file for an install builder ….

@Will#106: Building installers typically needs part of the project description (e.g. location of the produced binaries and their dependencies) anyway, so considering “creating installers” as a kind of “deployment” does not look overly odd.

This is a great idea and, having looked at the code, it is fundamentally different from the alternatives in ways that matter.

Generating makefiles is
1) a terrible timewaster
2) limited in many ways by make’s limitations (in summary it sucks above about 100k targets and it’s hard to get good information about what went wrong in very large builds)
3) Hard to debug because of the translation of input files to make – means that you have to debug problems at several levels.

So I think one can cross off that class of tools entirely where performance matters. Autotools is great at what it does best – helping people to port code across to an new platform but that’s a rare case.

QBS has potential to fix things because it can afford to change and because it’s written in a more modern way. It also uses a hierarchical input format which is clever because it scales up – you can have projects then collections of projects that make a subystem then a collection of subsystems that make an operating system and so on. Bad formats tend to force one to invent new formats and new parsers when one wants to build larger things. XML is a pain to work with by hand and doesn’t of itself come with a scripting language which can theoretically address nodes in the document so I haven’t ever enjoyed using it in builds.

Where QBS is probably not advancing the state of the art is in things that matter to integration of large amounts of software. I think that the way it’s written, the authors will be able to add these features very rapidly when they realise that they are important. An example is that build systems need an output format that’s as organised as the input format. It’s great to read QML but even better to write it out – so that a record of each build task can be kept, it’s status, any error messages and how long it took and other details like which machine it was built on and which QML file it comes from. When you have a lot of software to build and and many errors to cope with and you need to find out who is responsible for fixing those particular issues and so on then this all becomes useful.

None of the other build systems that I am aware of currently are particularly good at this, other than one I wrote which is not general purpose, unfortunately for me :-).

I also think this is promising!!! We use Qt as a GUI library to develop a scientific data evaluation package in our field of biophysics. In this university project there are additional needs that I feel important for the project:
1. I want to be able to give a student (who just wants to contribute a bit of code) more or less all he needs, when he can download QtCreator + checkout our repository. I solved this by adding some dependency libraries to the Repo and a build script for them (currently bash). This works on all three platforms we support (Windows incl. MinGW-w64, MaxOS X, Linux). Also the availablility of qmake with QtCreator helps here a lot.
2. Ease of use of the build system. For now we build with qmake, as this is greatly supported by QtCreator and the syntax is relatively simple (compared to e.g. Makefiles) although this requires some qmake-hacks that I tried to hide somehwere in included pri files.

But still I’m often struggling with qmake and it took me quite some time to figure out a .pri file that automatically reads the current SVN version and compile date (system independent!!!) and writes that into a svnversion.h and a compiledate.h file (speaking of autoversioning
In this respect qbs looks really promising. The only thing that I would love to see is some syntactic sugar in the declarative definition:
– Depends { name: “Qt.core” }
looks somehow uggly, why not simply write
Depends: “Qt.core”
and leave the extended syntax as the non-default alternative, if you need to specify something more general?
– the same for this construct:
Group {
condition: qbs.target == “windows”
files: [
“harddiskdeleter_win.cpp”,
“blowupmonitor_win.cpp”,
“setkeyboardonfire_win.cpp”
]
}
why not simply write:
Group (condition: qbs.target == “windows”) {
files: [
“harddiskdeleter_win.cpp”,
“blowupmonitor_win.cpp”,
“setkeyboardonfire_win.cpp”
]
}

I’m sure there are more cases like that, but I think sugaring these cases might improve the acceptance and readability of qbs code.

Do you see any chances of implementing this in a clean way? I’m not using QML (so I don’t know how the language is exactly defined) and haven’t tried qbs yet, but that’s what I’ve seen when reading your post. Especially with those decision/filter constructs such a syntax would lead to a clear separation between the condition and the effect!