Преглед изворни кода

cmCommonTargetGenerator: return forward linked target dirs too

This will be used for module forwarding in order to support
`$<TARGET_OBJECTS>` usage in source and link libraries calls.
Ben Boeckel пре 1 година
родитељ
комит
06df59b930

+ 44 - 29
Source/cmCommonTargetGenerator.cxx

@@ -163,50 +163,65 @@ std::string cmCommonTargetGenerator::GetIncludes(std::string const& l,
   return i->second;
 }
 
-std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories(
+cmCommonTargetGenerator::LinkedTargetDirs
+cmCommonTargetGenerator::GetLinkedTargetDirectories(
   const std::string& lang, const std::string& config) const
 {
-  std::vector<std::string> dirs;
-  std::set<cmGeneratorTarget const*> emitted;
+  LinkedTargetDirs dirs;
+  std::set<cmGeneratorTarget const*> forward_emitted;
+  std::set<cmGeneratorTarget const*> direct_emitted;
   cmGlobalCommonGenerator* const gg = this->GlobalCommonGenerator;
+
+  enum class Forwarding
+  {
+    Yes,
+    No
+  };
+
   if (cmComputeLinkInformation* cli =
         this->GeneratorTarget->GetLinkInformation(config)) {
-    auto addLinkedTarget = [this, &lang, &config, &dirs, &emitted,
-                            gg](cmGeneratorTarget const* linkee) {
-      if (linkee &&
-          !linkee->IsImported()
-          // Skip targets that build after this one in a static lib cycle.
-          && gg->TargetOrderIndexLess(linkee, this->GeneratorTarget)
-          // We can ignore the INTERFACE_LIBRARY items because
-          // Target->GetLinkInformation already processed their
-          // link interface and they don't have any output themselves.
-          && (linkee->GetType() != cmStateEnums::INTERFACE_LIBRARY
-              // Synthesized targets may have relevant rules.
-              || linkee->IsSynthetic()) &&
-          ((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(), '/',
-                                  lg->GetTargetDirectory(linkee));
-        if (lg->GetGlobalGenerator()->IsMultiConfig()) {
-          di = cmStrCat(di, '/', config);
+    auto addLinkedTarget =
+      [this, &lang, &config, &dirs, &direct_emitted, &forward_emitted,
+       gg](cmGeneratorTarget const* linkee, Forwarding forward) {
+        if (linkee &&
+            !linkee->IsImported()
+            // Skip targets that build after this one in a static lib cycle.
+            && gg->TargetOrderIndexLess(linkee, this->GeneratorTarget)
+            // We can ignore the INTERFACE_LIBRARY items because
+            // Target->GetLinkInformation already processed their
+            // link interface and they don't have any output themselves.
+            && (linkee->GetType() != cmStateEnums::INTERFACE_LIBRARY
+                // Synthesized targets may have relevant rules.
+                || linkee->IsSynthetic()) &&
+            ((lang == "CXX"_s && linkee->HaveCxx20ModuleSources()) ||
+             (lang == "Fortran"_s && linkee->HaveFortranSources(config)))) {
+          cmLocalGenerator* lg = linkee->GetLocalGenerator();
+          std::string di = cmStrCat(lg->GetCurrentBinaryDirectory(), '/',
+                                    lg->GetTargetDirectory(linkee));
+          if (lg->GetGlobalGenerator()->IsMultiConfig()) {
+            di = cmStrCat(di, '/', config);
+          }
+          if (forward == Forwarding::Yes &&
+              forward_emitted.insert(linkee).second) {
+            dirs.Forward.push_back(di);
+          }
+          if (direct_emitted.insert(linkee).second) {
+            dirs.Direct.emplace_back(di);
+          }
         }
-        dirs.push_back(std::move(di));
-      }
-    };
+      };
     for (auto const& item : cli->GetItems()) {
-      addLinkedTarget(item.Target);
+      addLinkedTarget(item.Target, Forwarding::No);
     }
     for (cmGeneratorTarget const* target : cli->GetExternalObjectTargets()) {
-      addLinkedTarget(target);
+      addLinkedTarget(target, Forwarding::No);
     }
     if (lang == "Fortran"_s) {
       // Fortran modules provided by `$<TARGET_OBJECTS>` as sources should be
       // collated for use in this target.
       for (cmGeneratorTarget const* target :
            this->GeneratorTarget->GetSourceObjectLibraries(config)) {
-        addLinkedTarget(target);
+        addLinkedTarget(target, Forwarding::Yes);
       }
     }
   }

+ 9 - 2
Source/cmCommonTargetGenerator.h

@@ -74,8 +74,15 @@ protected:
 
   std::string GetCompilerLauncher(std::string const& lang,
                                   std::string const& config);
-  std::vector<std::string> GetLinkedTargetDirectories(
-    const std::string& lang, const std::string& config) const;
+
+  struct LinkedTargetDirs
+  {
+    std::vector<std::string> Direct;
+    std::vector<std::string> Forward;
+  };
+
+  LinkedTargetDirs GetLinkedTargetDirectories(const std::string& lang,
+                                              const std::string& config) const;
   std::string ComputeTargetCompilePDB(const std::string& config) const;
 
   std::string GetLinkerLauncher(const std::string& config);

+ 2 - 2
Source/cmMakefileTargetGenerator.cxx

@@ -1440,9 +1440,9 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
        "# 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> const dirs =
+    auto const dirs =
       this->GetLinkedTargetDirectories("Fortran", this->GetConfigName());
-    for (std::string const& d : dirs) {
+    for (std::string const& d : dirs.Direct) {
       *this->InfoFileStream << "  \"" << d << "/DependInfo.cmake\"\n";
     }
     *this->InfoFileStream << "  )\n";

+ 7 - 5
Source/cmNinjaTargetGenerator.cxx

@@ -1206,10 +1206,10 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements(
 
     this->WriteTargetDependInfo(language, config);
 
-    for (std::string const& l :
-         this->GetLinkedTargetDirectories(language, config)) {
-      build.ImplicitDeps.emplace_back(
-        cmStrCat(l, '/', language, "Modules.json"));
+    auto const linked_directories =
+      this->GetLinkedTargetDirectories(language, config);
+    for (std::string const& l : linked_directories.Direct) {
+      build.ImplicitDeps.push_back(cmStrCat(l, '/', language, "Modules.json"));
     }
 
     this->GetGlobalGenerator()->WriteBuild(this->GetImplFileStream(fileConfig),
@@ -1909,7 +1909,9 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang,
 
   Json::Value& tdi_linked_target_dirs = tdi["linked-target-dirs"] =
     Json::arrayValue;
-  for (std::string const& l : this->GetLinkedTargetDirectories(lang, config)) {
+  auto const linked_directories =
+    this->GetLinkedTargetDirectories(lang, config);
+  for (std::string const& l : linked_directories.Direct) {
     tdi_linked_target_dirs.append(l);
   }