38

模块是#includes 的替代品。Clang 有一个完整的 C++ 实现。如果我现在想通过 Clang 使用模块,我会怎么做?


使用

import std.io;

在 C++ 源文件中还不能工作(编译),因为模块的规范(包括语法)不是最终的。


Clang 文档指出,当传递标志时-fmodules,#includes 将被重写为相应的导入。但是,检查预处理器会提示其他情况(test.cpp 仅包含#include <stdio.h>一个空的 main):

$ clang++-3.5 -fmodules -E test.cpp -o test
$ grep " printf " test
extern int printf (const char *__restrict __format, ...);

-fmodules此外,在完全没有标志的情况下编译这个测试文件会产生相同的目标文件。

我究竟做错了什么?

4

2 回答 2

35

截至本次提交,Clang 为Modules TS提供实验性支持。

让我们使用与VS 博客文章中关于实验模块支持的相同示例文件(稍作改动) 。

首先,定义模块接口文件。默认情况下,Clang 将带有cppm扩展名(和其他一些)的文件识别为 C++ 模块接口文件。

// file: foo.cppm
export module M;

export int f(int x)
{
    return 2 + x;
}
export double g(double y, int z)
{
    return y * z;
} 

请注意,模块接口声明必须是export module M;而不是module M;像 VS 博客文章中那样。

然后按如下方式使用模块:

// file: bar.cpp
import M;

int main()
{
    f(5);
    g(0.0, 1);
    return 0;
}

foo.cppm现在,使用预编译模块

clang++ -fmodules-ts --precompile foo.cppm -o M.pcm

或者,如果模块接口扩展不是cppm(比方说ixx,与 VS 一样),您可以使用:

clang++ -fmodules-ts --precompile -x c++-module foo.ixx -o M.pcm

然后构建程序

clang++ -fmodules-ts -c M.pcm -o M.o
clang++ -fmodules-ts -fprebuilt-module-path=. M.o bar.cpp

或者,如果 pcm 文件名与模块名不同,则必须使用:

clang++ -fmodules-ts -fmodule-file=M.pcm bar.cpp

我已经使用r303050 构建(2017 年 5 月 15 日)在 Windows 上测试了这些命令。

注意:使用该-fprebuilt-module-path=.选项时,我收到警告:

clang++.exe:警告:编译期间未使用的参数:'-fprebuilt-module-path=.' [-Wunused-command-line-argument]

这似乎是不正确的,因为没有该选项,M找不到该模块。

于 2016-12-05T22:52:46.307 回答
16

就像你提到的,clang 还没有用于导入的 C++ 语法,所以我怀疑在预处理文件时#include指令是否会被重写为导入,因此这可能不是测试模块是否按预期工作的最佳方法。

但是,如果您-fmodules-cache-path=<path>明确设置,您可以观察到在构建期间使用预编译模块文件 (*.pcm) 填充它的clang - 如果涉及任何模块。

如果您现在想使用启用模块的标准库,则需要使用 libc++(从 3.7.0 版开始似乎附带了一个 module.modulemap)——尽管根据我的经验,这还不能完全正常工作。(Visual Studio 2015 的 C++ 编译器也应该在 11 月的 Update 1 中获得某种形式的模块支持)

独立于标准库,您仍然可以在自己的代码中使用模块。clang 文档包含Module Map Language的详细描述。

于 2015-10-24T18:28:58.367 回答