1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmComputeTargetDepends.cxx,v $
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"
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");
108 //----------------------------------------------------------------------------
109 cmComputeTargetDepends::~cmComputeTargetDepends()
113 //----------------------------------------------------------------------------
114 bool cmComputeTargetDepends::Compute()
116 // Build the original graph.
117 this->CollectTargets();
118 this->CollectDepends();
121 this->DisplayGraph(this->InitialGraph
, "initial");
124 // Identify components.
125 cmComputeComponentGraph
ccg(this->InitialGraph
);
128 this->DisplayComponents(ccg
);
130 if(!this->CheckComponents(ccg
))
135 // Compute the final dependency graph.
136 this->ComputeFinalDepends(ccg
);
139 this->DisplayGraph(this->FinalGraph
, "final");
145 //----------------------------------------------------------------------------
147 cmComputeTargetDepends::GetTargetDirectDepends(cmTarget
* t
,
148 std::set
<cmTarget
*>& deps
)
150 // Lookup the index for this target. All targets should be known by
152 std::map
<cmTarget
*, int>::const_iterator tii
= this->TargetIndex
.find(t
);
153 assert(tii
!= this->TargetIndex
.end());
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
)
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
,
240 cmTarget
* depender
= this->Targets
[depender_index
];
242 // Check the target's makefile first.
244 depender
->GetMakefile()->FindTarget(dependee_name
);
246 // Then search globally.
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())
262 // If not found then skip then the dependee.
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
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 //----------------------------------------------------------------------------
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 //----------------------------------------------------------------------------
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
)
320 fprintf(stderr
, " contains target %d [%s]\n",
321 i
, this->Targets
[i
]->GetName());
324 fprintf(stderr
, "\n");
327 //----------------------------------------------------------------------------
329 cmComputeTargetDepends
330 ::CheckComponents(cmComputeComponentGraph
const& ccg
)
332 // All non-trivial components should consist only of static
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.
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
);
360 //----------------------------------------------------------------------------
362 cmComputeTargetDepends
363 ::ComplainAboutBadComponent(cmComputeComponentGraph
const& ccg
, int c
)
365 // Construct the error message.
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
)
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
)
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 //----------------------------------------------------------------------------
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();
435 for(++ni
; ni
!= nl
.end(); ++ni
)
438 this->FinalGraph
[last_i
].push_back(i
);