您参考的文档页面(http://clang.llvm.org/docs/Modules.html)上描述的实际上不是模块 TS。
利用预编译的头文件基础设施使它们模块化可重用是 clang 的非标准 hack。诀窍只是允许以任何顺序加载预编译的头文件,甚至在已经解析了一些代码之后加载。这是基于这样一个假设,即先前解析/加载的代码不应该对进一步的预编译代码产生任何副作用。其他更传统的 PCH 处理在这方面可能被认为过于迂腐,最终变得不那么灵活(即模块化程度低得多),因为它们需要一个需要首先加载的单片 PCH(例如 MSVC),或者具有固定排序 (GCC) 的 PCH 链。
Objective-C 语言增加了一个@import
关键字,该关键字有效地“包含”了相应文件中列出的所有module.modulemap
文件(这实际上意味着生成和/或加载相应的 PCH 文件)。
当未启用 Objective-C 扩展时,没有import
关键字,但您还有另一个技巧:它拦截#include
预处理器指令,以便它们“包含”相应文件中列出的所有module.modulemap
文件(这实际上意味着生成和/或加载相应的 PCH 文件)。
没有module
andexport
关键字(这些只出现在module.modulemap
文件中);一切都出口。
此模块化 PCH hack 使用-fmodules
编译器标志启用。
它的价值在于它有助于加快大型代码库的构建过程,并且它还允许懒惰地准备旧代码库向未来模块化结构的过渡,而无需立即重写整个世界。
我怀疑它是否在生产中得到了广泛的使用,除了像谷歌这样的一些非常参与的公司,谷歌有众所周知的clang开发人员可以在需要时修复错误。
要真正使您的代码与该系统一起工作,您需要:
在第一次使用时,请注意正确设置预处理器包含路径的重要性,-I
因为系统将在后台查找module.modulemap
预处理器路径上的文件,即使您没有#include
在代码中编写任何指令。
从技术上讲,您可以通过查看目录下生成的 PCH 文件来验证模块系统是否有效启用/tmp/org.llvm.clang.$USER/ModuleCache/
,如Catch-$HASHSUM.pcm
. 由于 PCH 依赖于所使用的编译器选项(例如,上面示例中的 Objective-C 支持),因此您最终可能会为同一个模块获得多个结果。Clang 自己管理这个缓存目录;它甚至会删除旧的未使用文件(无论如何/tmp/
也会在启动过程中被清除)。
正如您所发现的,新的-fmodules-ts
编译器标志有效地要求我们都在寻找未来的模块 TS 支持。请注意,它目前几乎不可用。
一个关于如何使用它的问题已经被问及回答:Clangs C++ Module TS support: How to tell clang++ where to find the module file?