Skip to main content
added compiler explorer link
Source Link
ComicSansMS
  • 56k
  • 15
  • 167
  • 182

You can also findtry this example in Compiler Explorer and find it on Github.

You can also find this example on Github.

You can try this example in Compiler Explorer and find it on Github.

added link to cppcon video
Source Link
ComicSansMS
  • 56k
  • 15
  • 167
  • 182
  • 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:
  • 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.
  • This feature is still in an early stage, so be prepared to encounter bugs in both the compiler and build system implementations.
  • 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.
    • 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.
  • This feature is still in an early stage, so be prepared to encounter bugs in both the compiler and build system implementations.
  • 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:
  • 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.
  • This feature is still in an early stage, so be prepared to encounter bugs in both the compiler and build system implementations.
updated answer for cmake 3.28
Source Link
ComicSansMS
  • 56k
  • 15
  • 167
  • 182

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.

Experimental Modules Support

This reflects the status as of CMake 3.27.

I will keep updating this answer as the situation changes.

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.

Proper integration currently only works with the following generators:

  • Ninja version 1.10 or newer
  • Visual Studio 2022 version 19.34 or newer.

Module dependency scanning is currently supported by the following compilers:

  • MSVC compiler version 19.34 or newer
  • LLVM/Clang version 16 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:
    • 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 feature that is mainly being made available so that compiler and tool implementers can iron out the bugs.

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

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.

CMake added support for C++20 named modules in version 3.28.

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.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
)

The project should build fine and rebuild correctly when changing the source files.

Further details

Ensure that your compiler has proper support for C++20 modules and dependency scanning:

  • MSVC compiler version 19.34 or newer
  • LLVM/Clang version 16 or newer. (I personally recommend at least version 17 due to a number of bugs in 16)
  • gcc version 14 or newer.

Also be aware that CMake only supports modules for the following generators:

  • Visual Studio 2022, toolset 19.34 (Visual Studio 17.4) or newer
  • Ninja version 1.11 or newer
  • 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.
    • 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.
  • This feature is still in an early stage, so be prepared to encounter bugs in both the compiler and build system implementations.

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.

rephrased original answer into the intro section
Source Link
ComicSansMS
  • 56k
  • 15
  • 167
  • 182
Loading
updated for CMake 3.27
Source Link
ComicSansMS
  • 56k
  • 15
  • 167
  • 182
Loading
updated issue link
Source Link
ComicSansMS
  • 56k
  • 15
  • 167
  • 182
Loading
current status of header units
Source Link
ComicSansMS
  • 56k
  • 15
  • 167
  • 182
Loading
corrected paragraph about implementation units
Source Link
ComicSansMS
  • 56k
  • 15
  • 167
  • 182
Loading
added note about internal partitions
Source Link
ComicSansMS
  • 56k
  • 15
  • 167
  • 182
Loading
fixed youtube link to point to the correct talk
Source Link
ComicSansMS
  • 56k
  • 15
  • 167
  • 182
Loading
additional reference; removed cmake 3.20 update
Source Link
ComicSansMS
  • 56k
  • 15
  • 167
  • 182
Loading
expanded the answer to reflect the latest developments
Source Link
ComicSansMS
  • 56k
  • 15
  • 167
  • 182
Loading
added update about experimental ninja support
Source Link
ComicSansMS
  • 56k
  • 15
  • 167
  • 182
Loading
Source Link
ComicSansMS
  • 56k
  • 15
  • 167
  • 182
Loading