summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Source/cmCxxModuleMapper.cxx83
-rw-r--r--Source/cmCxxModuleMapper.h4
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx4
3 files changed, 88 insertions, 3 deletions
diff --git a/Source/cmCxxModuleMapper.cxx b/Source/cmCxxModuleMapper.cxx
index b68e28cea1..84691c9fc7 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 6d29fc060e..8526a07506 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 f69c95f020..c326ca6101 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