/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmComputeLinkDepends.h"

#include "cmAlgorithms.h"
#include "cmComputeComponentGraph.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmRange.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmake.h"

#include <algorithm>
#include <assert.h>
#include <iterator>
#include <sstream>
#include <stdio.h>
#include <string.h>
#include <utility>

#include "cm_memory.hxx"

/*

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 edges lead from nodes to
those which must *follow* them on the link line.  For example, the
graph

  A -> B -> C

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", respectively.  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.  For items that look
like flags (beginning with '-') we trivially infer no dependencies,
and do not include them in the dependencies of other items.

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
explicit 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

Note that targets are never inferred as dependees because outside
libraries should not depend on them.

------------------------------------------------------------------------------

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.

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.

The complete graph formed from all known and inferred dependencies may
not be acyclic, so an acyclic version must be created.
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}

We then compute a topological order for the DAG nodes to serve as a
reference for satisfying dependencies efficiently.  We perform the DFS
in reverse order and assign topological order indices counting down so
that the result is as close to the original BFS order as possible
without violating dependencies.

------------------------------------------------------------------------------

The final link entry order is constructed as follows.  We first walk
through and emit the *original* link line as specified by the user.
As each item is emitted, a set of pending nodes in the component DAG
is maintained.  When a pending component has been completely seen, it
is removed from the pending set and its dependencies (following edges
of the DAG) are added.  A trivial component (those with one item) is
complete as soon as its item is seen.  A non-trivial component (one
with more than one item; assumed to be static libraries) is complete
when *all* its entries have been seen *twice* (all entries seen once,
then all entries seen again, not just each entry twice).  A pending
component tracks which items have been seen and a count of how many
times the component needs to be seen (once for trivial components,
twice for non-trivial).  If at any time another component finishes and
re-adds an already pending component, the pending component is reset
so that it needs to be seen in its entirety again.  This ensures that
all dependencies of a component are satisfied no matter where it
appears.

After the original link line has been completed, we append to it the
remaining pending components and their dependencies.  This is done by
repeatedly emitting the first item from the first pending component
and following the same update rules as when traversing the original
link line.  Since the pending components are kept in topological order
they are emitted with minimal repeats (we do not want to emit a
component just to have it added again when another component is
completed later).  This process continues until no pending components
remain.  We know it will terminate because the component graph is
guaranteed to be acyclic.

The final list of items produced by this procedure consists of the
original user link line followed by minimal additional items needed to
satisfy dependencies.  The final list is then filtered to de-duplicate
items that we know the linker will re-use automatically (shared libs).

*/

cmComputeLinkDepends::cmComputeLinkDepends(const cmGeneratorTarget* target,
                                           const std::string& config)
{
  // Store context information.
  this->Target = target;
  this->Makefile = this->Target->Target->GetMakefile();
  this->GlobalGenerator =
    this->Target->GetLocalGenerator()->GetGlobalGenerator();
  this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance();

  // The configuration being linked.
  this->HasConfig = !config.empty();
  this->Config = (this->HasConfig) ? config : std::string();
  std::vector<std::string> debugConfigs =
    this->Makefile->GetCMakeInstance()->GetDebugConfigs();
  this->LinkType = CMP0003_ComputeLinkType(this->Config, debugConfigs);

  // Enable debug mode if requested.
  this->DebugMode = this->Makefile->IsOn("CMAKE_LINK_DEPENDS_DEBUG_MODE");

  // Assume no compatibility until set.
  this->OldLinkDirMode = false;

  // No computation has been done.
  this->CCG = nullptr;
}

cmComputeLinkDepends::~cmComputeLinkDepends()
{
  cmDeleteAll(this->InferredDependSets);
}

void cmComputeLinkDepends::SetOldLinkDirMode(bool b)
{
  this->OldLinkDirMode = b;
}

std::vector<cmComputeLinkDepends::LinkEntry> const&
cmComputeLinkDepends::Compute()
{
  // Follow the link dependencies of the target to be linked.
  this->AddDirectLinkEntries();

  // 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().c_str(),
            this->HasConfig ? this->Config.c_str() : "noconfig");
    this->DisplayConstraintGraph();
  }

  // Compute the final ordering.
  this->OrderLinkEntires();

  // Compute the final set of link entries.
  // Iterate in reverse order so we can keep only the last occurrence
  // of a shared library.
  std::set<int> emmitted;
  for (int i : cmReverseRange(this->FinalLinkOrder)) {
    LinkEntry const& e = this->EntryList[i];
    cmGeneratorTarget const* t = e.Target;
    // Entries that we know the linker will re-use do not need to be repeated.
    bool uniquify = t && t->GetType() == cmStateEnums::SHARED_LIBRARY;
    if (!uniquify || emmitted.insert(i).second) {
      this->FinalLinkEntries.push_back(e);
    }
  }
  // Reverse the resulting order since we iterated in reverse.
  std::reverse(this->FinalLinkEntries.begin(), this->FinalLinkEntries.end());

  // Display the final set.
  if (this->DebugMode) {
    this->DisplayFinalEntries();
  }

  return this->FinalLinkEntries;
}

std::map<cmLinkItem, int>::iterator cmComputeLinkDepends::AllocateLinkEntry(
  cmLinkItem const& item)
{
  std::map<cmLinkItem, int>::value_type index_entry(
    item, static_cast<int>(this->EntryList.size()));
  std::map<cmLinkItem, int>::iterator lei =
    this->LinkEntryIndex.insert(index_entry).first;
  this->EntryList.emplace_back();
  this->InferredDependSets.push_back(nullptr);
  this->EntryConstraintGraph.emplace_back();
  return lei;
}

int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item)
{
  // Check if the item entry has already been added.
  std::map<cmLinkItem, 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.AsStr();
  entry.Target = item.Target;
  entry.IsFlag =
    (!entry.Target && entry.Item[0] == '-' && entry.Item[1] != 'l' &&
     entry.Item.substr(0, 10) != "-framework");

  // If the item has dependencies queue it to follow them.
  if (entry.Target) {
    // Target dependencies are always known.  Follow them.
    BFSEntry qe = { index, nullptr };
    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)) {
      // The item dependencies are known.  Follow them.
      BFSEntry qe = { index, val };
      this->BFSQueue.push(qe);
    } else if (!entry.IsFlag) {
      // The item dependencies are not known.  We need to infer them.
      this->InferredDependSets[index] = new DependSetList;
    }
  }

  return index;
}

void cmComputeLinkDepends::FollowLinkEntry(BFSEntry 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 (cmLinkInterface const* iface =
          entry.Target->GetLinkInterface(this->Config, this->Target)) {
      const bool isIface =
        entry.Target->GetType() == cmStateEnums::INTERFACE_LIBRARY;
      // This target provides its own link interface information.
      this->AddLinkEntries(depender_index, iface->Libraries);

      if (isIface) {
        return;
      }

      // Handle dependent shared libraries.
      this->FollowSharedDeps(depender_index, iface);

      // Support for CMP0003.
      for (cmLinkItem const& oi : iface->WrongConfigLibraries) {
        this->CheckWrongConfigItem(oi);
      }
    }
  } else {
    // Follow the old-style dependency list.
    this->AddVarLinkEntries(depender_index, qe.LibDepends);
  }
}

void cmComputeLinkDepends::FollowSharedDeps(int depender_index,
                                            cmLinkInterface const* iface,
                                            bool follow_interface)
{
  // Follow dependencies if we have not followed them already.
  if (this->SharedDepFollowed.insert(depender_index).second) {
    if (follow_interface) {
      this->QueueSharedDependencies(depender_index, iface->Libraries);
    }
    this->QueueSharedDependencies(depender_index, iface->SharedDeps);
  }
}

void cmComputeLinkDepends::QueueSharedDependencies(
  int depender_index, std::vector<cmLinkItem> const& deps)
{
  for (cmLinkItem const& li : deps) {
    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<cmLinkItem, 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.AsStr();
    entry.Target = dep.Item.Target;

    // 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 follow the item that listed
  // it.
  this->EntryConstraintGraph[dep.DependerIndex].emplace_back(
    index, true, cmListFileBacktrace());

  // Target items may have their own dependencies.
  if (entry.Target) {
    if (cmLinkInterface const* iface =
          entry.Target->GetLinkInterface(this->Config, this->Target)) {
      // Follow public and private dependencies transitively.
      this->FollowSharedDeps(index, iface, true);
    }
  }
}

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);

  // Look for entries meant for this configuration.
  std::vector<cmLinkItem> actual_libs;
  cmTargetLinkLibraryType llt = GENERAL_LibraryType;
  bool haveLLT = false;
  for (std::string const& d : deplist) {
    if (d == "debug") {
      llt = DEBUG_LibraryType;
      haveLLT = true;
    } else if (d == "optimized") {
      llt = OPTIMIZED_LibraryType;
      haveLLT = true;
    } else if (d == "general") {
      llt = GENERAL_LibraryType;
      haveLLT = true;
    } else if (!d.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 = d;
        var += "_LINK_TYPE";
        if (const char* val = this->Makefile->GetDefinition(var)) {
          if (strcmp(val, "debug") == 0) {
            llt = DEBUG_LibraryType;
          } else if (strcmp(val, "optimized") == 0) {
            llt = OPTIMIZED_LibraryType;
          }
        }
      }

      // If the library is meant for this link type then use it.
      if (llt == GENERAL_LibraryType || llt == this->LinkType) {
        actual_libs.emplace_back(this->ResolveLinkItem(depender_index, d));
      } else if (this->OldLinkDirMode) {
        cmLinkItem item = this->ResolveLinkItem(depender_index, d);
        this->CheckWrongConfigItem(item);
      }

      // Reset the link type until another explicit type is given.
      llt = GENERAL_LibraryType;
      haveLLT = false;
    }
  }

  // Add the entries from this list.
  this->AddLinkEntries(depender_index, actual_libs);
}

void cmComputeLinkDepends::AddDirectLinkEntries()
{
  // Add direct link dependencies in this configuration.
  cmLinkImplementation const* impl =
    this->Target->GetLinkImplementation(this->Config);
  this->AddLinkEntries(-1, impl->Libraries);
  for (cmLinkItem const& wi : impl->WrongConfigLibraries) {
    this->CheckWrongConfigItem(wi);
  }
}

template <typename T>
void cmComputeLinkDepends::AddLinkEntries(int depender_index,
                                          std::vector<T> 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 (T const& l : libs) {
    // Skip entries that will resolve to the target getting linked or
    // are empty.
    cmLinkItem const& item = l;
    if (item.AsStr() == this->Target->GetName() || item.AsStr().empty()) {
      continue;
    }

    // Add a link entry for this item.
    int dependee_index = this->AddLinkEntry(l);

    // The dependee must come after the depender.
    if (depender_index >= 0) {
      this->EntryConstraintGraph[depender_index].emplace_back(
        dependee_index, false, cmListFileBacktrace());
    } else {
      // This is a direct dependency of the target being linked.
      this->OriginalEntries.push_back(dependee_index);
    }

    // Update the inferred dependencies for earlier items.
    for (auto& dependSet : dependSets) {
      // Add this item to the inferred dependencies of other items.
      // Target items are never inferred dependees because unknown
      // items are outside libraries that should not be depending on
      // targets.
      if (!this->EntryList[dependee_index].Target &&
          !this->EntryList[dependee_index].IsFlag &&
          dependee_index != dependSet.first) {
        dependSet.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 (auto const& dependSet : dependSets) {
    this->InferredDependSets[dependSet.first]->push_back(dependSet.second);
  }
}

cmLinkItem cmComputeLinkDepends::ResolveLinkItem(int depender_index,
                                                 const std::string& name)
{
  // Look for a target in the scope of the depender.
  cmGeneratorTarget const* from = this->Target;
  if (depender_index >= 0) {
    if (cmGeneratorTarget const* depender =
          this->EntryList[depender_index].Target) {
      from = depender;
    }
  }
  return from->ResolveLinkItem(name, cmListFileBacktrace());
}

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.
    DependSet common = sets->front();
    for (DependSet const& i : cmMakeRange(*sets).advance(1)) {
      DependSet intersection;
      std::set_intersection(common.begin(), common.end(), i.begin(), i.end(),
                            std::inserter(intersection, intersection.begin()));
      common = intersection;
    }

    // Add the inferred dependencies to the graph.
    cmGraphEdgeList& edges = this->EntryConstraintGraph[depender_index];
    edges.reserve(edges.size() + common.size());
    for (auto const& c : common) {
      edges.emplace_back(c, true, cmListFileBacktrace());
    }
  }
}

void cmComputeLinkDepends::CleanConstraintGraph()
{
  for (cmGraphEdgeList& edgeList : this->EntryConstraintGraph) {
    // Sort the outgoing edges for each graph node so that the
    // original order will be preserved as much as possible.
    std::sort(edgeList.begin(), edgeList.end());

    // Make the edge list unique.
    edgeList.erase(std::unique(edgeList.begin(), edgeList.end()),
                   edgeList.end());
  }
}

void cmComputeLinkDepends::DisplayConstraintGraph()
{
  // Display the graph nodes and their edges.
  std::ostringstream e;
  for (unsigned int i = 0; i < this->EntryConstraintGraph.size(); ++i) {
    EdgeList const& nl = this->EntryConstraintGraph[i];
    e << "item " << i << " is [" << this->EntryList[i].Item << "]\n";
    e << cmWrap("  item ", nl, " must follow it", "\n") << "\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.
  this->CCG =
    cm::make_unique<cmComputeComponentGraph>(this->EntryConstraintGraph);

  // The component graph is guaranteed to be acyclic.  Start a DFS
  // from every entry to compute a topological order for the
  // components.
  Graph const& cgraph = this->CCG->GetComponentGraph();
  int n = static_cast<int>(cgraph.size());
  this->ComponentVisited.resize(cgraph.size(), 0);
  this->ComponentOrder.resize(cgraph.size(), n);
  this->ComponentOrderId = n;
  // Run in reverse order so the topological order will preserve the
  // original order where there are no constraints.
  for (int c = n - 1; c >= 0; --c) {
    this->VisitComponent(c);
  }

  // Display the component graph.
  if (this->DebugMode) {
    this->DisplayComponents();
  }

  // Start with the original link line.
  for (int originalEntry : this->OriginalEntries) {
    this->VisitEntry(originalEntry);
  }

  // Now explore anything left pending.  Since the component graph is
  // guaranteed to be acyclic we know this will terminate.
  while (!this->PendingComponents.empty()) {
    // Visit one entry from the first pending component.  The visit
    // logic will update the pending components accordingly.  Since
    // the pending components are kept in topological order this will
    // not repeat one.
    int e = *this->PendingComponents.begin()->second.Entries.begin();
    this->VisitEntry(e);
  }
}

void cmComputeLinkDepends::DisplayComponents()
{
  fprintf(stderr, "The strongly connected components are:\n");
  std::vector<NodeList> const& components = this->CCG->GetComponents();
  for (unsigned int c = 0; c < components.size(); ++c) {
    fprintf(stderr, "Component (%u):\n", c);
    NodeList const& nl = components[c];
    for (int i : nl) {
      fprintf(stderr, "  item %d [%s]\n", i, this->EntryList[i].Item.c_str());
    }
    EdgeList const& ol = this->CCG->GetComponentGraphEdges(c);
    for (cmGraphEdge const& oi : ol) {
      int i = oi;
      fprintf(stderr, "  followed by Component (%d)\n", i);
    }
    fprintf(stderr, "  topo order index %d\n", this->ComponentOrder[c]);
  }
  fprintf(stderr, "\n");
}

void cmComputeLinkDepends::VisitComponent(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.
  // Run in reverse order so the topological order will preserve the
  // original order where there are no constraints.
  EdgeList const& nl = this->CCG->GetComponentGraphEdges(c);
  for (cmGraphEdge const& edge : cmReverseRange(nl)) {
    this->VisitComponent(edge);
  }

  // Assign an ordering id to this component.
  this->ComponentOrder[c] = --this->ComponentOrderId;
}

void cmComputeLinkDepends::VisitEntry(int index)
{
  // Include this entry on the link line.
  this->FinalLinkOrder.push_back(index);

  // This entry has now been seen.  Update its component.
  bool completed = false;
  int component = this->CCG->GetComponentMap()[index];
  std::map<int, PendingComponent>::iterator mi =
    this->PendingComponents.find(this->ComponentOrder[component]);
  if (mi != this->PendingComponents.end()) {
    // The entry is in an already pending component.
    PendingComponent& pc = mi->second;

    // Remove the entry from those pending in its component.
    pc.Entries.erase(index);
    if (pc.Entries.empty()) {
      // The complete component has been seen since it was last needed.
      --pc.Count;

      if (pc.Count == 0) {
        // The component has been completed.
        this->PendingComponents.erase(mi);
        completed = true;
      } else {
        // The whole component needs to be seen again.
        NodeList const& nl = this->CCG->GetComponent(component);
        assert(nl.size() > 1);
        pc.Entries.insert(nl.begin(), nl.end());
      }
    }
  } else {
    // The entry is not in an already pending component.
    NodeList const& nl = this->CCG->GetComponent(component);
    if (nl.size() > 1) {
      // This is a non-trivial component.  It is now pending.
      PendingComponent& pc = this->MakePendingComponent(component);

      // The starting entry has already been seen.
      pc.Entries.erase(index);
    } else {
      // This is a trivial component, so it is already complete.
      completed = true;
    }
  }

  // If the entry completed a component, the component's dependencies
  // are now pending.
  if (completed) {
    EdgeList const& ol = this->CCG->GetComponentGraphEdges(component);
    for (cmGraphEdge const& oi : ol) {
      // This entire component is now pending no matter whether it has
      // been partially seen already.
      this->MakePendingComponent(oi);
    }
  }
}

cmComputeLinkDepends::PendingComponent&
cmComputeLinkDepends::MakePendingComponent(unsigned int component)
{
  // Create an entry (in topological order) for the component.
  PendingComponent& pc =
    this->PendingComponents[this->ComponentOrder[component]];
  pc.Id = component;
  NodeList const& nl = this->CCG->GetComponent(component);

  if (nl.size() == 1) {
    // Trivial components need be seen only once.
    pc.Count = 1;
  } else {
    // 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.
    pc.Count = this->ComputeComponentCount(nl);
  }

  // Store the entries to be seen.
  pc.Entries.insert(nl.begin(), nl.end());

  return pc;
}

int cmComputeLinkDepends::ComputeComponentCount(NodeList const& nl)
{
  unsigned int count = 2;
  for (int ni : nl) {
    if (cmGeneratorTarget const* target = this->EntryList[ni].Target) {
      if (cmLinkInterface const* iface =
            target->GetLinkInterface(this->Config, this->Target)) {
        if (iface->Multiplicity > count) {
          count = iface->Multiplicity;
        }
      }
    }
  }
  return count;
}

void cmComputeLinkDepends::DisplayFinalEntries()
{
  fprintf(stderr, "target [%s] links to:\n", this->Target->GetName().c_str());
  for (LinkEntry const& lei : this->FinalLinkEntries) {
    if (lei.Target) {
      fprintf(stderr, "  target [%s]\n", lei.Target->GetName().c_str());
    } else {
      fprintf(stderr, "  item [%s]\n", lei.Item.c_str());
    }
  }
  fprintf(stderr, "\n");
}

void cmComputeLinkDepends::CheckWrongConfigItem(cmLinkItem const& item)
{
  if (!this->OldLinkDirMode) {
    return;
  }

  // For CMake 2.4 bug-compatibility we need to consider the output
  // directories of targets linked in another configuration as link
  // directories.
  if (item.Target && !item.Target->IsImported()) {
    this->OldWrongConfigItems.insert(item.Target);
  }
}
