Issue
Given a module
// a-m.cc
export module A;
import B;
import C;
import "D.h";
...
Is there a way of invoking gcc (similar to what -M does for headers) that will list the direct dependencies on other modules and imported headers (i.e. B, C, and "D.h")?
Solution
[Edit]
It seems we can invoke gcc with the flag -MMD
, which also tracks module dependencies. Given an example project I have, I generated it like this:
// partition.cpp
export module partition;
import :partition1;
export import :partition2;
export import :partition3;
export void Hello1() { _Hello1(); }
For some reason I needed to compile the module partitions before compiling the primary module interface (file shown above), but perhaps this can somehow be circumvented. I compile the above file like this:
g++-11 -std=c++20 -fmodules-ts -c -MMD partition.cpp
This generates a file partition.d
listing module dependencies:
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
Seems promising, but more research is needed.
My own solution
I have written / am writing such a tool. It can be found on github: https://github.com/alexpanter/cpp_module_parser.
It is unfinished, but is actually working. If interest is shown, I will continue expanding it.
I also have a bundle of small example projects with modules, intended as a starting point for further research: https://github.com/alexpanter/modules_testing
GCC
GCC looks for precompiled modules (BMI's) in a local directory: ./gcm.cache/usr/include/c++/11/iostream.gcm
or (for local module units) ./gcm.cache/,/my-module.gcm
.
If user code imports a module, the the precompiled module unit must be already present in this directory, otherwise compilation will fail.
It is, unfortunately (at least currently) not possible to specify another directory, or a custom directory per build command. This would be very practical, and I'm hoping the GCC devs will add it at some point. The gcm.cache/
directory is used by the default module mapper. It is possible to create one's own module mapper, but from the reading I have done this sounds like a complicated procedure since a module mapper is essentially a web server:
- 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
Comparison
Comparing to @Laserskjöld's answer, I think collecting preprocessor output would be a viable solution as well, since module import/export commands are recognized by the preprocessor. However, I do not think it is a good solution since it would be much slower than a tool such as what I have written. An example:
module;
#include <iostream>
export module mymodule;
import myothermodule;
export
{
[...]
}
After preprocessing, this file will be ~100000 lines long, and all lines need to be processed by the preprocessor. But with my tool (or one that is potentially more efficient), only the first 9 lines will be read by the module-parsing tool, rest of the file will be ignored. Besides, the point of having modules is to be less dependent upon the preprocessor.
Answered By - alexpanter Answer Checked By - Gilberto Lyons (WPSolving Admin)