- Qbs Manual
- Config Module
- Qbs 3.3.0

Project Properties ◦ Configurable Library

# Config 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.

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

     // qbs/modules/config/install/module.qbs
     ConfigInstall {
     }

Here we inherit the ConfigInstall item in order to re-use its properies. Since custom qbsSearchPaths are searched first, now our version will be used instead of built-in one.

First, let's change the default value of the config.install.importLibraries in order to install import libraries on Windows:

     // qbs/modules/config/install/module.qbs
     ConfigInstall {
         importLibraries: true
     }

We could extend the config.install module with additional properties, but that could create collisions when someone tries to include the source code of your project into their project. Thus, we will create a new `config.myproject` module and use the same approach with the base item as Qbs does for the `config.install` module.

Let's create a new item and add a new property to it:

     // qbs/imports/ConfigMyProject.qbs
     Module {
         property bool enableAddressSanitizer: false
         Depends { name: "Sanitizers.address"; condition: enableAddressSanitizer }

We added the `enableAddressSanitizer` property and a dependency on the Sanitizer.address module if that property is set to `true`.

Now let's use the item in a module:

     // qbs/modules/config/myproject/module.qbs
     ConfigMyProject {
     }

Now we can use our module in the `MyLibrary.qbs` item by pulling in the new module using the Depends item:

     // qbs/imports/MyLibrary.qbs
     DynamicLibrary {
         version: project.version

         Depends { name: "config.myproject" }
         // ...

Now we can enable sanitizer build by setting the `enableAddressSanitizer` property from command-line:

     $ qbs resolve modules.config.myproject.enableAddressSanitizer:true
     $ qbs build

Instead of the `config.myproject.enableAddressSanitizer` property, we could also use the property in the Project item similar to how we did in the previous chapter. There is no strong preference which way to use, however using modules for configuration is more flexible as it is also possible to set properties of other modules as described below.

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:

     import qbs.FileInfo
     // qbs/imports/ConfigMyProject.qbs
     Module {
         property bool enableAddressSanitizer: false
         Depends { name: "Sanitizers.address"; condition: enableAddressSanitizer }

         Depends { name: "cpp" }
         Depends { name: "config.install" }

         property bool enableRPath: true
         property stringList libRPaths: {
             if (enableRPath && cpp.rpathOrigin && product.installDir) {
                 console.info(FileInfo.joinPaths(
                         cpp.rpathOrigin,
                         FileInfo.relativePath(
                             FileInfo.joinPaths('/', product.installDir),
                             FileInfo.joinPaths('/', config.install.dynamicLibrariesDirectory))));
                 return [
                     FileInfo.joinPaths(
                         cpp.rpathOrigin,
                         FileInfo.relativePath(
                             FileInfo.joinPaths('/', product.installDir),
                             FileInfo.joinPaths('/', config.install.dynamicLibrariesDirectory)))];
             }
             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 dynamicLibrariesDirectory (which is `"lib"` by default). Finally, we set cpp.rpaths to this property. This way, those `rpaths` will be automatically exported to all products that depend on the `config.myproject` module.

We should also update the `MyApplication` item to add a dependency on the `"config.myproject"` in order to inject cpp.rpaths we set in the module:

     // qbs/imports/MyApplication.qbs
     CppApplication {
         Depends { name: "config.myproject" }
         version: "1.0.0"
         consoleApplication: true
     }