|
|
@@ -129,7 +129,10 @@ bool cmComputeTargetDepends::Compute()
|
|
|
}
|
|
|
|
|
|
// Compute the final dependency graph.
|
|
|
- this->ComputeFinalDepends(ccg);
|
|
|
+ if(!this->ComputeFinalDepends(ccg))
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
if(this->DebugMode)
|
|
|
{
|
|
|
this->DisplayGraph(this->FinalGraph, "final");
|
|
|
@@ -368,7 +371,8 @@ cmComputeTargetDepends
|
|
|
//----------------------------------------------------------------------------
|
|
|
void
|
|
|
cmComputeTargetDepends
|
|
|
-::ComplainAboutBadComponent(cmComputeComponentGraph const& ccg, int c)
|
|
|
+::ComplainAboutBadComponent(cmComputeComponentGraph const& ccg, int c,
|
|
|
+ bool strong)
|
|
|
{
|
|
|
// Construct the error message.
|
|
|
cmOStringStream e;
|
|
|
@@ -400,7 +404,15 @@ cmComputeTargetDepends
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- if(this->NoCycles)
|
|
|
+ if(strong)
|
|
|
+ {
|
|
|
+ // Custom command executable dependencies cannot occur within a
|
|
|
+ // component of static libraries. The cycle must appear in calls
|
|
|
+ // to add_dependencies.
|
|
|
+ e << "The component contains at least one cycle consisting of strong "
|
|
|
+ << "dependencies (created by add_dependencies) that cannot be broken.";
|
|
|
+ }
|
|
|
+ else if(this->NoCycles)
|
|
|
{
|
|
|
e << "The GLOBAL_DEPENDS_NO_CYCLES global property is enabled, so "
|
|
|
<< "cyclic dependencies are not allowed even among static libraries.";
|
|
|
@@ -414,7 +426,49 @@ cmComputeTargetDepends
|
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
-void
|
|
|
+bool
|
|
|
+cmComputeTargetDepends
|
|
|
+::IntraComponent(std::vector<int> const& cmap, int c, int i, int* head,
|
|
|
+ std::set<int>& emitted, std::set<int>& visited)
|
|
|
+{
|
|
|
+ if(!visited.insert(i).second)
|
|
|
+ {
|
|
|
+ // Cycle in utility depends!
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if(emitted.insert(i).second)
|
|
|
+ {
|
|
|
+ // Honor strong intra-component edges in the final order.
|
|
|
+ EdgeList const& el = this->InitialGraph[i];
|
|
|
+ for(EdgeList::const_iterator ei = el.begin(); ei != el.end(); ++ei)
|
|
|
+ {
|
|
|
+ int j = *ei;
|
|
|
+ if(cmap[j] == c && ei->IsStrong())
|
|
|
+ {
|
|
|
+ this->FinalGraph[i].push_back(j);
|
|
|
+ if(!this->IntraComponent(cmap, c, j, head, emitted, visited))
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Prepend to a linear linked-list of intra-component edges.
|
|
|
+ if(*head >= 0)
|
|
|
+ {
|
|
|
+ this->FinalGraph[i].push_back(*head);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ this->ComponentTail[c] = i;
|
|
|
+ }
|
|
|
+ *head = i;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+bool
|
|
|
cmComputeTargetDepends
|
|
|
::ComputeFinalDepends(cmComputeComponentGraph const& ccg)
|
|
|
{
|
|
|
@@ -426,34 +480,43 @@ cmComputeTargetDepends
|
|
|
this->FinalGraph.resize(0);
|
|
|
this->FinalGraph.resize(this->InitialGraph.size());
|
|
|
|
|
|
+ // Choose intra-component edges to linearize dependencies.
|
|
|
+ std::vector<int> const& cmap = ccg.GetComponentMap();
|
|
|
+ this->ComponentHead.resize(components.size());
|
|
|
+ this->ComponentTail.resize(components.size());
|
|
|
+ int nc = static_cast<int>(components.size());
|
|
|
+ for(int c=0; c < nc; ++c)
|
|
|
+ {
|
|
|
+ int head = -1;
|
|
|
+ std::set<int> emitted;
|
|
|
+ NodeList const& nl = components[c];
|
|
|
+ for(NodeList::const_reverse_iterator ni = nl.rbegin();
|
|
|
+ ni != nl.rend(); ++ni)
|
|
|
+ {
|
|
|
+ std::set<int> visited;
|
|
|
+ if(!this->IntraComponent(cmap, c, *ni, &head, emitted, visited))
|
|
|
+ {
|
|
|
+ // Cycle in add_dependencies within component!
|
|
|
+ this->ComplainAboutBadComponent(ccg, c, true);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this->ComponentHead[c] = head;
|
|
|
+ }
|
|
|
+
|
|
|
// Convert inter-component edges to connect component tails to heads.
|
|
|
int n = static_cast<int>(cgraph.size());
|
|
|
for(int depender_component=0; depender_component < n; ++depender_component)
|
|
|
{
|
|
|
- int depender_component_tail = components[depender_component].back();
|
|
|
+ int depender_component_tail = this->ComponentTail[depender_component];
|
|
|
EdgeList const& nl = cgraph[depender_component];
|
|
|
for(EdgeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
|
|
|
{
|
|
|
int dependee_component = *ni;
|
|
|
- int dependee_component_head = components[dependee_component].front();
|
|
|
+ int dependee_component_head = this->ComponentHead[dependee_component];
|
|
|
this->FinalGraph[depender_component_tail]
|
|
|
.push_back(dependee_component_head);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- // Compute intra-component edges.
|
|
|
- int nc = static_cast<int>(components.size());
|
|
|
- for(int c=0; c < nc; ++c)
|
|
|
- {
|
|
|
- // Within the component each target depends on that following it.
|
|
|
- NodeList const& nl = components[c];
|
|
|
- NodeList::const_iterator ni = nl.begin();
|
|
|
- int last_i = *ni;
|
|
|
- for(++ni; ni != nl.end(); ++ni)
|
|
|
- {
|
|
|
- int i = *ni;
|
|
|
- this->FinalGraph[last_i].push_back(i);
|
|
|
- last_i = i;
|
|
|
- }
|
|
|
- }
|
|
|
+ return true;
|
|
|
}
|