错误:无法读取编译模块:没有这个文件或目录。

8

我刚购买了《Beginning C++20》这本书(电子版),现在我正在尝试使用新的C++20方法编译第一个示例。

源文件内容如下:

// Ex1_01.cpp
// A Complete C++ program
import <iostream>;

int main()
{
    int answer{42};     // Defines answer with 42
    std::cout << "The answer to life, the universe, and everything is "
        << answer
        << std::endl;
    return 0;
}

如果我理解正确,GCC 10或11版本尚不支持此功能(一些网站声称GCC 11支持它,但当我像一些人建议的使用-fmodules-ts标志时,会出现错误消息表明它未实现/实验性并退出)。
经过一些搜索,我发现了一些帖子引用https://gcc.gnu.org/wiki/cxx-modules,其中有安装支持模块的GCC 10版本的说明(使用-fmodules-ts标志),但是当我在我的示例代码中使用它时,会出现以下错误:
In module imported at Ex1_01.cpp:3:1:
/usr/local/include/c++/10.0.0/iostream: error: failed to read compiled module: No such file or directory
/usr/local/include/c++/10.0.0/iostream: note: compiled module file is ‘gcm.cache/./usr/local/include/c++/10.0.0/iostream.gcm’
/usr/local/include/c++/10.0.0/iostream: fatal error: jumping off the crazy train to crashville
compilation terminated.

版本号为: g++ (GCC) 10.0.0 20200110 (experimental) [svn-280157:20201220-1704] 我在Stack Overflow上找到了一篇帖子,其中有人指向这个版本(如何使用modules-ts和gcc(实验版)编译C ++代码?) 我还尝试了维基百科上的示例(hello.cc和main.cc),但这些也会出现错误消息:
In module imported at main.cpp:1:1:
hello: error: failed to read compiled module: No such file or directory
hello: note: compiled module file is ‘gcm.cache/hello.gcm’
hello: fatal error: jumping off the crazy train to crashville
compilation terminated.

有没有办法让这个工作起来,或者我应该使用“旧的”#include方法,直到GCC 11发布稳定版本并支持模块化?据我所知,如果我构建最新的GCC 11快照,大多数其他C ++20特定的代码应该可以工作?(或者只是使用由我的发行版提供的默认(g ++(Debian 10.2.1-1)10.2.1 20201207)版本?)


3
如果你正在尝试学习有关模块的知识,那么你可能会感到困惑。如果你是初学者,想要学习一些C++知识,那么一个实用的学习方法是切换回旧的#include <iostream>语法 :) - Mansoor
3
我是一位学习C++的新手,我发现使用import <iostream>;方法相对于#include <iostream>方法被认为更好。因此,我打算开始使用这种较新/更好的方式。但现在我只能使用#include方法。感谢您的回复! - user14598891
我完全同意,但我只看到了在MSVC编译器中使用模块的工作实现。你可能需要等一段时间,直到它被实现在GCC或Clang中。 - Mansoor
3个回答

5
我想我将回答自己的问题。
当我按照GCC Wiki(https://gcc.gnu.org/wiki/cxx-modules)上的说明操作时,它是与svn上找到的版本相比更新的版本。
svn拥有gcc的第10个版本,而github则拥有第11个版本。
当我编译github版本(g++ (GCC) 11.0.0 20201217 (experimental) [c++-modules revision 20201220-2203])时,GCC Wiki提供的示例编译并正常工作。这些文件是hello.cpp:
module;
#include <iostream>
#include <string_view>
export module hello;
export void greeter (std::string_view const &name)
{
  std::cout << "Hello " << name << "!\n";
}

以及 main.cpp

import hello;
int main (void)
{
  greeter ("world");
  return 0;
}

编译命令为:g++ -fmodules-ts hello.cpp main.cpp

据我了解,源文件的顺序很重要,所以需要先编译hello.cpp,再编译main.cpp。

目前似乎只有用户自制的模块可以工作,但标准库模块(对于这些模块仍需要使用#include)尚未支持。

[编辑] 看起来,现在模块支持已经与gcc-11的主分支合并,因此不再需要通过git或svn使用开发版本(不幸的是,像 这样的标准库头文件尚未转换为模块,因此目前 import 无法使用)。


您可以使用g++ -c -fmodules-ts -x c++-system-header -std=c++20 iostream string vector命令将std_lib头文件转换为模块。 - hr0m
如何分别构建模块和使用该模块的代码? - debashish.ghosh
@debashish.ghosh - 你可能是想问“当我编写自己的模块时,如何拥有单独的接口和实现?”。答案很有趣。在接口文件中,你需要写 export module foo;,然后为每个你想要提供给其他人的名称编写导出语句。在实现文件中,你需要写 module foo;。但是,在实现文件中不能有任何导出语句。 - Omnifarious
非常感谢您的回答!它适用于CMake 3.18.4。如上面的解决方案所述,请确保在列出${SOURCES}变量时,用户定义的模块首先列出。不要忘记在您的CMakeList.txt中添加set(CMAKE_CXX_FLAGS "-fmodules-ts") ;) 再次感谢! - Lorenzo_g

1

我已经通过两个命令构建了问题中的源文件// Ex1_01.cpp

$ g++ -std=c++20 -fmodules-ts -xc++-system-header iostream
$ g++ -std=c++20 -fmodules-ts -o Ex1_01 Ex1_01.cpp

运行Ex1_01后,我得到了:

The answer to life, the universe, and everything is 42

1

对于在Linux Ubuntu 20.04上的以下代码

import <iostream>;
import <limits>;

int main()
{
    int min{ std::numeric_limits<int>::max()};
    int max{ std::numeric_limits<int>::min() };
    bool any { false };
    int x;

    while(std::cin >> x)
    {
        any = true;
        if(x < min)
            min = x;
        if(x> max)
            max = x;
    }

    if(any)
        std::cout<<"min = "<<min<<"\nmax = "<<max<<'\n';
}

我必须安装g++-11

g++-11 -std=c++20 -fmodules-ts -xc++-system-header iostream
g++-11 -std=c++20 -fmodules-ts -xc++-system-header limits
g++-11 -std=c++20 -fmodules-ts list0201.cpp -o list0201
$ ./list0201
10
20
-100 
ctrl+D

min = -100
max = 20

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接