Merge topic 'modules-lang-specific-target-linked-dirs' into release-3.26

13810dee17 cmDependsFortran: require that dependency info files work
eed295fd8a cmGlobalNinjaGenerator: require that dependency info files work
837f7c113a cmCommonTargetGenerator: classify linked target directories by language
d19648a928 cmGeneratorTarget: add a method to query if Fortran sources exist
245a89d8b6 cmMakefileTargetGenerator: make "target linked info" variable Fortran-specific
aeb1b2ae3d cmMakefileTargetGenerator: simplify string streaming

Acked-by: Kitware Robot <kwrobot@kitware.com>
Tested-by: buildbot <buildbot@kitware.com>
Merge-request: !8146
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx
index 5fe6756..a065ba9 100644
--- a/Source/cmCommonTargetGenerator.cxx
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -6,6 +6,9 @@
 #include <sstream>
 #include <utility>
 
+#include <cm/string_view>
+#include <cmext/string_view>
+
 #include "cmComputeLinkInformation.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalCommonGenerator.h"
@@ -157,7 +160,7 @@
 }
 
 std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories(
-  const std::string& config) const
+  const std::string& lang, const std::string& config) const
 {
   std::vector<std::string> dirs;
   std::set<cmGeneratorTarget const*> emitted;
@@ -172,6 +175,8 @@
           // Target->GetLinkInformation already processed their
           // link interface and they don't have any output themselves.
           && linkee->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
+          ((lang == "CXX"_s && linkee->HaveCxx20ModuleSources()) ||
+           (lang == "Fortran"_s && linkee->HaveFortranSources(config))) &&
           emitted.insert(linkee).second) {
         cmLocalGenerator* lg = linkee->GetLocalGenerator();
         std::string di = cmStrCat(lg->GetCurrentBinaryDirectory(), '/',
diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h
index e8c5a19..2d23037 100644
--- a/Source/cmCommonTargetGenerator.h
+++ b/Source/cmCommonTargetGenerator.h
@@ -65,7 +65,7 @@
   std::string GetAIXExports(std::string const& config);
 
   std::vector<std::string> GetLinkedTargetDirectories(
-    const std::string& config) const;
+    const std::string& lang, const std::string& config) const;
   std::string ComputeTargetCompilePDB(const std::string& config) const;
 
   std::string GetLinkerLauncher(const std::string& config);
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index ac93c90..718097f 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -150,7 +150,9 @@
                                 std::ostream& internalDepends)
 {
   // Prepare the module search process.
-  this->LocateModules();
+  if (!this->LocateModules()) {
+    return false;
+  }
 
   // Get the directory in which stamp files will be stored.
   const std::string& stamp_dir = this->TargetDirectory;
@@ -216,7 +218,7 @@
   return true;
 }
 
-void cmDependsFortran::LocateModules()
+bool cmDependsFortran::LocateModules()
 {
   // Collect the set of modules provided and required by all sources.
   using ObjectInfoMap = cmDependsFortranInternals::ObjectInfoMap;
@@ -234,7 +236,7 @@
 
   // Short-circuit for simple targets.
   if (this->Internal->TargetRequires.empty()) {
-    return;
+    return true;
   }
 
   // Match modules provided by this target to those it requires.
@@ -243,15 +245,19 @@
   // Load information about other targets.
   cmMakefile* mf = this->LocalGenerator->GetMakefile();
   std::vector<std::string> infoFiles;
-  mf->GetDefExpandList("CMAKE_TARGET_LINKED_INFO_FILES", infoFiles);
+  mf->GetDefExpandList("CMAKE_Fortran_TARGET_LINKED_INFO_FILES", infoFiles);
   for (std::string const& i : infoFiles) {
     std::string targetDir = cmSystemTools::GetFilenamePath(i);
     std::string fname = targetDir + "/fortran.internal";
     cmsys::ifstream fin(fname.c_str());
-    if (fin) {
-      this->MatchRemoteModules(fin, targetDir);
+    if (!fin) {
+      cmSystemTools::Error(cmStrCat("-E cmake_depends failed to open ", fname,
+                                    " for module information"));
+      return false;
     }
+    this->MatchRemoteModules(fin, targetDir);
   }
+  return true;
 }
 
 void cmDependsFortran::MatchLocalModules()
diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h
index a74db91..763f7bb 100644
--- a/Source/cmDependsFortran.h
+++ b/Source/cmDependsFortran.h
@@ -55,7 +55,7 @@
                 std::ostream& internalDepends) override;
 
   // Find all the modules required by the target.
-  void LocateModules();
+  bool LocateModules();
   void MatchLocalModules();
   void MatchRemoteModules(std::istream& fin, const std::string& stampDir);
   void ConsiderModule(const std::string& name, const std::string& stampDir);
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 30aa99b..5e352b2 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -8860,6 +8860,15 @@
   return filename;
 }
 
+bool cmGeneratorTarget::HaveFortranSources(std::string const& config) const
+{
+  auto sources = cmGeneratorTarget::GetSourceFiles(config);
+  return std::any_of(sources.begin(), sources.end(),
+                     [](BT<cmSourceFile*> const& sf) -> bool {
+                       return sf.Value->GetLanguage() == "Fortran"_s;
+                     });
+}
+
 bool cmGeneratorTarget::HaveCxx20ModuleSources() const
 {
   auto const& fs_names = this->Target->GetAllFileSetNames();
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index dd10c64..afd9da4 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -1225,6 +1225,8 @@
                     cmGeneratorTarget const* t2) const;
   };
 
+  bool HaveFortranSources(std::string const& config) const;
+
   // C++20 module support queries.
 
   /**
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index b80a06e..93aa30a 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -2537,8 +2537,13 @@
       cmStrCat(linked_target_dir, '/', arg_lang, "Modules.json");
     Json::Value ltm;
     cmsys::ifstream ltmf(ltmn.c_str(), std::ios::in | std::ios::binary);
+    if (!ltmf) {
+      cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to open ",
+                                    ltmn, " for module information"));
+      return false;
+    }
     Json::Reader reader;
-    if (ltmf && !reader.parse(ltmf, ltm, false)) {
+    if (!reader.parse(ltmf, ltm, false)) {
       cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ",
                                     linked_target_dir,
                                     reader.getFormattedErrorMessages()));
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 9df1af7..c40d685 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -1494,11 +1494,11 @@
     /* clang-format off */
   *this->InfoFileStream
     << "\n"
-    << "# Targets to which this target links.\n"
-    << "set(CMAKE_TARGET_LINKED_INFO_FILES\n";
+       "# Targets to which this target links which contain Fortran sources.\n"
+       "set(CMAKE_Fortran_TARGET_LINKED_INFO_FILES\n";
     /* clang-format on */
     std::vector<std::string> dirs =
-      this->GetLinkedTargetDirectories(this->GetConfigName());
+      this->GetLinkedTargetDirectories("Fortran", this->GetConfigName());
     for (std::string const& d : dirs) {
       *this->InfoFileStream << "  \"" << d << "/DependInfo.cmake\"\n";
     }
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 6887376..13782b0 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -1675,7 +1675,7 @@
 
   Json::Value& tdi_linked_target_dirs = tdi["linked-target-dirs"] =
     Json::arrayValue;
-  for (std::string const& l : this->GetLinkedTargetDirectories(config)) {
+  for (std::string const& l : this->GetLinkedTargetDirectories(lang, config)) {
     tdi_linked_target_dirs.append(l);
   }