Buildconfig Module

In the previous chapter, we added some properties to our main Project file. While this is a perfect approach for public properties of the project, sometimes we want to add some private properties for better tuning. Of course, we could put everything in the Project file, but that would make it very convoluted. Also, accessing the top-level project all the way from products makes things strongly tied.

You can also use a Module that products may depend on. That way, a Product only uses properties of the module it depends on without the need to know about the top-level project.

Let's create a file named mybuildconfig.qbs and put it into the qbs/modules/mybuildconfig directory, near the qbs/imports directory:

// qbs/modules/mybuildconfig.qbs
Module {
}

So far, this is just an empty Module so let's add some properties to it:

// qbs/modules/mybuildconfig.qbs
Module {
    property string appInstallDir: "bin"
    property string libDirName: "lib"
    property string libInstallDir: qbs.targetOS.contains("windows") ? appInstallDir : libDirName

We added the appInstallDir and libInstallDir properties that will allow us to configure the installation location of the our application and library, respectively.

Now we can use our module in the MyApplication.qbs item:

CppApplication {
    Depends { name: "mybuildconfig" }
    installDir: mybuildconfig.appInstallDir

    version: "1.0.0"
    // ...

We pull in the new module using the Depends item, similar to how we pulled in the cpp module dependency earlier. We also set the installDir property to the corresponding module property, namely to mybuildconfig.appInstallDir.

Qbs modules have the feature to automatically export properties of other modules. Those exported properties are merged in the resulting product. We can use this feature to set the cpp.rpaths in our module rather than in products:

// qbs/modules/mybuildconfig.qbs
Module {
    property string appInstallDir: "bin"
    property string libDirName: "lib"
    property string libInstallDir: qbs.targetOS.contains("windows") ? appInstallDir : libDirName

    Depends { name: "cpp" }

    property bool enableRPath: true
    property stringList libRPaths: {
        if (enableRPath && cpp.rpathOrigin && product.installDir) {
            return [FileInfo.joinPaths(cpp.rpathOrigin, FileInfo.relativePath(
                                           FileInfo.joinPaths('/', product.installDir),
                                           FileInfo.joinPaths('/', libInstallDir)))];
        }
        return [];
    }

    cpp.rpaths: libRPaths
}

Here, we inject the dependency on the cpp module and calculate the libRPaths property. This is a relative path from the product.installDir (which is either "bin" or "lib", depending on product type to libInstallDir). Finally, we set cpp.rpaths to this property. This way, those rpaths will be automatically exported to all products that depend on the mybuildconfig module.

Now, we can also use our new module in the library item:

// qbs/imports/MyLibrary.qbs
    // ...
    Depends { name: "mybuildconfig" }
    installDir: mybuildconfig.libInstallDir

    Depends { name: "cpp" }
    property string libraryMacro: name.replace(" ", "_").toUpperCase() + "_LIBRARY"
    cpp.defines: [libraryMacro]
    cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined

    Export {
    // ...

Let's change the library folder name from "lib" to "lib64" when building our project:

$ qbs modules.mybuildconfig.libDirName:lib64
...
$ ls default/install-root/usr/local/
bin    lib64

© 2022 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.