cmake-cxxmodules(7)¶
版本 3.28 新增。
C++ 20 引入了语言的“模块”概念。其设计要求构建系统在编译之间进行排序,以可靠地满足 import
语句。CMake 的实现要求编译器在构建期间扫描源文件以获取模块依赖项,整理扫描结果以推断排序约束,并告知构建工具如何动态更新构建图。
编译策略¶
使用 C++ 模块,编译一组 C++ 源文件不再是高度并行的。也就是说,任何给定的源文件可能首先需要编译另一个源文件,以便提供 C++ 编译器用于满足其他源文件中的 import
语句的“CMI”(编译模块接口)或“BMI”(二进制模块接口)。使用头文件时,源文件可以共享它们的声明,以便任何使用者都可以独立编译。使用模块时,声明现在由编译器在编译期间根据源文件的内容及其 export
语句生成到这些 BMI 文件中。
编译所需的顺序需要在构建时解析,因为该顺序由源文件的内容控制。这意味着需要在构建期间从源文件中提取顺序,以避免为每次源文件更改重新生成构建图(通过配置和生成阶段)以获得正确的构建。
一般策略是使用“扫描器”提取排序依赖信息,并通过将每源扫描结果(由 P1689R5 文件表示)与目标内以及与目标可见的模块的依赖项进行“整理”,从而在现有边之间更新构建图。主要任务是生成“模块映射”文件,以传递给每个编译规则,其中包含满足 import
语句所需的 BMI 路径。整理器还负责使用构建时信息填充信息,包括模块接口单元及其 BMI 的 install
规则,以及任何具有 C++ 模块的导出目标的属性。
注意
CMake 正在专注于正确的构建,然后再考虑性能改进。所选策略中存在一些已知策略,它们可能会带来构建性能改进。然而,它们正在推迟,直到我们有一个可供比较的有效模型。还需要注意的是,在一种情况下(例如,全新构建)有用的策略在另一种情况(例如,增量构建)下可能表现不佳。寻找平衡并提供控件来选择策略是未来的工作。
扫描控制¶
源文件是否被扫描以查找 C++ 模块使用情况取决于以下查询。使用第一个提供是/否答案的查询。
如果源文件属于
CXX_MODULES
类型的文件集,它将被扫描。如果目标不使用至少 C++ 20,它将不会被扫描。
如果源文件不是
CXX
语言,它将不会被扫描。如果设置了
CXX_SCAN_FOR_MODULES
源文件属性,则使用其值。如果设置了
CXX_SCAN_FOR_MODULES
目标属性,则使用其值。设置CMAKE_CXX_SCAN_FOR_MODULES
变量,以便在创建所有目标时初始化此属性。否则,如果编译器和生成器支持扫描,源文件将被扫描。请参阅策略
CMP0155
。
请注意,任何被扫描的源文件都将从任何统一构建中排除(请参阅 UNITY_BUILD
),因为模块相关语句只能在 C++ 翻译单元中的一个位置出现。
编译器支持¶
CMake 原生支持模块依赖扫描的编译器包括:
MSVC 工具集 14.34 及更新版本(随 Visual Studio 17.4 及更新版本提供)
LLVM/Clang 16.0 及更新版本
GCC 14(适用于开发中分支,在 2023-09-20 之后)及更新版本
import std
支持¶
对 import std
的支持仅限于以下工具链和标准库组合:
Clang 18.1.2 及更高版本,支持
-stdlib=libc++
或-stdlib=libstdc++
MSVC 工具集 14.36 及更新版本(随 Visual Studio 17.6 预览版 2 及更新版本提供)
GCC 15 及更新版本。
可以使用 CMAKE_CXX_COMPILER_IMPORT_STD
变量检测活动 C++ 工具链对标准级别的支持。
注意
此支持仅在通过 CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
门启用 import std;
的实验性支持时提供。
生成器支持¶
支持扫描 C++ 模块源文件的生成器列表包括:
限制¶
CMake 当前的 C++ 模块支持存在许多已知限制。本文档不记录编译器中已知的限制或错误,因为这些限制或错误会随时间变化。
对于所有生成器:
不支持头单元。
不支持
import std;
或其他编译器提供的模块的内置支持。
对于 Ninja 生成器:
需要
ninja
1.11 或更新版本。
仅支持 Visual Studio 2022 和 MSVC 工具集 14.34 (Visual Studio 17.4) 及更新版本。
不支持导出或安装 BMI 或模块信息。
不支持从具有 C++ 模块的
IMPORTED
目标编译 BMI(包括import std
)。对于从
PUBLIC
模块源使用PRIVATE
源提供的模块,没有诊断。