#include
export module A;
)module A;
)export module A:part1;
)CXX_MODULES
flag-fmodules-ts
-std=c++20
cmake_minimum_required(VERSION 3.26)
project(ModernCpp LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
set(CMAKE_CXX_SCAN_FOR_MODULES ON) # Enable module dependency scanner
// math.ixx (MSVC) / math.cppm (GCC/Clang)
export module math;
export int add(int a, int b) {
return a + b;
}
import math;
int main() {
return add(2, 3);
}
add_executable(app
main.cpp
math.ixx # Module interface file
)
target_sources(app
FILE_SET CXX_MODULES
BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}
FILES math.ixx
)
set_target_properties(app
PROPERTIES
CXX_SCAN_FOR_MODULES ON # Enable module scanning
CXX_MODULE_STD_VERSION 20
)
import
statementstarget_link_libraries(app
PRIVATE
$ # Module target name
)
.ixx
for interface units.cppm
for interface units# Required in all cases
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
cmake --build . --verbose # See scanner commands
// math-impl.cppm
export module math:impl;
export int multiply(int a, int b) {
return a * b;
}
// math.cppm
export module math;
export import :impl;
target_sources(math
FILE_SET CXX_MODULES
FILES
math.cppm
math-impl.cppm
)
#if defined(_MSC_VER)
module; // MSVC preamble
#endif
export module platform;
if(MSVC)
set(MODULE_EXT .ixx)
else()
set(MODULE_EXT .cppm)
endif()
target_sources(app
FILE_SET CXX_MODULES
FILES math${MODULE_EXT}
)
project/
├── CMakeLists.txt
├── math.ixx
└── main.cpp
cmake_minimum_required(VERSION 3.28)
project(ModuleDemo LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_SCAN_FOR_MODULES ON)
add_executable(demo)
target_sources(demo
FILE_SET CXX_MODULES
FILES math.ixx
BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}
)
target_sources(demo
PRIVATE main.cpp
)
cmake -B build -S .
cmake --build build --verbose
demo.modmap
(module map).pcm
(precompiled module) files-std
/-fmodules-ts
flags are setQuestion 1
What are the correct ways to enable C++20 module support in CMake for different versions?
A) For CMake 3.26: Set CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API
to a specific hash.
B) For CMake 3.28: Enable CXX_STANDARD 20
and set CXX_SCAN_FOR_MODULES
property.
C) For all versions: Use target_compile_features(my_target PRIVATE cxx_modules)
.
D) For CMake 3.27: Add -DCMAKE_CXX_MODULES=ON
during configuration.
Question 2
Which target properties are critical for correctly handling C++20 modules in CMake?
A) CXX_STANDARD
B) INTERFACE_SOURCES
C) CXX_SCAN_FOR_MODULES
D) LINK_LIBRARIES
Question 3
How should module interface files (.ixx
) be added to a CMake target?
A) Use add_library
with TYPE MODULE
.
B) Use target_sources
with FILE_SET TYPE CXX_MODULES
.
C) Add them via target_include_directories
.
D) Use file(GLOB)
to collect all .ixx
files automatically.
Question 4
Which CMake commands are required to ensure modules are scanned and built correctly?
A) set_property(TARGET my_target PROPERTY CXX_SCAN_FOR_MODULES ON)
B) target_compile_definitions(my_target PRIVATE USE_MODULES)
C) target_link_libraries(my_target PRIVATE module_dependency)
D) target_compile_options(my_target PRIVATE -fmodules-ts)
Question 5
What is the role of the CXX_SCAN_FOR_MODULES
property?
A) Forces CMake to precompile all headers as modules.
B) Enables scanning source files for module dependencies.
C) Automatically generates module interface files.
D) Disables legacy header inclusion for modules.
Question 6
Which compiler flags are necessary for C++20 module support in GCC?
A) -std=c++20
B) -fmodules-ts
C) -fmodule-macros
D) -fprebuilt-modules
Question 7
How are module dependencies declared between targets in CMake?
A) Use target_link_libraries
with PUBLIC
visibility.
B) Use target_include_directories
with module paths.
C) Use target_sources
with FILE_SET
dependencies.
D) Use generator expressions like $
.
Question 8
What is a common mistake when configuring modules in CMake?
A) Forgetting to set CMAKE_CXX_STANDARD
to 20.
B) Using add_executable
instead of add_library
for modules.
C) Placing module interface files in include/
directories.
D) Omitting FILE_SET TYPE CXX_MODULES
in target_sources
.
Question 9
How does CMake handle transitive dependencies for modules?
A) Automatically propagates module dependencies via target_link_libraries
.
B) Requires manual declaration of all dependent modules.
C) Uses INTERFACE
properties to forward dependencies.
D) Only works with STATIC
libraries.
Question 10
Which configuration ensures cross-compiler compatibility for modules?
A) Use #ifdef
guards for compiler-specific module code.
B) Set CMAKE_CXX_COMPILER_FEATURES
to cxx_modules
.
C) Avoid module partitions for compatibility.
D) Conditionally enable compiler flags using $
.
Question 1
Correct Answers: A, B
CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API
variable to a hash (e.g., 2182bf5c-ef0d-489a-91da-49dbc3095d2a
).CXX_STANDARD 20
and enabling CXX_SCAN_FOR_MODULES
.cxx_modules
is not a valid feature flag in CMake.CMAKE_CXX_MODULES
is not a valid CMake variable.Question 2
Correct Answers: A, C
CXX_STANDARD
ensures the compiler uses C++20.CXX_SCAN_FOR_MODULES
enables module dependency scanning.INTERFACE_SOURCES
is unrelated to modules.LINK_LIBRARIES
handles libraries, not modules.Question 3
Correct Answer: B
FILE_SET TYPE CXX_MODULES
explicitly declares module interface files.TYPE MODULE
is for shared libraries, not C++20 modules.target_include_directories
is for headers, not modules.file(GLOB)
is discouraged for build reliability.Question 4
Correct Answers: A, D
-fmodules-ts
for module support.USE_MODULES
is not a standard definition.target_link_libraries
handles libraries, not modules.Question 5
Correct Answer: B
CXX_SCAN_FOR_MODULES
triggers CMake to scan sources for import
statements.Question 6
Correct Answers: A, B
-std=c++20
enables C++20 features.-fmodules-ts
enables GCC’s module TS implementation.Question 7
Correct Answer: C
FILE_SET
dependencies declare module relationships.target_link_libraries
handles libraries, not module dependencies.include_directories
does not resolve module imports.Question 8
Correct Answers: A, D
CXX_STANDARD 20
breaks module compilation.FILE_SET
prevents CMake from recognizing modules.add_executable
can use modules if configured properly..ixx
files can reside in any directory.Question 9
Correct Answer: C
INTERFACE
properties propagate dependencies transitively.target_link_libraries
does not auto-resolve module dependencies.Question 10
Correct Answer: D
-fmodules-ts
for GCC, /interface
for MSVC).#ifdef
guards are not CMake’s responsibility.cxx_modules
is not a standard feature flag.Exercise 1: Cross-Version CMake Compatibility for C++ Modules
Scenario:
Your project must support both CMake 3.26 (experimental modules) and CMake 3.28+ (stable modules). Write a CMakeLists.txt
that:
mymodule.cppm
(module interface) and client.cpp
(module consumer) compile without errors.Key Challenges:
Exercise 2: Multi-Module Dependency Management
Scenario:
A project has three modules:
math.cppm
(declares add(int, int)
)advanced.cppm
(imports math
and declares multiply(int, int)
)main.cpp
(imports advanced
).Write a CMakeLists.txt
that:
math
→ advanced
→ main
).math-impl.cppm
as a partition of math.cppm
).Key Challenges:
Exercise 3: Legacy Compiler Flag Injection for Modules
Scenario:
Your team uses a pre-3.28 CMake version but wants to manually inject compiler-specific flags for C++20 modules. Write a script that:
-std=c++20 -fmodules-ts
(Clang/GCC) or /std:c++20 /interface
(MSVC) flags.mymodule.cppm
generates a BMI and is consumed by client.cpp
.Key Challenges:
Exercise 1 Solution:
cmake_minimum_required(VERSION 3.26)
project(CrossVersionModules)
# Enable C++20 standard
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(CMAKE_VERSION VERSION_LESS 3.28)
# Experimental module support for CMake <3.28
set(CMAKE_CXX_EXTENSIONS OFF)
add_compile_options(-fmodules-ts) # Clang/GCC
if(MSVC)
add_compile_options(/experimental:module /std:c++latest)
endif()
else()
# Stable module support in CMake >=3.28
cmake_policy(SET CMP0157 NEW) # Enable module awareness
endif()
add_executable(app)
target_sources(app
PRIVATE
client.cpp
mymodule.cppm # Treated as module interface
)
Explanation:
CMAKE_VERSION
detects if the version is pre-3.28.-fmodules-ts
or /experimental:module
) are injected.CMP0157
.mymodule.cppm
is marked as a module interface implicitly in CMake 3.28+.Exercise 2 Solution:
cmake_minimum_required(VERSION 3.28)
project(MultiModule)
set(CMAKE_CXX_STANDARD 20)
cmake_policy(SET CMP0157 NEW) # Enable module processing
add_library(math)
target_sources(math
PUBLIC FILE_SET CXX_MODULES
FILES
math.cppm # Primary module interface
math-impl.cppm # Module partition (impl)
)
add_library(advanced)
target_sources(advanced
PUBLIC FILE_SET CXX_MODULES
FILES advanced.cppm
)
target_link_libraries(advanced PUBLIC math) # Declare dependency
add_executable(app main.cpp)
target_link_libraries(app PRIVATE advanced)
Explanation:
target_link_libraries
ensures advanced
depends on math
, enforcing build order.math.cppm
and advanced.cppm
as module interfaces.math-impl.cppm
is included in the math
target’s sources, treated as a partition.Exercise 3 Solution:
cmake_minimum_required(VERSION 3.26)
project(LegacyModuleFlags)
# Detect compiler and version
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 15)
set(MODULE_FLAGS "-std=c++20 -fmodules-ts -x c++-module")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 11)
set(MODULE_FLAGS "-std=c++20 -fmodules-ts")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.34)
set(MODULE_FLAGS "/std:c++20 /experimental:module /interface")
else()
message(FATAL_ERROR "Compiler does not support C++20 modules!")
endif()
add_executable(app)
target_compile_options(app PRIVATE ${MODULE_FLAGS})
target_sources(app
PRIVATE
client.cpp
mymodule.cppm
)
Explanation:
target_compile_options
.-x c++-module
(Clang) or /interface
(MSVC) ensure BMI files are generated.CMAKE_VERSION
and compiler detection to handle experimental vs. stable features.target_link_libraries
ensures correct build order for modules.FILE_SET CXX_MODULES
(CMake 3.28+) or implicit detection via file extensions (.cppm
).