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.
@iains @ChuanqiXu9 @dwblaikie
Consider these two translation units:
If I compile
hello.mxxwith Clang 16, then removehello.mxx, and attempt to compilemain.cxx, I get an error:This can be fixed by adding
-Xclang -fmodules-embed-all-fileswhen compilinghello.mxx.However,
-fmodules-embed-all-filesappears to no longer be necessary for this example if using Clang 17 or later:But a minor change in
main.cxxcan bring its requirement back if compiling via-frewrite-includes:But:
And if I add
-Xclang -fmodules-embed-all-filesto 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-filesthe default starting from Clang 17? If the answer is yes, then there seems to be a bug in the-fdirectives-onlyinteraction.If
-fmodules-embed-all-filesis 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.@iains @ChuanqiXu9 @dwblaikie