BUG: Fix find_* search order with path suffixes
[cmake.git] / Source / cmComputeLinkDepends.cxx
blob99609e97290255ab5a41552566d7a3f753761f12
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmComputeLinkDepends.cxx,v $
5 Language: C++
6 Date: $Date: 2008-09-04 21:34:24 $
7 Version: $Revision: 1.29 $
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->AddTargetLinkEntries(-1, this->Target->GetOriginalLinkLibraries());
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(std::string const& item)
300 // Check if the item entry has already been added.
301 std::map<cmStdString, int>::iterator lei = this->LinkEntryIndex.find(item);
302 if(lei != this->LinkEntryIndex.end())
304 // Yes. We do not need to follow the item's dependencies again.
305 return lei->second;
308 // Allocate a spot for the item entry.
309 lei = this->AllocateLinkEntry(item);
311 // Initialize the item entry.
312 int index = lei->second;
313 LinkEntry& entry = this->EntryList[index];
314 entry.Item = item;
315 entry.Target = this->FindTargetToLink(entry.Item.c_str());
316 entry.IsFlag = (!entry.Target && item[0] == '-' && item[1] != 'l' &&
317 item.substr(0, 10) != "-framework");
319 // If the item has dependencies queue it to follow them.
320 if(entry.Target)
322 // Target dependencies are always known. Follow them.
323 BFSEntry qe = {index, 0};
324 this->BFSQueue.push(qe);
326 else
328 // Look for an old-style <item>_LIB_DEPENDS variable.
329 std::string var = entry.Item;
330 var += "_LIB_DEPENDS";
331 if(const char* val = this->Makefile->GetDefinition(var.c_str()))
333 // The item dependencies are known. Follow them.
334 BFSEntry qe = {index, val};
335 this->BFSQueue.push(qe);
337 else if(!entry.IsFlag)
339 // The item dependencies are not known. We need to infer them.
340 this->InferredDependSets[index] = new DependSetList;
344 return index;
347 //----------------------------------------------------------------------------
348 void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
350 // Get this entry representation.
351 int depender_index = qe.Index;
352 LinkEntry const& entry = this->EntryList[depender_index];
354 // Follow the item's dependencies.
355 if(entry.Target)
357 // Follow the target dependencies.
358 if(cmTargetLinkInterface const* iface =
359 entry.Target->GetLinkInterface(this->Config))
361 // This target provides its own link interface information.
362 this->AddLinkEntries(depender_index, iface->Libraries);
364 // Handle dependent shared libraries.
365 this->QueueSharedDependencies(depender_index, iface->SharedDeps);
367 else if(!entry.Target->IsImported() &&
368 entry.Target->GetType() != cmTarget::EXECUTABLE)
370 // Use the target's link implementation as the interface.
371 this->AddTargetLinkEntries(depender_index,
372 entry.Target->GetOriginalLinkLibraries());
375 else
377 // Follow the old-style dependency list.
378 this->AddVarLinkEntries(depender_index, qe.LibDepends);
382 //----------------------------------------------------------------------------
383 void
384 cmComputeLinkDepends
385 ::QueueSharedDependencies(int depender_index,
386 std::vector<std::string> const& deps)
388 for(std::vector<std::string>::const_iterator li = deps.begin();
389 li != deps.end(); ++li)
391 SharedDepEntry qe;
392 qe.Item = *li;
393 qe.DependerIndex = depender_index;
394 this->SharedDepQueue.push(qe);
398 //----------------------------------------------------------------------------
399 void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
401 // Check if the target already has an entry.
402 std::map<cmStdString, int>::iterator lei =
403 this->LinkEntryIndex.find(dep.Item);
404 if(lei == this->LinkEntryIndex.end())
406 // Allocate a spot for the item entry.
407 lei = this->AllocateLinkEntry(dep.Item);
409 // Initialize the item entry.
410 LinkEntry& entry = this->EntryList[lei->second];
411 entry.Item = dep.Item;
412 entry.Target = this->FindTargetToLink(dep.Item.c_str());
414 // This item was added specifically because it is a dependent
415 // shared library. It may get special treatment
416 // in cmComputeLinkInformation.
417 entry.IsSharedDep = true;
420 // Get the link entry for this target.
421 int index = lei->second;
422 LinkEntry& entry = this->EntryList[index];
424 // This shared library dependency must follow the item that listed
425 // it.
426 this->EntryConstraintGraph[dep.DependerIndex].push_back(index);
428 // Target items may have their own dependencies.
429 if(entry.Target)
431 if(cmTargetLinkInterface const* iface =
432 entry.Target->GetLinkInterface(this->Config))
434 // We use just the shared dependencies, not the interface.
435 this->QueueSharedDependencies(index, iface->SharedDeps);
440 //----------------------------------------------------------------------------
441 void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
442 const char* value)
444 // This is called to add the dependencies named by
445 // <item>_LIB_DEPENDS. The variable contains a semicolon-separated
446 // list. The list contains link-type;item pairs and just items.
447 std::vector<std::string> deplist;
448 cmSystemTools::ExpandListArgument(value, deplist);
450 // Look for entries meant for this configuration.
451 std::vector<std::string> actual_libs;
452 cmTarget::LinkLibraryType llt = cmTarget::GENERAL;
453 bool haveLLT = false;
454 for(std::vector<std::string>::const_iterator di = deplist.begin();
455 di != deplist.end(); ++di)
457 if(*di == "debug")
459 llt = cmTarget::DEBUG;
460 haveLLT = true;
462 else if(*di == "optimized")
464 llt = cmTarget::OPTIMIZED;
465 haveLLT = true;
467 else if(*di == "general")
469 llt = cmTarget::GENERAL;
470 haveLLT = true;
472 else if(!di->empty())
474 // If no explicit link type was given prior to this entry then
475 // check if the entry has its own link type variable. This is
476 // needed for compatibility with dependency files generated by
477 // the export_library_dependencies command from CMake 2.4 and
478 // lower.
479 if(!haveLLT)
481 std::string var = *di;
482 var += "_LINK_TYPE";
483 if(const char* val = this->Makefile->GetDefinition(var.c_str()))
485 if(strcmp(val, "debug") == 0)
487 llt = cmTarget::DEBUG;
489 else if(strcmp(val, "optimized") == 0)
491 llt = cmTarget::OPTIMIZED;
496 // If the library is meant for this link type then use it.
497 if(llt == cmTarget::GENERAL || llt == this->LinkType)
499 actual_libs.push_back(*di);
501 else if(this->OldLinkDirMode)
503 this->CheckWrongConfigItem(*di);
506 // Reset the link type until another explicit type is given.
507 llt = cmTarget::GENERAL;
508 haveLLT = false;
512 // Add the entries from this list.
513 this->AddLinkEntries(depender_index, actual_libs);
516 //----------------------------------------------------------------------------
517 void
518 cmComputeLinkDepends::AddTargetLinkEntries(int depender_index,
519 LinkLibraryVectorType const& libs)
521 // Look for entries meant for this configuration.
522 std::vector<std::string> actual_libs;
523 for(cmTarget::LinkLibraryVectorType::const_iterator li = libs.begin();
524 li != libs.end(); ++li)
526 if(li->second == cmTarget::GENERAL || li->second == this->LinkType)
528 actual_libs.push_back(li->first);
530 else if(this->OldLinkDirMode)
532 this->CheckWrongConfigItem(li->first);
536 // Add these entries.
537 this->AddLinkEntries(depender_index, actual_libs);
540 //----------------------------------------------------------------------------
541 void
542 cmComputeLinkDepends::AddLinkEntries(int depender_index,
543 std::vector<std::string> const& libs)
545 // Track inferred dependency sets implied by this list.
546 std::map<int, DependSet> dependSets;
548 // Loop over the libraries linked directly by the depender.
549 for(std::vector<std::string>::const_iterator li = libs.begin();
550 li != libs.end(); ++li)
552 // Skip entries that will resolve to the target getting linked or
553 // are empty.
554 std::string item = this->CleanItemName(*li);
555 if(item == this->Target->GetName() || item.empty())
557 continue;
560 // Add a link entry for this item.
561 int dependee_index = this->AddLinkEntry(item);
563 // The dependee must come after the depender.
564 if(depender_index >= 0)
566 this->EntryConstraintGraph[depender_index].push_back(dependee_index);
568 else
570 // This is a direct dependency of the target being linked.
571 this->OriginalEntries.push_back(dependee_index);
574 // Update the inferred dependencies for earlier items.
575 for(std::map<int, DependSet>::iterator dsi = dependSets.begin();
576 dsi != dependSets.end(); ++dsi)
578 // Add this item to the inferred dependencies of other items.
579 // Target items are never inferred dependees because unknown
580 // items are outside libraries that should not be depending on
581 // targets.
582 if(!this->EntryList[dependee_index].Target &&
583 !this->EntryList[dependee_index].IsFlag &&
584 dependee_index != dsi->first)
586 dsi->second.insert(dependee_index);
590 // If this item needs to have dependencies inferred, do so.
591 if(this->InferredDependSets[dependee_index])
593 // Make sure an entry exists to hold the set for the item.
594 dependSets[dependee_index];
598 // Store the inferred dependency sets discovered for this list.
599 for(std::map<int, DependSet>::iterator dsi = dependSets.begin();
600 dsi != dependSets.end(); ++dsi)
602 this->InferredDependSets[dsi->first]->push_back(dsi->second);
606 //----------------------------------------------------------------------------
607 std::string cmComputeLinkDepends::CleanItemName(std::string const& item)
609 // Strip whitespace off the library names because we used to do this
610 // in case variables were expanded at generate time. We no longer
611 // do the expansion but users link to libraries like " ${VAR} ".
612 std::string lib = item;
613 std::string::size_type pos = lib.find_first_not_of(" \t\r\n");
614 if(pos != lib.npos)
616 lib = lib.substr(pos, lib.npos);
618 pos = lib.find_last_not_of(" \t\r\n");
619 if(pos != lib.npos)
621 lib = lib.substr(0, pos+1);
623 if(lib != item)
625 switch(this->Target->GetPolicyStatusCMP0004())
627 case cmPolicies::WARN:
629 cmOStringStream w;
630 w << (this->Makefile->GetPolicies()
631 ->GetPolicyWarning(cmPolicies::CMP0004)) << "\n"
632 << "Target \"" << this->Target->GetName() << "\" links to item \""
633 << item << "\" which has leading or trailing whitespace.";
634 this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(),
635 this->Target->GetBacktrace());
637 case cmPolicies::OLD:
638 break;
639 case cmPolicies::NEW:
641 cmOStringStream e;
642 e << "Target \"" << this->Target->GetName() << "\" links to item \""
643 << item << "\" which has leading or trailing whitespace. "
644 << "This is now an error according to policy CMP0004.";
645 this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(),
646 this->Target->GetBacktrace());
648 break;
649 case cmPolicies::REQUIRED_IF_USED:
650 case cmPolicies::REQUIRED_ALWAYS:
652 cmOStringStream e;
653 e << (this->Makefile->GetPolicies()
654 ->GetRequiredPolicyError(cmPolicies::CMP0004)) << "\n"
655 << "Target \"" << this->Target->GetName() << "\" links to item \""
656 << item << "\" which has leading or trailing whitespace.";
657 this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(),
658 this->Target->GetBacktrace());
660 break;
663 return lib;
666 //----------------------------------------------------------------------------
667 cmTarget* cmComputeLinkDepends::FindTargetToLink(const char* name)
669 // Look for a target.
670 cmTarget* tgt = this->Makefile->FindTargetToUse(name);
672 // Skip targets that will not really be linked. This is probably a
673 // name conflict between an external library and an executable
674 // within the project.
675 if(tgt && tgt->GetType() == cmTarget::EXECUTABLE &&
676 !tgt->IsExecutableWithExports())
678 tgt = 0;
681 // Return the target found, if any.
682 return tgt;
685 //----------------------------------------------------------------------------
686 void cmComputeLinkDepends::InferDependencies()
688 // The inferred dependency sets for each item list the possible
689 // dependencies. The intersection of the sets for one item form its
690 // inferred dependencies.
691 for(unsigned int depender_index=0;
692 depender_index < this->InferredDependSets.size(); ++depender_index)
694 // Skip items for which dependencies do not need to be inferred or
695 // for which the inferred dependency sets are empty.
696 DependSetList* sets = this->InferredDependSets[depender_index];
697 if(!sets || sets->empty())
699 continue;
702 // Intersect the sets for this item.
703 DependSetList::const_iterator i = sets->begin();
704 DependSet common = *i;
705 for(++i; i != sets->end(); ++i)
707 DependSet intersection;
708 cmsys_stl::set_intersection
709 (common.begin(), common.end(), i->begin(), i->end(),
710 std::inserter(intersection, intersection.begin()));
711 common = intersection;
714 // Add the inferred dependencies to the graph.
715 for(DependSet::const_iterator j = common.begin(); j != common.end(); ++j)
717 int dependee_index = *j;
718 this->EntryConstraintGraph[depender_index].push_back(dependee_index);
723 //----------------------------------------------------------------------------
724 void cmComputeLinkDepends::CleanConstraintGraph()
726 for(Graph::iterator i = this->EntryConstraintGraph.begin();
727 i != this->EntryConstraintGraph.end(); ++i)
729 // Sort the outgoing edges for each graph node so that the
730 // original order will be preserved as much as possible.
731 cmsys_stl::sort(i->begin(), i->end());
733 // Make the edge list unique.
734 NodeList::iterator last = cmsys_stl::unique(i->begin(), i->end());
735 i->erase(last, i->end());
739 //----------------------------------------------------------------------------
740 void cmComputeLinkDepends::DisplayConstraintGraph()
742 // Display the graph nodes and their edges.
743 cmOStringStream e;
744 for(unsigned int i=0; i < this->EntryConstraintGraph.size(); ++i)
746 NodeList const& nl = this->EntryConstraintGraph[i];
747 e << "item " << i << " is [" << this->EntryList[i].Item << "]\n";
748 for(NodeList::const_iterator j = nl.begin(); j != nl.end(); ++j)
750 e << " item " << *j << " must follow it\n";
753 fprintf(stderr, "%s\n", e.str().c_str());
756 //----------------------------------------------------------------------------
757 void cmComputeLinkDepends::OrderLinkEntires()
759 // Compute the DAG of strongly connected components. The algorithm
760 // used by cmComputeComponentGraph should identify the components in
761 // the same order in which the items were originally discovered in
762 // the BFS. This should preserve the original order when no
763 // constraints disallow it.
764 this->CCG = new cmComputeComponentGraph(this->EntryConstraintGraph);
766 // The component graph is guaranteed to be acyclic. Start a DFS
767 // from every entry to compute a topological order for the
768 // components.
769 Graph const& cgraph = this->CCG->GetComponentGraph();
770 int n = static_cast<int>(cgraph.size());
771 this->ComponentVisited.resize(cgraph.size(), 0);
772 this->ComponentOrder.resize(cgraph.size(), n);
773 this->ComponentOrderId = n;
774 // Run in reverse order so the topological order will preserve the
775 // original order where there are no constraints.
776 for(int c = n-1; c >= 0; --c)
778 this->VisitComponent(c);
781 // Display the component graph.
782 if(this->DebugMode)
784 this->DisplayComponents();
787 // Start with the original link line.
788 for(std::vector<int>::const_iterator i = this->OriginalEntries.begin();
789 i != this->OriginalEntries.end(); ++i)
791 this->VisitEntry(*i);
794 // Now explore anything left pending. Since the component graph is
795 // guaranteed to be acyclic we know this will terminate.
796 while(!this->PendingComponents.empty())
798 // Visit one entry from the first pending component. The visit
799 // logic will update the pending components accordingly. Since
800 // the pending components are kept in topological order this will
801 // not repeat one.
802 int e = *this->PendingComponents.begin()->second.Entries.begin();
803 this->VisitEntry(e);
807 //----------------------------------------------------------------------------
808 void
809 cmComputeLinkDepends::DisplayComponents()
811 fprintf(stderr, "The strongly connected components are:\n");
812 std::vector<NodeList> const& components = this->CCG->GetComponents();
813 for(unsigned int c=0; c < components.size(); ++c)
815 fprintf(stderr, "Component (%u):\n", c);
816 NodeList const& nl = components[c];
817 for(NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
819 int i = *ni;
820 fprintf(stderr, " item %d [%s]\n", i,
821 this->EntryList[i].Item.c_str());
823 NodeList const& ol = this->CCG->GetComponentGraphEdges(c);
824 for(NodeList::const_iterator oi = ol.begin(); oi != ol.end(); ++oi)
826 fprintf(stderr, " followed by Component (%d)\n", *oi);
828 fprintf(stderr, " topo order index %d\n",
829 this->ComponentOrder[c]);
831 fprintf(stderr, "\n");
834 //----------------------------------------------------------------------------
835 void cmComputeLinkDepends::VisitComponent(unsigned int c)
837 // Check if the node has already been visited.
838 if(this->ComponentVisited[c])
840 return;
843 // We are now visiting this component so mark it.
844 this->ComponentVisited[c] = 1;
846 // Visit the neighbors of the component first.
847 // Run in reverse order so the topological order will preserve the
848 // original order where there are no constraints.
849 NodeList const& nl = this->CCG->GetComponentGraphEdges(c);
850 for(NodeList::const_reverse_iterator ni = nl.rbegin();
851 ni != nl.rend(); ++ni)
853 this->VisitComponent(*ni);
856 // Assign an ordering id to this component.
857 this->ComponentOrder[c] = --this->ComponentOrderId;
860 //----------------------------------------------------------------------------
861 void cmComputeLinkDepends::VisitEntry(int index)
863 // Include this entry on the link line.
864 this->FinalLinkOrder.push_back(index);
866 // This entry has now been seen. Update its component.
867 bool completed = false;
868 int component = this->CCG->GetComponentMap()[index];
869 std::map<int, PendingComponent>::iterator mi =
870 this->PendingComponents.find(this->ComponentOrder[component]);
871 if(mi != this->PendingComponents.end())
873 // The entry is in an already pending component.
874 PendingComponent& pc = mi->second;
876 // Remove the entry from those pending in its component.
877 pc.Entries.erase(index);
878 if(pc.Entries.empty())
880 // The complete component has been seen since it was last needed.
881 --pc.Count;
883 if(pc.Count == 0)
885 // The component has been completed.
886 this->PendingComponents.erase(mi);
887 completed = true;
889 else
891 // The whole component needs to be seen again.
892 NodeList const& nl = this->CCG->GetComponent(component);
893 assert(nl.size() > 1);
894 pc.Entries.insert(nl.begin(), nl.end());
898 else
900 // The entry is not in an already pending component.
901 NodeList const& nl = this->CCG->GetComponent(component);
902 if(nl.size() > 1)
904 // This is a non-trivial component. It is now pending.
905 PendingComponent& pc = this->MakePendingComponent(component);
907 // The starting entry has already been seen.
908 pc.Entries.erase(index);
910 else
912 // This is a trivial component, so it is already complete.
913 completed = true;
917 // If the entry completed a component, the component's dependencies
918 // are now pending.
919 if(completed)
921 NodeList const& ol = this->CCG->GetComponentGraphEdges(component);
922 for(NodeList::const_iterator oi = ol.begin(); oi != ol.end(); ++oi)
924 // This entire component is now pending no matter whether it has
925 // been partially seen already.
926 this->MakePendingComponent(*oi);
931 //----------------------------------------------------------------------------
932 cmComputeLinkDepends::PendingComponent&
933 cmComputeLinkDepends::MakePendingComponent(unsigned int component)
935 // Create an entry (in topological order) for the component.
936 PendingComponent& pc =
937 this->PendingComponents[this->ComponentOrder[component]];
938 pc.Id = component;
939 NodeList const& nl = this->CCG->GetComponent(component);
941 if(nl.size() == 1)
943 // Trivial components need be seen only once.
944 pc.Count = 1;
946 else
948 // This is a non-trivial strongly connected component of the
949 // original graph. It consists of two or more libraries
950 // (archives) that mutually require objects from one another. In
951 // the worst case we may have to repeat the list of libraries as
952 // many times as there are object files in the biggest archive.
953 // For now we just list them twice.
955 // The list of items in the component has been sorted by the order
956 // of discovery in the original BFS of dependencies. This has the
957 // advantage that the item directly linked by a target requiring
958 // this component will come first which minimizes the number of
959 // repeats needed.
960 pc.Count = 2;
963 // Store the entries to be seen.
964 pc.Entries.insert(nl.begin(), nl.end());
966 return pc;
969 //----------------------------------------------------------------------------
970 void cmComputeLinkDepends::DisplayFinalEntries()
972 fprintf(stderr, "target [%s] links to:\n", this->Target->GetName());
973 for(std::vector<LinkEntry>::const_iterator lei =
974 this->FinalLinkEntries.begin();
975 lei != this->FinalLinkEntries.end(); ++lei)
977 if(lei->Target)
979 fprintf(stderr, " target [%s]\n", lei->Target->GetName());
981 else
983 fprintf(stderr, " item [%s]\n", lei->Item.c_str());
986 fprintf(stderr, "\n");
989 //----------------------------------------------------------------------------
990 void cmComputeLinkDepends::CheckWrongConfigItem(std::string const& item)
992 if(!this->OldLinkDirMode)
994 return;
997 // For CMake 2.4 bug-compatibility we need to consider the output
998 // directories of targets linked in another configuration as link
999 // directories.
1000 if(cmTarget* tgt = this->FindTargetToLink(item.c_str()))
1002 if(!tgt->IsImported())
1004 this->OldWrongConfigItems.insert(tgt);