[Edit]
看来我们可以用标志调用 gcc-MMD
,它还跟踪模块依赖性。给定一个我拥有的示例项目,我是这样生成的:
// partition.cpp
export module partition;
import :partition1;
export import :partition2;
export import :partition3;
export void Hello1() { _Hello1(); }
由于某种原因,我需要在编译主模块接口(上面显示的文件)之前编译模块分区,但也许可以以某种方式规避这一点。我这样编译上面的文件:
g++-11 -std=c++20 -fmodules-ts -c -MMD partition.cpp
这会生成一个文件partition.d
列出模块依赖项:
partition.o gcm.cache/partition.gcm: partition.cpp
partition.o gcm.cache/partition.gcm: partition:partition3.c++m \
partition:partition2.c++m partition:partition1.c++m
partition.c++m: gcm.cache/partition.gcm
.PHONY: partition.c++m
gcm.cache/partition.gcm:| partition.o
CXX_IMPORTS += partition:partition3.c++m partition:partition2.c++m \
partition:partition1.c++m
看起来很有希望,但还需要更多的研究。
我自己的解决方案
我已经编写/正在编写这样一个工具。可以在github上找到:https://github.com/alexpanter/cpp_module_parser https://github.com/alexpanter/cpp_module_parser.
它尚未完成,但实际上正在发挥作用。如果有兴趣,我会继续扩大它。
我还有一系列带有模块的小型示例项目,旨在作为进一步研究的起点:https://github.com/alexpanter/modules_testing https://github.com/alexpanter/modules_testing
GCC
GCC 在本地目录中查找预编译模块 (BMI):./gcm.cache/usr/include/c++/11/iostream.gcm
或(对于本地模块单元)./gcm.cache/,/my-module.gcm
.
如果用户代码导入模块,则预编译模块单元must已经存在于该目录中,否则编译将失败。
不幸的是(至少目前)不可能为每个构建命令指定另一个目录或自定义目录。这将非常实用,我希望 GCC 开发人员能够在某个时候添加它。这gcm.cache/
目录由默认模块映射器使用。可以创建自己的模块映射器,但从我所做的阅读来看,这听起来像是一个复杂的过程,因为模块映射器本质上是一个 Web 服务器:
- https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Module-Mapper.html https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Module-Mapper.html
- http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1184r2.pdf http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1184r2.pdf
比较
与@Laserskjöld的答案相比,我认为收集预处理器输出也是一个可行的解决方案,因为模块导入/导出命令可以被预处理器识别。然而,我不认为这是一个good解决方案,因为它比我编写的工具慢得多。一个例子:
module;
#include <iostream>
export module mymodule;
import myothermodule;
export
{
[...]
}
预处理后,该文件将有约 100000 行长,并且所有行都需要由预处理器处理。但使用我的工具(或可能更高效的工具),模块解析工具只会读取前 9 行,文件的其余部分将被忽略。
此外,拥有模块的目的是减少对预处理器的依赖。