2

看起来Clang 正在为模块 TS 提供支持。我使用从 SVN(主干)编译的 Clang进行了尝试,它按预期工作。

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

我试图以module.modulemap这种方式声明 a :

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;
}

编译模型指出“模块的二进制表示是编译器根据需要自动生成的。

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

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

知道如何解决吗?

4

1 回答 1

3

您参考的文档页面(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 文件)。

没有moduleandexport关键字(这些只出现在module.modulemap文件中);一切都出口。

此模块化 PCH hack 使用-fmodules编译器标志启用。

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

我怀疑它是否在生产中得到了广泛的使用,除了像谷歌这样的一些非常参与的公司,谷歌有众所周知的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在代码中编写任何指令。

从技术上讲,您可以通过查看目录下生成的 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?

于 2018-07-15T03:53:54.353 回答