Description
Consider these two translation units:
// hello.mxx
module;
#include <string>
#include <string_view>
export module hello;
export namespace hello
{
std::string
say_hello (const std::string_view& name)
{
return "Hello, " + std::string (name) + '!';
}
}
// main.cxx
#include <string_view>
import hello;
void f (const std::string_view&) {}
int
main ()
{
hello::say_hello ("World");
}
If I compile hello.mxx
with Clang 16, then remove hello.mxx
, and attempt to compile main.cxx
, I get an error:
clang++-16 -std=c++2b -fmodule-output=hello.pcm -o hello.pcm.o -c -x c++-module hello.mxx
mv hello.mxx hello.mxx.bak
clang++-16 -std=c++2b -fmodule-file=hello=hello.pcm -o main.o -c -x c++ main.cxx
main.cxx:5:1: fatal error: malformed or corrupted AST file: 'could not find file '/tmp/hello-simple/hello.mxx' referenced by AST file 'hello.pcm''
This can be fixed by adding -Xclang -fmodules-embed-all-files
when compiling hello.mxx
.
However, -fmodules-embed-all-files
appears to no longer be necessary for this example if using Clang 17 or later:
clang++-17 -std=c++2b -fmodule-output=hello.pcm -o hello.pcm.o -c -x c++-module hello.mxx
mv hello.mxx hello.mxx.bak
clang++-17 -std=c++2b -fmodule-file=hello=hello.pcm -o hello.o -c -x c++ main.cxx
# no error
But a minor change in main.cxx
can bring its requirement back if compiling via -frewrite-includes
:
// main.cxx
#include <string_view>
import hello;
void f (const std::string_view&) {}
int
main ()
{
f (hello::say_hello ("World")); // <-- NOW CALLING f().
}
clang++-17 -std=c++2b -fmodule-output=hello.pcm -o hello.pcm.o -c -x c++-module hello.mxx
mv hello.mxx hello.mxx.bak
clang++-17 -std=c++2b -fmodule-file=hello=hello.pcm -o hello.o -c -x c++ main.cxx
# no error
But:
clang++-17 -std=c++2b -x c++-module -E -frewrite-includes -o hello.ii hello.mxx
clang++-17 -std=c++2b -fmodule-output=hello.pcm -o hello.pcm.o -c -x c++-module hello.ii
rm hello.ii
clang++-17 -std=c++2b -fmodule-file=hello=hello.pcm -o hello.o -c -x c++ main.cxx
fatal error: cannot open file '/tmp/hello-simple1/hello.ii': No such file or directory
And if I add -Xclang -fmodules-embed-all-files
to the second command, then everything again compiles fine. I get exactly the same behavior with Clang 18.
I have two questions about this:
-
Is
-fmodules-embed-all-files
the default starting from Clang 17? If the answer is yes, then there seems to be a bug in the-fdirectives-only
interaction. -
If
-fmodules-embed-all-files
is not the default, then should it not be made so? A BMI that still has references to source files is quite brittle since it can be moved around. AFAIK, neither GCC nor MSVC have this restriction for their BMIs.