Modules in Clang 11

In my previous post, I wrote about the support for C++20 modules in Visual Studio 2019 16.5. VC++ is not the only major compiler that has experimental support for modules. Clang has its own implementation, although only partial. In this post, I will discuss the support available in Clang 11. You can check the current status here.

Disclaimer: My experience with Clang is limited to compiling various snippets of code. Although documentation may exist in some inner circle of trust, it is not easily found using search engines. The content of this article was put together from several bits of information found online and large amounts of trial and error. Therefore, the information I present below may not be complete (although I hope it is correct). If you find anything that needs to be complemented or corrected, please leave a comment and I will update accordingly.

A first example

Let’s start again with the typical hello world application in C++ that looks as follows:

To compile this with Clang you need to run the following command:

Noticed that I specified -std=c++2a to indicate support for C++20, although any other version would have worked. However, this switch is required to enable modules support, which used to be available only by specifying -fmodules-ts. This is now no longer necessarily when compiling with -std=c++2a.

This program can be modified to use modules instead by replacing the #include preprocessor directive with an import directive, as follows:

Compiling this program requires some changes to the command we executed previously.

So, what do these additional arguments represent?

  • -fimplicit-modules tells the compiler to use implicit modules, which is a feature that automatically translates #include directives into import statements (i.e. headers into modules).
  • -fimplicit-module-maps tells the compiler to implicitly search the file system for module map files. A module map file is a file containing the mapping between existing headers and the logical structure of a module. You can learn more about these from here.

Writing a module

The next step is to write a module that exports a function, called get_greeting_text() in this example, that returns the text that will be printed to the console in the main program. The following snippet shows the content of the module from a file called greetings.cpp.

The changes to the main program are simple: import the greetings module and call the get_greeting_text() function.

Compiling the module and the main program this time gets a bit more complicated. The following commands must be executed:

The first command, compiles the module and generates a file called greetings.pcm. PCM here stands for “precompiled module”. This file is the Binary Module Interface (BMI) file and is the equivalent of the IFC file generated by the VC++ compiler. GCC is using yet another term, “Compiled Module Interfaces” and the extension CMI. The second command, compiles the main program. You will notice in the arguments, a new switch called -fprebuilt-module-path. This tells the compiler what is the path of the folder containing the prebuilt modules (the .pcm files).

In this example, the module file had the extension .cpp. However, Clang supports other extensions, including .cppm and even .ixx. However, when using different extensions, the commands for building the module change.

These are the commands to build the same sample if the greetings module was available in a file called greetings.cppm.

These are the commands to build the same sample if the greetings module was available in a file called greetings.ixx.

We can add more exports to the module, just as we did in the previous article. In the following example, the greeter class returns a random text every time its call operator is invoked.

This new class can be used as shown below. If you run this program multiple times, you should see the second line changing randomly.

The commands required to build this program are the following:

Exporting templates

Templates can also be exported from a module. In the next example, a module called foo, available in a file foo.cpp exports a class template foo and a function template called make_foo.

The exports from this module can be used as follows in main.cpp:

To build this program, we must run the following commands:

Partitions

As I mentioned in the beginning, Clang only supports C++20 modules partially. Unfortunately, this features is not available yet.

See also

You can learn more about Clang support for modules from the following articles:

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.