【问题标题】:How do I use C++ modules in Clang?如何在 Clang 中使用 C++ 模块?
【发布时间】:2016-01-23 07:17:39
【问题描述】:

模块是#includes 的替代品。 Clang has a complete implementation for C++。如果我现在想通过 Clang 使用模块,我该怎么做?


使用

import std.io;

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


Clang documentation 声明,当传递-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 与完全不使用标志编译此测试文件会产生相同的目标文件。

我做错了什么?

【问题讨论】:

    标签: c++ clang c++20 c++-modules


    【解决方案1】:

    截至this commit,Clang 对Modules TS 提供了实验性支持。

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

    首先,定义模块接口文件。默认情况下,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; 而不仅仅是 VS 博文中的 module M;

    然后按如下方式消费模块:

    // 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 build(2017 年 5 月 15 日)在 Windows 上测试了这些命令。

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

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

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

    【讨论】:

    • 使用这些命令我得到:clang++ -fmodules-ts -fmodule-file=M.pcm bar.cpp Undefined symbols for architecture x86_64: "f(int)", referenced from: _main in bar-1b6ad3.o "g(double, int)", referenced from: _main in bar-1b6ad3.o ld: symbol(s) not found for architecture x86_64 with:` clang++ --version Apple LLVM 版本 9.1.0 (clang-902.0.39.1) 目标:x86_64-apple-darwin17.4.0 线程模型:posix安装目录:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin`
    • 编辑:这个答案缺少的是一个额外的编译步骤clang++ -fmodules-ts -c M.pcm -o M.o,然后将 M.o 添加到此处提到的最终编译步骤:stackoverflow.com/questions/48596805/…;我确定了答案
    • 可以导入iostream吗?
    【解决方案2】:

    就像你提到的,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 的详细描述。

    【讨论】:

    • 看起来你的小示例项目已经消失了。有机会更新这个答案吗?
    • 在过去 5 年中,模块和实现发生了很大变化。 Smi 的回答更好地反映了当前状态,也许@xjcl 可以将接受的答案更改为那个。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-05
    • 2012-01-11
    • 1970-01-01
    相关资源
    最近更新 更多