我为系统头逐个创建了预编译头。
$ 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
我将所需的系统标头收集到反向中。
$ cat Reverse
import <concepts>;
import <limits>;
import <iostream>;
$ g++ -fmodules-ts -std=c++20 -x c++-header Reverse
$ ls gcm.cache/,
Reverse.gcm
我尝试导入模块头
$ 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中更改了导入,它就会编译
$ head Reverse.cpp
import <concepts>;
import <limits>;
import <iostream>;
$ make
g++ -fmodules-ts -std=c++20 -o Reverse Reverse.cpp
我发现了一个相关的bug。
错误c++/98944无法读取带有未导出分区的已编译模块。
$ 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)
我做错了什么?为什么我会得到这个错误,
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
发布于 2021-09-29 11:46:31
我假设您正在尝试将几个标准标头收集到一个可导入的实体中。(我一开始并没有意识到这一点,并认为您面临的是一个bug)。
为什么不创建一个合适的模块而不是头单元呢?
这是我尝试过的方法。首先,按照您所做的那样编译头单元:
$ 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
然后,创建一个导出所有头部的模块:
export module Reverse;
export import <concepts>;
export import <limits>;
export import <iostream>;
并编译它:
$ g++ -fmodules-ts -std=c++20 -c Reverse.cpp
最后在一个程序(Program.cpp)中使用它:
import Reverse;
int main()
{
static_assert(std::integral<decltype(std::numeric_limits<int>::max())>);
std::cout << "Hello world\n";
return 0;
}
编译时使用:
$ g++ -fmodules-ts -std=c++20 Program.cpp Reverse.o -o foo
它可以为我编译并正确运行。
我在linux-gnu x86_64下使用了GCC 11.2版进行了测试。
发布于 2021-09-29 19:03:00
这适用于捆绑预编译系统头文件的特殊情况。如果你需要做一些实质性的事情呢?例如,
$ 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++上使用导入的不同方法可能不容易实现跨平台兼容性。这对我来说是一种耻辱。
发布于 2021-09-29 21:28:08
我让它或多或少地发挥了作用。我很惊讶,我仍然需要声明内联的所有东西,我认为constexpr和consteval修饰符将消除内联的需要。
为了让事情更简单,创建了Makefile,
.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
带着它去跑步,
$ 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;
}
除了看似多余的内联之外,所有这些似乎都能正常工作。
https://stackoverflow.com/questions/69346372
复制相似问题