diff options
author | Ben Boeckel <ben.boeckel@kitware.com> | 2022-07-19 20:03:32 (GMT) |
---|---|---|
committer | Ben Boeckel <ben.boeckel@kitware.com> | 2022-08-02 14:53:38 (GMT) |
commit | 297e0f4dce189183ff07cc8a79de6ae72c81974b (patch) | |
tree | a7349a45e0a1430ea57fb78d17b45baae841c291 /Source | |
parent | b3c2880cb2d5750c8a4508fa41e6552808da2bd3 (diff) | |
download | CMake-297e0f4dce189183ff07cc8a79de6ae72c81974b.zip CMake-297e0f4dce189183ff07cc8a79de6ae72c81974b.tar.gz CMake-297e0f4dce189183ff07cc8a79de6ae72c81974b.tar.bz2 |
cmCxxModuleMapper: support MSVC module map format
THis is a set of flags stored in a response file which informs the
compiler about where to place output BMI files as well as find the
required BMIs.
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmCxxModuleMapper.cxx | 83 | ||||
-rw-r--r-- | Source/cmCxxModuleMapper.h | 4 | ||||
-rw-r--r-- | Source/cmGlobalNinjaGenerator.cxx | 4 |
3 files changed, 88 insertions, 3 deletions
diff --git a/Source/cmCxxModuleMapper.cxx b/Source/cmCxxModuleMapper.cxx index b68e28c..84691c9 100644 --- a/Source/cmCxxModuleMapper.cxx +++ b/Source/cmCxxModuleMapper.cxx @@ -4,7 +4,9 @@ #include <cassert> #include <cstddef> +#include <set> #include <sstream> +#include <string> #include <utility> #include <vector> @@ -54,6 +56,80 @@ std::string CxxModuleMapContentGcc(CxxModuleLocations const& loc, return mm.str(); } + +std::string CxxModuleMapContentMsvc(CxxModuleLocations const& loc, + cmScanDepInfo const& obj, + CxxModuleUsage const& usages) +{ + std::stringstream mm; + + // A response file of `-reference NAME=PATH` arguments. + + // MSVC'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 {}; + } + + auto flag_for_method = [](LookupMethod method) -> cm::static_string_view { + switch (method) { + case LookupMethod::ByName: + return "-reference"_s; + case LookupMethod::IncludeAngle: + return "-headerUnit:angle"_s; + case LookupMethod::IncludeQuote: + return "-headerUnit:quote"_s; + } + assert(false && "unsupported lookup method"); + return ""_s; + }; + + for (auto const& p : obj.Provides) { + if (p.IsInterface) { + mm << "-interface\n"; + } else { + mm << "-internalPartition\n"; + } + + if (auto bmi_loc = loc.BmiGeneratorPathForModule(p.LogicalName)) { + mm << "-ifcOutput " << *bmi_loc << '\n'; + } + } + + std::set<std::string> transitive_usage_directs; + std::set<std::string> transitive_usage_names; + + for (auto const& r : obj.Requires) { + if (auto bmi_loc = loc.BmiGeneratorPathForModule(r.LogicalName)) { + auto flag = flag_for_method(r.Method); + + mm << flag << ' ' << r.LogicalName << '=' << *bmi_loc << "\n"; + transitive_usage_directs.insert(r.LogicalName); + + // Insert transitive usages. + auto transitive_usages = usages.Usage.find(r.LogicalName); + if (transitive_usages != usages.Usage.end()) { + transitive_usage_names.insert(transitive_usages->second.begin(), + transitive_usages->second.end()); + } + } + } + + for (auto const& transitive_name : transitive_usage_names) { + if (transitive_usage_directs.count(transitive_name)) { + continue; + } + + auto module_ref = usages.Reference.find(transitive_name); + if (module_ref != usages.Reference.end()) { + auto flag = flag_for_method(module_ref->second.Method); + mm << flag << ' ' << transitive_name << '=' << module_ref->second.Path + << "\n"; + } + } + + return mm.str(); +} } bool CxxModuleUsage::AddReference(std::string const& logical, @@ -105,6 +181,8 @@ cm::static_string_view CxxModuleMapExtension( switch (*format) { case CxxModuleMapFormat::Gcc: return ".gcm"_s; + case CxxModuleMapFormat::Msvc: + return ".ifc"_s; } } @@ -215,11 +293,14 @@ std::set<std::string> CxxModuleUsageSeed( std::string CxxModuleMapContent(CxxModuleMapFormat format, CxxModuleLocations const& loc, - cmScanDepInfo const& obj) + cmScanDepInfo const& obj, + CxxModuleUsage const& usages) { switch (format) { case CxxModuleMapFormat::Gcc: return CxxModuleMapContentGcc(loc, obj); + case CxxModuleMapFormat::Msvc: + return CxxModuleMapContentMsvc(loc, obj, usages); } assert(false); diff --git a/Source/cmCxxModuleMapper.h b/Source/cmCxxModuleMapper.h index 6d29fc0..8526a07 100644 --- a/Source/cmCxxModuleMapper.h +++ b/Source/cmCxxModuleMapper.h @@ -18,6 +18,7 @@ enum class CxxModuleMapFormat { Gcc, + Msvc, }; struct CxxModuleLocations @@ -80,4 +81,5 @@ std::set<std::string> CxxModuleUsageSeed( // object file. std::string CxxModuleMapContent(CxxModuleMapFormat format, CxxModuleLocations const& loc, - cmScanDepInfo const& obj); + cmScanDepInfo const& obj, + CxxModuleUsage const& usages); diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index f69c95f..c326ca6 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -2625,6 +2625,8 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( // nothing to do. } else if (arg_modmapfmt == "gcc") { modmap_fmt = CxxModuleMapFormat::Gcc; + } else if (arg_modmapfmt == "msvc") { + modmap_fmt = CxxModuleMapFormat::Msvc; } else { cmSystemTools::Error( cmStrCat("-E cmake_ninja_dyndep does not understand the ", arg_modmapfmt, @@ -2712,7 +2714,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( } if (modmap_fmt) { - auto mm = CxxModuleMapContent(*modmap_fmt, locs, object); + auto mm = CxxModuleMapContent(*modmap_fmt, locs, object, usages); // XXX(modmap): If changing this path construction, change // `cmNinjaTargetGenerator::WriteObjectBuildStatements` to generate the |