Modules

Contents[Show]

Modules is one of the five prominent features of C++20. Modules will overcome the restrictions of header files. They promise a lot. For example, the separation of header and source files becomes as obsolete as the preprocessor. In the end, we will also have faster build times and an easier way to build packages.

 

 graphic 3578346 1280

Explaining modules for the users perspective is quite easy, but this will not hold for the implementers perspective. My plan for this post is to start with a simple example to modules and add more features to it as we go.

A First Example

First of all, here is my first module math.

// math.cppm

export module math;

export int add(int fir, int sec){
    return fir + sec;
} 

The expression export module math is the module declaration. By putting export before the function add, add is exported and can, therefore, be used by a consumer of my module. 

 

// main.cpp

import math;

int main(){
   
   add(2000, 20);
   
}

import math imports the module math and makes the exported names in main.cpp visible. This was the easy part. The challenge started when I compiled the program.

Module Declaration Files

But first, did you noticed the strange name of the module: math.cppm.

  • The extension cppm stands presumably for cpp module declaration and is the suggested extension for Clang.
  • cl.exe uses the extension ixx. The i should stand in this case for interface.
  • I don't know of a GCC extension.

Compile the Module math

To compile the module you have to use a very current clang or cl.exe compiler. It is also possible to use gcc to compile the examples of this post, but I will go in this post with clang and cl.exe on Windows. Here are more details to my compilers:

  • clang++

 clang

 

  • cl.exe

clExe

 

Here is precisely the point where the fun started: to figure out the command line for clang++ and cl.exe.

 

clang++ -std=c++2a -fmodules-ts --precompile math.cppm -o math.pcm                   // 1
clang++ -std=c++2a -fmodules-ts -c math.pcm -o math.o                                // 2
clang++ -std=c++2a -fmodules-ts -fprebuilt-module-path=. math.o main.cpp -o math     // 3


cl.exe /std:c++latest /experimental:module /TP /EHsc /MD /c math.cppm /module:interface /Fo: math.obj /module:output math.pcm // 1
cl.exe /std:c++latest /experimental:module /TP /EHsc /MD /c main.cpp /module:reference math.pcm /Fo: main.obj                 // 2
cl.exe math.obj main.obj                                                                                                      // 3

 

  1. Creates a precompiled module math.pcm out of the module declaration math.cppm
  2. Creates the non-module translation unit math.o
  3. Creates the executable math or math.exe. For clang++ I have to specify the module path.

For obvious reasons, I will not show you the output of the program execution. I will do if I have something to show.

From the implementor's perspective we can split the module definition into a module interface unit and a module implementation unit. Before I come to these units let me take a step back and answer the question:

What are the Advantages of Modules?

  • Compile-time speedup: A module is only imported once and should be literally for free. Compare this with M headers which are included in N translation units. The combinatorial explosion means, that the header has to be parsed M*N times.
  • Isolation from the preprocessor macros: If there is one consensus in the C++ community, it's the following one: we should get rid of the preprocessor macros. Why? Using a macro is just text substitution excluding any C++ semantic. Of course, this has many negative consequences: For example, it may depend on in which sequence you include macros or macros can clash with already defined macros or names in your application. In contrast, it makes no difference, in which order you import modules.
  • Express the logical structure of your code: Modules allow you to express which names should be exported or not explicitly. You can bundle a few modules into a bigger module and provide them to your customer as a logical package.
  • No need for header files: There is no need to separate your files into an interface and an implementation part. This means, modules just half the number of source files.
  • Get rid of ugly workarounds: We are used to ugly workarounds such as "put an include guard around your header", or "write macros with LONG_UPPERCASE_NAMES". To the contrary, identical names in modules will not clash.

In my first module math, I declared and defined the module in one file math.cppm. Let me talk about the new units.

Module Interface Unit, and Module Implementation Unit

 First of all, the new module math1 consists of a module interface unit and a module implementation unit.

Module Interface Unit

// math1.cppm

export module math1;

export int add(int fir, int sec);

 

  • The module interface unit contains the exporting module declaration: export module math1.
  • Names such as add can only be exported in the module interface unit.
  • Names which are not exported are not visible outside the module. I will come to this point in my next post.
  • A module can have only one module interface unit.

Module Implementation Unit

// math1.cpp

module math1;

int add(int fir, int sec){
    return fir + sec;
}

 

  • The module implementation unit contains non-exporting module declarations: module math1;
  • A module can have more than one module implementation unit.

Main Program

 

// main1.cpp

import math1;

int main(){
   
   add(2000, 20);
   
}

  • From the users perspective, just the module name changed from math to math1.

Compiling the modularised module is a little bit more involved.

Compile the Module math1

 

clang++ -std=c++2a -fmodules-ts --precompile math1.cppm -o math1.pcm               // 1
clang++ -std=c++2a -fmodules-ts  -c math1.pcm -o math1.pcm.o                       // 2
clang++ -std=c++2a -fmodules-ts -c math1.cpp -fmodule-file=math1.pcm -o math1.o    // 2
clang++ -std=c++2a -fmodules-ts -c main1.cpp -fmodule-file=math1.pcm -o main1.o    // 3
clang++  math1.pcm main1.o math1.o -o math                                         // 4

cl.exe /std:c++latest /experimental:module /TP /EHsc /MD /c math1.cppm /module:interface /Fo: math1.pcm.obj /module:output math1.pcm  // 1
cl.exe /std:c++latest /experimental:module /TP /EHsc /MD /c math1.cpp /module:reference math1.pcm /Fo: math1.obj                      // 2
cl.exe /std:c++latest /experimental:module /TP /EHsc /MD /c main1.cpp /module:reference math1.pcm /Fo: main1.obj                      // 3
cl.exe math1.obj main1.obj math1.pcm.obj                                                                                              // 4

  1. Creates a precompiled module math1.pcm out of the module declaration math1.cppm
  2. Compiles the precompiled module math1.pcm: math1.pcm.o. Compile the source file math1.cpp: math1.o. cl.exe does this in one step.
  3. Compiles the main program: main1.o or main1.obj.
  4. Creates the executable math1 or math1.exe.

What's next?

As promised, this was only an introduction to modules. In my next post, I dive more into the details. In particular, I want to show the output of the program and have, therefore, to include standard headers such as <iostream> or import modules such as std.core.

Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, Marko, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Darshan Mody, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Animus24, Jozo Leko, John Breland, espkk, Wolfgang Gärtner,  Louis St-Amour, Stephan Roslen, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Avi Kohn, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Neil Wang, Friedrich Huber, Sudhakar Balagurusamy, lennonli, and Pramod Tikare Muralidhara.

 

Thanks in particular to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, and Dendi Suhubdy

 

Seminars

I'm happy to give online-seminars or face-to-face seminars world-wide. Please call me if you have any questions.

Bookable (Online)

Deutsch

English

Standard Seminars 

Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.

New

Contact Me

Modernes C++,

RainerGrimmSmall

Tags: modules

Comments   

+1 #1 Daniel 2020-04-01 09:17
What an excellent article.

In
import math imports the module math and makes the exported names in main.cpp visible

I think there is a mistake though; shouldn't it be
import math imports the module math and makes the exported names in math.cppm visible

?
Quote
+3 #2 iceflower 2020-04-27 10:47
>>> No need for header files: There is no need to separate your files into an interface and an implementation part. This means, modules just half the number of source files.

And a second later mentioning that the module should be split into a .cppm and a .cpp.
Quote
0 #3 Aria 2020-05-15 05:54
I love this. Let's get rid of those preprocessors! C++ is a very cluttered language. Though, I know, old language, and gotta keep that old code working. I understand.
Quote
-3 #4 Lothar Scholz 2020-08-30 15:00
Just skimmed the article and stopped taking it serious after two serious mistakes. First it was never about speeding up the compilation process (read the protest paper in the special interest group about parallel compilation performance impact). Second that macros should be removed. No, i would even say they should be improved become like M4.
Quote
0 #5 Vitaly Ivanov 2020-09-24 03:06
Well, the whole thing looks like straight-up static library to me. Universal cross-platform support is nice though, don't have to rely on CMake or __declspec(dllexport) / __attribute__ ((visibility ("default"))) anymore
Quote

My Newest E-Books

Course: Modern C++ Concurrency in Practice

Course: C++ Standard Library including C++14 & C++17

Course: Embedded Programming with Modern C++

Course: Generic Programming (Templates)

Course: C++ Fundamentals for Professionals

Subscribe to the newsletter (+ pdf bundle)

Blog archive

Source Code

Visitors

Today 2769

Yesterday 7515

Week 34380

Month 192811

All 5062125

Currently are 156 guests and no members online

Kubik-Rubik Joomla! Extensions

Latest comments