Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / cmComputeTargetDepends.cxx
blobfe452e89581e7df5c52db3b4994f01943c551eef
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmComputeTargetDepends.cxx,v $
5 Language: C++
6 Date: $Date: 2008/02/07 21:14:05 $
7 Version: $Revision: 1.2 $
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"
24 #include "cmTarget.h"
25 #include "cmake.h"
27 #include <algorithm>
29 #include <assert.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
36 build order is safe.
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
67 safe manner.
69 For example, consider targets A0, A1, A2, B0, B1, B2, and C with these
70 dependencies:
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
78 Component 2: C
80 Intra-component dependencies are:
82 0: A0 -> A1 -> A2 , head=A0, tail=A2
83 1: B0 -> B1 -> B2 , head=B0, tail=B2
84 2: head=C, tail=C
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");
108 //----------------------------------------------------------------------------
109 cmComputeTargetDepends::~cmComputeTargetDepends()
113 //----------------------------------------------------------------------------
114 bool cmComputeTargetDepends::Compute()
116 // Build the original graph.
117 this->CollectTargets();
118 this->CollectDepends();
119 if(this->DebugMode)
121 this->DisplayGraph(this->InitialGraph, "initial");
124 // Identify components.
125 cmComputeComponentGraph ccg(this->InitialGraph);
126 if(this->DebugMode)
128 this->DisplayComponents(ccg);
130 if(!this->CheckComponents(ccg))
132 return false;
135 // Compute the final dependency graph.
136 this->ComputeFinalDepends(ccg);
137 if(this->DebugMode)
139 this->DisplayGraph(this->FinalGraph, "final");
142 return true;
145 //----------------------------------------------------------------------------
146 void
147 cmComputeTargetDepends::GetTargetDirectDepends(cmTarget* t,
148 std::set<cmTarget*>& deps)
150 // Lookup the index for this target. All targets should be known by
151 // this point.
152 std::map<cmTarget*, int>::const_iterator tii = this->TargetIndex.find(t);
153 assert(tii != this->TargetIndex.end());
154 int i = tii->second;
156 // Get its final dependencies.
157 NodeList const& nl = this->FinalGraph[i];
158 for(NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
160 deps.insert(this->Targets[*ni]);
164 //----------------------------------------------------------------------------
165 void cmComputeTargetDepends::CollectTargets()
167 // Collect all targets from all generators.
168 std::vector<cmLocalGenerator*> const& lgens =
169 this->GlobalGenerator->GetLocalGenerators();
170 for(unsigned int i = 0; i < lgens.size(); ++i)
172 cmTargets& targets = lgens[i]->GetMakefile()->GetTargets();
173 for(cmTargets::iterator ti = targets.begin(); ti != targets.end(); ++ti)
175 cmTarget* target = &ti->second;
176 int index = static_cast<int>(this->Targets.size());
177 this->TargetIndex[target] = index;
178 this->Targets.push_back(target);
183 //----------------------------------------------------------------------------
184 void cmComputeTargetDepends::CollectDepends()
186 // Allocate the dependency graph adjacency lists.
187 this->InitialGraph.resize(this->Targets.size());
189 // Compute each dependency list.
190 for(unsigned int i=0; i < this->Targets.size(); ++i)
192 this->CollectTargetDepends(i);
196 //----------------------------------------------------------------------------
197 void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
199 // Get the depender.
200 cmTarget* depender = this->Targets[depender_index];
202 // Keep track of dependencies already listed.
203 std::set<cmStdString> emitted;
205 // A target should not depend on itself.
206 emitted.insert(depender->GetName());
208 // Loop over all targets linked directly.
209 cmTarget::LinkLibraryVectorType const& tlibs =
210 depender->GetOriginalLinkLibraries();
211 for(cmTarget::LinkLibraryVectorType::const_iterator lib = tlibs.begin();
212 lib != tlibs.end(); ++lib)
214 // Don't emit the same library twice for this target.
215 if(emitted.insert(lib->first).second)
217 this->AddTargetDepend(depender_index, lib->first.c_str());
221 // Loop over all utility dependencies.
222 std::set<cmStdString> const& tutils = depender->GetUtilities();
223 for(std::set<cmStdString>::const_iterator util = tutils.begin();
224 util != tutils.end(); ++util)
226 // Don't emit the same utility twice for this target.
227 if(emitted.insert(*util).second)
229 this->AddTargetDepend(depender_index, util->c_str());
234 //----------------------------------------------------------------------------
235 void cmComputeTargetDepends::AddTargetDepend(int depender_index,
236 const char* dependee_name)
238 // Get the depender.
239 cmTarget* depender = this->Targets[depender_index];
241 // Check the target's makefile first.
242 cmTarget* dependee =
243 depender->GetMakefile()->FindTarget(dependee_name);
245 // Then search globally.
246 if(!dependee)
248 dependee = this->GlobalGenerator->FindTarget(0, dependee_name);
251 // If not found then skip then the dependee.
252 if(!dependee)
254 return;
257 // No imported targets should have been found.
258 assert(!dependee->IsImported());
260 // Lookup the index for this target. All targets should be known by
261 // this point.
262 std::map<cmTarget*, int>::const_iterator tii =
263 this->TargetIndex.find(dependee);
264 assert(tii != this->TargetIndex.end());
265 int dependee_index = tii->second;
267 // Add this entry to the dependency graph.
268 this->InitialGraph[depender_index].push_back(dependee_index);
271 //----------------------------------------------------------------------------
272 void
273 cmComputeTargetDepends::DisplayGraph(Graph const& graph, const char* name)
275 fprintf(stderr, "The %s target dependency graph is:\n", name);
276 int n = static_cast<int>(graph.size());
277 for(int depender_index = 0; depender_index < n; ++depender_index)
279 NodeList const& nl = graph[depender_index];
280 cmTarget* depender = this->Targets[depender_index];
281 fprintf(stderr, "target %d is [%s]\n",
282 depender_index, depender->GetName());
283 for(NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
285 int dependee_index = *ni;
286 cmTarget* dependee = this->Targets[dependee_index];
287 fprintf(stderr, " depends on target %d [%s]\n", dependee_index,
288 dependee->GetName());
291 fprintf(stderr, "\n");
294 //----------------------------------------------------------------------------
295 void
296 cmComputeTargetDepends
297 ::DisplayComponents(cmComputeComponentGraph const& ccg)
299 fprintf(stderr, "The strongly connected components are:\n");
300 std::vector<NodeList> const& components = ccg.GetComponents();
301 int n = static_cast<int>(components.size());
302 for(int c = 0; c < n; ++c)
304 NodeList const& nl = components[c];
305 fprintf(stderr, "Component (%d):\n", c);
306 for(NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
308 int i = *ni;
309 fprintf(stderr, " contains target %d [%s]\n",
310 i, this->Targets[i]->GetName());
313 fprintf(stderr, "\n");
316 //----------------------------------------------------------------------------
317 bool
318 cmComputeTargetDepends
319 ::CheckComponents(cmComputeComponentGraph const& ccg)
321 // All non-trivial components should consist only of static
322 // libraries.
323 std::vector<NodeList> const& components = ccg.GetComponents();
324 int nc = static_cast<int>(components.size());
325 for(int c=0; c < nc; ++c)
327 // Get the current component.
328 NodeList const& nl = components[c];
330 // Skip trivial components.
331 if(nl.size() < 2)
333 continue;
336 // Make sure the component is all STATIC_LIBRARY targets.
337 for(NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
339 if(this->Targets[*ni]->GetType() != cmTarget::STATIC_LIBRARY)
341 this->ComplainAboutBadComponent(ccg, c);
342 return false;
346 return true;
349 //----------------------------------------------------------------------------
350 void
351 cmComputeTargetDepends
352 ::ComplainAboutBadComponent(cmComputeComponentGraph const& ccg, int c)
354 // Construct the error message.
355 cmOStringStream e;
356 e << "The inter-target dependency graph contains the following "
357 << "strongly connected component (cycle):\n";
358 std::vector<NodeList> const& components = ccg.GetComponents();
359 std::vector<int> const& cmap = ccg.GetComponentMap();
360 NodeList const& cl = components[c];
361 for(NodeList::const_iterator ci = cl.begin(); ci != cl.end(); ++ci)
363 // Get the depender.
364 int i = *ci;
365 cmTarget* depender = this->Targets[i];
367 // Describe the depender.
368 e << " " << depender->GetName() << " of type "
369 << cmTarget::TargetTypeNames[depender->GetType()] << "\n";
371 // List its dependencies that are inside the component.
372 NodeList const& nl = this->InitialGraph[i];
373 for(NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
375 int j = *ni;
376 if(cmap[j] == c)
378 cmTarget* dependee = this->Targets[j];
379 e << " depends on " << dependee->GetName() << "\n";
383 e << "At least one of these targets is not a STATIC_LIBRARY. "
384 << "Cyclic dependencies are allowed only among static libraries.";
385 cmSystemTools::Error(e.str().c_str());
388 //----------------------------------------------------------------------------
389 void
390 cmComputeTargetDepends
391 ::ComputeFinalDepends(cmComputeComponentGraph const& ccg)
393 // Get the component graph information.
394 std::vector<NodeList> const& components = ccg.GetComponents();
395 Graph const& cgraph = ccg.GetComponentGraph();
397 // Allocate the final graph.
398 this->FinalGraph.resize(0);
399 this->FinalGraph.resize(this->InitialGraph.size());
401 // Convert inter-component edges to connect component tails to heads.
402 int n = static_cast<int>(cgraph.size());
403 for(int depender_component=0; depender_component < n; ++depender_component)
405 int depender_component_tail = components[depender_component].back();
406 NodeList const& nl = cgraph[depender_component];
407 for(NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
409 int dependee_component = *ni;
410 int dependee_component_head = components[dependee_component].front();
411 this->FinalGraph[depender_component_tail]
412 .push_back(dependee_component_head);
416 // Compute intra-component edges.
417 int nc = static_cast<int>(components.size());
418 for(int c=0; c < nc; ++c)
420 // Within the component each target depends on that following it.
421 NodeList const& nl = components[c];
422 NodeList::const_iterator ni = nl.begin();
423 int last_i = *ni;
424 for(++ni; ni != nl.end(); ++ni)
426 int i = *ni;
427 this->FinalGraph[last_i].push_back(i);
428 last_i = i;