diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index 50a63ebd9..b5cee4201 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -900,7 +900,7 @@ cmComputeLinkDepends::MakePendingComponent(unsigned int component) // advantage that the item directly linked by a target requiring // this component will come first which minimizes the number of // repeats needed. - pc.Count = 2; + pc.Count = this->ComputeComponentCount(nl); } // Store the entries to be seen. @@ -909,6 +909,27 @@ cmComputeLinkDepends::MakePendingComponent(unsigned int component) return pc; } +//---------------------------------------------------------------------------- +int cmComputeLinkDepends::ComputeComponentCount(NodeList const& nl) +{ + int count = 2; + for(NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni) + { + if(cmTarget* target = this->EntryList[*ni].Target) + { + if(cmTarget::LinkInterface const* iface = + target->GetLinkInterface(this->Config)) + { + if(iface->Multiplicity > count) + { + count = iface->Multiplicity; + } + } + } + } + return count; +} + //---------------------------------------------------------------------------- void cmComputeLinkDepends::DisplayFinalEntries() { diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index d6920101a..f31331994 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -153,6 +153,7 @@ private: void VisitComponent(unsigned int c); void VisitEntry(int index); PendingComponent& MakePendingComponent(unsigned int component); + int ComputeComponentCount(NodeList const& nl); void DisplayFinalEntries(); // Record of the original link line. diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 8c15a2622..b8ef41746 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -161,6 +161,14 @@ cmExportFileGenerator this->SetImportLinkProperty(suffix, target, "IMPORTED_LINK_DEPENDENT_LIBRARIES", iface->SharedDeps, properties); + if(iface->Multiplicity > 0) + { + std::string prop = "IMPORTED_LINK_INTERFACE_MULTIPLICITY"; + prop += suffix; + cmOStringStream m; + m << iface->Multiplicity; + properties[prop] = m.str(); + } } } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 4885b0714..8b4ac6f43 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -334,6 +334,18 @@ void cmTarget::DefineProperties(cmake *cm) "If set, this property completely overrides the generic property " "for the named configuration."); + cm->DefineProperty + ("IMPORTED_LINK_INTERFACE_MULTIPLICITY", cmProperty::TARGET, + "Repetition count for cycles of IMPORTED static libraries.", + "This is LINK_INTERFACE_MULTIPLICITY for IMPORTED targets."); + cm->DefineProperty + ("IMPORTED_LINK_INTERFACE_MULTIPLICITY_", cmProperty::TARGET, + "Per-configuration repetition count for cycles of IMPORTED archives.", + "This is the configuration-specific version of " + "IMPORTED_LINK_INTERFACE_MULTIPLICITY. " + "If set, this property completely overrides the generic property " + "for the named configuration."); + cm->DefineProperty ("IMPORTED_LOCATION", cmProperty::TARGET, "Full path to the main file on disk for an IMPORTED target.", @@ -507,6 +519,25 @@ void cmTarget::DefineProperties(cmake *cm) "If set, this property completely overrides the generic property " "for the named configuration."); + cm->DefineProperty + ("LINK_INTERFACE_MULTIPLICITY", cmProperty::TARGET, + "Repetition count for STATIC libraries with cyclic dependencies.", + "When linking to a STATIC library target with cyclic dependencies the " + "linker may need to scan more than once through the archives in the " + "strongly connected component of the dependency graph. " + "CMake by default constructs the link line so that the linker will " + "scan through the component at least twice. " + "This property specifies the minimum number of scans if it is larger " + "than the default. " + "CMake uses the largest value specified by any target in a component."); + cm->DefineProperty + ("LINK_INTERFACE_MULTIPLICITY_", cmProperty::TARGET, + "Per-configuration repetition count for cycles of STATIC libraries.", + "This is the configuration-specific version of " + "LINK_INTERFACE_MULTIPLICITY. " + "If set, this property completely overrides the generic property " + "for the named configuration."); + cm->DefineProperty ("MAP_IMPORTED_CONFIG_", cmProperty::TARGET, "Map from project configuration to IMPORTED target's configuration.", @@ -3877,6 +3908,22 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config, info.LinkInterface.Languages); } } + + // Get the cyclic repetition count. + if(this->GetType() == cmTarget::STATIC_LIBRARY) + { + std::string linkProp = "IMPORTED_LINK_INTERFACE_MULTIPLICITY"; + linkProp += suffix; + if(const char* config_reps = this->GetProperty(linkProp.c_str())) + { + sscanf(config_reps, "%u", &info.LinkInterface.Multiplicity); + } + else if(const char* reps = + this->GetProperty("IMPORTED_LINK_INTERFACE_MULTIPLICITY")) + { + sscanf(reps, "%u", &info.LinkInterface.Multiplicity); + } + } } //---------------------------------------------------------------------------- @@ -4010,6 +4057,23 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface) } } + if(this->GetType() == cmTarget::STATIC_LIBRARY) + { + // How many repetitions are needed if this library has cyclic + // dependencies? + std::string propName = "LINK_INTERFACE_MULTIPLICITY"; + propName += suffix; + if(const char* config_reps = this->GetProperty(propName.c_str())) + { + sscanf(config_reps, "%u", &iface.Multiplicity); + } + else if(const char* reps = + this->GetProperty("LINK_INTERFACE_MULTIPLICITY")) + { + sscanf(reps, "%u", &iface.Multiplicity); + } + } + return true; } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index e0118fcdc..7b8c2ba80 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -249,9 +249,15 @@ public: // Shared library dependencies needed for linking on some platforms. std::vector SharedDeps; + // Number of repetitions of a strongly connected component of two + // or more static libraries. + int Multiplicity; + // Libraries listed for other configurations. // Needed only for OLD behavior of CMP0003. std::vector WrongConfigLibraries; + + LinkInterface(): Multiplicity(0) {} }; /** Get the link interface for the given configuration. Returns 0