Skip to content

Add experimental support for C++ Modules TS if the compiler supports it

Whisperity requested to merge whisperity/cmake:clang-modules into master

This change adds an experimental support for C++ Modules TS (there are various other addendums, fixes and such for the standards proposal) which is in itself a currently just proposed feature to C++, aimed at making compilation more componential, better express dependencies, cut down on the ugliness headers and macros can bring in, and maybe even speed up compilation a little.

This feature is yet to be standardised and yet to be supported in a common fashion by compilers. Currently, I think only Clang (and maybe MSVC?) supports it.

This patch is aimed to add support in CMake's language to express the compilation and usage of Modules. I have tried to make the patch's new parts very modular (... pun not indented) so that once Modules are standardised (if they ever will be, according to sneaky tongues...) or if other compilers start to give their own experimental implementation of the thing, it should be easy to add the new rules to CMake's "knowledge base".

A new command, add_cxx_module() is added. This is to distinguish between C++ Modules TS modules, and add_library(foobar MODULE bazqux.cpp) which is an intriguing name clash but do not refer to the same concept. A C++ Module is a compilation unit which is used in other compilations (through a(n optional, but in our case, implemented) precompile mechanism) and in linkage. In layman's terms, if you are unfamiliar with the innards of the language, C++ modules aim to be something in between a static library and a header file. This command creates a target just like add_library() would, but also sets up the extra actions needed to do the necessary precompilation, as opposed to just spitting out an object.

(In case of CMake not knowing about how to support the current compiler's Modules implementation, a neat error is issued and generation eventually stops.)

To ensure dependency information between the used modules and the headers are kept (as I could not figure a reasonable way to put this into cmDependsC — unfortunately at dependency check time the running CMake instance does not know about other targets, so I can't GetGlobalGenerator()->FindTarget("modulename") and use the information obtained from that. So because of this, target_link_libraries() has been extended to allow specification of C++ Modules TS module names which are translated to these precompiled module files and given to Clang at compilation. Unfortunately here the user must specify the modules their target uses. This has two goals: the linker invocation (which unfortunately needs the module's object or precompilation file, otherwise Undefined symbol errors are emitted...) will contain the proper bindings, and CMake will know and propagate the necessary dependencies between the target and their dependencies.

Merge request reports