使用 clang 的 C++ 模块

C++ modules using clang

As it looks like Clang is providing support for the modules TS. I 使用 Clang,从 SVN(主干)编译,并且按预期工作。

我想将它带到下一步,将 catch 库包装到一个模块中。

我试过这样声明一个module.modulemap

module Catch {
  header "catch/catch.hpp"
  export *
}

main.cpp包含:

import Catch;

int main(int argc, char* const argv[])
{
  int result = Catch::Session().run(argc, argv);
  return result;
}

compilation model 声明“模块的二进制表示由编译器根据需要自动生成。

使用 clang-4.0 -std=c++1z -fmodules-ts main.cpp 编译 main.cpp 我得到:

main.cpp:1:8: fatal error: module 'Catch' not found
import Catch;
~~~~~~~^~~~~
1 error generated.

知道如何解决吗?

您参考的文档页面上描述的(http://clang.llvm.org/docs/Modules.html)实际上不是模块TS。

这是 clang 的 non-standard hack,它利用预编译的 headers 基础设施使它们模块化可重用。诀窍就是允许预编译的 headers 以任何顺序加载,甚至在已经解析了一些代码之后加载。这是基于这样的假设,即以前的 parsed/loaded 代码不应该对进一步的预编译代码产生任何副作用。其他更传统的 PCH 处理在这方面被认为过于迂腐,最终变得非常不灵活(即模块化程度低得多),因为它们需要一个需要首先加载的整体 PCH(例如 MSVC),或者一个具有固定顺序 (GCC) 的 PCH 链。

objective-C 语言增加了一个 @import 关键字,该关键字有效 "include" 相应 module.modulemap 文件中列出的所有文件(这实际上意味着生成 and/or加载相应的PCH文件)。

当 objective-C 扩展未启用时,没有 import 关键字,但您还有另一个技巧:它拦截 #include 预处理器指令,以便它们代替 "include" 相应 module.modulemap 文件中列出的所有文件(这实际上意味着生成 and/or 加载相应的 PCH 文件)。

没有 moduleexport 关键字(这些仅出现在 module.modulemap 文件中);全部导出。

此 modular-PCH hack 是通过 -fmodules 编译器标志启用的。

它的价值在于它有助于加快大型代码库的构建过程,并且它还允许延迟准备旧代码库向未来模块化结构的过渡,而无需立即重写整个世界。

我怀疑它是否在生产中得到广泛使用,除了像 google 这样的少数 very-involved 公司,这些公司拥有知名的 clang 开发人员,他们可以在需要时修复错误。

要使您的代码真正适用于该系统,您需要:

  • 编辑你的 main.cpp 以使用 @import Catch; 并使用以下命令编译 clang++ -fmodules -I . -xobjective-c++ main.cpp

  • 编辑你main.cpp使用#include "catch/catch.hpp"并使用下面的命令编译clang++ -fmodules main.cpp

第一次使用时,请注意使用 -I 正确设置预处理器包含路径的重要性,因为系统会在后台查找预处理器路径上的 module.modulemap 文件,即使您不要在代码中写任何 #include 指令。

从技术上讲,您可以通过查看 /tmp/org.llvm.clang.$USER/ModuleCache/ 目录下生成的 PCH 文件来验证模块系统是否已有效启用,如 Catch-$HASHSUM.pcm。由于 PCH 依赖于(amgonst 其他东西)所使用的编译器选项(例如,上面示例中的 objective-C 支持),因此您可能最终会为同一个模块得到多个。 Clang 自己管理这个缓存目录;它甚至会删除未使用的旧文件(无论如何 /tmp/ 在启动期间也会被清除)。

正如您所发现的,新的 -fmodules-ts 编译器标志有效地请求我们都在寻找的未来模块 TS 支持。请注意,它目前几乎无法使用。

关于如何使用它的问题已经被提出并得到回答:Clangs C++ Module TS support: How to tell clang++ where to find the module file?