Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use C++ modules in Clang?

Modules are an alternative to #includes. Clang has a complete implementation for C++. How would I go about if I wanted to use modules using Clang now?


Using

import std.io;

in a C++ source file does not work (compile) yet, as the specification for modules (which includes syntax) isn't final.


The Clang documentation states that, when passing the -fmodules flag, #includes will be rewritten to their appropriate imports. However, checking the preprocessor suggests otherwise (test.cpp only contains #include <stdio.h> and an empty main):

$ clang++-3.5 -fmodules -E test.cpp -o test
$ grep " printf " test
extern int printf (const char *__restrict __format, ...);

Furthermore, compiling this test file with -fmodules vs no flags at all produces the same object file.

What am I doing wrong?

like image 539
xjcl Avatar asked Oct 23 '15 16:10

xjcl


People also ask

How do you use Clang modules?

First, define the module interface file. By default, Clang recognizes files with cppm extension (and some others) as C++ module interface files. Note that the module interface declaration needs to be export module M; and not just module M; like in the VS blog post.

Does Clang support C++20 modules?

Clang has support for some of the features of the ISO C++ 2020 standard. You can use Clang in C++20 mode with the -std=c++20 option (use -std=c++2a in Clang 9 and earlier).

What is a module Modulemap?

Modulemap exposes C header files for external binaries. It is a bridge between module and headers. Modulemap helps to convert #include, #import -> @import because it has a mapping between module name and headers inside. Also modulemap helps to create standalone additional modules and submodules.

Does GCC support modules?

C++ Modules. A module system is coming to C++20, this page describes the GCC implementation state. A module system will provide several benefits: Reduce build times due to not reparsing large header files.


2 Answers

As of this commit, Clang has experimental support for the Modules TS.

Let's take the same example files (with a small change) as in the VS blog post about experimental module support.

First, define the module interface file. By default, Clang recognizes files with cppm extension (and some others) as C++ module interface files.

// file: foo.cppm
export module M;

export int f(int x)
{
    return 2 + x;
}
export double g(double y, int z)
{
    return y * z;
} 

Note that the module interface declaration needs to be export module M; and not just module M; like in the VS blog post.

Then consume the module as follows:

// file: bar.cpp
import M;

int main()
{
    f(5);
    g(0.0, 1);
    return 0;
}

Now, precompile the module foo.cppm with

clang++ -fmodules-ts --precompile foo.cppm -o M.pcm

or, if the module interface extension is other than cppm (let's say ixx, as it is with VS), you can use:

clang++ -fmodules-ts --precompile -x c++-module foo.ixx -o M.pcm

Then build the program with

clang++ -fmodules-ts -c M.pcm -o M.o
clang++ -fmodules-ts -fprebuilt-module-path=. M.o bar.cpp

or, if the pcm file name is not the same as the module name, you'd have to use:

clang++ -fmodules-ts -fmodule-file=M.pcm bar.cpp

I've tested these commands on Windows using the r303050 build (15th May 2017).

Note: When using the -fprebuilt-module-path=. option, I get a warning:

clang++.exe: warning: argument unused during compilation: '-fprebuilt-module-path=.' [-Wunused-command-line-argument]

which appears to be incorrect because without that option, the module M is not found.

like image 137
Smi Avatar answered Oct 16 '22 16:10

Smi


Like you mentioned, clang does not yet have a C++ syntax for imports, so I doubt that #include directives are going to be literally rewritten as imports when preprocessing a file, so that may not be the best way to test if modules are working as intended.

However, if you set -fmodules-cache-path=<path> explicitly, you can observe clang populating it with precompiled module files (*.pcm) during a build - if there are any modules involved.

You'll need to use libc++ (which seems to come with a module.modulemap as of version 3.7.0) if you want to use a modules enabled standard library right now - though in my experience this isn't working entirely just yet. (Visual Studio 2015's C++ compiler is also supposed to get some form of module support with Update 1 in November)

Independently of the stdlib, you could still use modules in your own code. The clang docs contain a detailed description of the Module Map Language.

like image 16
melak47 Avatar answered Oct 16 '22 17:10

melak47