cmake-cxxmodules(7)¶
在 3.28 版本中添加。
C++ 20 在语言中引入了“模块”的概念。这种设计要求构建系统对编译进行排序,以便可靠地满足 import
语句。CMake 的实现要求编译器在构建期间扫描源文件以查找模块依赖项,整理扫描结果以推断排序约束,并告知构建工具如何动态更新构建图。
编译策略¶
使用 C++ 模块,编译一组 C++ 源文件不再是易于并行化的。也就是说,任何给定的源文件可能首先需要先编译另一个源文件,以便提供 CMI(编译模块接口)或 BMI(二进制模块接口),C++ 编译器使用它们来满足其他源文件中的 import
语句。使用头文件,源文件可以共享它们的声明,以便任何使用者都可以独立编译。使用模块,声明现在由编译器在编译期间基于源文件的内容及其 export
语句生成到这些 BMI 文件中。
编译所需的顺序需要构建时解析排序,因为顺序由源文件的内容控制。这意味着需要从构建期间的源文件中提取排序,以避免为每个源文件更改重新生成构建图,从而通过配置和生成阶段来获得正确的构建。
一般策略是使用“扫描器”来提取排序依赖信息,并通过获取每个源文件的扫描结果(由 P1689R5 文件表示)和“整理”目标内部以及目标可见的目标产生的模块的依赖关系,来更新构建图中现有边之间的新边。主要任务是生成“模块映射”文件,以将满足 import
语句所需的 BMI 路径传递给每个编译规则。整理器还具有使用构建时信息来填充信息(包括模块接口单元的 install
规则、它们的 BMI 以及任何导出的带有 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++
MSVC 工具集 14.36 及更高版本(随 Visual Studio 17.6 Preview 2 及更高版本提供)
可以使用 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
源提供的模块。