Introduce "generator expressions" to add_test()
[cmake.git] / Source / cmComputeLinkDepends.cxx
blobcec36ce2b6a47e8dde959441f6143694bdbb57b6
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmComputeLinkDepends.cxx,v $
5 Language: C++
6 Date: $Date: 2009-07-08 16:04:47 $
7 Version: $Revision: 1.34 $
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 "cmComputeLinkDepends.h"
19 #include "cmComputeComponentGraph.h"
20 #include "cmGlobalGenerator.h"
21 #include "cmLocalGenerator.h"
22 #include "cmMakefile.h"
23 #include "cmTarget.h"
24 #include "cmake.h"
26 #include <cmsys/stl/algorithm>
28 #include <assert.h>
32 This file computes an ordered list of link items to use when linking a
33 single target in one configuration. Each link item is identified by
34 the string naming it. A graph of dependencies is created in which
35 each node corresponds to one item and directed eges lead from nodes to
36 those which must *follow* them on the link line. For example, the
37 graph
39 A -> B -> C
41 will lead to the link line order
43 A B C
45 The set of items placed in the graph is formed with a breadth-first
46 search of the link dependencies starting from the main target.
48 There are two types of items: those with known direct dependencies and
49 those without known dependencies. We will call the two types "known
50 items" and "unknown items", respecitvely. Known items are those whose
51 names correspond to targets (built or imported) and those for which an
52 old-style <item>_LIB_DEPENDS variable is defined. All other items are
53 unknown and we must infer dependencies for them. For items that look
54 like flags (beginning with '-') we trivially infer no dependencies,
55 and do not include them in the dependencies of other items.
57 Known items have dependency lists ordered based on how the user
58 specified them. We can use this order to infer potential dependencies
59 of unknown items. For example, if link items A and B are unknown and
60 items X and Y are known, then we might have the following dependency
61 lists:
63 X: Y A B
64 Y: A B
66 The explicitly known dependencies form graph edges
68 X -> Y , X -> A , X -> B , Y -> A , Y -> B
70 We can also infer the edge
72 A -> B
74 because *every* time A appears B is seen on its right. We do not know
75 whether A really needs symbols from B to link, but it *might* so we
76 must preserve their order. This is the case also for the following
77 explict lists:
79 X: A B Y
80 Y: A B
82 Here, A is followed by the set {B,Y} in one list, and {B} in the other
83 list. The intersection of these sets is {B}, so we can infer that A
84 depends on at most B. Meanwhile B is followed by the set {Y} in one
85 list and {} in the other. The intersection is {} so we can infer that
86 B has no dependencies.
88 Let's make a more complex example by adding unknown item C and
89 considering these dependency lists:
91 X: A B Y C
92 Y: A C B
94 The explicit edges are
96 X -> Y , X -> A , X -> B , X -> C , Y -> A , Y -> B , Y -> C
98 For the unknown items, we infer dependencies by looking at the
99 "follow" sets:
101 A: intersect( {B,Y,C} , {C,B} ) = {B,C} ; infer edges A -> B , A -> C
102 B: intersect( {Y,C} , {} ) = {} ; infer no edges
103 C: intersect( {} , {B} ) = {} ; infer no edges
105 Note that targets are never inferred as dependees because outside
106 libraries should not depend on them.
108 ------------------------------------------------------------------------------
110 The initial exploration of dependencies using a BFS associates an
111 integer index with each link item. When the graph is built outgoing
112 edges are sorted by this index.
114 After the initial exploration of the link interface tree, any
115 transitive (dependent) shared libraries that were encountered and not
116 included in the interface are processed in their own BFS. This BFS
117 follows only the dependent library lists and not the link interfaces.
118 They are added to the link items with a mark indicating that the are
119 transitive dependencies. Then cmComputeLinkInformation deals with
120 them on a per-platform basis.
122 The complete graph formed from all known and inferred dependencies may
123 not be acyclic, so an acyclic version must be created.
124 The original graph is converted to a directed acyclic graph in which
125 each node corresponds to a strongly connected component of the
126 original graph. For example, the dependency graph
128 X -> A -> B -> C -> A -> Y
130 contains strongly connected components {X}, {A,B,C}, and {Y}. The
131 implied directed acyclic graph (DAG) is
133 {X} -> {A,B,C} -> {Y}
135 We then compute a topological order for the DAG nodes to serve as a
136 reference for satisfying dependencies efficiently. We perform the DFS
137 in reverse order and assign topological order indices counting down so
138 that the result is as close to the original BFS order as possible
139 without violating dependencies.
141 ------------------------------------------------------------------------------
143 The final link entry order is constructed as follows. We first walk
144 through and emit the *original* link line as specified by the user.
145 As each item is emitted, a set of pending nodes in the component DAG
146 is maintained. When a pending component has been completely seen, it
147 is removed from the pending set and its dependencies (following edges
148 of the DAG) are added. A trivial component (those with one item) is
149 complete as soon as its item is seen. A non-trivial component (one
150 with more than one item; assumed to be static libraries) is complete
151 when *all* its entries have been seen *twice* (all entries seen once,
152 then all entries seen again, not just each entry twice). A pending
153 component tracks which items have been seen and a count of how many
154 times the component needs to be seen (once for trivial components,
155 twice for non-trivial). If at any time another component finishes and
156 re-adds an already pending component, the pending component is reset
157 so that it needs to be seen in its entirety again. This ensures that
158 all dependencies of a component are satisified no matter where it
159 appears.
161 After the original link line has been completed, we append to it the
162 remaining pending components and their dependencies. This is done by
163 repeatedly emitting the first item from the first pending component
164 and following the same update rules as when traversing the original
165 link line. Since the pending components are kept in topological order
166 they are emitted with minimal repeats (we do not want to emit a
167 component just to have it added again when another component is
168 completed later). This process continues until no pending components
169 remain. We know it will terminate because the component graph is
170 guaranteed to be acyclic.
172 The final list of items produced by this procedure consists of the
173 original user link line followed by minimal additional items needed to
174 satisfy dependencies.
178 //----------------------------------------------------------------------------
179 cmComputeLinkDepends
180 ::cmComputeLinkDepends(cmTarget* target, const char* config)
182 // Store context information.
183 this->Target = target;
184 this->Makefile = this->Target->GetMakefile();
185 this->LocalGenerator = this->Makefile->GetLocalGenerator();
186 this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
187 this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance();
189 // The configuration being linked.
190 this->Config = (config && *config)? config : 0;
191 this->LinkType = this->Target->ComputeLinkType(this->Config);
193 // Enable debug mode if requested.
194 this->DebugMode = this->Makefile->IsOn("CMAKE_LINK_DEPENDS_DEBUG_MODE");
196 // Assume no compatibility until set.
197 this->OldLinkDirMode = false;
199 // No computation has been done.
200 this->CCG = 0;
203 //----------------------------------------------------------------------------
204 cmComputeLinkDepends::~cmComputeLinkDepends()
206 for(std::vector<DependSetList*>::iterator
207 i = this->InferredDependSets.begin();
208 i != this->InferredDependSets.end(); ++i)
210 delete *i;
212 delete this->CCG;
215 //----------------------------------------------------------------------------
216 void cmComputeLinkDepends::SetOldLinkDirMode(bool b)
218 this->OldLinkDirMode = b;
221 //----------------------------------------------------------------------------
222 std::vector<cmComputeLinkDepends::LinkEntry> const&
223 cmComputeLinkDepends::Compute()
225 // Follow the link dependencies of the target to be linked.
226 this->AddDirectLinkEntries();
228 // Complete the breadth-first search of dependencies.
229 while(!this->BFSQueue.empty())
231 // Get the next entry.
232 BFSEntry qe = this->BFSQueue.front();
233 this->BFSQueue.pop();
235 // Follow the entry's dependencies.
236 this->FollowLinkEntry(qe);
239 // Complete the search of shared library dependencies.
240 while(!this->SharedDepQueue.empty())
242 // Handle the next entry.
243 this->HandleSharedDependency(this->SharedDepQueue.front());
244 this->SharedDepQueue.pop();
247 // Infer dependencies of targets for which they were not known.
248 this->InferDependencies();
250 // Cleanup the constraint graph.
251 this->CleanConstraintGraph();
253 // Display the constraint graph.
254 if(this->DebugMode)
256 fprintf(stderr,
257 "---------------------------------------"
258 "---------------------------------------\n");
259 fprintf(stderr, "Link dependency analysis for target %s, config %s\n",
260 this->Target->GetName(), this->Config?this->Config:"noconfig");
261 this->DisplayConstraintGraph();
264 // Compute the final ordering.
265 this->OrderLinkEntires();
267 // Compute the final set of link entries.
268 for(std::vector<int>::const_iterator li = this->FinalLinkOrder.begin();
269 li != this->FinalLinkOrder.end(); ++li)
271 this->FinalLinkEntries.push_back(this->EntryList[*li]);
274 // Display the final set.
275 if(this->DebugMode)
277 this->DisplayFinalEntries();
280 return this->FinalLinkEntries;
283 //----------------------------------------------------------------------------
284 std::map<cmStdString, int>::iterator
285 cmComputeLinkDepends::AllocateLinkEntry(std::string const& item)
287 std::map<cmStdString, int>::value_type
288 index_entry(item, static_cast<int>(this->EntryList.size()));
289 std::map<cmStdString, int>::iterator
290 lei = this->LinkEntryIndex.insert(index_entry).first;
291 this->EntryList.push_back(LinkEntry());
292 this->InferredDependSets.push_back(0);
293 this->EntryConstraintGraph.push_back(NodeList());
294 return lei;
297 //----------------------------------------------------------------------------
298 int cmComputeLinkDepends::AddLinkEntry(int depender_index,
299 std::string const& item)
301 // Check if the item entry has already been added.
302 std::map<cmStdString, int>::iterator lei = this->LinkEntryIndex.find(item);
303 if(lei != this->LinkEntryIndex.end())
305 // Yes. We do not need to follow the item's dependencies again.
306 return lei->second;
309 // Allocate a spot for the item entry.
310 lei = this->AllocateLinkEntry(item);
312 // Initialize the item entry.
313 int index = lei->second;
314 LinkEntry& entry = this->EntryList[index];
315 entry.Item = item;
316 entry.Target = this->FindTargetToLink(depender_index, entry.Item.c_str());
317 entry.IsFlag = (!entry.Target && item[0] == '-' && item[1] != 'l' &&
318 item.substr(0, 10) != "-framework");
320 // If the item has dependencies queue it to follow them.
321 if(entry.Target)
323 // Target dependencies are always known. Follow them.
324 BFSEntry qe = {index, 0};
325 this->BFSQueue.push(qe);
327 else
329 // Look for an old-style <item>_LIB_DEPENDS variable.
330 std::string var = entry.Item;
331 var += "_LIB_DEPENDS";
332 if(const char* val = this->Makefile->GetDefinition(var.c_str()))
334 // The item dependencies are known. Follow them.
335 BFSEntry qe = {index, val};
336 this->BFSQueue.push(qe);
338 else if(!entry.IsFlag)
340 // The item dependencies are not known. We need to infer them.
341 this->InferredDependSets[index] = new DependSetList;
345 return index;
348 //----------------------------------------------------------------------------
349 void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
351 // Get this entry representation.
352 int depender_index = qe.Index;
353 LinkEntry const& entry = this->EntryList[depender_index];
355 // Follow the item's dependencies.
356 if(entry.Target)
358 // Follow the target dependencies.
359 if(cmTarget::LinkInterface const* iface =
360 entry.Target->GetLinkInterface(this->Config))
362 // This target provides its own link interface information.
363 this->AddLinkEntries(depender_index, iface->Libraries);
365 // Handle dependent shared libraries.
366 this->QueueSharedDependencies(depender_index, iface->SharedDeps);
368 // Support for CMP0003.
369 for(std::vector<std::string>::const_iterator
370 oi = iface->WrongConfigLibraries.begin();
371 oi != iface->WrongConfigLibraries.end(); ++oi)
373 this->CheckWrongConfigItem(depender_index, *oi);
377 else
379 // Follow the old-style dependency list.
380 this->AddVarLinkEntries(depender_index, qe.LibDepends);
384 //----------------------------------------------------------------------------
385 void
386 cmComputeLinkDepends
387 ::QueueSharedDependencies(int depender_index,
388 std::vector<std::string> const& deps)
390 for(std::vector<std::string>::const_iterator li = deps.begin();
391 li != deps.end(); ++li)
393 SharedDepEntry qe;
394 qe.Item = *li;
395 qe.DependerIndex = depender_index;
396 this->SharedDepQueue.push(qe);
400 //----------------------------------------------------------------------------
401 void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
403 // Check if the target already has an entry.
404 std::map<cmStdString, int>::iterator lei =
405 this->LinkEntryIndex.find(dep.Item);
406 if(lei == this->LinkEntryIndex.end())
408 // Allocate a spot for the item entry.
409 lei = this->AllocateLinkEntry(dep.Item);
411 // Initialize the item entry.
412 LinkEntry& entry = this->EntryList[lei->second];
413 entry.Item = dep.Item;
414 entry.Target = this->FindTargetToLink(dep.DependerIndex,
415 dep.Item.c_str());
417 // This item was added specifically because it is a dependent
418 // shared library. It may get special treatment
419 // in cmComputeLinkInformation.
420 entry.IsSharedDep = true;
423 // Get the link entry for this target.
424 int index = lei->second;
425 LinkEntry& entry = this->EntryList[index];
427 // This shared library dependency must follow the item that listed
428 // it.
429 this->EntryConstraintGraph[dep.DependerIndex].push_back(index);
431 // Target items may have their own dependencies.
432 if(entry.Target)
434 if(cmTarget::LinkInterface const* iface =
435 entry.Target->GetLinkInterface(this->Config))
437 // We use just the shared dependencies, not the interface.
438 this->QueueSharedDependencies(index, iface->SharedDeps);
443 //----------------------------------------------------------------------------
444 void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
445 const char* value)
447 // This is called to add the dependencies named by
448 // <item>_LIB_DEPENDS. The variable contains a semicolon-separated
449 // list. The list contains link-type;item pairs and just items.
450 std::vector<std::string> deplist;
451 cmSystemTools::ExpandListArgument(value, deplist);
453 // Look for entries meant for this configuration.
454 std::vector<std::string> actual_libs;
455 cmTarget::LinkLibraryType llt = cmTarget::GENERAL;
456 bool haveLLT = false;
457 for(std::vector<std::string>::const_iterator di = deplist.begin();
458 di != deplist.end(); ++di)
460 if(*di == "debug")
462 llt = cmTarget::DEBUG;
463 haveLLT = true;
465 else if(*di == "optimized")
467 llt = cmTarget::OPTIMIZED;
468 haveLLT = true;
470 else if(*di == "general")
472 llt = cmTarget::GENERAL;
473 haveLLT = true;
475 else if(!di->empty())
477 // If no explicit link type was given prior to this entry then
478 // check if the entry has its own link type variable. This is
479 // needed for compatibility with dependency files generated by
480 // the export_library_dependencies command from CMake 2.4 and
481 // lower.
482 if(!haveLLT)
484 std::string var = *di;
485 var += "_LINK_TYPE";
486 if(const char* val = this->Makefile->GetDefinition(var.c_str()))
488 if(strcmp(val, "debug") == 0)
490 llt = cmTarget::DEBUG;
492 else if(strcmp(val, "optimized") == 0)
494 llt = cmTarget::OPTIMIZED;
499 // If the library is meant for this link type then use it.
500 if(llt == cmTarget::GENERAL || llt == this->LinkType)
502 actual_libs.push_back(*di);
504 else if(this->OldLinkDirMode)
506 this->CheckWrongConfigItem(depender_index, *di);
509 // Reset the link type until another explicit type is given.
510 llt = cmTarget::GENERAL;
511 haveLLT = false;
515 // Add the entries from this list.
516 this->AddLinkEntries(depender_index, actual_libs);
519 //----------------------------------------------------------------------------
520 void cmComputeLinkDepends::AddDirectLinkEntries()
522 // Add direct link dependencies in this configuration.
523 cmTarget::LinkImplementation const* impl =
524 this->Target->GetLinkImplementation(this->Config);
525 this->AddLinkEntries(-1, impl->Libraries);
526 for(std::vector<std::string>::const_iterator
527 wi = impl->WrongConfigLibraries.begin();
528 wi != impl->WrongConfigLibraries.end(); ++wi)
530 this->CheckWrongConfigItem(-1, *wi);
534 //----------------------------------------------------------------------------
535 void
536 cmComputeLinkDepends::AddLinkEntries(int depender_index,
537 std::vector<std::string> const& libs)
539 // Track inferred dependency sets implied by this list.
540 std::map<int, DependSet> dependSets;
542 // Loop over the libraries linked directly by the depender.
543 for(std::vector<std::string>::const_iterator li = libs.begin();
544 li != libs.end(); ++li)
546 // Skip entries that will resolve to the target getting linked or
547 // are empty.
548 std::string item = this->Target->CheckCMP0004(*li);
549 if(item == this->Target->GetName() || item.empty())
551 continue;
554 // Add a link entry for this item.
555 int dependee_index = this->AddLinkEntry(depender_index, item);
557 // The dependee must come after the depender.
558 if(depender_index >= 0)
560 this->EntryConstraintGraph[depender_index].push_back(dependee_index);
562 else
564 // This is a direct dependency of the target being linked.
565 this->OriginalEntries.push_back(dependee_index);
568 // Update the inferred dependencies for earlier items.
569 for(std::map<int, DependSet>::iterator dsi = dependSets.begin();
570 dsi != dependSets.end(); ++dsi)
572 // Add this item to the inferred dependencies of other items.
573 // Target items are never inferred dependees because unknown
574 // items are outside libraries that should not be depending on
575 // targets.
576 if(!this->EntryList[dependee_index].Target &&
577 !this->EntryList[dependee_index].IsFlag &&
578 dependee_index != dsi->first)
580 dsi->second.insert(dependee_index);
584 // If this item needs to have dependencies inferred, do so.
585 if(this->InferredDependSets[dependee_index])
587 // Make sure an entry exists to hold the set for the item.
588 dependSets[dependee_index];
592 // Store the inferred dependency sets discovered for this list.
593 for(std::map<int, DependSet>::iterator dsi = dependSets.begin();
594 dsi != dependSets.end(); ++dsi)
596 this->InferredDependSets[dsi->first]->push_back(dsi->second);
600 //----------------------------------------------------------------------------
601 cmTarget* cmComputeLinkDepends::FindTargetToLink(int depender_index,
602 const char* name)
604 // Look for a target in the scope of the depender.
605 cmMakefile* mf = this->Makefile;
606 if(depender_index >= 0)
608 if(cmTarget* depender = this->EntryList[depender_index].Target)
610 mf = depender->GetMakefile();
613 cmTarget* tgt = mf->FindTargetToUse(name);
615 // Skip targets that will not really be linked. This is probably a
616 // name conflict between an external library and an executable
617 // within the project.
618 if(tgt && tgt->GetType() == cmTarget::EXECUTABLE &&
619 !tgt->IsExecutableWithExports())
621 tgt = 0;
624 // Return the target found, if any.
625 return tgt;
628 //----------------------------------------------------------------------------
629 void cmComputeLinkDepends::InferDependencies()
631 // The inferred dependency sets for each item list the possible
632 // dependencies. The intersection of the sets for one item form its
633 // inferred dependencies.
634 for(unsigned int depender_index=0;
635 depender_index < this->InferredDependSets.size(); ++depender_index)
637 // Skip items for which dependencies do not need to be inferred or
638 // for which the inferred dependency sets are empty.
639 DependSetList* sets = this->InferredDependSets[depender_index];
640 if(!sets || sets->empty())
642 continue;
645 // Intersect the sets for this item.
646 DependSetList::const_iterator i = sets->begin();
647 DependSet common = *i;
648 for(++i; i != sets->end(); ++i)
650 DependSet intersection;
651 cmsys_stl::set_intersection
652 (common.begin(), common.end(), i->begin(), i->end(),
653 std::inserter(intersection, intersection.begin()));
654 common = intersection;
657 // Add the inferred dependencies to the graph.
658 for(DependSet::const_iterator j = common.begin(); j != common.end(); ++j)
660 int dependee_index = *j;
661 this->EntryConstraintGraph[depender_index].push_back(dependee_index);
666 //----------------------------------------------------------------------------
667 void cmComputeLinkDepends::CleanConstraintGraph()
669 for(Graph::iterator i = this->EntryConstraintGraph.begin();
670 i != this->EntryConstraintGraph.end(); ++i)
672 // Sort the outgoing edges for each graph node so that the
673 // original order will be preserved as much as possible.
674 cmsys_stl::sort(i->begin(), i->end());
676 // Make the edge list unique.
677 NodeList::iterator last = cmsys_stl::unique(i->begin(), i->end());
678 i->erase(last, i->end());
682 //----------------------------------------------------------------------------
683 void cmComputeLinkDepends::DisplayConstraintGraph()
685 // Display the graph nodes and their edges.
686 cmOStringStream e;
687 for(unsigned int i=0; i < this->EntryConstraintGraph.size(); ++i)
689 NodeList const& nl = this->EntryConstraintGraph[i];
690 e << "item " << i << " is [" << this->EntryList[i].Item << "]\n";
691 for(NodeList::const_iterator j = nl.begin(); j != nl.end(); ++j)
693 e << " item " << *j << " must follow it\n";
696 fprintf(stderr, "%s\n", e.str().c_str());
699 //----------------------------------------------------------------------------
700 void cmComputeLinkDepends::OrderLinkEntires()
702 // Compute the DAG of strongly connected components. The algorithm
703 // used by cmComputeComponentGraph should identify the components in
704 // the same order in which the items were originally discovered in
705 // the BFS. This should preserve the original order when no
706 // constraints disallow it.
707 this->CCG = new cmComputeComponentGraph(this->EntryConstraintGraph);
709 // The component graph is guaranteed to be acyclic. Start a DFS
710 // from every entry to compute a topological order for the
711 // components.
712 Graph const& cgraph = this->CCG->GetComponentGraph();
713 int n = static_cast<int>(cgraph.size());
714 this->ComponentVisited.resize(cgraph.size(), 0);
715 this->ComponentOrder.resize(cgraph.size(), n);
716 this->ComponentOrderId = n;
717 // Run in reverse order so the topological order will preserve the
718 // original order where there are no constraints.
719 for(int c = n-1; c >= 0; --c)
721 this->VisitComponent(c);
724 // Display the component graph.
725 if(this->DebugMode)
727 this->DisplayComponents();
730 // Start with the original link line.
731 for(std::vector<int>::const_iterator i = this->OriginalEntries.begin();
732 i != this->OriginalEntries.end(); ++i)
734 this->VisitEntry(*i);
737 // Now explore anything left pending. Since the component graph is
738 // guaranteed to be acyclic we know this will terminate.
739 while(!this->PendingComponents.empty())
741 // Visit one entry from the first pending component. The visit
742 // logic will update the pending components accordingly. Since
743 // the pending components are kept in topological order this will
744 // not repeat one.
745 int e = *this->PendingComponents.begin()->second.Entries.begin();
746 this->VisitEntry(e);
750 //----------------------------------------------------------------------------
751 void
752 cmComputeLinkDepends::DisplayComponents()
754 fprintf(stderr, "The strongly connected components are:\n");
755 std::vector<NodeList> const& components = this->CCG->GetComponents();
756 for(unsigned int c=0; c < components.size(); ++c)
758 fprintf(stderr, "Component (%u):\n", c);
759 NodeList const& nl = components[c];
760 for(NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
762 int i = *ni;
763 fprintf(stderr, " item %d [%s]\n", i,
764 this->EntryList[i].Item.c_str());
766 NodeList const& ol = this->CCG->GetComponentGraphEdges(c);
767 for(NodeList::const_iterator oi = ol.begin(); oi != ol.end(); ++oi)
769 fprintf(stderr, " followed by Component (%d)\n", *oi);
771 fprintf(stderr, " topo order index %d\n",
772 this->ComponentOrder[c]);
774 fprintf(stderr, "\n");
777 //----------------------------------------------------------------------------
778 void cmComputeLinkDepends::VisitComponent(unsigned int c)
780 // Check if the node has already been visited.
781 if(this->ComponentVisited[c])
783 return;
786 // We are now visiting this component so mark it.
787 this->ComponentVisited[c] = 1;
789 // Visit the neighbors of the component first.
790 // Run in reverse order so the topological order will preserve the
791 // original order where there are no constraints.
792 NodeList const& nl = this->CCG->GetComponentGraphEdges(c);
793 for(NodeList::const_reverse_iterator ni = nl.rbegin();
794 ni != nl.rend(); ++ni)
796 this->VisitComponent(*ni);
799 // Assign an ordering id to this component.
800 this->ComponentOrder[c] = --this->ComponentOrderId;
803 //----------------------------------------------------------------------------
804 void cmComputeLinkDepends::VisitEntry(int index)
806 // Include this entry on the link line.
807 this->FinalLinkOrder.push_back(index);
809 // This entry has now been seen. Update its component.
810 bool completed = false;
811 int component = this->CCG->GetComponentMap()[index];
812 std::map<int, PendingComponent>::iterator mi =
813 this->PendingComponents.find(this->ComponentOrder[component]);
814 if(mi != this->PendingComponents.end())
816 // The entry is in an already pending component.
817 PendingComponent& pc = mi->second;
819 // Remove the entry from those pending in its component.
820 pc.Entries.erase(index);
821 if(pc.Entries.empty())
823 // The complete component has been seen since it was last needed.
824 --pc.Count;
826 if(pc.Count == 0)
828 // The component has been completed.
829 this->PendingComponents.erase(mi);
830 completed = true;
832 else
834 // The whole component needs to be seen again.
835 NodeList const& nl = this->CCG->GetComponent(component);
836 assert(nl.size() > 1);
837 pc.Entries.insert(nl.begin(), nl.end());
841 else
843 // The entry is not in an already pending component.
844 NodeList const& nl = this->CCG->GetComponent(component);
845 if(nl.size() > 1)
847 // This is a non-trivial component. It is now pending.
848 PendingComponent& pc = this->MakePendingComponent(component);
850 // The starting entry has already been seen.
851 pc.Entries.erase(index);
853 else
855 // This is a trivial component, so it is already complete.
856 completed = true;
860 // If the entry completed a component, the component's dependencies
861 // are now pending.
862 if(completed)
864 NodeList const& ol = this->CCG->GetComponentGraphEdges(component);
865 for(NodeList::const_iterator oi = ol.begin(); oi != ol.end(); ++oi)
867 // This entire component is now pending no matter whether it has
868 // been partially seen already.
869 this->MakePendingComponent(*oi);
874 //----------------------------------------------------------------------------
875 cmComputeLinkDepends::PendingComponent&
876 cmComputeLinkDepends::MakePendingComponent(unsigned int component)
878 // Create an entry (in topological order) for the component.
879 PendingComponent& pc =
880 this->PendingComponents[this->ComponentOrder[component]];
881 pc.Id = component;
882 NodeList const& nl = this->CCG->GetComponent(component);
884 if(nl.size() == 1)
886 // Trivial components need be seen only once.
887 pc.Count = 1;
889 else
891 // This is a non-trivial strongly connected component of the
892 // original graph. It consists of two or more libraries
893 // (archives) that mutually require objects from one another. In
894 // the worst case we may have to repeat the list of libraries as
895 // many times as there are object files in the biggest archive.
896 // For now we just list them twice.
898 // The list of items in the component has been sorted by the order
899 // of discovery in the original BFS of dependencies. This has the
900 // advantage that the item directly linked by a target requiring
901 // this component will come first which minimizes the number of
902 // repeats needed.
903 pc.Count = 2;
906 // Store the entries to be seen.
907 pc.Entries.insert(nl.begin(), nl.end());
909 return pc;
912 //----------------------------------------------------------------------------
913 void cmComputeLinkDepends::DisplayFinalEntries()
915 fprintf(stderr, "target [%s] links to:\n", this->Target->GetName());
916 for(std::vector<LinkEntry>::const_iterator lei =
917 this->FinalLinkEntries.begin();
918 lei != this->FinalLinkEntries.end(); ++lei)
920 if(lei->Target)
922 fprintf(stderr, " target [%s]\n", lei->Target->GetName());
924 else
926 fprintf(stderr, " item [%s]\n", lei->Item.c_str());
929 fprintf(stderr, "\n");
932 //----------------------------------------------------------------------------
933 void cmComputeLinkDepends::CheckWrongConfigItem(int depender_index,
934 std::string const& item)
936 if(!this->OldLinkDirMode)
938 return;
941 // For CMake 2.4 bug-compatibility we need to consider the output
942 // directories of targets linked in another configuration as link
943 // directories.
944 if(cmTarget* tgt = this->FindTargetToLink(depender_index, item.c_str()))
946 if(!tgt->IsImported())
948 this->OldWrongConfigItems.insert(tgt);