有没有办法用gcc查询直接的模块依赖关系?

wmvff8tz  于 12个月前  发布在  其他
关注(0)|答案(3)|浏览(178)

给定一个模块

// a-m.cc
export module A;

import B;
import C;

import "D.h";

...

字符串
是否有一种方法可以调用gcc(类似于-M对头文件所做的),它将列出对其他模块和导入的头文件(即B、C和“D. h”)的直接依赖关系?

ulydmbyx

ulydmbyx1#

[修改]

看起来我们可以用标志-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
它还未完成,但实际上正在工作。如果有兴趣,我将继续扩大它。
我也有一个带有模块的小示例项目包,作为进一步研究的起点:

GCC

GCC在本地目录中查找预编译模块(BMI):./gcm.cache/usr/include/c++/11/iostream.gcm或(对于本地模块单元)./gcm.cache/,/my-module.gcm
如果用户代码导入了一个模块,那么预编译的模块单元 * 必须 * 已经存在于这个目录中,否则编译将失败。(至少目前)不可能指定另一个目录,或每个构建命令的自定义目录。这将是非常实用的,我希望GCC开发人员会在某个时候添加它。gcm.cache/目录被默认的模块Map器使用。可以创建自己的模块Map器,但从我所做的阅读来看,这听起来像是一个复杂的过程,因为模块Map器本质上是一个Web服务器:

对比

与@Laserskjöld的答案相比,我认为收集预处理器输出也是一个可行的解决方案,因为模块导入/导出命令是由预处理器识别的。然而,我不认为这是一个 * 好 * 的解决方案,因为它比我写的工具慢得多。举个例子:

module;

#include <iostream>

export module mymodule;

import myothermodule;

export
{
    [...]
}


经过预处理后,这个文件将有大约100000行,所有的行都需要由预处理器处理。但是使用我的工具(或者一个可能更有效的工具),只有前9行会被模块解析工具读取,文件的其余部分将被忽略。此外,使用模块的目的是减少对预处理器的依赖。

rqqzpn5f

rqqzpn5f2#

GCC 14支持使用-fdeps-file=$depoutput -fdeps-format=p1689r5标志的P1689R5输出。示例:

export module c;
import b;

export int c()
{
  return b();
}

个字符
将生成:

{
"rules": [
{
"primary-output": "c.cxx.o",
"provides": [
{
"logical-name": "c",
"is-interface": true
}
],
"requires": [
{
"logical-name": "b"
}
]
}
],
"version": 0,
"revision": 0
}

eoxn13cs

eoxn13cs3#

我不知道gcc有什么方法可以做到这一点,但我建议编写一个帮助脚本,扩展文件并查找所有名为import的内容,然后您可能需要使用"<对导入进行排序,并将它们作为头文件输出。
然后你需要找到哪些文件导出了所选的模块,以匹配你的导入。也就是说,你需要遍历扩展的文件,并找到以export module开头的语句。
您可以使用

g++ -E {include flags, standard version etc} > tmpfile

字符串
-E也可以和clang++一起工作,但是对于msvc,你需要/E
如果有一种直接的方法可以用gcc来做这件事,我也很想知道,但问题随之而来:gcc如何知道在哪里寻找模块?
相反,如果你有一个构建系统来跟踪每个模块的位置,你可以像编译命令一样指定它。(用clang你可以用-fmodule-file=指定它,我想这和gcc是一样的,但没有测试过)。至少我在my build system中是这样做的。
但总结一下我对你问题的回答。我认为你需要:

  • 扩展您的源文件
  • 找到所有包含importexport importexport module的文件并处理它们。

相关问题