Home » C++20: More details on module support from the big three compilers

C++20: More details on module support from the big three compilers

by admin
C++20: More details on module support from the big three compilers

C++20: More details on module support from the big three compilers

In my last article, “C++20: Module Support from the Big Three Compilers,” I compiled a simple module using the Big Three. Today I’ll go deeper and use GCC, Clang and the Microsoft compiler.

Advertisement

Rainer Grimm has been working as a software architect, team and training manager for many years. He enjoys writing articles on the programming languages ​​C++, Python and Haskell, but also enjoys speaking frequently at specialist conferences. On his blog Modern C++ he deals intensively with his passion C++.

This article is quite technical and ends with a curious observation. In addition, it requires basic knowledge of modules, which can be found in the previous articles about modules:

The advantages of modulesA simple math moduleModule interface unit and module implementation unitStructuring modulesMore open questions about modulesPrivate module fragment and header units

Compiler support of modules

I use Microsoft’s cl.exe 19.29.20133 for x64, the Clang 16.0.5 and the GCC 11.1.0 compiler for my experiments.

Microsoft Visual Compiler

Let’s start with the Microsoft compiler.

The Microsoft Visual Compiler offers several options for using modules:

There are also a few general cl.exe compiler options:

In the following command lines I use various compiler options on the ifc file. The ifc file is the module and contains the metadata description of the module interface.

Use the math.cppm module to create the obj and ifc files. cl.exe /c /std:c++latest /interface /TP math.cppm​ Use the math.cppm module to create only the ifc file. cl.exe /c /std:c++latest /ifcOnly /interface /TP math.cppm​ Use the math.cppm module to create the obj file math.obj and the ifc file mathematic.ifc. cl.exe /c /std:c++latest /interface /TP math.cppm /ifcOutput mathematic.ifc​ Create the executable file client.exe using the ifc file math.inter. cl.exe /std:c++latest client.cpp math.obj /reference math.inter​ Creates the executable file client.exe and explicitly uses the ifc file math.inter, which is located in the ifcFiles directory. cl.exe /std:c++latest client.cpp math.obj /ifcSearchDir ifcFiles /reference math.inter

See also  C++20: Module support from the big three compilers

Now the Clang compiler is used.

Clang-Compiler

The Clang compiler offers various options for creating modules:

Further details can be found in the official Standard C++ Modules documentation. In the following command lines I use the compiler options for the module and the ifc file.

Use the module declaration file math.cppm to create the pcm file math.pcm. clang++ -c -std=c++20 -fmodule-output math.cppm -o math.pcm​

Use the module with the extension ixx (math.ixx) to create the pcm file math.pcm.

clang++ -std=c++20 –precompile -x c++-module math.ixx -o math.pcm​

Create the pcm file and use it.

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

Use the pcm file other.pcm and compile it.

clang++ -std=c++20 -c client.cpp -fmodule-file=math=other.pcm -o client.o

This brings me to the GCC compiler.

The Concepts introduced with C++20, along with the Ranges library, modules and coroutines, have redefined how to build modern C++ applications. From November 7th to 9th, 2023, Rainer Grimm will bring you up to date in his intensive workshop C++20: the new concepts will be comprehensively explained and will address the many useful functions that C++20 brings.

GCC-Compiler

The following table shows the few GCC options:

Many options from the Big Three address header units.

Header Units are a binary representation of header files and represent a transition from headers to modules. You must replace the #include directive with the new import directive and add a semicolon (;).

#include => import ;
#include “myHeader.h” => import “myHeader.h”;

For more information about Header Units, see my previous article “Private Module Fragment and Header Units”. In the following lines I’m playing with Header Units and using the following files:

See also  The product workers: Proxy Product Owner — How useful is this role?

// head.h

#include

void hello(); The source file head.cpp that imports the header unit // head.cpp import “head.h”; void hello() { std::cout World: header unitsn”; std::cout I will create a header unit from the header file head.h for the Microsoft Visual Compiler and GCC Compiler. Contrary to the official Standard C++ Modules documentation, I was unable to create header units with the Clang compiler.

Microsoft Visual Compiler

These are the necessary steps to use Header Units.

cl.exe /std:c++latest /EHsc /exportHeader head.h cl.exe /c /std:c++latest /EHsc /headerUnit head.h=head.h.ifc head.cpp cl.exe /std :c++latest /EHsc /headerUnit head.h=head.h.ifc helloWorld3.cpp head.obj The /exportHeader flag on line 1 causes the ifc file head.h.ifc to be exported from the header file head. h is created.The implementation file head.cpp (line 2) and the client file helloWordl3.cpp (line 3) use the header unit. The /headerUnit head.h=head.h.ifc flag imports the header unit and tells the compiler the name of the ifc file for the specified header.

Creating and using the module consists of three steps.

g++ -fmodules-ts -fmodule-header head.h -std=c++20 g++ -fmodules-ts -c -std=c++20 head.cpp g++ -fmodules-ts -std=c++20 head. o helloWorld3.cpp -o helloWorld3 (1) creates the module head.gcm. The -fmodule-header flag specifies that a header unit should be created from head.h. The following line creates the object file head.o. Finally, line 3 creates the executable file that implicitly uses the head.gcm module.

As promised, here is the curious observation.

When it comes to modules, you have to differentiate between accessibility and visibility. When a module exports an entity, an importing client can see and use it. Entities that are not exported are not visible, but can be reachable.

// bar.cppm

See also  KEF R Series Full Atmos Immersive Experience Night- Site Events

module;

#include

export module bar;

struct Foo {
void writeName() {
std::cout The bar module exports the Bar class. Bar is visible and accessible. Foo, on the other hand, is not visible.

// bar.cpp

#include

import bar;

int main() {

Bar b;
// Foo f; // (1)
auto f = b.getFoo();
f.writeName(); // (2)

using FooAlias =
decltype(std::declval().getFoo()); // (3) FooAlias ​​f2; // (4) f2.writeName(); // (5) }

The Foo class is not exported and is therefore not visible. Using it in (1) would cause a linker error. On the contrary, Foo is reachable because the member function getFoo (in bar.cppm) returns it. Consequently, the writeName (2) function can be called. Also, I can create a data type alias to Foo (3) and use it to instantiate Foo (4) and call writeName (5). The expression std::declval().getFoo() (3) returns the object that a call to Bar.getFoo() would return. Finally, decltype returns the data type of this hypothetical object.

In my next article I will dive deeper into the Ranges library in C++20.

(rme)

To home page

You may also like

Leave a Comment

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

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More

Privacy & Cookies Policy