首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >g++ 11.2.0无法读取已编译的模块:文件数据错误

g++ 11.2.0无法读取已编译的模块:文件数据错误
EN

Stack Overflow用户
提问于 2021-09-27 12:09:52
回答 3查看 433关注 0票数 0

我为系统头逐个创建了预编译头。

代码语言:javascript
复制
$ g++ -fmodules-ts -std=c++20 -x c++-system-header concepts
$ g++ -fmodules-ts -std=c++20 -x c++-system-header limits
$ g++ -fmodules-ts -std=c++20 -x c++-system-header iostream

我将所需的系统标头收集到反向中。

代码语言:javascript
复制
$ cat Reverse
import <concepts>;
import <limits>;
import <iostream>;

$  g++ -fmodules-ts -std=c++20 -x c++-header Reverse

$ ls gcm.cache/,
Reverse.gcm

我尝试导入模块头

代码语言:javascript
复制
$ head Reverse.cpp
import <Reverse>;

$ make
g++ -fmodules-ts -std=c++20 -I./  -o Reverseexec Reverse.cpp
In module imported at Reverse.cpp:4:1:
./Reverse: error: failed to read compiled module: Bad file data
./Reverse: note: compiled module file is ‘gcm.cache/,/Reverse.gcm’
./Reverse: fatal error: returning to the gate for a mechanical issue
compilation terminated.
make: *** [Makefile:2: Reverseexec] Error 1

我在Reverse.cpp中更改了导入,它就会编译

代码语言:javascript
复制
$ head Reverse.cpp
import <concepts>;
import <limits>;
import <iostream>;

$ make
g++ -fmodules-ts -std=c++20 -o Reverse Reverse.cpp

我发现了一个相关的bug。

错误c++/98944无法读取带有未导出分区的已编译模块。

代码语言:javascript
复制
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-cygwin/11/lto-wrapper.exe
Target: x86_64-pc-cygwin
Configured with: /mnt/share/cygpkgs/gcc/gcc.x86_64/src/gcc- 
11.2.0/configure --srcdir=/mnt/share/cygpkgs/gcc/gcc.x86_64/src/gcc-11.2.0 
--prefix=/usr --exec-prefix=/usr --localstatedir=/var --sysconfdir=/etc -- 
docdir=/usr/share/doc/gcc --htmldir=/usr/share/doc/gcc/html -C -- 
build=x86_64-pc-cygwin --host=x86_64-pc-cygwin --target=x86_64-pc-cygwin - 
-without-libiconv-prefix --without-libintl-prefix --libexecdir=/usr/lib -- 
with-gcc-major-version-only --enable-shared --enable-shared-libgcc -- 
enable-static --enable-version-specific-runtime-libs --enable-bootstrap -- 
enable-__cxa_atexit --with-dwarf2 --with-tune=generic --disable-bootstrap 
--enable-languages=c,c++,fortran,lto,objc,obj-c++,jit --enable-graphite -- 
enable-threads=posix --enable-libatomic --enable-libgomp --enable- 
libquadmath --enable-libquadmath-support --disable-libssp --enable-libada 
--disable-symvers --with-gnu-ld --with-gnu-as --with-cloog- 
include=/usr/include/cloog-isl --without-libiconv-prefix --without- 
libintl-prefix --with-system-zlib --enable-linker-build-id --with-default- 
libstdcxx-abi=gcc4-compatible --enable-libstdcxx-filesystem-ts
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 11.2.0 (GCC)

我做错了什么?为什么我会得到这个错误,

代码语言:javascript
复制
g++ -fmodules-ts -std=c++20 -I./  -o Reverseexec Reverse.cpp
In module imported at Reverse.cpp:4:1:
./Reverse: error: failed to read compiled module: Bad file data
./Reverse: note: compiled module file is ‘gcm.cache/,/Reverse.gcm’
./Reverse: fatal error: returning to the gate for a mechanical issue
compilation terminated.
make: *** [Makefile:2: Reverseexec] Error 1
EN

回答 3

Stack Overflow用户

发布于 2021-09-29 11:46:31

我假设您正在尝试将几个标准标头收集到一个可导入的实体中。(我一开始并没有意识到这一点,并认为您面临的是一个bug)。

为什么不创建一个合适的模块而不是头单元呢?

这是我尝试过的方法。首先,按照您所做的那样编译头单元:

代码语言:javascript
复制
$ g++ -fmodules-ts -std=c++20 -x c++-system-header concepts
$ g++ -fmodules-ts -std=c++20 -x c++-system-header limits
$ g++ -fmodules-ts -std=c++20 -x c++-system-header iostream

然后,创建一个导出所有头部的模块:

代码语言:javascript
复制
export module Reverse;

export import <concepts>;
export import <limits>;
export import <iostream>;

并编译它:

代码语言:javascript
复制
$ g++ -fmodules-ts -std=c++20 -c Reverse.cpp

最后在一个程序(Program.cpp)中使用它:

代码语言:javascript
复制
import Reverse;

int main()
{
  static_assert(std::integral<decltype(std::numeric_limits<int>::max())>);
  std::cout << "Hello world\n";
  return 0;
}

编译时使用:

代码语言:javascript
复制
$  g++ -fmodules-ts -std=c++20 Program.cpp Reverse.o -o foo

它可以为我编译并正确运行。

我在linux-gnu x86_64下使用了GCC 11.2版进行了测试。

票数 0
EN

Stack Overflow用户

发布于 2021-09-29 19:03:00

这适用于捆绑预编译系统头文件的特殊情况。如果你需要做一些实质性的事情呢?例如,

代码语言:javascript
复制
$ cat Reverse.cpp
export module Reverse;

export import <concepts>;
export import <limits>;
export import <iostream>;

namespace Reverse {
    constexpr int TEST = { 1 };
}

$ cat main.cpp
import Reverse;

int
main(int, char **)
{
    std::cout << Reverse::TEST << std::endl;
    return 0;
}

$ g++ -fmodules-ts -std=c++20 main.cpp Reverse.o -o main
    main.cpp: In function ‘int main(int, char**)’:
    main.cpp:6:22: error: ‘Reverse’ has not been declared
    6 |         std::cout << Reverse::TEST << std::endl;
      |                      ^~~~~~~

谢谢你的帮助。

我担心的另一个问题是,让实验模块工作的神奇方法强烈依赖于平台。这将降低跨平台兼容性,并可能需要从构建系统进行更多的工作。我知道模块是为了简化事情,但是在VS和g++上使用导入的不同方法可能不容易实现跨平台兼容性。这对我来说是一种耻辱。

票数 0
EN

Stack Overflow用户

发布于 2021-09-29 21:28:08

我让它或多或少地发挥了作用。我很惊讶,我仍然需要声明内联的所有东西,我认为constexpr和consteval修饰符将消除内联的需要。

为了让事情更简单,创建了Makefile,

代码语言:javascript
复制
.PHONY: default
default: main ;

gcmcache:
        g++ -fmodules-ts -std=c++20 -x c++-system-header iostream

hello.o: hello.cpp
        g++ -c -std=c++20 -fmodules-ts hello.cpp

main: main.cpp hello.o
        g++ -fmodules-ts -std=c++20 -o main main.cpp hello.o

clean:
        rm hello.o main.exe rm -rf gcm.cache

带着它去跑步,

代码语言:javascript
复制
$ make clean gcmcache main
rm hello.o main.exe rm -rf gcm.cache
g++ -fmodules-ts -std=c++20 -x c++-system-header iostream
g++ -c -std=c++20 -fmodules-ts hello.cpp
g++ -fmodules-ts -std=c++20 -o main main.cpp hello.o

$ cat hello.cpp
module;

export import <iostream>;

export module hello;

namespace hello {

        export inline constexpr const int TEST = { 1 };

        export inline consteval int foo( const int testing = TEST )
        {
                return testing;
        }
}

$ cat main.cpp
import hello;

int main ( int, char** )
{
        std::cout << hello::TEST << std::endl;
        std::cout << hello::foo( hello::TEST ) << std::endl;
        return 0;
}

除了看似多余的内联之外,所有这些似乎都能正常工作。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69346372

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档