Hi all,
Recently I am playing with C++20 modules and I found that the command line support of GCC
is much better than Clang. Here is an example:// say_hello.cpp module; #include <iostream> #include <string_view> export module Hello; export void SayHello (std::string_view const &name) { std::cout << "Hello " << name << "!\n"; } // main.cpp #include <string_view> import Hello; int main() { SayHello("world"); return 0; }To compile the example, in gcc we need:
g++ -std=c++20 -fmodules-ts say_hello.cpp main.cppAnd in clang, we need:
clang++ -std=c++20 -fmodules-ts -Xclang -emit-module-interface -c say_hello.cpp -o Hello.pcm clang++ -std=c++20 -fmodules-ts -fprebuilt-module-path=. main.cpp say_hello.cpp
Your point is well-taken. However, some part of the extra work required here is that you’re not doing things in the expected way.
The above is not a correct way to enable C++20 modules in Clang: -fmodules-ts enables the old Modules TS mode, not C++20 modules. -std=c++20 is enough to enable C++20 modules.
For the ‘-Xclang -emit-module-interface’ portion, what Clang expects is that files that define module interfaces are either named .cppm or are specified with -x c+±module. With that file type, you can use --precompile to produce a .pcm file (just like you’d use -E or -c to produce other kinds of output). For example:
clang++ -std=c++20 say_hello.cppm --precompile -o Hello.pcm
The above commands are also parsing say_hello.cpp twice. You can avoid that by using the precompiled form, say_hello.pcm, as a compilation input instead:
clang++ -std=c++20 -fprebuilt-module-path=. say_hello.pcm main.cpp
However, this is all based on a model where the PCM file contains a complete description of the input .cppm file, which is not a great model for us to use moving forward due to all the extra stuff ending up in the .pcm file. Currently, Clang lacks two important features here:
- Produce a .pcm file and a .o file from a single compilation action.
- Produce a .pcm file that contains only the information needed for an importer, not a complete description of the input.
We will of course need some command-line support for those features, and being compatible with GCC (which already provides these features) would likely make sense.
As for building and using modules in a single clang command, I agree that’d be nice to have, both for convenience and for GCC compatibility. But ideally this shouldn’t depend on what order the files are specified in on the command line, which would require some kind of pre-scanning to find which modules are defined in which files so they can be processed in topological order. (Otherwise, specifying the files in the wrong order would presumably result in stale .pcm files getting used, which would seem quite user-hostile. I don’t know if that’s what you get from GCC or if it does better somehow.) That kind of prescan might be more complexity than we’d want in the compiler driver, though we can discuss that and figure out where we want to draw that line.
In any case, I’m hoping we get some clear guidance from SG15 that we can follow.