summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Boeckel <ben.boeckel@kitware.com>2023-11-18 03:53:45 (GMT)
committerBrad King <brad.king@kitware.com>2023-11-23 19:25:09 (GMT)
commitd2fa56772f290c61925a70161c77be5f4334fd77 (patch)
treef049f8a15a723b6a7bb70a8efecfb7e1ab254cb3
parent06df59b9308d74b3f8a5eada84cf2402dd22b434 (diff)
downloadCMake-d2fa56772f290c61925a70161c77be5f4334fd77.zip
CMake-d2fa56772f290c61925a70161c77be5f4334fd77.tar.gz
CMake-d2fa56772f290c61925a70161c77be5f4334fd77.tar.bz2
Ninja: support "forwarding" modules from other targets
When a target uses objects from another target which provides modules as sources, the modules provided by the referenced target must also be treated as if they were provided by the referencing target. Add the concept of "forwarding" modules so that consumers can use modules created by these sources as well. Note that this is only sensible for Fortran where module usages are implicit as far as CMake's visibility model is concerned. C++ modules have their own concept of visibility which does not require or support such `$<TARGET_OBJECTS>` reuse in this way.
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx59
-rw-r--r--Source/cmGlobalNinjaGenerator.h1
-rw-r--r--Source/cmNinjaTargetGenerator.cxx9
-rw-r--r--Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-private.json1
-rw-r--r--Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-public.json1
-rw-r--r--Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-private.json1
-rw-r--r--Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-public.json1
-rw-r--r--Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-private.json1
-rw-r--r--Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-public.json1
9 files changed, 74 insertions, 1 deletions
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index d691d88..cba48f4 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -2527,6 +2527,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
std::string const& arg_dd, std::vector<std::string> const& arg_ddis,
std::string const& module_dir,
std::vector<std::string> const& linked_target_dirs,
+ std::vector<std::string> const& forward_modules_from_target_dirs,
std::string const& arg_lang, std::string const& arg_modmapfmt,
cmCxxModuleExportInfo const& export_info)
{
@@ -2804,6 +2805,51 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
// use by dependents that reference this target in linked-target-dirs.
std::string const target_mods_file = cmStrCat(
cmSystemTools::GetFilenamePath(arg_dd), '/', arg_lang, "Modules.json");
+
+ // Populate the module map with those provided by linked targets first.
+ for (std::string const& forward_modules_from_target_dir :
+ forward_modules_from_target_dirs) {
+ std::string const fmftn =
+ cmStrCat(forward_modules_from_target_dir, '/', arg_lang, "Modules.json");
+ Json::Value fmft;
+ cmsys::ifstream fmftf(fmftn.c_str(), std::ios::in | std::ios::binary);
+ if (!fmftf) {
+ cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to open ",
+ fmftn, " for module information"));
+ return false;
+ }
+ Json::Reader reader;
+ if (!reader.parse(fmftf, fmft, false)) {
+ cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ",
+ forward_modules_from_target_dir,
+ reader.getFormattedErrorMessages()));
+ return false;
+ }
+ if (!fmft.isObject()) {
+ continue;
+ }
+
+ auto forward_info = [](Json::Value& target, Json::Value const& source) {
+ if (!source.isObject()) {
+ return;
+ }
+
+ for (auto i = source.begin(); i != source.end(); ++i) {
+ std::string const key = i.key().asString();
+ if (target.isMember(key)) {
+ continue;
+ }
+ target[key] = *i;
+ }
+ };
+
+ // Forward info from forwarding targets into our collation.
+ Json::Value& tmi_target_modules = target_module_info["modules"];
+ forward_info(tmi_target_modules, fmft["modules"]);
+ forward_info(target_references, fmft["references"]);
+ forward_info(target_usages, fmft["usages"]);
+ }
+
cmGeneratedFileStream tmf(target_mods_file);
tmf << target_module_info;
@@ -2891,6 +2937,16 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
linked_target_dirs.push_back(tdi_linked_target_dir.asString());
}
}
+ std::vector<std::string> forward_modules_from_target_dirs;
+ Json::Value const& tdi_forward_modules_from_target_dirs =
+ tdi["forward-modules-from-target-dirs"];
+ if (tdi_forward_modules_from_target_dirs.isArray()) {
+ for (auto const& tdi_forward_modules_from_target_dir :
+ tdi_forward_modules_from_target_dirs) {
+ forward_modules_from_target_dirs.push_back(
+ tdi_forward_modules_from_target_dir.asString());
+ }
+ }
std::string const compilerId = tdi["compiler-id"].asString();
std::string const simulateId = tdi["compiler-simulate-id"].asString();
std::string const compilerFrontendVariant =
@@ -2914,7 +2970,8 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
# endif
return gg.WriteDyndepFile(dir_top_src, dir_top_bld, dir_cur_src, dir_cur_bld,
arg_dd, arg_ddis, module_dir, linked_target_dirs,
- arg_lang, arg_modmapfmt, *export_info)
+ forward_modules_from_target_dirs, arg_lang,
+ arg_modmapfmt, *export_info)
? 0
: 1;
}
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index c5d6901..220d393 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -430,6 +430,7 @@ public:
std::string const& arg_dd, std::vector<std::string> const& arg_ddis,
std::string const& module_dir,
std::vector<std::string> const& linked_target_dirs,
+ std::vector<std::string> const& forward_modules_from_target_dirs,
std::string const& arg_lang, std::string const& arg_modmapfmt,
cmCxxModuleExportInfo const& export_info);
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 1adcaad..2283923 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -1211,6 +1211,9 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements(
for (std::string const& l : linked_directories.Direct) {
build.ImplicitDeps.push_back(cmStrCat(l, '/', language, "Modules.json"));
}
+ for (std::string const& l : linked_directories.Forward) {
+ build.ImplicitDeps.push_back(cmStrCat(l, '/', language, "Modules.json"));
+ }
this->GetGlobalGenerator()->WriteBuild(this->GetImplFileStream(fileConfig),
build);
@@ -1915,6 +1918,12 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang,
tdi_linked_target_dirs.append(l);
}
+ Json::Value& tdi_forward_modules_from_target_dirs =
+ tdi["forward-modules-from-target-dirs"] = Json::arrayValue;
+ for (std::string const& l : linked_directories.Forward) {
+ tdi_forward_modules_from_target_dirs.append(l);
+ }
+
cmDyndepGeneratorCallbacks cb;
cb.ObjectFilePath = [this](cmSourceFile const* sf, std::string const& cnf) {
return this->GetObjectFilePath(sf, cnf);
diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-private.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-private.json
index 45b0396..78f7928 100644
--- a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-private.json
+++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-private.json
@@ -45,6 +45,7 @@
"exports": [],
"include-dirs": [],
"language": "CXX",
+ "forward-modules-from-target-dirs": [],
"linked-target-dirs": [],
"module-dir": "<BINARY_DIR>/CMakeFiles/ninja-bmi-install-private.dir<CONFIG_DIR>"
}
diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-public.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-public.json
index 30b55e3..6c23354 100644
--- a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-public.json
+++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-public.json
@@ -45,6 +45,7 @@
"exports": [],
"include-dirs": [],
"language": "CXX",
+ "forward-modules-from-target-dirs": [],
"linked-target-dirs": [],
"module-dir": "<BINARY_DIR>/CMakeFiles/ninja-bmi-install-public.dir<CONFIG_DIR>"
}
diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-private.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-private.json
index f06a846..61f8f64 100644
--- a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-private.json
+++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-private.json
@@ -73,6 +73,7 @@
],
"include-dirs": [],
"language": "CXX",
+ "forward-modules-from-target-dirs": [],
"linked-target-dirs": [],
"module-dir": "<BINARY_DIR>/CMakeFiles/ninja-exports-private.dir<CONFIG_DIR>"
}
diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-public.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-public.json
index 938481c..d0263b0 100644
--- a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-public.json
+++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-public.json
@@ -73,6 +73,7 @@
],
"include-dirs": [],
"language": "CXX",
+ "forward-modules-from-target-dirs": [],
"linked-target-dirs": [],
"module-dir": "<BINARY_DIR>/CMakeFiles/ninja-exports-public.dir<CONFIG_DIR>"
}
diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-private.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-private.json
index 3a66a94..ed61e0e 100644
--- a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-private.json
+++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-private.json
@@ -40,6 +40,7 @@
"exports": [],
"include-dirs": [],
"language": "CXX",
+ "forward-modules-from-target-dirs": [],
"linked-target-dirs": [],
"module-dir": "<BINARY_DIR>/CMakeFiles/ninja-file-sets-private.dir<CONFIG_DIR>"
}
diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-public.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-public.json
index ac06c0f..171935f 100644
--- a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-public.json
+++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-public.json
@@ -40,6 +40,7 @@
"exports": [],
"include-dirs": [],
"language": "CXX",
+ "forward-modules-from-target-dirs": [],
"linked-target-dirs": [],
"module-dir": "<BINARY_DIR>/CMakeFiles/ninja-file-sets-public.dir<CONFIG_DIR>"
}