12 December, 2021

Command lines for compiling and using C++20 modules from both clang and MSVC.

Example files

Here are some example files that are used in the command lines below.

A C++ module interface unit with both interface and implementation

Here is a C++ module interface unit, greetings.cpp. Despite the name, a module interface unit can contain both interface and implementation.

export module greetings;

export
{
    const char* greet();
}

const char* greet()
{
    return "Hello.";
}

A C++ module interface unit with an interface only

Here is a C++ module interface unit, hello.cpp. This example contains an interface, but it does not contain an implementation.

export module hello;

export const char* hello_world();

A C++ module implementation unit

Here is a C++ module implementation unit, hello_impl.cpp. It contains the implementation for the interface defined in hello.cpp.

module hello;

const char* hello_world()
{
	return "Hello, world!";
}

Programs that import modules

Here is greet.cpp. This imports the greetings module.

import greetings;

#include <iostream>

int main()
{
	std::cout << greet() << '\n';
}

And here’s say_hello.cpp. This imports the hello module.

import hello;

#include <iostream>

int main()
{
    std::cout << hello_world() << '\n';
}

Command lines for compiling modules with clang

Compiling a module interface unit with clang

This compiles greetings.cpp and generates a .pcm file which is a binary representation of the module. It does not generate a .o file.

$ clang -c --std=c++20 greetings.cpp -Xclang -emit-module-interface -o greetings.pcm

Compiling a module implementation unit with clang

First, compile the module interface unit. This compiles hello.cpp and generates a .pcm file.

$ clang -c --std=c++20 hello.cpp -Xclang -emit-module-interface -o hello.pcm

Then compile the module implementation unit. This compiles hello_impl.cpp. It needs to be told about the .pcm file with -fmodule-file. It generates a .o file.

$ clang -c --std=c++20 hello_impl.cpp -fmodule-file=hello.pcm

Using a pre-compiled module with clang

When importing a module, the compiler needs to know how to find module binaries. Use -fprebuilt-module-path to provide a search path.

This example uses the greetings module which combined both interface and implementation.

$ clang --std=c++20 -fprebuilt-module-path=. greet.cpp greetings.pcm -o greet

If the imported module name differs from the .pcm then use -fmodule-file to specify the mapping.

$ mv greetings.pcm test.pcm
$ clang --std=c++20 -fmodule-file=greetings=test.pcm greet.cpp test.pcm -o greet

This example uses the hello module, which was split into interface and implementation.

clang --std=c++20 -fprebuilt-module-path=. say_hello.cpp hello.pcm hello_impl.o -o say_hello

Command lines for compiling modules with MSVC

Compiling a module interface unit with MSVC

This compiles greetings.cpp and generates an .ifc file and an .obj file. The .ifc file is a binary representation of the module’s interface.

C:> cl /c /std:c++20 /interface /TP greetings.cpp

By default, MSVC expects module interfaces to have an .ixx extension. The /interface and /TP options allow us to use a .cpp file.

Compiling a module implementation unit with MSVC

First, compile the module interface unit. This compiles hello.cpp and generates an .ifc file.

C:> cl /c /std:c++20 /interface /TP hello.cpp

Then compile the module implementation unit. This compiles hello_impl.cpp. The .ifc file for the module must exist. It generates a .obj file.

C:> cl /c /std:c++20 hello_impl.cpp

Using a pre-compiled module with MSVC

When importing a module, the compiler needs to know how to find module binaries. It implicitly searches in the current directory.

This example uses the greetings module which combined both interface and implementation.

C:> cl /std:c++20 greet.cpp greetings.obj

If the module’s .ifc file isn’t in the current directory then use /ifcSearchDir to add to the search path.

C:> cl /std:c++20 greet.cpp greetings.obj /ifcSearchDir C:/modules

This example uses the hello module, which was split into interface and implementation.

C:> cl /std:c++20 say_hello.cpp hello.obj hello_impl.obj

Further reading

For more information, follow these links.

Clang

MSVC