- Qbs Manual
- C++20 Modules
- Qbs 2.5.0

Version Header ◦ How-tos

# C++20 Modules

This tutorial implies you have some knowledge about C++20 modules. If not, see Overview of modules in C++ for introduction.

## Named Modules

Using C++20 modules with Qbs is pretty straightforward. Let's suppose you have a module file that exports a single function `printHello`:

     // hello.cppm
     module;

     #include <iostream>
     #include <string_view>

     export module hello;

     export namespace Hello {

     void printHello(std::string_view name)
     {
         std::cout << "Hello, " << name << '!' << std::endl;
     }

     } // namespace Hello

Note: Currently, Clang only recognizes `.cppm` files as modules, however, for GCC and MSVC Qbs also recognizes `.ixx` files as C++ modules. Qbs assigns the `"cppm"` file tag to these files. You can assign this tag manually to module files with different extensions.

This function is later used in the `main.cpp` file as follows:

     // main.cpp

     import hello;

     int main()
     {
         Hello::printHello("World");
     }

The project file simply lists files and sets the cpp.forceUseCxxModules property to `true`.

     // myproject.qbs
     CppApplication {
         consoleApplication: true
         install: true
         files: ["hello.cppm", "main.cpp"]
         cpp.cxxLanguageVersion: "c++20"
         cpp.forceUseCxxModules: true
     }

Now, you can build the project by simply calling `qbs`, assuming that your compiler supports C++20 modules.

## Module Partitions

Module partitions are treated as regular modules and should also have the same extension or assigned the `"cppm"` tag manually. See this example on how to use both interface module and partitions.

## Modules and Libraries

Using modules in dynamic libraries requires using the same export/import macros as it was shown in the Dynamic Library section:

     // lib/hello.cppm
     module;

     #include "lib_global.h"
     #include <iostream>
     #include <string_view>

     export module hello;

     export namespace Hello {

     void MYLIB_EXPORT printHello(std::string_view name)
     {
         std::cout << "Hello, " << name << '!' << std::endl;
     }

     } // namespace Hello

As shown in that section, the library `.qbs` file should also define the `MYLIB_LIBRARY` macro in order to mark symbols as exported:

     // lib/lib.qbs
     DynamicLibrary {
         name: "mylib"
         files: ["hello.cppm", "lib_global.h"]
         version: "1.0.0"
         install: true

         Depends { name: "cpp" }
         cpp.defines: "MYLIB_LIBRARY"
         cpp.cxxLanguageVersion: "c++20"
         cpp.forceUseCxxModules: true
         // ...
     }

For more details, see the complete example.

Version Header ◦ How-tos