cmake-cxxmodules(7)¶
添加于 3.28 版本。
C++ 20 向该语言引入了“模块”的概念。该设计要求构建系统相互对编译进行排序,以可靠地满足 import
语句。CMake 的实现要求编译器在构建期间扫描源文件,查找模块依赖项,整理扫描结果以推断排序约束条件,并将动态更新构建图的方法告知构建工具。
编译策略¶
采用 C++ 模块后,就不再能并发的编译一组 C++ 源代码。也就是说,为了提供 C++ 编译器用来满足其他源代码中 import
语句的“CMI”(编译的模块接口)或“BMI”(二进制模块接口),任何给定的源代码可能首先需要编译另一个源文件。有了头文件,源代码就可以共享它们的声明,这样任何消费者都可以独立地进行编译。有了模块,编译器将根据源文件的内容及其 export
语句,在编译期间将声明生成为这些 BMI 文件。
编译必需的顺序需要在编译时解析该顺序,因为该顺序由源代码的内容控制。这意味着在构建期间需要从源代码中提取顺序,以避免因每个源代码更改而重新通过配置和生成阶段来生成构建图,以获取正确的构建结果。
总体策略是使用“扫描器”提取顺序依赖项信息,并通过使用按源扫描结果(由 P1689R5 文件表示)以及“整理”目标内的依赖项和在目标中可见的其他目标所生成模块,来使用现有的边更新构建图中的新边,。最重要的任务是生成“模块映射”文件,以便将包含满足 import
语句所需的 BMI 路径传递到每个编译规则。整理器还有使用构建时信息来填写导出目标的模块接口单元、其 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 年 9 月 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++ 工具链的标准级别的支持。
注意
仅当 import std;
的实验性支持已通过 CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
闸门启用时,才提供此支持。
生成器支持¶
支持扫描 C++ 模块源的生成器包括
限制¶
目前在 CMake 中 C++ 模块支持存在一些已知限制。这不记录编译器中的已知限制或错误,因为它们会随着时间的推移而改变。
所有生成器
不支持标头单元。
不支持
import std;
或其他编译器提供的模块。
Ninja 生成器
需要
ninja
1.11 或更高版本。
仅 Visual Studio 2022 和 MSVC 工具集 14.34(Visual Studio 17.4)及更高版本。
不支持导出或安装 BMI 或模块信息。
不支持使用 C++ 模块(包括
import std
)从IMPORTED
目标编译 BMI。不诊断使用
PRIVATE
源中提供的模块PUBLIC
模块源。