1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmComputeTargetDepends.cxx,v $
6 Date: $Date: 2009-08-24 13:54:26 $
7 Version: $Revision: 1.5 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmComputeTargetDepends.h"
19 #include "cmComputeComponentGraph.h"
20 #include "cmGlobalGenerator.h"
21 #include "cmLocalGenerator.h"
22 #include "cmMakefile.h"
23 #include "cmSystemTools.h"
33 This class is meant to analyze inter-target dependencies globally
34 during the generation step. The goal is to produce a set of direct
35 dependencies for each target such that no cycles are left and the
38 For most target types cyclic dependencies are not allowed. However
39 STATIC libraries may depend on each other in a cyclic fasion. In
40 general the directed dependency graph forms a directed-acyclic-graph
41 of strongly connected components. All strongly connected components
42 should consist of only STATIC_LIBRARY targets.
44 In order to safely break dependency cycles we must preserve all other
45 dependencies passing through the corresponding strongly connected component.
46 The approach taken by this class is as follows:
48 - Collect all targets and form the original dependency graph
49 - Run Tarjan's algorithm to extract the strongly connected components
50 (error if any member of a non-trivial component is not STATIC)
51 - The original dependencies imply a DAG on the components.
52 Use the implied DAG to construct a final safe set of dependencies.
54 The final dependency set is constructed as follows:
56 - For each connected component targets are placed in an arbitrary
57 order. Each target depends on the target following it in the order.
58 The first target is designated the head and the last target the tail.
59 (most components will be just 1 target anyway)
61 - Original dependencies between targets in different components are
62 converted to connect the depender's component tail to the
63 dependee's component head.
65 In most cases this will reproduce the original dependencies. However
66 when there are cycles of static libraries they will be broken in a
69 For example, consider targets A0, A1, A2, B0, B1, B2, and C with these
72 A0 -> A1 -> A2 -> A0 , B0 -> B1 -> B2 -> B0 -> A0 , C -> B0
74 Components may be identified as
76 Component 0: A0, A1, A2
77 Component 1: B0, B1, B2
80 Intra-component dependencies are:
82 0: A0 -> A1 -> A2 , head=A0, tail=A2
83 1: B0 -> B1 -> B2 , head=B0, tail=B2
86 The inter-component dependencies are converted as:
88 B0 -> A0 is component 1->0 and becomes B2 -> A0
89 C -> B0 is component 2->1 and becomes C -> B0
91 This leads to the final target dependencies:
93 C -> B0 -> B1 -> B2 -> A0 -> A1 -> A2
95 These produce a safe build order since C depends directly or
96 transitively on all the static libraries it links.
100 //----------------------------------------------------------------------------
101 cmComputeTargetDepends::cmComputeTargetDepends(cmGlobalGenerator
* gg
)
103 this->GlobalGenerator
= gg
;
104 cmake
* cm
= this->GlobalGenerator
->GetCMakeInstance();
105 this->DebugMode
= cm
->GetPropertyAsBool("GLOBAL_DEPENDS_DEBUG_MODE");
106 this->NoCycles
= cm
->GetPropertyAsBool("GLOBAL_DEPENDS_NO_CYCLES");
109 //----------------------------------------------------------------------------
110 cmComputeTargetDepends::~cmComputeTargetDepends()
114 //----------------------------------------------------------------------------
115 bool cmComputeTargetDepends::Compute()
117 // Build the original graph.
118 this->CollectTargets();
119 this->CollectDepends();
122 this->DisplayGraph(this->InitialGraph
, "initial");
125 // Identify components.
126 cmComputeComponentGraph
ccg(this->InitialGraph
);
129 this->DisplayComponents(ccg
);
131 if(!this->CheckComponents(ccg
))
136 // Compute the final dependency graph.
137 this->ComputeFinalDepends(ccg
);
140 this->DisplayGraph(this->FinalGraph
, "final");
146 //----------------------------------------------------------------------------
148 cmComputeTargetDepends::GetTargetDirectDepends(cmTarget
* t
,
149 std::set
<cmTarget
*>& deps
)
151 // Lookup the index for this target. All targets should be known by
153 std::map
<cmTarget
*, int>::const_iterator tii
= this->TargetIndex
.find(t
);
154 assert(tii
!= this->TargetIndex
.end());
157 // Get its final dependencies.
158 NodeList
const& nl
= this->FinalGraph
[i
];
159 for(NodeList::const_iterator ni
= nl
.begin(); ni
!= nl
.end(); ++ni
)
161 deps
.insert(this->Targets
[*ni
]);
165 //----------------------------------------------------------------------------
166 void cmComputeTargetDepends::CollectTargets()
168 // Collect all targets from all generators.
169 std::vector
<cmLocalGenerator
*> const& lgens
=
170 this->GlobalGenerator
->GetLocalGenerators();
171 for(unsigned int i
= 0; i
< lgens
.size(); ++i
)
173 cmTargets
& targets
= lgens
[i
]->GetMakefile()->GetTargets();
174 for(cmTargets::iterator ti
= targets
.begin(); ti
!= targets
.end(); ++ti
)
176 cmTarget
* target
= &ti
->second
;
177 int index
= static_cast<int>(this->Targets
.size());
178 this->TargetIndex
[target
] = index
;
179 this->Targets
.push_back(target
);
184 //----------------------------------------------------------------------------
185 void cmComputeTargetDepends::CollectDepends()
187 // Allocate the dependency graph adjacency lists.
188 this->InitialGraph
.resize(this->Targets
.size());
190 // Compute each dependency list.
191 for(unsigned int i
=0; i
< this->Targets
.size(); ++i
)
193 this->CollectTargetDepends(i
);
197 //----------------------------------------------------------------------------
198 void cmComputeTargetDepends::CollectTargetDepends(int depender_index
)
201 cmTarget
* depender
= this->Targets
[depender_index
];
203 // Keep track of dependencies already listed.
204 std::set
<cmStdString
> emitted
;
206 // A target should not depend on itself.
207 emitted
.insert(depender
->GetName());
209 // Loop over all targets linked directly.
210 cmTarget::LinkLibraryVectorType
const& tlibs
=
211 depender
->GetOriginalLinkLibraries();
212 for(cmTarget::LinkLibraryVectorType::const_iterator lib
= tlibs
.begin();
213 lib
!= tlibs
.end(); ++lib
)
215 // Don't emit the same library twice for this target.
216 if(emitted
.insert(lib
->first
).second
)
218 this->AddTargetDepend(depender_index
, lib
->first
.c_str(), true);
222 // Loop over all utility dependencies.
223 std::set
<cmStdString
> const& tutils
= depender
->GetUtilities();
224 for(std::set
<cmStdString
>::const_iterator util
= tutils
.begin();
225 util
!= tutils
.end(); ++util
)
227 // Don't emit the same utility twice for this target.
228 if(emitted
.insert(*util
).second
)
230 this->AddTargetDepend(depender_index
, util
->c_str(), false);
235 //----------------------------------------------------------------------------
236 void cmComputeTargetDepends::AddTargetDepend(int depender_index
,
237 const char* dependee_name
,
241 cmTarget
* depender
= this->Targets
[depender_index
];
243 // Check the target's makefile first.
245 depender
->GetMakefile()->FindTarget(dependee_name
);
247 // Then search globally.
250 dependee
= this->GlobalGenerator
->FindTarget(0, dependee_name
);
253 // Skip targets that will not really be linked. This is probably a
254 // name conflict between an external library and an executable
255 // within the project.
256 if(linking
&& dependee
&&
257 dependee
->GetType() == cmTarget::EXECUTABLE
&&
258 !dependee
->IsExecutableWithExports())
263 // If not found then skip then the dependee.
269 // No imported targets should have been found.
270 assert(!dependee
->IsImported());
272 // Lookup the index for this target. All targets should be known by
274 std::map
<cmTarget
*, int>::const_iterator tii
=
275 this->TargetIndex
.find(dependee
);
276 assert(tii
!= this->TargetIndex
.end());
277 int dependee_index
= tii
->second
;
279 // Add this entry to the dependency graph.
280 this->InitialGraph
[depender_index
].push_back(dependee_index
);
283 //----------------------------------------------------------------------------
285 cmComputeTargetDepends::DisplayGraph(Graph
const& graph
, const char* name
)
287 fprintf(stderr
, "The %s target dependency graph is:\n", name
);
288 int n
= static_cast<int>(graph
.size());
289 for(int depender_index
= 0; depender_index
< n
; ++depender_index
)
291 NodeList
const& nl
= graph
[depender_index
];
292 cmTarget
* depender
= this->Targets
[depender_index
];
293 fprintf(stderr
, "target %d is [%s]\n",
294 depender_index
, depender
->GetName());
295 for(NodeList::const_iterator ni
= nl
.begin(); ni
!= nl
.end(); ++ni
)
297 int dependee_index
= *ni
;
298 cmTarget
* dependee
= this->Targets
[dependee_index
];
299 fprintf(stderr
, " depends on target %d [%s]\n", dependee_index
,
300 dependee
->GetName());
303 fprintf(stderr
, "\n");
306 //----------------------------------------------------------------------------
308 cmComputeTargetDepends
309 ::DisplayComponents(cmComputeComponentGraph
const& ccg
)
311 fprintf(stderr
, "The strongly connected components are:\n");
312 std::vector
<NodeList
> const& components
= ccg
.GetComponents();
313 int n
= static_cast<int>(components
.size());
314 for(int c
= 0; c
< n
; ++c
)
316 NodeList
const& nl
= components
[c
];
317 fprintf(stderr
, "Component (%d):\n", c
);
318 for(NodeList::const_iterator ni
= nl
.begin(); ni
!= nl
.end(); ++ni
)
321 fprintf(stderr
, " contains target %d [%s]\n",
322 i
, this->Targets
[i
]->GetName());
325 fprintf(stderr
, "\n");
328 //----------------------------------------------------------------------------
330 cmComputeTargetDepends
331 ::CheckComponents(cmComputeComponentGraph
const& ccg
)
333 // All non-trivial components should consist only of static
335 std::vector
<NodeList
> const& components
= ccg
.GetComponents();
336 int nc
= static_cast<int>(components
.size());
337 for(int c
=0; c
< nc
; ++c
)
339 // Get the current component.
340 NodeList
const& nl
= components
[c
];
342 // Skip trivial components.
348 // Immediately complain if no cycles are allowed at all.
351 this->ComplainAboutBadComponent(ccg
, c
);
355 // Make sure the component is all STATIC_LIBRARY targets.
356 for(NodeList::const_iterator ni
= nl
.begin(); ni
!= nl
.end(); ++ni
)
358 if(this->Targets
[*ni
]->GetType() != cmTarget::STATIC_LIBRARY
)
360 this->ComplainAboutBadComponent(ccg
, c
);
368 //----------------------------------------------------------------------------
370 cmComputeTargetDepends
371 ::ComplainAboutBadComponent(cmComputeComponentGraph
const& ccg
, int c
)
373 // Construct the error message.
375 e
<< "The inter-target dependency graph contains the following "
376 << "strongly connected component (cycle):\n";
377 std::vector
<NodeList
> const& components
= ccg
.GetComponents();
378 std::vector
<int> const& cmap
= ccg
.GetComponentMap();
379 NodeList
const& cl
= components
[c
];
380 for(NodeList::const_iterator ci
= cl
.begin(); ci
!= cl
.end(); ++ci
)
384 cmTarget
* depender
= this->Targets
[i
];
386 // Describe the depender.
387 e
<< " \"" << depender
->GetName() << "\" of type "
388 << cmTarget::TargetTypeNames
[depender
->GetType()] << "\n";
390 // List its dependencies that are inside the component.
391 NodeList
const& nl
= this->InitialGraph
[i
];
392 for(NodeList::const_iterator ni
= nl
.begin(); ni
!= nl
.end(); ++ni
)
397 cmTarget
* dependee
= this->Targets
[j
];
398 e
<< " depends on \"" << dependee
->GetName() << "\"\n";
404 e
<< "The GLOBAL_DEPENDS_NO_CYCLES global property is enabled, so "
405 << "cyclic dependencies are not allowed even among static libraries.";
409 e
<< "At least one of these targets is not a STATIC_LIBRARY. "
410 << "Cyclic dependencies are allowed only among static libraries.";
412 cmSystemTools::Error(e
.str().c_str());
415 //----------------------------------------------------------------------------
417 cmComputeTargetDepends
418 ::ComputeFinalDepends(cmComputeComponentGraph
const& ccg
)
420 // Get the component graph information.
421 std::vector
<NodeList
> const& components
= ccg
.GetComponents();
422 Graph
const& cgraph
= ccg
.GetComponentGraph();
424 // Allocate the final graph.
425 this->FinalGraph
.resize(0);
426 this->FinalGraph
.resize(this->InitialGraph
.size());
428 // Convert inter-component edges to connect component tails to heads.
429 int n
= static_cast<int>(cgraph
.size());
430 for(int depender_component
=0; depender_component
< n
; ++depender_component
)
432 int depender_component_tail
= components
[depender_component
].back();
433 NodeList
const& nl
= cgraph
[depender_component
];
434 for(NodeList::const_iterator ni
= nl
.begin(); ni
!= nl
.end(); ++ni
)
436 int dependee_component
= *ni
;
437 int dependee_component_head
= components
[dependee_component
].front();
438 this->FinalGraph
[depender_component_tail
]
439 .push_back(dependee_component_head
);
443 // Compute intra-component edges.
444 int nc
= static_cast<int>(components
.size());
445 for(int c
=0; c
< nc
; ++c
)
447 // Within the component each target depends on that following it.
448 NodeList
const& nl
= components
[c
];
449 NodeList::const_iterator ni
= nl
.begin();
451 for(++ni
; ni
!= nl
.end(); ++ni
)
454 this->FinalGraph
[last_i
].push_back(i
);