zurück zum Artikel

C++20: Modulunterstützung der großen drei Compiler

Rainer Grimm

(Bild: Shutterstock.com/Kenishirotie)

Module gehören zu den vier wichtigen Neuerungen in C++20. Zeit für einen Blick darauf, wie gut die Großen Drei (GCC, Clang und MSVC) mit Modulen arbeiten.

Module sind eine der großen vier Neuerungen in C++20. In meinen C++20-Klassen sind sie eines der Hauptthemen. Leider lag die Implementierung in GCC und Clang weit hinter der des Microsoft Compilers zurück. Deshalb habe ich in meinen Klassen, Vorträgen und Büchern meist den Microsoft Compiler verwendet, um Module vorzustellen. Ich freue mich, dass sich die Modulunterstützung von GCC und Clang verbessert hat. Deshalb werde ich in diesem Artikel den aktuellen Stand der Modulimplementierung (10/2023) der großen drei Compiler GCC, Clang und MSVC vorstellen.

Modernes C++ – Rainer Grimm

Rainer Grimm ist seit vielen Jahren als Softwarearchitekt, Team- und Schulungsleiter tätig. Er schreibt gerne Artikel zu den Programmiersprachen C++, Python und Haskell, spricht aber auch gerne und häufig auf Fachkonferenzen. Auf seinem Blog Modernes C++ beschäftigt er sich intensiv mit seiner Leidenschaft C++.

In den letzten vier Jahren habe ich fast 100 Artikel über C++20 geschrieben, aber ich bin noch nicht fertig. In meinem nächsten Artikel werde ich meine Geschichte über C++20 [1] fortsetzen.

Wer mit Modulen in C++20 nicht vertraut ist, findet hier ein einfaches Beispiel:

Dies ist das Modul math.

// math1.ixx

module;                  // (1)          

#include <numeric>
#include <vector>

export module math;      // (2) 

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

export int getProduct(const std::vector<int>& vec) {
    return std::accumulate(vec.begin(), vec.end(), 1, std::multiplies<int>());
}

Das globale Modulfragment beginnt mit dem Schlüsselwort module (1) und endet mit der exportierenden Moduldeklaration (3). Das globale Modulfragment ist der Ort, an dem Präprozessoranweisungen wie #include verwendet werden, damit das Modul kompiliert werden kann. Präprozessor-Entities, die innerhalb des globalen Modulfragments verwendet werden, sind nur innerhalb des Moduls sichtbar. Das Modul math exportiert die beiden Funktionen add und getProduct.

Der Client importiert das Modul math (1) und nutzt seine Funktionen:

// client1.cpp

#include <iostream>
#include <vector>

import math;                        // (1)

int main() {
    
    std::cout << '\n';   
   
    std::cout << "add(2000, 20): " << add(2000, 20) << '\n';
    
    std::vector<int> myVec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    std::cout << "getProduct(myVec): " << getProduct(myVec) << '\n';
    
    std::cout << '\n';
   
}

Dies ist die Ausgabe des Programms:

Mehr über Module findet sich in folgenden Artikeln:

  1. Die Vorteile von Modulen [2]
  2. Ein einfaches math Modul [3]
  3. Module Interface Unit und Module Implementation Unit [4]
  4. Module strukturieren [5]
  5. Weitere offene Fragen zu Modulen [6]
  6. Private Module Fragment und Header Units [7]

Ich habe mit einem einfachen Modul begonnen und werde es noch einfacher machen, wenn ich den Modulimplementierungsstatus von GCC, Clang und MSVC vorstelle.

iX-Workshop mit Rainer Grimm: C++20 Deep Dive

Die mit C++20 eingeführten Concepts haben zusammen mit der Ranges-Bibliothek, Modulen und Coroutinen das Erstellen von modernen C++- Anwendungen neu definiert. Vom 7. bis zum 9. November 2023 bringt Sie Rainer Grimm in seinem Intensiv-Workshop C++20: die neuen Konzepte umfassend erklärt [8] auf Stand und geht auf die vielen nützlichen Funktionen ein, die C++20 mitbringt.

math.ixx definiert das Modul math, das ich im folgenden Vergleich verwenden werde.

// math.ixx

export module math;     // (1)

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

Außerdem ist hier das Client-Programm client.cpp, das das Modul math importiert.

// client.cpp

import math;       // (2)

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

(1) ist die exportierende Moduldeklaration, und (2) importiert das Modul. Aus offensichtlichen Gründen werde ich die Ausgabe des Programms ignorieren.

Warum ich die Moduldeklarationsdatei math.ixx genannt habe, könnte zunächst irritieren.

Dies sind nur die Konventionen, die sich ändern lassen. Nun werde ich das Modul math kompilieren und verwenden.

Zuerst beginne ich mit Microsofts cl.exe 19.29.30133 für x64 Compiler.

Dies sind die Schritte zum Kompilieren und Verwenden des Moduls mit dem Microsoft-Compiler. Ich zeige nur die minimale Befehlszeile. Wie versprochen, werde ich im nächsten Artikel mehr dazu schreiben. Bei einem älteren Microsoft-Compiler muss statt dem Flag /std:c++20 das Flag /std:c++latest verwendet werden.

cl.exe /std:c++20 /c math.ixx
cl.exe /std:c++20 client.cpp math.obj

Weiter geht es mit dem Clang-Compiler.

Ich verwende den Clang 16.0.5 Compiler.

Der Clang-Compiler erwartet ein Modul mit der Erweiterung cppm. Daher werde ich die Datei math.ixx in math.cppm umbenennen. Die Datei client.cpp lässt sich hingegen unverändert weiterverwenden. Abschließend sind hier die entsprechenden Schritte zum Erstellen und Verwenden des Moduls:

clang++ -std=c++20 -c math.cppm --precompile -o math.pcm
clang++ -std=c++20 client.cpp -fprebuilt-module-path=. math.pcm -o client.exe

Zum Abschluss verwende ich den GCC-Compiler.

Nun kommt der GCC 11.1.0 Compiler zum Einsatz.

Der GCC-Compiler erwartet weder das Suffix ixx von Windows noch das Suffix cppm von Clang. Deshalb benenne ich die Datei math.ixx in eine cpp-Datei um: math.cxx. Die Datei client.cpp ist identisch mit der, die ich mit dem Microsoft und dem Clang-Compiler verwendet habe.

g++ -c -std=c++20 -fmodules-ts math.cxx
g++ -std=c++20 -fmodules-ts client.cpp math.o -o client

In diesem Artikel habe ich dir die ersten Schritte gezeigt, wie du ein Modul mit den Big Three erstellen kannst. In meinem nächsten Artikel werde ich tiefer in die Modulunterstützung der Großen Drei einsteigen. (rme [10])


URL dieses Artikels:
https://www.heise.de/-9329291

Links in diesem Artikel:
[1] https://www.grimm-jaud.de/index.php/blog/category/c-20
[2] https://heise.de/-4717856
[3] https://heise.de/-4722629
[4] https://heise.de/-4727382
[5] https://heise.de/-4770234
[6] https://heise.de/-4776210
[7] https://heise.de/-6182100
[8] https://heise-academy.de/schulungen/cplusplus20?wt_mc=intern.academy.ix.ws_cplusplus20.newsticker.link.link
[9] https://www.stroustrup.com/gdr-bs-macis09.pdf
[10] mailto:rme@ix.de