浏览代码

Ninja Multi-Config: Fix issue with framework dependencies and Autogen

Fixes: #20345
Kyle Edwards 5 年之前
父节点
当前提交
7abc3d61ac

+ 1 - 1
Source/cmAddDependenciesCommand.cxx

@@ -29,7 +29,7 @@ bool cmAddDependenciesCommand(std::vector<std::string> const& args,
 
     // skip over target_name
     for (std::string const& arg : cmMakeRange(args).advance(1)) {
-      target->AddUtility(arg, &mf);
+      target->AddUtility(arg, false, &mf);
     }
   } else {
     mf.IssueMessage(

+ 1 - 1
Source/cmComputeComponentGraph.cxx

@@ -123,7 +123,7 @@ void cmComputeComponentGraph::TransferEdges()
         // We do not attempt to combine duplicate edges, but instead
         // store the inter-component edges with suitable multiplicity.
         this->ComponentGraph[i_component].emplace_back(
-          j_component, ni.IsStrong(), ni.GetBacktrace());
+          j_component, ni.IsStrong(), ni.IsCross(), ni.GetBacktrace());
       }
     }
   }

+ 3 - 3
Source/cmComputeLinkDepends.cxx

@@ -412,7 +412,7 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
   // This shared library dependency must follow the item that listed
   // it.
   this->EntryConstraintGraph[dep.DependerIndex].emplace_back(
-    index, true, cmListFileBacktrace());
+    index, true, false, cmListFileBacktrace());
 
   // Target items may have their own dependencies.
   if (entry.Target) {
@@ -514,7 +514,7 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index,
     // The dependee must come after the depender.
     if (depender_index >= 0) {
       this->EntryConstraintGraph[depender_index].emplace_back(
-        dependee_index, false, cmListFileBacktrace());
+        dependee_index, false, false, cmListFileBacktrace());
     } else {
       // This is a direct dependency of the target being linked.
       this->OriginalEntries.push_back(dependee_index);
@@ -587,7 +587,7 @@ void cmComputeLinkDepends::InferDependencies()
     cmGraphEdgeList& edges = this->EntryConstraintGraph[depender_index];
     edges.reserve(edges.size() + common.size());
     for (auto const& c : common) {
-      edges.emplace_back(c, true, cmListFileBacktrace());
+      edges.emplace_back(c, true, false, cmListFileBacktrace());
     }
   }
 }

+ 22 - 15
Source/cmComputeTargetDepends.cxx

@@ -151,6 +151,7 @@ void cmComputeTargetDepends::GetTargetDirectDepends(cmGeneratorTarget const* t,
     cmGeneratorTarget const* dep = this->Targets[ni];
     auto di = deps.insert(dep).first;
     di->SetType(ni.IsStrong());
+    di->SetCross(ni.IsCross());
     di->SetBacktrace(ni.GetBacktrace());
   }
 }
@@ -217,7 +218,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
               return;
             }
             const_cast<cmGeneratorTarget*>(depender)->Target->AddUtility(
-              objLib);
+              objLib, false);
           }
         }
       }
@@ -225,11 +226,12 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
       cmLinkImplementation const* impl = depender->GetLinkImplementation(it);
 
       // A target should not depend on itself.
-      emitted.insert(cmLinkItem(depender, cmListFileBacktrace()));
+      emitted.insert(cmLinkItem(depender, false, cmListFileBacktrace()));
+      emitted.insert(cmLinkItem(depender, true, cmListFileBacktrace()));
       for (cmLinkImplItem const& lib : impl->Libraries) {
         // Don't emit the same library twice for this target.
         if (emitted.insert(lib).second) {
-          this->AddTargetDepend(depender_index, lib, true);
+          this->AddTargetDepend(depender_index, lib, true, false);
           this->AddInterfaceDepends(depender_index, lib, it, emitted);
         }
       }
@@ -241,11 +243,12 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
     std::set<cmLinkItem> const& tutils = depender->GetUtilityItems();
     std::set<cmLinkItem> emitted;
     // A target should not depend on itself.
-    emitted.insert(cmLinkItem(depender, cmListFileBacktrace()));
+    emitted.insert(cmLinkItem(depender, false, cmListFileBacktrace()));
+    emitted.insert(cmLinkItem(depender, true, cmListFileBacktrace()));
     for (cmLinkItem const& litem : tutils) {
       // Don't emit the same utility twice for this target.
       if (emitted.insert(litem).second) {
-        this->AddTargetDepend(depender_index, litem, false);
+        this->AddTargetDepend(depender_index, litem, false, litem.Cross);
       }
     }
   }
@@ -267,7 +270,7 @@ void cmComputeTargetDepends::AddInterfaceDepends(
         // code in the project that caused this dependency to be added.
         cmLinkItem libBT = lib;
         libBT.Backtrace = dependee_backtrace;
-        this->AddTargetDepend(depender_index, libBT, true);
+        this->AddTargetDepend(depender_index, libBT, true, false);
         this->AddInterfaceDepends(depender_index, libBT, config, emitted);
       }
     }
@@ -290,7 +293,8 @@ void cmComputeTargetDepends::AddInterfaceDepends(
 
   if (dependee) {
     // A target should not depend on itself.
-    emitted.insert(cmLinkItem(depender, cmListFileBacktrace()));
+    emitted.insert(cmLinkItem(depender, false, cmListFileBacktrace()));
+    emitted.insert(cmLinkItem(depender, true, cmListFileBacktrace()));
     this->AddInterfaceDepends(depender_index, dependee,
                               dependee_name.Backtrace, config, emitted);
   }
@@ -298,7 +302,7 @@ void cmComputeTargetDepends::AddInterfaceDepends(
 
 void cmComputeTargetDepends::AddTargetDepend(int depender_index,
                                              cmLinkItem const& dependee_name,
-                                             bool linking)
+                                             bool linking, bool cross)
 {
   // Get the depender.
   cmGeneratorTarget const* depender = this->Targets[depender_index];
@@ -343,13 +347,13 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index,
 
   if (dependee) {
     this->AddTargetDepend(depender_index, dependee, dependee_name.Backtrace,
-                          linking);
+                          linking, cross);
   }
 }
 
 void cmComputeTargetDepends::AddTargetDepend(
   int depender_index, cmGeneratorTarget const* dependee,
-  cmListFileBacktrace const& dependee_backtrace, bool linking)
+  cmListFileBacktrace const& dependee_backtrace, bool linking, bool cross)
 {
   if (dependee->IsImported() ||
       dependee->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
@@ -359,7 +363,7 @@ void cmComputeTargetDepends::AddTargetDepend(
     for (cmLinkItem const& i : utils) {
       if (cmGeneratorTarget const* transitive_dependee = i.Target) {
         this->AddTargetDepend(depender_index, transitive_dependee, i.Backtrace,
-                              false);
+                              false, i.Cross);
       }
     }
   } else {
@@ -371,7 +375,7 @@ void cmComputeTargetDepends::AddTargetDepend(
 
     // Add this entry to the dependency graph.
     this->InitialGraph[depender_index].emplace_back(dependee_index, !linking,
-                                                    dependee_backtrace);
+                                                    cross, dependee_backtrace);
   }
 }
 
@@ -505,7 +509,8 @@ bool cmComputeTargetDepends::IntraComponent(std::vector<int> const& cmap,
     for (cmGraphEdge const& edge : el) {
       int j = edge;
       if (cmap[j] == c && edge.IsStrong()) {
-        this->FinalGraph[i].emplace_back(j, true, edge.GetBacktrace());
+        this->FinalGraph[i].emplace_back(j, true, edge.IsCross(),
+                                         edge.GetBacktrace());
         if (!this->IntraComponent(cmap, c, j, head, emitted, visited)) {
           return false;
         }
@@ -514,7 +519,8 @@ bool cmComputeTargetDepends::IntraComponent(std::vector<int> const& cmap,
 
     // Prepend to a linear linked-list of intra-component edges.
     if (*head >= 0) {
-      this->FinalGraph[i].emplace_back(*head, false, cmListFileBacktrace());
+      this->FinalGraph[i].emplace_back(*head, false, false,
+                                       cmListFileBacktrace());
     } else {
       this->ComponentTail[c] = i;
     }
@@ -564,7 +570,8 @@ bool cmComputeTargetDepends::ComputeFinalDepends(
       int dependee_component = ni;
       int dependee_component_head = this->ComponentHead[dependee_component];
       this->FinalGraph[depender_component_tail].emplace_back(
-        dependee_component_head, ni.IsStrong(), ni.GetBacktrace());
+        dependee_component_head, ni.IsStrong(), ni.IsCross(),
+        ni.GetBacktrace());
     }
   }
   return true;

+ 2 - 2
Source/cmComputeTargetDepends.h

@@ -46,10 +46,10 @@ private:
   void CollectDepends();
   void CollectTargetDepends(int depender_index);
   void AddTargetDepend(int depender_index, cmLinkItem const& dependee_name,
-                       bool linking);
+                       bool linking, bool cross);
   void AddTargetDepend(int depender_index, cmGeneratorTarget const* dependee,
                        cmListFileBacktrace const& dependee_backtrace,
-                       bool linking);
+                       bool linking, bool cross);
   bool ComputeFinalDepends(cmComputeComponentGraph const& ccg);
   void AddInterfaceDepends(int depender_index, cmLinkItem const& dependee_name,
                            const std::string& config,

+ 17 - 14
Source/cmGeneratorTarget.cxx

@@ -978,13 +978,15 @@ std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const
 {
   if (!this->UtilityItemsDone) {
     this->UtilityItemsDone = true;
-    std::set<BT<std::string>> const& utilities = this->GetUtilities();
-    for (BT<std::string> const& i : utilities) {
+    std::set<BT<std::pair<std::string, bool>>> const& utilities =
+      this->GetUtilities();
+    for (BT<std::pair<std::string, bool>> const& i : utilities) {
       if (cmGeneratorTarget* gt =
-            this->LocalGenerator->FindGeneratorTargetToUse(i.Value)) {
-        this->UtilityItems.insert(cmLinkItem(gt, i.Backtrace));
+            this->LocalGenerator->FindGeneratorTargetToUse(i.Value.first)) {
+        this->UtilityItems.insert(cmLinkItem(gt, i.Value.second, i.Backtrace));
       } else {
-        this->UtilityItems.insert(cmLinkItem(i.Value, i.Backtrace));
+        this->UtilityItems.insert(
+          cmLinkItem(i.Value.first, i.Value.second, i.Backtrace));
       }
     }
   }
@@ -2182,7 +2184,8 @@ cmListFileBacktrace cmGeneratorTarget::GetBacktrace() const
   return this->Target->GetBacktrace();
 }
 
-const std::set<BT<std::string>>& cmGeneratorTarget::GetUtilities() const
+const std::set<BT<std::pair<std::string, bool>>>&
+cmGeneratorTarget::GetUtilities() const
 {
   return this->Target->GetUtilities();
 }
@@ -2731,7 +2734,7 @@ void cmTargetTraceDependencies::FollowName(std::string const& name)
   if (cmTarget* t = i->second.Target) {
     // The name is a byproduct of a utility target or a PRE_BUILD, PRE_LINK, or
     // POST_BUILD command.
-    this->GeneratorTarget->Target->AddUtility(t->GetName());
+    this->GeneratorTarget->Target->AddUtility(t->GetName(), false);
   }
   if (cmSourceFile* sf = i->second.Source) {
     // For now only follow the dependency if the source file is not a
@@ -2786,14 +2789,14 @@ bool cmTargetTraceDependencies::IsUtility(std::string const& dep)
         depLocation = cmSystemTools::CollapseFullPath(depLocation);
         tLocation = cmSystemTools::CollapseFullPath(tLocation);
         if (depLocation == tLocation) {
-          this->GeneratorTarget->Target->AddUtility(util);
+          this->GeneratorTarget->Target->AddUtility(util, false);
           return true;
         }
       }
     } else {
       // The original name of the dependency was not a full path.  It
       // must name a target, so add the target-level dependency.
-      this->GeneratorTarget->Target->AddUtility(util);
+      this->GeneratorTarget->Target->AddUtility(util, false);
       return true;
     }
   }
@@ -2821,7 +2824,7 @@ void cmTargetTraceDependencies::CheckCustomCommand(cmCustomCommand const& cc)
         // this project.  Add the target-level dependency to make
         // sure the executable is up to date before this custom
         // command possibly runs.
-        this->GeneratorTarget->Target->AddUtility(command);
+        this->GeneratorTarget->Target->AddUtility(command, true);
       }
     }
 
@@ -2836,7 +2839,7 @@ void cmTargetTraceDependencies::CheckCustomCommand(cmCustomCommand const& cc)
   }
 
   for (cmGeneratorTarget* target : targets) {
-    this->GeneratorTarget->Target->AddUtility(target->GetName());
+    this->GeneratorTarget->Target->AddUtility(target->GetName(), true);
   }
 
   // Queue the custom command dependencies.
@@ -6681,7 +6684,7 @@ cmLinkItem cmGeneratorTarget::ResolveLinkItem(std::string const& name,
   TargetOrString resolved = this->ResolveTargetReference(name, lg);
 
   if (!resolved.Target) {
-    return cmLinkItem(resolved.String, bt);
+    return cmLinkItem(resolved.String, false, bt);
   }
 
   // Check deprecation, issue message with `bt` backtrace.
@@ -6702,10 +6705,10 @@ cmLinkItem cmGeneratorTarget::ResolveLinkItem(std::string const& name,
   // within the project.
   if (resolved.Target->GetType() == cmStateEnums::EXECUTABLE &&
       !resolved.Target->IsExecutableWithExports()) {
-    return cmLinkItem(resolved.Target->GetName(), bt);
+    return cmLinkItem(resolved.Target->GetName(), false, bt);
   }
 
-  return cmLinkItem(resolved.Target, bt);
+  return cmLinkItem(resolved.Target, false, bt);
 }
 
 std::string cmGeneratorTarget::GetPDBDirectory(const std::string& config) const

+ 1 - 1
Source/cmGeneratorTarget.h

@@ -291,7 +291,7 @@ public:
 
   cmListFileBacktrace GetBacktrace() const;
 
-  std::set<BT<std::string>> const& GetUtilities() const;
+  std::set<BT<std::pair<std::string, bool>>> const& GetUtilities() const;
 
   bool LinkLanguagePropagatesToDependents() const
   {

+ 1 - 1
Source/cmGlobalGenerator.cxx

@@ -2689,7 +2689,7 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti,
     target.SetProperty("EchoString", gti.Message);
   }
   for (std::string const& d : gti.Depends) {
-    target.AddUtility(d);
+    target.AddUtility(d, false);
   }
 
   // Organize in the "predefined targets" folder:

+ 4 - 6
Source/cmGlobalNinjaGenerator.cxx

@@ -1125,10 +1125,11 @@ void cmGlobalNinjaGenerator::AppendTargetDepends(
 {
   if (target->GetType() == cmStateEnums::GLOBAL_TARGET) {
     // These depend only on other CMake-provided targets, e.g. "all".
-    for (BT<std::string> const& util : target->GetUtilities()) {
+    for (BT<std::pair<std::string, bool>> const& util :
+         target->GetUtilities()) {
       std::string d =
         target->GetLocalGenerator()->GetCurrentBinaryDirectory() + "/" +
-        util.Value;
+        util.Value.first;
       outputs.push_back(this->BuildAlias(this->ConvertToNinjaPath(d), config));
     }
   } else {
@@ -1138,10 +1139,7 @@ void cmGlobalNinjaGenerator::AppendTargetDepends(
       if (targetDep->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
         continue;
       }
-      // For some reason, object libraries show up as "utility" dependencies
-      // even though they're used for linking. Treat them as link dependencies.
-      if (targetDep.IsUtil() &&
-          targetDep->GetType() != cmStateEnums::OBJECT_LIBRARY) {
+      if (targetDep.IsCross()) {
         this->AppendTargetOutputs(targetDep, outs, fileConfig, depends);
       } else {
         this->AppendTargetOutputs(targetDep, outs, config, depends);

+ 4 - 3
Source/cmGlobalVisualStudio71Generator.cxx

@@ -157,7 +157,8 @@ void cmGlobalVisualStudio71Generator::WriteProjectDepends(
 // executables to the libraries it uses are also done here
 void cmGlobalVisualStudio71Generator::WriteExternalProject(
   std::ostream& fout, const std::string& name, const std::string& location,
-  const char* typeGuid, const std::set<BT<std::string>>& depends)
+  const char* typeGuid,
+  const std::set<BT<std::pair<std::string, bool>>>& depends)
 {
   fout << "Project(\"{"
        << (typeGuid ? typeGuid : this->ExternalProjectType(location))
@@ -169,8 +170,8 @@ void cmGlobalVisualStudio71Generator::WriteExternalProject(
   // project instead of in the global section
   if (!depends.empty()) {
     fout << "\tProjectSection(ProjectDependencies) = postProject\n";
-    for (BT<std::string> const& it : depends) {
-      std::string const& dep = it.Value;
+    for (BT<std::pair<std::string, bool>> const& it : depends) {
+      std::string const& dep = it.Value.first;
       if (!dep.empty()) {
         fout << "\t\t{" << this->GetGUID(dep) << "} = {" << this->GetGUID(dep)
              << "}\n";

+ 4 - 3
Source/cmGlobalVisualStudio71Generator.h

@@ -32,9 +32,10 @@ protected:
     cmGeneratorTarget const& target, std::vector<std::string> const& configs,
     const std::set<std::string>& configsPartOfDefaultBuild,
     const std::string& platformMapping = "") override;
-  void WriteExternalProject(std::ostream& fout, const std::string& name,
-                            const std::string& path, const char* typeGuid,
-                            const std::set<BT<std::string>>& depends) override;
+  void WriteExternalProject(
+    std::ostream& fout, const std::string& name, const std::string& path,
+    const char* typeGuid,
+    const std::set<BT<std::pair<std::string, bool>>>& depends) override;
 
   // Folders are not supported by VS 7.1.
   bool UseFolderProperty() const override { return false; }

+ 2 - 1
Source/cmGlobalVisualStudio7Generator.h

@@ -143,7 +143,8 @@ protected:
 
   virtual void WriteExternalProject(
     std::ostream& fout, const std::string& name, const std::string& path,
-    const char* typeGuid, const std::set<BT<std::string>>& dependencies) = 0;
+    const char* typeGuid,
+    const std::set<BT<std::pair<std::string, bool>>>& dependencies) = 0;
 
   std::string ConvertToSolutionPath(const std::string& path);
 

+ 4 - 3
Source/cmGlobalVisualStudio8Generator.cxx

@@ -211,7 +211,7 @@ void cmGlobalVisualStudio8Generator::AddExtraIDETargets()
       // All targets depend on the build-system check target.
       for (const auto& ti : tgts) {
         if (ti->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
-          ti->Target->AddUtility(CMAKE_CHECK_BUILD_SYSTEM_TARGET);
+          ti->Target->AddUtility(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false);
         }
       }
     }
@@ -325,9 +325,10 @@ bool cmGlobalVisualStudio8Generator::NeedLinkLibraryDependencies(
   cmGeneratorTarget* target)
 {
   // Look for utility dependencies that magically link.
-  for (BT<std::string> const& ui : target->GetUtilities()) {
+  for (BT<std::pair<std::string, bool>> const& ui : target->GetUtilities()) {
     if (cmGeneratorTarget* depTarget =
-          target->GetLocalGenerator()->FindGeneratorTargetToUse(ui.Value)) {
+          target->GetLocalGenerator()->FindGeneratorTargetToUse(
+            ui.Value.first)) {
       if (depTarget->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
           depTarget->GetProperty("EXTERNAL_MSPROJECT")) {
         // This utility dependency names an external .vcproj target.

+ 1 - 1
Source/cmGlobalVisualStudioGenerator.cxx

@@ -219,7 +219,7 @@ void cmGlobalVisualStudioGenerator::AddExtraIDETargets()
             continue;
           }
           if (!this->IsExcluded(gen[0], tgt.get())) {
-            allBuild->AddUtility(tgt->GetName());
+            allBuild->AddUtility(tgt->GetName(), false);
           }
         }
       }

+ 2 - 2
Source/cmGlobalXCodeGenerator.cxx

@@ -552,7 +552,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
 
       if (regenerate &&
           (target->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET)) {
-        target->Target->AddUtility(CMAKE_CHECK_BUILD_SYSTEM_TARGET);
+        target->Target->AddUtility(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false);
       }
 
       // make all exe, shared libs and modules
@@ -571,7 +571,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
       }
 
       if (!this->IsExcluded(gens[0], target.get())) {
-        allbuild->AddUtility(target->GetName());
+        allbuild->AddUtility(target->GetName(), false);
       }
     }
   }

+ 5 - 1
Source/cmGraphAdjacencyList.h

@@ -18,9 +18,10 @@
 class cmGraphEdge
 {
 public:
-  cmGraphEdge(int n, bool s, cmListFileBacktrace bt)
+  cmGraphEdge(int n, bool s, bool c, cmListFileBacktrace bt)
     : Dest(n)
     , Strong(s)
+    , Cross(c)
     , Backtrace(std::move(bt))
   {
   }
@@ -28,11 +29,14 @@ public:
 
   bool IsStrong() const { return this->Strong; }
 
+  bool IsCross() const { return this->Cross; }
+
   cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; }
 
 private:
   int Dest;
   bool Strong;
+  bool Cross;
   cmListFileBacktrace Backtrace;
 };
 struct cmGraphEdgeList : public std::vector<cmGraphEdge>

+ 1 - 1
Source/cmGraphVizWriter.cxx

@@ -289,7 +289,7 @@ void cmGraphVizWriter::Write()
   }
 
   for (auto const gt : sortedGeneratorTargets) {
-    auto item = cmLinkItem(gt, gt->GetBacktrace());
+    auto item = cmLinkItem(gt, false, gt->GetBacktrace());
     this->VisitItem(item);
   }
 }

+ 1 - 1
Source/cmIncludeExternalMSProjectCommand.cxx

@@ -97,7 +97,7 @@ bool cmIncludeExternalMSProjectCommand(std::vector<std::string> const& args,
       target->SetProperty("VS_PLATFORM_MAPPING", platformMapping);
 
     for (std::string const& d : depends) {
-      target->AddUtility(d);
+      target->AddUtility(d, false);
     }
   }
 #endif

+ 11 - 4
Source/cmLinkItem.cxx

@@ -8,14 +8,17 @@
 
 cmLinkItem::cmLinkItem() = default;
 
-cmLinkItem::cmLinkItem(std::string n, cmListFileBacktrace bt)
+cmLinkItem::cmLinkItem(std::string n, bool c, cmListFileBacktrace bt)
   : String(std::move(n))
+  , Cross(c)
   , Backtrace(std::move(bt))
 {
 }
 
-cmLinkItem::cmLinkItem(cmGeneratorTarget const* t, cmListFileBacktrace bt)
+cmLinkItem::cmLinkItem(cmGeneratorTarget const* t, bool c,
+                       cmListFileBacktrace bt)
   : Target(t)
+  , Cross(c)
   , Backtrace(std::move(bt))
 {
 }
@@ -39,12 +42,16 @@ bool operator<(cmLinkItem const& l, cmLinkItem const& r)
     return false;
   }
   // Order among strings.
-  return l.String < r.String;
+  if (l.String < r.String) {
+    return true;
+  }
+  // Order among cross-config.
+  return l.Cross < r.Cross;
 }
 
 bool operator==(cmLinkItem const& l, cmLinkItem const& r)
 {
-  return l.Target == r.Target && l.String == r.String;
+  return l.Target == r.Target && l.String == r.String && l.Cross == r.Cross;
 }
 
 std::ostream& operator<<(std::ostream& os, cmLinkItem const& item)

+ 3 - 2
Source/cmLinkItem.h

@@ -24,10 +24,11 @@ class cmLinkItem
 
 public:
   cmLinkItem();
-  cmLinkItem(std::string s, cmListFileBacktrace bt);
-  cmLinkItem(cmGeneratorTarget const* t, cmListFileBacktrace bt);
+  cmLinkItem(std::string s, bool c, cmListFileBacktrace bt);
+  cmLinkItem(cmGeneratorTarget const* t, bool c, cmListFileBacktrace bt);
   std::string const& AsStr() const;
   cmGeneratorTarget const* Target = nullptr;
+  bool Cross = false;
   cmListFileBacktrace Backtrace;
   friend bool operator<(cmLinkItem const& l, cmLinkItem const& r);
   friend bool operator==(cmLinkItem const& l, cmLinkItem const& r);

+ 1 - 1
Source/cmLinkItemGraphVisitor.cxx

@@ -127,7 +127,7 @@ void cmLinkItemGraphVisitor::GetDependencies(cmGeneratorTarget const& target,
   for (auto const& lib : objectLibraries) {
     auto const& name = lib->GetName();
     if (dependencies.find(name) == dependencies.cend()) {
-      auto objectItem = cmLinkItem(lib, lib->GetBacktrace());
+      auto objectItem = cmLinkItem(lib, false, lib->GetBacktrace());
       dependencies[name] = Dependency(DependencyType::Object, objectItem);
     }
   }

+ 2 - 2
Source/cmLocalUnixMakefileGenerator3.cxx

@@ -1579,8 +1579,8 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
         text = "Running external command ...";
       }
       depends.reserve(gt->GetUtilities().size());
-      for (BT<std::string> const& u : gt->GetUtilities()) {
-        depends.push_back(u.Value);
+      for (BT<std::pair<std::string, bool>> const& u : gt->GetUtilities()) {
+        depends.push_back(u.Value.first);
       }
       this->AppendEcho(commands, text,
                        cmLocalUnixMakefileGenerator3::EchoGlobal);

+ 2 - 2
Source/cmQtAutoGenGlobalInitializer.cxx

@@ -180,7 +180,7 @@ void cmQtAutoGenGlobalInitializer::AddToGlobalAutoGen(
   if (it != GlobalAutoGenTargets_.end()) {
     cmGeneratorTarget* target = localGen->FindGeneratorTargetToUse(it->second);
     if (target != nullptr) {
-      target->Target->AddUtility(targetName, localGen->GetMakefile());
+      target->Target->AddUtility(targetName, false, localGen->GetMakefile());
     }
   }
 }
@@ -192,7 +192,7 @@ void cmQtAutoGenGlobalInitializer::AddToGlobalAutoRcc(
   if (it != GlobalAutoRccTargets_.end()) {
     cmGeneratorTarget* target = localGen->FindGeneratorTargetToUse(it->second);
     if (target != nullptr) {
-      target->Target->AddUtility(targetName, localGen->GetMakefile());
+      target->Target->AddUtility(targetName, false, localGen->GetMakefile());
     }
   }
 }

+ 8 - 7
Source/cmQtAutoGenInitializer.cxx

@@ -1125,7 +1125,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
   if (usePRE_BUILD) {
     // Add additional autogen target dependencies to origin target
     for (cmTarget* depTarget : this->AutogenTarget.DependTargets) {
-      this->GenTarget->Target->AddUtility(depTarget->GetName(),
+      this->GenTarget->Target->AddUtility(depTarget->GetName(), false,
                                           this->Makefile);
     }
 
@@ -1229,14 +1229,15 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
 
     // Forward origin utilities to autogen target
     if (this->AutogenTarget.DependOrigin) {
-      for (BT<std::string> const& depName : this->GenTarget->GetUtilities()) {
-        autogenTarget->AddUtility(depName.Value, this->Makefile);
+      for (BT<std::pair<std::string, bool>> const& depName :
+           this->GenTarget->GetUtilities()) {
+        autogenTarget->AddUtility(depName.Value.first, false, this->Makefile);
       }
     }
     if (!useNinjaDepfile) {
       // Add additional autogen target dependencies to autogen target
       for (cmTarget* depTarget : this->AutogenTarget.DependTargets) {
-        autogenTarget->AddUtility(depTarget->GetName(), this->Makefile);
+        autogenTarget->AddUtility(depTarget->GetName(), false, this->Makefile);
       }
     }
 
@@ -1246,7 +1247,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
     }
 
     // Add autogen target to the origin target dependencies
-    this->GenTarget->Target->AddUtility(this->AutogenTarget.Name,
+    this->GenTarget->Target->AddUtility(this->AutogenTarget.Name, false,
                                         this->Makefile);
 
     // Add autogen target to the global autogen target dependencies
@@ -1317,12 +1318,12 @@ bool cmQtAutoGenInitializer::InitRccTargets()
           autoRccTarget->SetProperty("FOLDER", this->TargetsFolder);
         }
         if (!this->Rcc.ExecutableTargetName.empty()) {
-          autoRccTarget->AddUtility(this->Rcc.ExecutableTargetName,
+          autoRccTarget->AddUtility(this->Rcc.ExecutableTargetName, false,
                                     this->Makefile);
         }
       }
       // Add autogen target to the origin target dependencies
-      this->GenTarget->Target->AddUtility(ccName, this->Makefile);
+      this->GenTarget->Target->AddUtility(ccName, false, this->Makefile);
 
       // Add autogen target to the global autogen target dependencies
       if (this->Rcc.GlobalTarget) {

+ 15 - 7
Source/cmTarget.cxx

@@ -178,7 +178,7 @@ public:
   bool ImportedGloballyVisible;
   bool BuildInterfaceIncludesAppended;
   bool PerConfig;
-  std::set<BT<std::string>> Utilities;
+  std::set<BT<std::pair<std::string, bool>>> Utilities;
   std::vector<cmCustomCommand> PreBuildCommands;
   std::vector<cmCustomCommand> PreLinkCommands;
   std::vector<cmCustomCommand> PostBuildCommands;
@@ -583,13 +583,14 @@ cmGlobalGenerator* cmTarget::GetGlobalGenerator() const
   return impl->Makefile->GetGlobalGenerator();
 }
 
-void cmTarget::AddUtility(std::string const& name, cmMakefile* mf)
+void cmTarget::AddUtility(std::string const& name, bool cross, cmMakefile* mf)
 {
-  impl->Utilities.insert(
-    BT<std::string>(name, mf ? mf->GetBacktrace() : cmListFileBacktrace()));
+  impl->Utilities.insert(BT<std::pair<std::string, bool>>(
+    { name, cross }, mf ? mf->GetBacktrace() : cmListFileBacktrace()));
 }
 
-std::set<BT<std::string>> const& cmTarget::GetUtilities() const
+std::set<BT<std::pair<std::string, bool>>> const& cmTarget::GetUtilities()
+  const
 {
   return impl->Utilities;
 }
@@ -1293,7 +1294,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
 
     this->SetProperty("COMPILE_PDB_NAME",
                       reusedTarget->GetProperty("COMPILE_PDB_NAME"));
-    this->AddUtility(reusedFrom, impl->Makefile);
+    this->AddUtility(reusedFrom, false, impl->Makefile);
   } else {
     impl->Properties.SetProperty(prop, value);
   }
@@ -1720,7 +1721,14 @@ const char* cmTarget::GetProperty(const std::string& prop) const
       }
 
       static std::string output;
-      output = cmJoin(impl->Utilities, ";");
+      static std::vector<std::string> utilities;
+      utilities.resize(impl->Utilities.size());
+      std::transform(
+        impl->Utilities.cbegin(), impl->Utilities.cend(), utilities.begin(),
+        [](const BT<std::pair<std::string, bool>>& item) -> std::string {
+          return item.Value.first;
+        });
+      output = cmJoin(utilities, ";");
       return output.c_str();
     }
     if (prop == propPRECOMPILE_HEADERS) {

+ 3 - 2
Source/cmTarget.h

@@ -156,9 +156,10 @@ public:
    * name as would be specified to the ADD_EXECUTABLE or UTILITY_SOURCE
    * commands. It is not a full path nor does it have an extension.
    */
-  void AddUtility(std::string const& name, cmMakefile* mf = nullptr);
+  void AddUtility(std::string const& name, bool cross,
+                  cmMakefile* mf = nullptr);
   //! Get the utilities used by this target
-  std::set<BT<std::string>> const& GetUtilities() const;
+  std::set<BT<std::pair<std::string, bool>>> const& GetUtilities() const;
 
   //! Set/Get a property of this target file
   void SetProperty(const std::string& prop, const char* value);

+ 4 - 0
Source/cmTargetDepend.h

@@ -19,6 +19,7 @@ class cmTargetDepend
   // mutable members to achieve a map with set syntax.
   mutable bool Link;
   mutable bool Util;
+  mutable bool Cross;
   mutable cmListFileBacktrace Backtrace;
 
 public:
@@ -26,6 +27,7 @@ public:
     : Target(t)
     , Link(false)
     , Util(false)
+    , Cross(false)
   {
   }
   operator cmGeneratorTarget const*() const { return this->Target; }
@@ -43,12 +45,14 @@ public:
       this->Link = true;
     }
   }
+  void SetCross(bool cross) const { this->Cross = cross; }
   void SetBacktrace(cmListFileBacktrace const& bt) const
   {
     this->Backtrace = bt;
   }
   bool IsLink() const { return this->Link; }
   bool IsUtil() const { return this->Util; }
+  bool IsCross() const { return this->Cross; }
   cmListFileBacktrace const& GetBacktrace() const { return this->Backtrace; }
 };
 

+ 20 - 0
Tests/RunCMake/NinjaMultiConfig/FrameworkDependencyAutogen.cmake

@@ -0,0 +1,20 @@
+enable_language(C)
+
+set(CMAKE_LINK_DEPENDS_NO_SHARED ON)
+
+set(QT_VERSION_MAJOR 6)
+set(fake_moc_path "${CMAKE_CURRENT_BINARY_DIR}/fake_moc")
+file(WRITE "${fake_moc_path}" "")
+
+add_library(test1 SHARED simplelib.c)
+add_library(test2 SHARED empty.c)
+target_link_libraries(test2 test1)
+
+set_target_properties(test1 test2 PROPERTIES
+  FRAMEWORK ON
+  AUTOMOC ON
+  AUTOMOC_EXECUTABLE "${fake_moc_path}"
+  )
+
+include(${CMAKE_CURRENT_LIST_DIR}/Common.cmake)
+generate_output_files(test1 test2)

+ 7 - 0
Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake

@@ -198,6 +198,13 @@ unset(RunCMake_TEST_OPTIONS)
 include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake)
 run_cmake_build(Framework framework Debug all)
 
+set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/FrameworkDependencyAutogen-build)
+set(RunCMake_TEST_OPTIONS "-DCMAKE_NMC_CROSS_CONFIGS=all")
+run_cmake_configure(FrameworkDependencyAutogen)
+unset(RunCMake_TEST_OPTIONS)
+include(${RunCMake_TEST_BINARY_DIR}/target_files.cmake)
+run_cmake_build(FrameworkDependencyAutogen framework Release test2:Debug)
+
 set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CustomCommandGenerator-build)
 set(RunCMake_TEST_OPTIONS "-DCMAKE_CONFIGURATION_TYPES=Debug\\;Release\\;MinSizeRel\\;RelWithDebInfo;-DCMAKE_NMC_CROSS_CONFIGS=all")
 run_cmake_configure(CustomCommandGenerator)