| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811 | 
							- /*=========================================================================
 
-   Program:   CMake - Cross-Platform Makefile Generator
 
-   Module:    $RCSfile$
 
-   Language:  C++
 
-   Date:      $Date$
 
-   Version:   $Revision$
 
-   Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
 
-   See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
 
-      This software is distributed WITHOUT ANY WARRANTY; without even
 
-      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 
-      PURPOSE.  See the above copyright notices for more information.
 
- =========================================================================*/
 
- #include "cmComputeLinkDepends.h"
 
- #include "cmComputeComponentGraph.h"
 
- #include "cmGlobalGenerator.h"
 
- #include "cmLocalGenerator.h"
 
- #include "cmMakefile.h"
 
- #include "cmTarget.h"
 
- #include "cmake.h"
 
- #include <cmsys/stl/algorithm>
 
- #include <assert.h>
 
- /*
 
- This file computes an ordered list of link items to use when linking a
 
- single target in one configuration.  Each link item is identified by
 
- the string naming it.  A graph of dependencies is created in which
 
- each node corresponds to one item and directed eges lead from nodes to
 
- those which must *precede* them on the link line.  For example, the
 
- graph
 
-   C -> B -> A
 
- will lead to the link line order
 
-   A B C
 
- The set of items placed in the graph is formed with a breadth-first
 
- search of the link dependencies starting from the main target.
 
- There are two types of items: those with known direct dependencies and
 
- those without known dependencies.  We will call the two types "known
 
- items" and "unknown items", respecitvely.  Known items are those whose
 
- names correspond to targets (built or imported) and those for which an
 
- old-style <item>_LIB_DEPENDS variable is defined.  All other items are
 
- unknown and we must infer dependencies for them.
 
- Known items have dependency lists ordered based on how the user
 
- specified them.  We can use this order to infer potential dependencies
 
- of unknown items.  For example, if link items A and B are unknown and
 
- items X and Y are known, then we might have the following dependency
 
- lists:
 
-   X: Y A B
 
-   Y: A B
 
- The explicitly known dependencies form graph edges
 
-   X <- Y  ,  X <- A  ,  X <- B  ,  Y <- A  ,  Y <- B
 
- We can also infer the edge
 
-   A <- B
 
- because *every* time A appears B is seen on its right.  We do not know
 
- whether A really needs symbols from B to link, but it *might* so we
 
- must preserve their order.  This is the case also for the following
 
- explict lists:
 
-   X: A B Y
 
-   Y: A B
 
- Here, A is followed by the set {B,Y} in one list, and {B} in the other
 
- list.  The intersection of these sets is {B}, so we can infer that A
 
- depends on at most B.  Meanwhile B is followed by the set {Y} in one
 
- list and {} in the other.  The intersection is {} so we can infer that
 
- B has no dependencies.
 
- Let's make a more complex example by adding unknown item C and
 
- considering these dependency lists:
 
-   X: A B Y C
 
-   Y: A C B
 
- The explicit edges are
 
-   X <- Y  ,  X <- A  ,  X <- B  ,  X <- C  ,  Y <- A  ,  Y <- B  ,  Y <- C
 
- For the unknown items, we infer dependencies by looking at the
 
- "follow" sets:
 
-   A: intersect( {B,Y,C} , {C,B} ) = {B,C} ; infer edges  A <- B  ,  A <- C
 
-   B: intersect( {Y,C}   , {}    ) = {}    ; infer no edges
 
-   C: intersect( {}      , {B}   ) = {}    ; infer no edges
 
- ------------------------------------------------------------------------------
 
- Once the complete graph is formed from all known and inferred
 
- dependencies we must use it to produce a valid link line.  If the
 
- dependency graph were known to be acyclic a simple depth-first-search
 
- would produce a correct link line.  Unfortunately we cannot make this
 
- assumption so the following technique is used.
 
- The original graph is converted to a directed acyclic graph in which
 
- each node corresponds to a strongly connected component of the
 
- original graph.  For example, the dependency graph
 
-   X <- A <- B <- C <- A <- Y
 
- contains strongly connected components {X}, {A,B,C}, and {Y}.  The
 
- implied directed acyclic graph (DAG) is
 
-   {X} <- {A,B,C} <- {Y}
 
- The final list of link items is constructed by a series of
 
- depth-first-searches through this DAG of components.  When visiting a
 
- component all outgoing edges are followed first because the neighbors
 
- must precede it.  Once neighbors across all edges have been emitted it
 
- is safe to emit the current component.
 
- Trivial components (those with one item) are handled simply by
 
- emitting the item.  Non-trivial components (those with more than one
 
- item) are assumed to consist only of static libraries that may be
 
- safely repeated on the link line.  We emit members of the component
 
- multiple times (see code below for details).  The final link line for
 
- the example graph might be
 
-   X A B C A B C Y
 
- ------------------------------------------------------------------------------
 
- The initial exploration of dependencies using a BFS associates an
 
- integer index with each link item.  When the graph is built outgoing
 
- edges are sorted by this index.
 
- This preserves the original link
 
- order as much as possible subject to the dependencies.
 
- After the initial exploration of the link interface tree, any
 
- transitive (dependent) shared libraries that were encountered and not
 
- included in the interface are processed in their own BFS.  This BFS
 
- follows only the dependent library lists and not the link interfaces.
 
- They are added to the link items with a mark indicating that the are
 
- transitive dependencies.  Then cmComputeLinkInformation deals with
 
- them on a per-platform basis.
 
- */
 
- //----------------------------------------------------------------------------
 
- cmComputeLinkDepends
 
- ::cmComputeLinkDepends(cmTarget* target, const char* config)
 
- {
 
-   // Store context information.
 
-   this->Target = target;
 
-   this->Makefile = this->Target->GetMakefile();
 
-   this->LocalGenerator = this->Makefile->GetLocalGenerator();
 
-   this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
 
-   this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance();
 
-   // The configuration being linked.
 
-   this->Config = config;
 
-   // Enable debug mode if requested.
 
-   this->DebugMode = this->Makefile->IsOn("CMAKE_LINK_DEPENDS_DEBUG_MODE");
 
- }
 
- //----------------------------------------------------------------------------
 
- cmComputeLinkDepends::~cmComputeLinkDepends()
 
- {
 
-   for(std::vector<DependSetList*>::iterator
 
-         i = this->InferredDependSets.begin();
 
-       i != this->InferredDependSets.end(); ++i)
 
-     {
 
-     delete *i;
 
-     }
 
- }
 
- //----------------------------------------------------------------------------
 
- std::vector<cmComputeLinkDepends::LinkEntry> const&
 
- cmComputeLinkDepends::Compute()
 
- {
 
-   // Follow the link dependencies of the target to be linked.
 
-   this->AddTargetLinkEntries(-1, this->Target->GetOriginalLinkLibraries());
 
-   // Complete the breadth-first search of dependencies.
 
-   while(!this->BFSQueue.empty())
 
-     {
 
-     // Get the next entry.
 
-     BFSEntry qe = this->BFSQueue.front();
 
-     this->BFSQueue.pop();
 
-     // Follow the entry's dependencies.
 
-     this->FollowLinkEntry(qe);
 
-     }
 
-   // Complete the search of shared library dependencies.
 
-   while(!this->SharedDepQueue.empty())
 
-     {
 
-     // Handle the next entry.
 
-     this->HandleSharedDependency(this->SharedDepQueue.front());
 
-     this->SharedDepQueue.pop();
 
-     }
 
-   // Infer dependencies of targets for which they were not known.
 
-   this->InferDependencies();
 
-   // Cleanup the constraint graph.
 
-   this->CleanConstraintGraph();
 
-   // Display the constraint graph.
 
-   if(this->DebugMode)
 
-     {
 
-     fprintf(stderr,
 
-             "---------------------------------------"
 
-             "---------------------------------------\n");
 
-     fprintf(stderr, "Link dependency analysis for target %s, config %s\n",
 
-             this->Target->GetName(), this->Config?this->Config:"noconfig");
 
-     this->DisplayConstraintGraph();
 
-     }
 
-   // Compute the final set of link entries.
 
-   this->OrderLinkEntires();
 
-   // Display the final set.
 
-   if(this->DebugMode)
 
-     {
 
-     this->DisplayFinalEntries();
 
-     }
 
-   return this->FinalLinkEntries;
 
- }
 
- //----------------------------------------------------------------------------
 
- std::map<cmStdString, int>::iterator
 
- cmComputeLinkDepends::AllocateLinkEntry(std::string const& item)
 
- {
 
-   std::map<cmStdString, int>::value_type
 
-     index_entry(item, static_cast<int>(this->EntryList.size()));
 
-   std::map<cmStdString, int>::iterator
 
-     lei = this->LinkEntryIndex.insert(index_entry).first;
 
-   this->EntryList.push_back(LinkEntry());
 
-   this->InferredDependSets.push_back(0);
 
-   this->EntryConstraintGraph.push_back(NodeList());
 
-   return lei;
 
- }
 
- //----------------------------------------------------------------------------
 
- int cmComputeLinkDepends::AddLinkEntry(std::string const& item)
 
- {
 
-   // Check if the item entry has already been added.
 
-   std::map<cmStdString, int>::iterator lei = this->LinkEntryIndex.find(item);
 
-   if(lei != this->LinkEntryIndex.end())
 
-     {
 
-     // Yes.  We do not need to follow the item's dependencies again.
 
-     return lei->second;
 
-     }
 
-   // Allocate a spot for the item entry.
 
-   lei = this->AllocateLinkEntry(item);
 
-   // Initialize the item entry.
 
-   int index = lei->second;
 
-   LinkEntry& entry = this->EntryList[index];
 
-   entry.Item = item;
 
-   entry.Target = this->Makefile->FindTargetToUse(entry.Item.c_str());
 
-   // If the item has dependencies queue it to follow them.
 
-   if(entry.Target)
 
-     {
 
-     // Target dependencies are always known.  Follow them.
 
-     BFSEntry qe = {index, 0};
 
-     this->BFSQueue.push(qe);
 
-     }
 
-   else
 
-     {
 
-     // Look for an old-style <item>_LIB_DEPENDS variable.
 
-     std::string var = entry.Item;
 
-     var += "_LIB_DEPENDS";
 
-     if(const char* val = this->Makefile->GetDefinition(var.c_str()))
 
-       {
 
-       // The item dependencies are known.  Follow them.
 
-       BFSEntry qe = {index, val};
 
-       this->BFSQueue.push(qe);
 
-       }
 
-     else
 
-       {
 
-       // The item dependencies are not known.  We need to infer them.
 
-       this->InferredDependSets[index] = new DependSetList;
 
-       }
 
-     }
 
-   return index;
 
- }
 
- //----------------------------------------------------------------------------
 
- void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
 
- {
 
-   // Get this entry representation.
 
-   int depender_index = qe.Index;
 
-   LinkEntry const& entry = this->EntryList[depender_index];
 
-   // Follow the item's dependencies.
 
-   if(entry.Target)
 
-     {
 
-     // Follow the target dependencies.
 
-     if(cmTargetLinkInterface const* iface =
 
-        entry.Target->GetLinkInterface(this->Config))
 
-       {
 
-       // This target provides its own link interface information.
 
-       this->AddLinkEntries(depender_index, iface->Libraries);
 
-       // Handle dependent shared libraries.
 
-       this->QueueSharedDependencies(depender_index, iface->SharedDeps);
 
-       }
 
-     else if(!entry.Target->IsImported() &&
 
-             entry.Target->GetType() != cmTarget::EXECUTABLE)
 
-       {
 
-       // Use the target's link implementation as the interface.
 
-       this->AddTargetLinkEntries(depender_index,
 
-                                  entry.Target->GetOriginalLinkLibraries());
 
-       }
 
-     }
 
-   else
 
-     {
 
-     // Follow the old-style dependency list.
 
-     this->AddVarLinkEntries(depender_index, qe.LibDepends);
 
-     }
 
- }
 
- //----------------------------------------------------------------------------
 
- void
 
- cmComputeLinkDepends
 
- ::QueueSharedDependencies(int depender_index,
 
-                           std::vector<std::string> const& deps)
 
- {
 
-   for(std::vector<std::string>::const_iterator li = deps.begin();
 
-       li != deps.end(); ++li)
 
-     {
 
-     SharedDepEntry qe;
 
-     qe.Item = *li;
 
-     qe.DependerIndex = depender_index;
 
-     this->SharedDepQueue.push(qe);
 
-     }
 
- }
 
- //----------------------------------------------------------------------------
 
- void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
 
- {
 
-   // Check if the target already has an entry.
 
-   std::map<cmStdString, int>::iterator lei =
 
-     this->LinkEntryIndex.find(dep.Item);
 
-   if(lei == this->LinkEntryIndex.end())
 
-     {
 
-     // Allocate a spot for the item entry.
 
-     lei = this->AllocateLinkEntry(dep.Item);
 
-     // Initialize the item entry.
 
-     LinkEntry& entry = this->EntryList[lei->second];
 
-     entry.Item = dep.Item;
 
-     entry.Target = this->Makefile->FindTargetToUse(dep.Item.c_str());
 
-     // This item was added specifically because it is a dependent
 
-     // shared library.  It may get special treatment
 
-     // in cmComputeLinkInformation.
 
-     entry.IsSharedDep = true;
 
-     }
 
-   // Get the link entry for this target.
 
-   int index = lei->second;
 
-   LinkEntry& entry = this->EntryList[index];
 
-   // This shared library dependency must be preceded by the item that
 
-   // listed it.
 
-   this->EntryConstraintGraph[index].push_back(dep.DependerIndex);
 
-   // Target items may have their own dependencies.
 
-   if(entry.Target)
 
-     {
 
-     if(cmTargetLinkInterface const* iface =
 
-        entry.Target->GetLinkInterface(this->Config))
 
-       {
 
-       // We use just the shared dependencies, not the interface.
 
-       this->QueueSharedDependencies(index, iface->SharedDeps);
 
-       }
 
-     }
 
- }
 
- //----------------------------------------------------------------------------
 
- void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
 
-                                              const char* value)
 
- {
 
-   // This is called to add the dependencies named by
 
-   // <item>_LIB_DEPENDS.  The variable contains a semicolon-separated
 
-   // list.  The list contains link-type;item pairs and just items.
 
-   std::vector<std::string> deplist;
 
-   cmSystemTools::ExpandListArgument(value, deplist);
 
-   // Compute which library configuration to link.
 
-   cmTarget::LinkLibraryType linkType = cmTarget::OPTIMIZED;
 
-   if(this->Config && cmSystemTools::UpperCase(this->Config) == "DEBUG")
 
-     {
 
-     linkType = cmTarget::DEBUG;
 
-     }
 
-   // Look for entries meant for this configuration.
 
-   std::vector<std::string> actual_libs;
 
-   cmTarget::LinkLibraryType llt = cmTarget::GENERAL;
 
-   bool haveLLT = false;
 
-   for(std::vector<std::string>::const_iterator di = deplist.begin();
 
-       di != deplist.end(); ++di)
 
-     {
 
-     if(*di == "debug")
 
-       {
 
-       llt = cmTarget::DEBUG;
 
-       haveLLT = true;
 
-       }
 
-     else if(*di == "optimized")
 
-       {
 
-       llt = cmTarget::OPTIMIZED;
 
-       haveLLT = true;
 
-       }
 
-     else if(*di == "general")
 
-       {
 
-       llt = cmTarget::GENERAL;
 
-       haveLLT = true;
 
-       }
 
-     else if(!di->empty())
 
-       {
 
-       // If no explicit link type was given prior to this entry then
 
-       // check if the entry has its own link type variable.  This is
 
-       // needed for compatibility with dependency files generated by
 
-       // the export_library_dependencies command from CMake 2.4 and
 
-       // lower.
 
-       if(!haveLLT)
 
-         {
 
-         std::string var = *di;
 
-         var += "_LINK_TYPE";
 
-         if(const char* val = this->Makefile->GetDefinition(var.c_str()))
 
-           {
 
-           if(strcmp(val, "debug") == 0)
 
-             {
 
-             llt = cmTarget::DEBUG;
 
-             }
 
-           else if(strcmp(val, "optimized") == 0)
 
-             {
 
-             llt = cmTarget::OPTIMIZED;
 
-             }
 
-           }
 
-         }
 
-       // If the library is meant for this link type then use it.
 
-       if(llt == cmTarget::GENERAL || llt == linkType)
 
-         {
 
-         actual_libs.push_back(*di);
 
-         }
 
-       // Reset the link type until another explicit type is given.
 
-       llt = cmTarget::GENERAL;
 
-       haveLLT = false;
 
-       }
 
-     }
 
-   // Add the entries from this list.
 
-   this->AddLinkEntries(depender_index, actual_libs);
 
- }
 
- //----------------------------------------------------------------------------
 
- void
 
- cmComputeLinkDepends::AddTargetLinkEntries(int depender_index,
 
-                                            LinkLibraryVectorType const& libs)
 
- {
 
-   // Compute which library configuration to link.
 
-   cmTarget::LinkLibraryType linkType = cmTarget::OPTIMIZED;
 
-   if(this->Config && cmSystemTools::UpperCase(this->Config) == "DEBUG")
 
-     {
 
-     linkType = cmTarget::DEBUG;
 
-     }
 
-   // Look for entries meant for this configuration.
 
-   std::vector<std::string> actual_libs;
 
-   for(cmTarget::LinkLibraryVectorType::const_iterator li = libs.begin();
 
-       li != libs.end(); ++li)
 
-     {
 
-     if(li->second == cmTarget::GENERAL || li->second == linkType)
 
-       {
 
-       actual_libs.push_back(li->first);
 
-       }
 
-     }
 
-   // Add these entries.
 
-   this->AddLinkEntries(depender_index, actual_libs);
 
- }
 
- //----------------------------------------------------------------------------
 
- void
 
- cmComputeLinkDepends::AddLinkEntries(int depender_index,
 
-                                      std::vector<std::string> const& libs)
 
- {
 
-   // Track inferred dependency sets implied by this list.
 
-   std::map<int, DependSet> dependSets;
 
-   // Loop over the libraries linked directly by the depender.
 
-   for(std::vector<std::string>::const_iterator li = libs.begin();
 
-       li != libs.end(); ++li)
 
-     {
 
-     // Skip entries that will resolve to the target getting linked or
 
-     // are empty.
 
-     std::string item = this->CleanItemName(*li);
 
-     if(item == this->Target->GetName() || item.empty())
 
-       {
 
-       continue;
 
-       }
 
-     // Add a link entry for this item.
 
-     int dependee_index = this->AddLinkEntry(item);
 
-     // The depender must come before the dependee.
 
-     if(depender_index >= 0)
 
-       {
 
-       this->EntryConstraintGraph[dependee_index].push_back(depender_index);
 
-       }
 
-     // Update the inferred dependencies for earlier items.
 
-     for(std::map<int, DependSet>::iterator dsi = dependSets.begin();
 
-         dsi != dependSets.end(); ++dsi)
 
-       {
 
-       if(dependee_index != dsi->first)
 
-         {
 
-         dsi->second.insert(dependee_index);
 
-         }
 
-       }
 
-     // If this item needs to have dependencies inferred, do so.
 
-     if(this->InferredDependSets[dependee_index])
 
-       {
 
-       // Make sure an entry exists to hold the set for the item.
 
-       dependSets[dependee_index];
 
-       }
 
-     }
 
-   // Store the inferred dependency sets discovered for this list.
 
-   for(std::map<int, DependSet>::iterator dsi = dependSets.begin();
 
-       dsi != dependSets.end(); ++dsi)
 
-     {
 
-     this->InferredDependSets[dsi->first]->push_back(dsi->second);
 
-     }
 
- }
 
- //----------------------------------------------------------------------------
 
- std::string cmComputeLinkDepends::CleanItemName(std::string const& item)
 
- {
 
-   // Strip whitespace off the library names because we used to do this
 
-   // in case variables were expanded at generate time.  We no longer
 
-   // do the expansion but users link to libraries like " ${VAR} ".
 
-   std::string lib = item;
 
-   std::string::size_type pos = lib.find_first_not_of(" \t\r\n");
 
-   if(pos != lib.npos)
 
-     {
 
-     lib = lib.substr(pos, lib.npos);
 
-     }
 
-   pos = lib.find_last_not_of(" \t\r\n");
 
-   if(pos != lib.npos)
 
-     {
 
-     lib = lib.substr(0, pos+1);
 
-     }
 
-   if(lib != item)
 
-     {
 
-     switch(this->Target->GetPolicyStatusCMP0004())
 
-       {
 
-       case cmPolicies::WARN:
 
-         {
 
-         cmOStringStream w;
 
-         w << (this->Makefile->GetPolicies()
 
-               ->GetPolicyWarning(cmPolicies::CMP0004)) << "\n"
 
-           << "Target \"" << this->Target->GetName() << "\" links to item \""
 
-           << item << "\" which has leading or trailing whitespace.";
 
-         this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(),
 
-                                           this->Target->GetBacktrace());
 
-         }
 
-       case cmPolicies::OLD:
 
-         break;
 
-       case cmPolicies::NEW:
 
-         {
 
-         cmOStringStream e;
 
-         e << "Target \"" << this->Target->GetName() << "\" links to item \""
 
-           << item << "\" which has leading or trailing whitespace.  "
 
-           << "This is now an error according to policy CMP0004.";
 
-         this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(),
 
-                                           this->Target->GetBacktrace());
 
-         }
 
-         break;
 
-       case cmPolicies::REQUIRED_IF_USED:
 
-       case cmPolicies::REQUIRED_ALWAYS:
 
-         {
 
-         cmOStringStream e;
 
-         e << (this->Makefile->GetPolicies()
 
-               ->GetRequiredPolicyError(cmPolicies::CMP0004)) << "\n"
 
-           << "Target \"" << this->Target->GetName() << "\" links to item \""
 
-           << item << "\" which has leading or trailing whitespace.";
 
-         this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(),
 
-                                           this->Target->GetBacktrace());
 
-         }
 
-         break;
 
-       }
 
-     }
 
-   return lib;
 
- }
 
- //----------------------------------------------------------------------------
 
- void cmComputeLinkDepends::InferDependencies()
 
- {
 
-   // The inferred dependency sets for each item list the possible
 
-   // dependencies.  The intersection of the sets for one item form its
 
-   // inferred dependencies.
 
-   for(unsigned int depender_index=0;
 
-       depender_index < this->InferredDependSets.size(); ++depender_index)
 
-     {
 
-     // Skip items for which dependencies do not need to be inferred or
 
-     // for which the inferred dependency sets are empty.
 
-     DependSetList* sets = this->InferredDependSets[depender_index];
 
-     if(!sets || sets->empty())
 
-       {
 
-       continue;
 
-       }
 
-     // Intersect the sets for this item.
 
-     DependSetList::const_iterator i = sets->begin();
 
-     DependSet common = *i;
 
-     for(++i; i != sets->end(); ++i)
 
-       {
 
-       DependSet intersection;
 
-       cmsys_stl::set_intersection
 
-         (common.begin(), common.end(), i->begin(), i->end(),
 
-          std::inserter(intersection, intersection.begin()));
 
-       common = intersection;
 
-       }
 
-     // Add the inferred dependencies to the graph.
 
-     for(DependSet::const_iterator j = common.begin(); j != common.end(); ++j)
 
-       {
 
-       int dependee_index = *j;
 
-       this->EntryConstraintGraph[dependee_index].push_back(depender_index);
 
-       }
 
-     }
 
- }
 
- //----------------------------------------------------------------------------
 
- void cmComputeLinkDepends::CleanConstraintGraph()
 
- {
 
-   for(Graph::iterator i = this->EntryConstraintGraph.begin();
 
-       i != this->EntryConstraintGraph.end(); ++i)
 
-     {
 
-     // Sort the outgoing edges for each graph node so that the
 
-     // original order will be preserved as much as possible.
 
-     cmsys_stl::sort(i->begin(), i->end());
 
-     // Make the edge list unique.
 
-     NodeList::iterator last = cmsys_stl::unique(i->begin(), i->end());
 
-     i->erase(last, i->end());
 
-     }
 
- }
 
- //----------------------------------------------------------------------------
 
- void cmComputeLinkDepends::DisplayConstraintGraph()
 
- {
 
-   // Display the graph nodes and their edges.
 
-   cmOStringStream e;
 
-   for(unsigned int i=0; i < this->EntryConstraintGraph.size(); ++i)
 
-     {
 
-     NodeList const& nl = this->EntryConstraintGraph[i];
 
-     e << "item " << i << " is [" << this->EntryList[i].Item << "]\n";
 
-     for(NodeList::const_iterator j = nl.begin(); j != nl.end(); ++j)
 
-       {
 
-       e << "  item " << *j << " must precede it\n";
 
-       }
 
-     }
 
-   fprintf(stderr, "%s\n", e.str().c_str());
 
- }
 
- //----------------------------------------------------------------------------
 
- void cmComputeLinkDepends::OrderLinkEntires()
 
- {
 
-   // Compute the DAG of strongly connected components.  The algorithm
 
-   // used by cmComputeComponentGraph should identify the components in
 
-   // the same order in which the items were originally discovered in
 
-   // the BFS.  This should preserve the original order when no
 
-   // constraints disallow it.
 
-   cmComputeComponentGraph ccg(this->EntryConstraintGraph);
 
-   Graph const& cgraph = ccg.GetComponentGraph();
 
-   if(this->DebugMode)
 
-     {
 
-     this->DisplayComponents(ccg);
 
-     }
 
-   // Setup visit tracking.
 
-   this->ComponentVisited.resize(cgraph.size(), 0);
 
-   // The component graph is guaranteed to be acyclic.  Start a DFS
 
-   // from every entry.
 
-   for(unsigned int c=0; c < cgraph.size(); ++c)
 
-     {
 
-     this->VisitComponent(ccg, c);
 
-     }
 
- }
 
- //----------------------------------------------------------------------------
 
- void
 
- cmComputeLinkDepends::DisplayComponents(cmComputeComponentGraph const& ccg)
 
- {
 
-   fprintf(stderr, "The strongly connected components are:\n");
 
-   std::vector<NodeList> const& components = ccg.GetComponents();
 
-   for(unsigned int c=0; c < components.size(); ++c)
 
-     {
 
-     fprintf(stderr, "Component (%u):\n", c);
 
-     NodeList const& nl = components[c];
 
-     for(NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
 
-       {
 
-       int i = *ni;
 
-       fprintf(stderr, "  item %d [%s]\n", i,
 
-               this->EntryList[i].Item.c_str());
 
-       }
 
-     }
 
-   fprintf(stderr, "\n");
 
- }
 
- //----------------------------------------------------------------------------
 
- void
 
- cmComputeLinkDepends::VisitComponent(cmComputeComponentGraph const& ccg,
 
-                                      unsigned int c)
 
- {
 
-   // Check if the node has already been visited.
 
-   if(this->ComponentVisited[c])
 
-     {
 
-     return;
 
-     }
 
-   // We are now visiting this component so mark it.
 
-   this->ComponentVisited[c] = 1;
 
-   // Visit the neighbors of the component first.
 
-   NodeList const& nl = ccg.GetComponentGraphEdges(c);
 
-   for(NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
 
-     {
 
-     this->VisitComponent(ccg, *ni);
 
-     }
 
-   // Now that all items required to come before this one have been
 
-   // emmitted, emit this component's items.
 
-   this->EmitComponent(ccg.GetComponent(c));
 
- }
 
- //----------------------------------------------------------------------------
 
- void cmComputeLinkDepends::EmitComponent(NodeList const& nl)
 
- {
 
-   assert(!nl.empty());
 
-   // Handle trivial components.
 
-   if(nl.size() == 1)
 
-     {
 
-     this->FinalLinkEntries.push_back(this->EntryList[nl[0]]);
 
-     return;
 
-     }
 
-   // This is a non-trivial strongly connected component of the
 
-   // original graph.  It consists of two or more libraries (archives)
 
-   // that mutually require objects from one another.  In the worst
 
-   // case we may have to repeat the list of libraries as many times as
 
-   // there are object files in the biggest archive.  For now we just
 
-   // list them twice.
 
-   //
 
-   // The list of items in the component has been sorted by the order
 
-   // of discovery in the original BFS of dependencies.  This has the
 
-   // advantage that the item directly linked by a target requiring
 
-   // this component will come first which minimizes the number of
 
-   // repeats needed.
 
-   for(NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
 
-     {
 
-     this->FinalLinkEntries.push_back(this->EntryList[*ni]);
 
-     }
 
-   for(NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
 
-     {
 
-     this->FinalLinkEntries.push_back(this->EntryList[*ni]);
 
-     }
 
- }
 
- //----------------------------------------------------------------------------
 
- void cmComputeLinkDepends::DisplayFinalEntries()
 
- {
 
-   fprintf(stderr, "target [%s] links to:\n", this->Target->GetName());
 
-   for(std::vector<LinkEntry>::const_iterator lei =
 
-         this->FinalLinkEntries.begin();
 
-       lei != this->FinalLinkEntries.end(); ++lei)
 
-     {
 
-     if(lei->Target)
 
-       {
 
-       fprintf(stderr, "  target [%s]\n", lei->Target->GetName());
 
-       }
 
-     else
 
-       {
 
-       fprintf(stderr, "  item [%s]\n", lei->Item.c_str());
 
-       }
 
-     }
 
-   fprintf(stderr, "\n");
 
- }
 
 
  |