给定一个模块
// a-m.cc
export module A;
import B;
import C;
import "D.h";
...
是否有一种调用gcc的方式(类似于对头文件执行的-M操作),可以列出其他模块和导入头文件的直接依赖关系(即B、C和“D.h”)?
给定一个模块
// a-m.cc
export module A;
import B;
import C;
import "D.h";
...
是否有一种调用gcc的方式(类似于对头文件执行的-M操作),可以列出其他模块和导入头文件的直接依赖关系(即B、C和“D.h”)?
看起来我们可以使用标志-MMD
调用gcc,它也可以跟踪模块依赖关系。以我拥有的一个示例项目为例,我是这样生成它的:
// 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/modules_testing
GCC在本地目录中查找预编译的模块(BMI):./gcm.cache/usr/include/c++/11/iostream.gcm
或者(对于本地模块单元)./gcm.cache/,/my-module.gcm
。
gcm.cache/
目录由默认模块映射器使用。可以创建自己的模块映射器,但从我所读的内容来看,这听起来像是一个复杂的过程,因为模块映射器本质上是一个Web服务器:
与@Laserskjöld的答案相比,我认为收集预处理器输出也是一种可行的解决方案,因为模块导入/导出命令可以被预处理器识别。但是,我认为这不是一个好的解决方案,因为它比我编写的工具慢得多。例如:
module;
#include <iostream>
export module mymodule;
import myothermodule;
export
{
[...]
}
预处理后,该文件将有大约100000行,并且所有行都需要由预处理器处理。但是使用我的工具(或者一个潜在更有效的工具),模块解析工具只会读取前9行,文件的其余部分将被忽略。 此外,拥有模块的目的是减少对于预处理器的依赖。
-fdeps-file=$depoutput -fdeps-format=p1689r5
标志输出 P1689R5。示例:export module c;
import b;
export int c()
{
return b();
}
$ g++ -E -fmodules-ts -MD -MF c.cxx.d -fdeps-file=/dev/stdout -fdeps-format=p1689r5 -fdeps-target=c.cxx.o c.cxx -o c.cxx.pp
{
"rules": [
{
"primary-output": "c.cxx.o",
"provides": [
{
"logical-name": "c",
"is-interface": true
}
],
"requires": [
{
"logical-name": "b"
}
]
}
],
"version": 0,
"revision": 0
}
我不知道gcc有任何方法可以做到这一点,但我建议编写一个帮助脚本来扩展文件并查找所有名为import
的内容,然后您可能需要使用"
和<
来对导入进行排序,并将其输出为头文件。
然后,您需要找到将所选模块导出到与您的导入匹配的文件。也就是说,您需要浏览扩展文件并查找以export module
开头的语句。
您可以使用以下方式扩展文件:
g++ -E {include flags, standard version etc} > tmpfile
-E
在 clang++ 中同样适用,但对于 msvc,你需要使用 /E
如果有直接在 gcc 中完成这个的方法,我也很感兴趣,但是问题就出现了:gcc 如何知道在哪里查找模块?
相反,如果您有一个构建系统来跟踪每个模块的位置,您可以像编译命令那样指定它。 (使用 clang,您可以使用-fmodule-file=
指定,我认为在 gcc 中也是一样,但没有测试过)。至少这就是我在我的构建系统中完成的方式。
但是总结一下,回答您的问题。
import
、export import
和 export module
的文件并进行处理。
-fmodule-mapper
来指定额外的导入目录。在较大规模上进行逐文件管理似乎有点棘手... - alexpanter