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.
This commit is contained in:
Ben Boeckel
2023-11-17 22:53:45 -05:00
committed by Brad King
parent 06df59b930
commit d2fa56772f
9 changed files with 74 additions and 1 deletions

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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>"
}

View File

@@ -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>"
}

View File

@@ -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>"
}

View File

@@ -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>"
}

View File

@@ -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>"
}

View File

@@ -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>"
}