From 21b9fb1e8c7348ac4493f4fc245a3c5c5828d2d3 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 31 Aug 2022 11:53:05 -0400 Subject: cmCxxModuleMapper: support the `clang` module map format --- Help/dev/experimental.rst | 9 ++++-- Source/cmCxxModuleMapper.cxx | 36 ++++++++++++++++++++++ Source/cmCxxModuleMapper.h | 1 + Source/cmGlobalNinjaGenerator.cxx | 2 ++ .../CXXModules/examples/cxx-modules-find-bmi.cmake | 2 +- 5 files changed, 46 insertions(+), 4 deletions(-) diff --git a/Help/dev/experimental.rst b/Help/dev/experimental.rst index 03eb076..83e3c11 100644 --- a/Help/dev/experimental.rst +++ b/Help/dev/experimental.rst @@ -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=") -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 diff --git a/Source/cmCxxModuleMapper.cxx b/Source/cmCxxModuleMapper.cxx index 84691c9..ca4ffdf 100644 --- a/Source/cmCxxModuleMapper.cxx +++ b/Source/cmCxxModuleMapper.cxx @@ -28,6 +28,38 @@ cm::optional 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: diff --git a/Source/cmCxxModuleMapper.h b/Source/cmCxxModuleMapper.h index 8526a07..9271978 100644 --- a/Source/cmCxxModuleMapper.h +++ b/Source/cmCxxModuleMapper.h @@ -17,6 +17,7 @@ enum class CxxModuleMapFormat { + Clang, Gcc, Msvc, }; diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 4500f33..f7753da 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -2567,6 +2567,8 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( cm::optional 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") { diff --git a/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi.cmake b/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi.cmake index 91f3995..88d50db 100644 --- a/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi.cmake +++ b/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi.cmake @@ -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 () -- cgit v0.12