给定一个模块
// a-m.cc export module A; import B; import C; import "D.h"; ...
字符串是否有一种方法可以调用gcc(类似于-M对头文件所做的),它将列出对其他模块和导入的头文件(即B、C和“D. h”)的直接依赖关系?
ulydmbyx1#
看起来我们可以用标志-MMD调用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.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在本地目录中查找预编译模块(BMI):./gcm.cache/usr/include/c++/11/iostream.gcm或(对于本地模块单元)./gcm.cache/,/my-module.gcm。如果用户代码导入了一个模块,那么预编译的模块单元 * 必须 * 已经存在于这个目录中,否则编译将失败。(至少目前)不可能指定另一个目录,或每个构建命令的自定义目录。这将是非常实用的,我希望GCC开发人员会在某个时候添加它。gcm.cache/目录被默认的模块Map器使用。可以创建自己的模块Map器,但从我所做的阅读来看,这听起来像是一个复杂的过程,因为模块Map器本质上是一个Web服务器:
./gcm.cache/usr/include/c++/11/iostream.gcm
./gcm.cache/,/my-module.gcm
gcm.cache/
与@Laserskjöld的答案相比,我认为收集预处理器输出也是一个可行的解决方案,因为模块导入/导出命令是由预处理器识别的。然而,我不认为这是一个 * 好 * 的解决方案,因为它比我写的工具慢得多。举个例子:
module; #include <iostream> export module mymodule; import myothermodule; export { [...] }
型经过预处理后,这个文件将有大约100000行,所有的行都需要由预处理器处理。但是使用我的工具(或者一个可能更有效的工具),只有前9行会被模块解析工具读取,文件的其余部分将被忽略。此外,使用模块的目的是减少对预处理器的依赖。
rqqzpn5f2#
GCC 14支持使用-fdeps-file=$depoutput -fdeps-format=p1689r5标志的P1689R5输出。示例:
-fdeps-file=$depoutput -fdeps-format=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 }
型
eoxn13cs3#
我不知道gcc有什么方法可以做到这一点,但我建议编写一个帮助脚本,扩展文件并查找所有名为import的内容,然后您可能需要使用"和<对导入进行排序,并将它们作为头文件输出。然后你需要找到哪些文件导出了所选的模块,以匹配你的导入。也就是说,你需要遍历扩展的文件,并找到以export module开头的语句。您可以使用
import
"
<
export module
g++ -E {include flags, standard version etc} > tmpfile
字符串-E也可以和clang++一起工作,但是对于msvc,你需要/E如果有一种直接的方法可以用gcc来做这件事,我也很想知道,但问题随之而来:gcc如何知道在哪里寻找模块?相反,如果你有一个构建系统来跟踪每个模块的位置,你可以像编译命令一样指定它。(用clang你可以用-fmodule-file=指定它,我想这和gcc是一样的,但没有测试过)。至少我在my build system中是这样做的。但总结一下我对你问题的回答。我认为你需要:
-E
/E
-fmodule-file=
export import
3条答案
按热度按时间ulydmbyx1#
[修改]
看起来我们可以用标志
-MMD
调用gcc,它也跟踪模块依赖关系。给出我的一个示例项目,我像这样生成它:字符串
出于某种原因,我需要在编译主模块接口(上面显示的文件)之前编译模块分区,但也许这可以以某种方式绕过。我编译上面的文件如下:
型
这将生成一个文件
partition.d
,列出模块依赖项:型
看起来很有希望,但还需要更多的研究。
我自己的解决方案
我已经写了/正在写这样一个工具。它可以在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的答案相比,我认为收集预处理器输出也是一个可行的解决方案,因为模块导入/导出命令是由预处理器识别的。然而,我不认为这是一个 * 好 * 的解决方案,因为它比我写的工具慢得多。举个例子:
型
经过预处理后,这个文件将有大约100000行,所有的行都需要由预处理器处理。但是使用我的工具(或者一个可能更有效的工具),只有前9行会被模块解析工具读取,文件的其余部分将被忽略。此外,使用模块的目的是减少对预处理器的依赖。
rqqzpn5f2#
GCC 14支持使用
-fdeps-file=$depoutput -fdeps-format=p1689r5
标志的P1689R5输出。示例:个字符
将生成:
型
eoxn13cs3#
我不知道gcc有什么方法可以做到这一点,但我建议编写一个帮助脚本,扩展文件并查找所有名为
import
的内容,然后您可能需要使用"
和<
对导入进行排序,并将它们作为头文件输出。然后你需要找到哪些文件导出了所选的模块,以匹配你的导入。也就是说,你需要遍历扩展的文件,并找到以
export module
开头的语句。您可以使用
字符串
-E
也可以和clang++一起工作,但是对于msvc,你需要/E
如果有一种直接的方法可以用gcc来做这件事,我也很想知道,但问题随之而来:gcc如何知道在哪里寻找模块?
相反,如果你有一个构建系统来跟踪每个模块的位置,你可以像编译命令一样指定它。(用clang你可以用
-fmodule-file=
指定它,我想这和gcc是一样的,但没有测试过)。至少我在my build system中是这样做的。但总结一下我对你问题的回答。我认为你需要:
import
、export import
和export module
的文件并处理它们。