ENH: put the 64 bit paths first
[cmake.git] / Source / cmComputeTargetDepends.cxx
blob6ea3232a7fd22e1734ceb3e172fbea718734b0ef
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmComputeTargetDepends.cxx,v $
5 Language: C++
6 Date: $Date: 2008-08-06 21:48:53 $
7 Version: $Revision: 1.4 $
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(), true);
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(), false);
234 //----------------------------------------------------------------------------
235 void cmComputeTargetDepends::AddTargetDepend(int depender_index,
236 const char* dependee_name,
237 bool linking)
239 // Get the depender.
240 cmTarget* depender = this->Targets[depender_index];
242 // Check the target's makefile first.
243 cmTarget* dependee =
244 depender->GetMakefile()->FindTarget(dependee_name);
246 // Then search globally.
247 if(!dependee)
249 dependee = this->GlobalGenerator->FindTarget(0, dependee_name);
252 // Skip targets that will not really be linked. This is probably a
253 // name conflict between an external library and an executable
254 // within the project.
255 if(linking && dependee &&
256 dependee->GetType() == cmTarget::EXECUTABLE &&
257 !dependee->IsExecutableWithExports())
259 dependee = 0;
262 // If not found then skip then the dependee.
263 if(!dependee)
265 return;
268 // No imported targets should have been found.
269 assert(!dependee->IsImported());
271 // Lookup the index for this target. All targets should be known by
272 // this point.
273 std::map<cmTarget*, int>::const_iterator tii =
274 this->TargetIndex.find(dependee);
275 assert(tii != this->TargetIndex.end());
276 int dependee_index = tii->second;
278 // Add this entry to the dependency graph.
279 this->InitialGraph[depender_index].push_back(dependee_index);
282 //----------------------------------------------------------------------------
283 void
284 cmComputeTargetDepends::DisplayGraph(Graph const& graph, const char* name)
286 fprintf(stderr, "The %s target dependency graph is:\n", name);
287 int n = static_cast<int>(graph.size());
288 for(int depender_index = 0; depender_index < n; ++depender_index)
290 NodeList const& nl = graph[depender_index];
291 cmTarget* depender = this->Targets[depender_index];
292 fprintf(stderr, "target %d is [%s]\n",
293 depender_index, depender->GetName());
294 for(NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
296 int dependee_index = *ni;
297 cmTarget* dependee = this->Targets[dependee_index];
298 fprintf(stderr, " depends on target %d [%s]\n", dependee_index,
299 dependee->GetName());
302 fprintf(stderr, "\n");
305 //----------------------------------------------------------------------------
306 void
307 cmComputeTargetDepends
308 ::DisplayComponents(cmComputeComponentGraph const& ccg)
310 fprintf(stderr, "The strongly connected components are:\n");
311 std::vector<NodeList> const& components = ccg.GetComponents();
312 int n = static_cast<int>(components.size());
313 for(int c = 0; c < n; ++c)
315 NodeList const& nl = components[c];
316 fprintf(stderr, "Component (%d):\n", c);
317 for(NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
319 int i = *ni;
320 fprintf(stderr, " contains target %d [%s]\n",
321 i, this->Targets[i]->GetName());
324 fprintf(stderr, "\n");
327 //----------------------------------------------------------------------------
328 bool
329 cmComputeTargetDepends
330 ::CheckComponents(cmComputeComponentGraph const& ccg)
332 // All non-trivial components should consist only of static
333 // libraries.
334 std::vector<NodeList> const& components = ccg.GetComponents();
335 int nc = static_cast<int>(components.size());
336 for(int c=0; c < nc; ++c)
338 // Get the current component.
339 NodeList const& nl = components[c];
341 // Skip trivial components.
342 if(nl.size() < 2)
344 continue;
347 // Make sure the component is all STATIC_LIBRARY targets.
348 for(NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
350 if(this->Targets[*ni]->GetType() != cmTarget::STATIC_LIBRARY)
352 this->ComplainAboutBadComponent(ccg, c);
353 return false;
357 return true;
360 //----------------------------------------------------------------------------
361 void
362 cmComputeTargetDepends
363 ::ComplainAboutBadComponent(cmComputeComponentGraph const& ccg, int c)
365 // Construct the error message.
366 cmOStringStream e;
367 e << "The inter-target dependency graph contains the following "
368 << "strongly connected component (cycle):\n";
369 std::vector<NodeList> const& components = ccg.GetComponents();
370 std::vector<int> const& cmap = ccg.GetComponentMap();
371 NodeList const& cl = components[c];
372 for(NodeList::const_iterator ci = cl.begin(); ci != cl.end(); ++ci)
374 // Get the depender.
375 int i = *ci;
376 cmTarget* depender = this->Targets[i];
378 // Describe the depender.
379 e << " \"" << depender->GetName() << "\" of type "
380 << cmTarget::TargetTypeNames[depender->GetType()] << "\n";
382 // List its dependencies that are inside the component.
383 NodeList const& nl = this->InitialGraph[i];
384 for(NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
386 int j = *ni;
387 if(cmap[j] == c)
389 cmTarget* dependee = this->Targets[j];
390 e << " depends on \"" << dependee->GetName() << "\"\n";
394 e << "At least one of these targets is not a STATIC_LIBRARY. "
395 << "Cyclic dependencies are allowed only among static libraries.";
396 cmSystemTools::Error(e.str().c_str());
399 //----------------------------------------------------------------------------
400 void
401 cmComputeTargetDepends
402 ::ComputeFinalDepends(cmComputeComponentGraph const& ccg)
404 // Get the component graph information.
405 std::vector<NodeList> const& components = ccg.GetComponents();
406 Graph const& cgraph = ccg.GetComponentGraph();
408 // Allocate the final graph.
409 this->FinalGraph.resize(0);
410 this->FinalGraph.resize(this->InitialGraph.size());
412 // Convert inter-component edges to connect component tails to heads.
413 int n = static_cast<int>(cgraph.size());
414 for(int depender_component=0; depender_component < n; ++depender_component)
416 int depender_component_tail = components[depender_component].back();
417 NodeList const& nl = cgraph[depender_component];
418 for(NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
420 int dependee_component = *ni;
421 int dependee_component_head = components[dependee_component].front();
422 this->FinalGraph[depender_component_tail]
423 .push_back(dependee_component_head);
427 // Compute intra-component edges.
428 int nc = static_cast<int>(components.size());
429 for(int c=0; c < nc; ++c)
431 // Within the component each target depends on that following it.
432 NodeList const& nl = components[c];
433 NodeList::const_iterator ni = nl.begin();
434 int last_i = *ni;
435 for(++ni; ni != nl.end(); ++ni)
437 int i = *ni;
438 this->FinalGraph[last_i].push_back(i);
439 last_i = i;