cpp-modules
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseC++20 Modules
C++20 Modules
Purpose
用途
Guide agents through authoring, building, and debugging C++20 modules: named modules vs header units, module partitions, CMake integration, compiler-specific flags, and interoperability with legacy headers.
指导Agent完成C++20模块的编写、构建与调试:包括命名模块与头单元的区别、模块分区、CMake集成、编译器专属标志,以及与传统头文件的互操作性。
Triggers
触发场景
- "How do I write a C++20 module?"
- "How do I import a module in CMake?"
- "What's the difference between a named module and a header unit?"
- "My module gives 'cannot find module' errors"
- "How do I use C++20 modules with Clang?"
- "How do I migrate from headers to modules?"
- "如何编写C++20模块?"
- "如何在CMake中导入模块?"
- "命名模块和头单元有什么区别?"
- "我的模块报'无法找到模块'错误"
- "如何在Clang中使用C++20模块?"
- "如何从头文件迁移到模块?"
Workflow
工作流程
1. Module concepts overview
1. 模块概念概述
C++20 module kinds:
├── Named module interface unit (.cppm / .ixx) — exports declarations
├── Module implementation unit (.cpp) — defines module members
├── Module partition (.cppm) — internal module subdivision
└── Header unit (any header) — import a legacy header as moduleNamed modules are the primary target. Header units are a bridge for legacy code. Avoid Global Module Fragment unless required for macro access.
C++20 module kinds:
├── Named module interface unit (.cppm / .ixx) — exports declarations
├── Module implementation unit (.cpp) — defines module members
├── Module partition (.cppm) — internal module subdivision
└── Header unit (any header) — import a legacy header as module命名模块是主要使用目标。头单元是传统代码的过渡方案。除非需要访问宏,否则避免使用全局模块片段。
2. Named module — minimal example
2. 命名模块——最简示例
cpp
// math.cppm — module interface unit
export module math; // declares the module name
export int add(int a, int b) { return a + b; }
export double pi = 3.14159;
// Non-exported (module-private)
int internal_helper() { return 42; }cpp
// main.cpp — consumer
import math; // import the module
#include <iostream> // legacy header (still works)
int main() {
std::cout << add(2, 3) << "\n"; // 5
std::cout << pi << "\n";
}cpp
// math.cppm — module interface unit
export module math; // declares the module name
export int add(int a, int b) { return a + b; }
export double pi = 3.14159;
// Non-exported (module-private)
int internal_helper() { return 42; }cpp
// main.cpp — consumer
import math; // import the module
#include <iostream> // legacy header (still works)
int main() {
std::cout << add(2, 3) << "\n"; // 5
std::cout << pi << "\n";
}3. Module partitions
3. 模块分区
cpp
// math-core.cppm — partition
export module math:core; // partition 'core' of module 'math'
export int add(int a, int b) { return a + b; }cpp
// math.cppm — primary module interface
export module math;
export import :core; // re-export the partitioncpp
// math-impl.cpp — implementation unit (no export)
module math; // belongs to 'math' module, not a partition
// has access to all math declarations, but exports nothingcpp
// math-core.cppm — partition
export module math:core; // partition 'core' of module 'math'
export int add(int a, int b) { return a + b; }cpp
// math.cppm — primary module interface
export module math;
export import :core; // re-export the partitioncpp
// math-impl.cpp — implementation unit (no export)
module math; // belongs to 'math' module, not a partition
// has access to all math declarations, but exports nothing4. Header units — bridging legacy headers
4. 头单元——衔接传统头文件
cpp
// Import a standard library header as a module unit
import <iostream>; // header unit (compiler generates BMI)
import <vector>;
// Or import a project header (must be compilable as header unit)
import "myheader.h";Header units do NOT provide macros to importers. For macro access, use the Global Module Fragment:
cpp
module; // Global Module Fragment starts here
#include <cassert> // macros like assert() are available
export module mymod;
// ... rest of modulecpp
// Import a standard library header as a module unit
import <iostream>; // header unit (compiler generates BMI)
import <vector>;
// Or import a project header (must be compilable as header unit)
import "myheader.h";头单元不会向导入者提供宏。若需要访问宏,请使用全局模块片段:
cpp
module; // Global Module Fragment starts here
#include <cassert> // macros like assert() are available
export module mymod;
// ... rest of module5. Building with Clang
5. 使用Clang构建
bash
undefinedbash
undefinedCompile module interface → produces .pcm (precompiled module)
Compile module interface → produces .pcm (precompiled module)
clang++ -std=c++20 --precompile math.cppm -o math.pcm
clang++ -std=c++20 --precompile math.cppm -o math.pcm
Compile implementation using the .pcm
Compile implementation using the .pcm
clang++ -std=c++20 -fmodule-file=math=math.pcm -c math.cpp -o math.o
clang++ -std=c++20 -fmodule-file=math=math.pcm -c math.cpp -o math.o
Compile consumer
Compile consumer
clang++ -std=c++20 -fmodule-file=math=math.pcm main.cpp math.o -o prog
undefinedclang++ -std=c++20 -fmodule-file=math=math.pcm main.cpp math.o -o prog
undefined6. Building with GCC
6. 使用GCC构建
bash
undefinedbash
undefinedGCC ≥11 supports modules (experimental ≥11, better ≥14)
GCC ≥11 supports modules (experimental ≥11, better ≥14)
Compile interface unit → produces .gcm in gcm.cache/
Compile interface unit → produces .gcm in gcm.cache/
g++ -std=c++20 -fmodules-ts math.cppm -c -o math.o
g++ -std=c++20 -fmodules-ts math.cppm -c -o math.o
Compiler auto-discovers .gcm files in gcm.cache/
Compiler auto-discovers .gcm files in gcm.cache/
g++ -std=c++20 -fmodules-ts main.cpp math.o -o prog
undefinedg++ -std=c++20 -fmodules-ts main.cpp math.o -o prog
undefined7. CMake integration (CMake ≥3.28)
7. CMake集成(CMake ≥3.28)
cmake
cmake_minimum_required(VERSION 3.28)
project(myproject LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
add_library(math)
target_sources(math
PUBLIC
FILE_SET CXX_MODULES FILES # module interface units
src/math.cppm
src/math-core.cppm
PRIVATE
src/math-impl.cpp # implementation unit
)
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE math)bash
undefinedcmake
cmake_minimum_required(VERSION 3.28)
project(myproject LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
add_library(math)
target_sources(math
PUBLIC
FILE_SET CXX_MODULES FILES # module interface units
src/math.cppm
src/math-core.cppm
PRIVATE
src/math-impl.cpp # implementation unit
)
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE math)bash
undefinedRequires a generator that supports modules (Ninja ≥1.11 or MSBuild)
Requires a generator that supports modules (Ninja ≥1.11 or MSBuild)
cmake -S . -B build -G Ninja
cmake --build build
For CMake 3.25–3.27 (experimental):
```cmake
cmake_minimum_required(VERSION 3.25)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP ON)cmake -S . -B build -G Ninja
cmake --build build
对于CMake 3.25–3.27(实验性支持):
```cmake
cmake_minimum_required(VERSION 3.25)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP ON)8. Common errors
8. 常见错误
| Error | Cause | Fix |
|---|---|---|
| BMI not found in search path | Compile interface unit first; check |
| | Move |
| Two | Only one primary interface per module |
| Macros don't cross module boundaries | Move macro-dependent code to GMF or use |
| Same name in multiple partitions | Each name exported from exactly one partition |
| BMI cache stale | | Clean build or ensure dependency tracking is working |
| 错误信息 | 原因 | 修复方案 |
|---|---|---|
| 搜索路径中未找到BMI | 先编译接口单元;检查 |
| 在模块范围内使用 | 将 |
| 两个 | 每个模块只能有一个主接口 |
| 宏无法跨模块边界传递 | 将依赖宏的代码移至全局模块片段,或使用 |
| 多个分区中存在同名内容 | 每个导出名称仅来自一个分区 |
| BMI cache stale | 修改后未重新构建 | 清理构建产物,或确保依赖跟踪正常工作 |
9. Interop with legacy headers
9. 与传统头文件的互操作性
cpp
// Wrapping a C library for module use
export module cjson;
module; // Global Module Fragment
#include <cjson/cJSON.h> // C header with macros
export module cjson; // back to module purview
// Re-export key types (optional)
export using ::cJSON;
export using ::cJSON_Parse;For CMake module support details, see references/modules-cmake-support.md.
cpp
// Wrapping a C library for module use
export module cjson;
module; // Global Module Fragment
#include <cjson/cJSON.h> // C header with macros
export module cjson; // back to module purview
// Re-export key types (optional)
export using ::cJSON;
export using ::cJSON_Parse;关于CMake模块支持的详细信息,请参阅references/modules-cmake-support.md。
Related skills
相关技能
- Use for PCH as a modules alternative
skills/build-systems/build-acceleration - Use or
skills/compilers/gccfor compiler-specific module flagsskills/compilers/clang - Use for CMake project configuration
skills/build-systems/cmake
- 若需将PCH作为模块替代方案,请使用
skills/build-systems/build-acceleration - 若需编译器专属模块标志,请使用或
skills/compilers/gccskills/compilers/clang - 若需CMake项目配置,请使用
skills/build-systems/cmake