cmCxxModuleMapper: support the clang module map format

This commit is contained in:
Ben Boeckel 2022-08-31 11:53:05 -04:00
parent 9c66224668
commit 21b9fb1e8c
5 changed files with 46 additions and 4 deletions

View File

@ -77,9 +77,9 @@ For compilers that generate module maps, tell CMake as follows:
set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG
"${compiler_flags_for_module_map} -fmodule-mapper=<MODULE_MAP_FILE>")
Currently, the only supported formats are ``gcc`` and ``msvc``. The ``gcc``
format is described in the GCC documentation, but the relevant section for the
purposes of CMake is:
Currently, the only supported formats are, ``clang``, ``gcc``, and ``msvc``.
The ``gcc`` format is described in the GCC documentation, but the relevant
section for the purposes of CMake is:
A mapping file consisting of space-separated module-name, filename
pairs, one per line. Only the mappings for the direct imports and any
@ -94,6 +94,9 @@ The ``msvc`` format is a response file containing flags required to compile
any module interfaces properly as well as find any required files to satisfy
``import`` statements as required for Microsoft's Visual Studio toolchains.
Similarly, the ``clang`` format is a response file containing flags using
Clang's module flags.
.. _`D1483r1`: https://mathstuf.fedorapeople.org/fortran-modules/fortran-modules.html
.. _`P1689r5`: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1689r5.html
.. _`cxx-modules-sandbox`: https://github.com/mathstuf/cxx-modules-sandbox

View File

@ -28,6 +28,38 @@ cm::optional<std::string> CxxModuleLocations::BmiGeneratorPathForModule(
namespace {
std::string CxxModuleMapContentClang(CxxModuleLocations const& loc,
cmScanDepInfo const& obj)
{
std::stringstream mm;
// Clang's command line only supports a single output. If more than one is
// expected, we cannot make a useful module map file.
if (obj.Provides.size() > 1) {
return {};
}
// A series of flags which tell the compiler where to look for modules.
for (auto const& p : obj.Provides) {
if (auto bmi_loc = loc.BmiGeneratorPathForModule(p.LogicalName)) {
// Force the TU to be considered a C++ module source file regardless of
// extension.
mm << "-x c++-module\n";
mm << "-fsave-std-c++-module-file=" << *bmi_loc << '\n';
break;
}
}
for (auto const& r : obj.Requires) {
if (auto bmi_loc = loc.BmiGeneratorPathForModule(r.LogicalName)) {
mm << "-fmodule-file=" << *bmi_loc << '\n';
}
}
return mm.str();
}
std::string CxxModuleMapContentGcc(CxxModuleLocations const& loc,
cmScanDepInfo const& obj)
{
@ -179,6 +211,8 @@ cm::static_string_view CxxModuleMapExtension(
{
if (format) {
switch (*format) {
case CxxModuleMapFormat::Clang:
return ".pcm"_s;
case CxxModuleMapFormat::Gcc:
return ".gcm"_s;
case CxxModuleMapFormat::Msvc:
@ -297,6 +331,8 @@ std::string CxxModuleMapContent(CxxModuleMapFormat format,
CxxModuleUsage const& usages)
{
switch (format) {
case CxxModuleMapFormat::Clang:
return CxxModuleMapContentClang(loc, obj);
case CxxModuleMapFormat::Gcc:
return CxxModuleMapContentGcc(loc, obj);
case CxxModuleMapFormat::Msvc:

View File

@ -17,6 +17,7 @@
enum class CxxModuleMapFormat
{
Clang,
Gcc,
Msvc,
};

View File

@ -2567,6 +2567,8 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
cm::optional<CxxModuleMapFormat> modmap_fmt;
if (arg_modmapfmt.empty()) {
// nothing to do.
} else if (arg_modmapfmt == "clang") {
modmap_fmt = CxxModuleMapFormat::Clang;
} else if (arg_modmapfmt == "gcc") {
modmap_fmt = CxxModuleMapFormat::Gcc;
} else if (arg_modmapfmt == "msvc") {

View File

@ -1,6 +1,6 @@
function (check_for_bmi prefix destination name)
set(found 0)
foreach (ext IN ITEMS gcm ifc)
foreach (ext IN ITEMS gcm ifc pcm)
if (EXISTS "${prefix}/${destination}/${name}.${ext}")
set(found 1)
break ()