Experimental Modules Support
This reflects the status as of CMake 3.27CMake added support for C++20 named modules in version 3.28.
A complete working example
I will keep updatingYou can also find this answer as the situation changesexample on Github.
// a.cppm
module;
#include <iostream>
export module MyModule;
int hidden() {
return 42;
}
export void printMessage() {
std::cout << "The hidden value is " << hidden() << "\n";
}
// main.cpp
import MyModule;
int main() {
printMessage();
}
# CMakeLists.txt
cmake_minimum_required(VERSION 3.28)
project(modules-example)
set(CMAKE_CXX_STANDARD 20)
add_executable(demo)
target_sources(demo
PUBLIC
main.cpp
)
target_sources(demo
PUBLIC
FILE_SET all_my_modules TYPE CXX_MODULES FILES
a.cppm
)
Important: CMake's support for C++20 modules is currently functional, but still experimental. Things may work in some cases but break in others. Expect bugs and breaking changes between versions!
See also the relevant issue in the CMake issue tracker The project should build fine and rebuild correctly when changing the source files.
Further details
Proper integration currently only works with the following generatorsEnsure that your compiler has proper support for C++20 modules and dependency scanning:
- NinjaMSVC compiler version 119.1034 or newer
- Visual Studio 2022LLVM/Clang version 1916 or newer.34 (I personally recommend at least version 17 due to a number of bugs in 16)
- gcc version 14 or newer.
Module dependency scanning is currently supported byAlso be aware that CMake only supports modules for the following compilersgenerators:
- MSVC compiler versionVisual Studio 2022, toolset 19.34 (Visual Studio 17.4) or newer
- LLVM/ClangNinja version 161.11 or newer.
Note: Getting Clang to work requires at least Clang version 16 and additionally may at this point still require some fiddling with CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE. Since this is way too deep into the tool internals, I will not cover that in this answer! Check out CMake's feature guide if you want to try this out. This should get resolved in a future version of CMake though.
- Always use the absolute latest CMake, build tool, and compiler versions that you can. This feature is still under heavy development and receives a constant stream of vital bugfixes.
- Read the docs:
- CMake cxxmodules page documents the limitations of the current implementation in CMake. If something doesn't work as expected, check here first.
- D1483 explains how the build process looks like for modules and why it's considerably more difficult than a non-modules build. This is an essential read.
- CMake Experimental Features Guide Documents the limitations of the current experimental implementation in CMake. If something doesn't work as expected, check here first.
- Familiarize yourself with the basic feature set and vocabulary of Modules. Daniela Engert's talk is an excellent introduction.
- Read Kitware's blog post for additional info not covered in this answer, like how to try out Modules with a custom build of gcc.
- The tooling will produce a bunch of
.json files during the build, which contain the data used by the build system to track module dependencies. If something doesn't work as expected, these can be very useful for debugging.
- None of this is cleared for use in production at this point! Keep in mind that this is an experimental This feature that is mainly being made availablestill in an early stage, so thatbe prepared to encounter bugs in both the compiler and tool implementers can iron out the bugsbuild system implementations.
Activating Modules Support in CMake
Since CMake's support for modules is experimental at this point, you will have to opt-in to the feature before being able to use it:
cmake_minimum_required(VERSION 3.27)
project(my_modules_project)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API aa1f7df0-828a-4fcd-9afc-2dc80491aca7)
set(CMAKE_CXX_STANDARD 20)
The last line here is optional, but your compiler may refuse to compile code using modules if you don't request C++20 support. Note that C++20 does not contain a modularized version of the standard library, you will need at least C++23 for that.
Setting CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API activates the modules support. The magic number for CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API changes with every CMake release, so be sure to double-check the docs for your CMake release if CMake complains about not recognizing the module-related commands.
Using Modules
Limitations
Header units are currently not supported anywhere (neither by CMake nor by any of the major build systems) and there are serious concerns about the implementability of this feature. Daniel Ruoso gave an excellent talk at C++Now 2023 (video) explaining those concerns. You should stick with named modules for now.
A complete working example
You can also find this example on Github.
// a.cppm
module;
#include <iostream>
export module MyModule;
int hidden() {
return 42;
}
export void printMessage() {
std::cout << "The hidden value is " << hidden() << "\n";
}
// main.cpp
import MyModule;
int main() {
printMessage();
}
# CMakeLists.txt
cmake_minimum_required(VERSION 3.27)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API aa1f7df0-828a-4fcd-9afc-2dc80491aca7)
project(modules-example)
set(CMAKE_CXX_STANDARD 20)
add_executable(demo)
target_sources(demo
PUBLIC
main.cpp
)
target_sources(demo
PUBLIC
FILE_SET all_my_modules TYPE CXX_MODULES FILES
a.cppm
)
If you set everything up correctly, CMake should give you the following warning during its configure stage:
CMake Warning (dev) at CMakeLists.txt:??? (target_sources):
CMake's C++ module support is experimental. It is meant only for
experimentation and feedback to CMake developers.
This warning is for project developers. Use -Wno-dev to suppress it.
The project should still build fine and rebuild correctly when changing the source files.
If you get an error saying
target_sources File set TYPE may only be "HEADERS"
it means that either your CMake version is too old, or you did not set up the Modules support correctly. Double-check CMake's documentation in this case.