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

#include <cassert>
#include <cstddef>
#include <cstdio>
#include <memory>
#include <sstream>
#include <utility>

#include "cmComputeComponentGraph.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLinkItem.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocationKind.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetDepend.h"
#include "cmValue.h"
#include "cmake.h"

/*

This class is meant to analyze inter-target dependencies globally
during the generation step.  The goal is to produce a set of direct
dependencies for each target such that no cycles are left and the
build order is safe.

For most target types cyclic dependencies are not allowed.  However
STATIC libraries may depend on each other in a cyclic fashion.  In
general the directed dependency graph forms a directed-acyclic-graph
of strongly connected components.  All strongly connected components
should consist of only STATIC_LIBRARY targets.

In order to safely break dependency cycles we must preserve all other
dependencies passing through the corresponding strongly connected component.
The approach taken by this class is as follows:

  - Collect all targets and form the original dependency graph
  - Run Tarjan's algorithm to extract the strongly connected components
    (error if any member of a non-trivial component is not STATIC)
  - The original dependencies imply a DAG on the components.
    Use the implied DAG to construct a final safe set of dependencies.

The final dependency set is constructed as follows:

  - For each connected component targets are placed in an arbitrary
    order.  Each target depends on the target following it in the order.
    The first target is designated the head and the last target the tail.
    (most components will be just 1 target anyway)

  - Original dependencies between targets in different components are
    converted to connect the depender's component tail to the
    dependee's component head.

In most cases this will reproduce the original dependencies.  However
when there are cycles of static libraries they will be broken in a
safe manner.

For example, consider targets A0, A1, A2, B0, B1, B2, and C with these
dependencies:

  A0 -> A1 -> A2 -> A0  ,  B0 -> B1 -> B2 -> B0 -> A0  ,  C -> B0

Components may be identified as

  Component 0: A0, A1, A2
  Component 1: B0, B1, B2
  Component 2: C

Intra-component dependencies are:

  0: A0 -> A1 -> A2   , head=A0, tail=A2
  1: B0 -> B1 -> B2   , head=B0, tail=B2
  2: head=C, tail=C

The inter-component dependencies are converted as:

  B0 -> A0  is component 1->0 and becomes  B2 -> A0
  C  -> B0  is component 2->1 and becomes  C  -> B0

This leads to the final target dependencies:

  C -> B0 -> B1 -> B2 -> A0 -> A1 -> A2

These produce a safe build order since C depends directly or
transitively on all the static libraries it links.

*/

cmComputeTargetDepends::cmComputeTargetDepends(cmGlobalGenerator* gg)
{
  this->GlobalGenerator = gg;
  cmake* cm = this->GlobalGenerator->GetCMakeInstance();
  this->DebugMode =
    cm->GetState()->GetGlobalPropertyAsBool("GLOBAL_DEPENDS_DEBUG_MODE");
  this->NoCycles =
    cm->GetState()->GetGlobalPropertyAsBool("GLOBAL_DEPENDS_NO_CYCLES");
}

cmComputeTargetDepends::~cmComputeTargetDepends() = default;

bool cmComputeTargetDepends::Compute()
{
  // Build the original graph.
  this->CollectTargets();
  this->CollectDepends();
  if (this->DebugMode) {
    this->DisplayGraph(this->InitialGraph, "initial");
  }
  cmComputeComponentGraph ccg1(this->InitialGraph);
  ccg1.Compute();
  if (!this->CheckComponents(ccg1)) {
    return false;
  }

  // Compute the intermediate graph.
  this->CollectSideEffects();
  this->ComputeIntermediateGraph();
  if (this->DebugMode) {
    this->DisplaySideEffects();
    this->DisplayGraph(this->IntermediateGraph, "intermediate");
  }

  // Identify components.
  cmComputeComponentGraph ccg2(this->IntermediateGraph);
  ccg2.Compute();
  if (this->DebugMode) {
    this->DisplayComponents(ccg2, "intermediate");
  }
  if (!this->CheckComponents(ccg2)) {
    return false;
  }

  // Compute the final dependency graph.
  if (!this->ComputeFinalDepends(ccg2)) {
    return false;
  }
  if (this->DebugMode) {
    this->DisplayGraph(this->FinalGraph, "final");
  }

  return true;
}

void cmComputeTargetDepends::GetTargetDirectDepends(cmGeneratorTarget const* t,
                                                    cmTargetDependSet& deps)
{
  // Lookup the index for this target.  All targets should be known by
  // this point.
  auto tii = this->TargetIndex.find(t);
  assert(tii != this->TargetIndex.end());
  size_t i = tii->second;

  // Get its final dependencies.
  EdgeList const& nl = this->FinalGraph[i];
  for (cmGraphEdge const& ni : nl) {
    cmGeneratorTarget const* dep = this->Targets[ni];
    auto di = deps.insert(dep).first;
    di->SetType(ni.IsStrong());
    di->SetCross(ni.IsCross());
    di->SetBacktrace(ni.GetBacktrace());
  }
}

void cmComputeTargetDepends::CollectTargets()
{
  // Collect all targets from all generators.
  auto const& lgens = this->GlobalGenerator->GetLocalGenerators();
  for (const auto& lgen : lgens) {
    for (const auto& ti : lgen->GetGeneratorTargets()) {
      size_t index = this->Targets.size();
      this->TargetIndex[ti.get()] = index;
      this->Targets.push_back(ti.get());
    }
  }
}

void cmComputeTargetDepends::CollectDepends()
{
  // Allocate the dependency graph adjacency lists.
  this->InitialGraph.resize(this->Targets.size());

  // Compute each dependency list.
  for (size_t i = 0; i < this->Targets.size(); ++i) {
    this->CollectTargetDepends(i);
  }
}

void cmComputeTargetDepends::CollectTargetDepends(size_t depender_index)
{
  // Get the depender.
  cmGeneratorTarget const* depender = this->Targets[depender_index];
  if (!depender->IsInBuildSystem()) {
    return;
  }

  // Loop over all targets linked directly in all configs.
  // We need to make targets depend on the union of all config-specific
  // dependencies in all targets, because the generated build-systems can't
  // deal with config-specific dependencies.
  {
    std::set<cmLinkItem> emitted;

    std::vector<std::string> const& configs =
      depender->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
    for (std::string const& it : configs) {
      // A target should not depend on itself.
      emitted.insert(cmLinkItem(depender, false, cmListFileBacktrace()));
      emitted.insert(cmLinkItem(depender, true, cmListFileBacktrace()));

      if (cmLinkImplementation const* impl = depender->GetLinkImplementation(
            it, cmGeneratorTarget::UseTo::Link)) {
        for (cmLinkImplItem const& lib : impl->Libraries) {
          // Don't emit the same library twice for this target.
          if (emitted.insert(lib).second) {
            this->AddTargetDepend(depender_index, lib, true, false);
            this->AddInterfaceDepends(depender_index, lib, it, emitted);
          }
        }
        for (cmLinkItem const& obj : impl->Objects) {
          if (cmSourceFile const* o = depender->Makefile->GetSource(
                obj.AsStr(), cmSourceFileLocationKind::Known)) {
            this->AddObjectDepends(depender_index, o, emitted);
          }
        }
      }

      // Add dependencies on object libraries not otherwise handled above.
      std::vector<cmSourceFile const*> objectFiles;
      depender->GetExternalObjects(objectFiles, it);
      for (cmSourceFile const* o : objectFiles) {
        this->AddObjectDepends(depender_index, o, emitted);
      }
    }
  }

  // Loop over all utility dependencies.
  {
    std::set<cmLinkItem> const& tutils = depender->GetUtilityItems();
    std::set<cmLinkItem> emitted;
    // A target should not depend on itself.
    emitted.insert(cmLinkItem(depender, false, cmListFileBacktrace()));
    emitted.insert(cmLinkItem(depender, true, cmListFileBacktrace()));
    for (cmLinkItem const& litem : tutils) {
      // Don't emit the same utility twice for this target.
      if (emitted.insert(litem).second) {
        this->AddTargetDepend(depender_index, litem, false, litem.Cross);
      }
    }
  }
}

void cmComputeTargetDepends::AddInterfaceDepends(
  size_t depender_index, const cmGeneratorTarget* dependee,
  cmListFileBacktrace const& dependee_backtrace, const std::string& config,
  std::set<cmLinkItem>& emitted)
{
  cmGeneratorTarget const* depender = this->Targets[depender_index];
  if (cmLinkInterface const* iface =
        dependee->GetLinkInterface(config, depender)) {
    for (cmLinkItem const& lib : iface->Libraries) {
      // Don't emit the same library twice for this target.
      if (emitted.insert(lib).second) {
        // Inject the backtrace of the original link dependency whose
        // link interface we are adding.  This indicates the line of
        // code in the project that caused this dependency to be added.
        cmLinkItem libBT = lib;
        libBT.Backtrace = dependee_backtrace;
        this->AddTargetDepend(depender_index, libBT, true, false);
        this->AddInterfaceDepends(depender_index, libBT, config, emitted);
      }
    }
    for (cmLinkItem const& obj : iface->Objects) {
      if (cmSourceFile const* o = depender->Makefile->GetSource(
            obj.AsStr(), cmSourceFileLocationKind::Known)) {
        this->AddObjectDepends(depender_index, o, emitted);
      }
    }
  }
}

void cmComputeTargetDepends::AddInterfaceDepends(
  size_t depender_index, cmLinkItem const& dependee_name,
  const std::string& config, std::set<cmLinkItem>& emitted)
{
  cmGeneratorTarget const* depender = this->Targets[depender_index];
  cmGeneratorTarget const* dependee = dependee_name.Target;
  // Skip targets that will not really be linked.  This is probably a
  // name conflict between an external library and an executable
  // within the project.
  if (dependee && dependee->GetType() == cmStateEnums::EXECUTABLE &&
      !dependee->IsExecutableWithExports()) {
    dependee = nullptr;
  }

  if (dependee) {
    // A target should not depend on itself.
    emitted.insert(cmLinkItem(depender, false, cmListFileBacktrace()));
    emitted.insert(cmLinkItem(depender, true, cmListFileBacktrace()));
    this->AddInterfaceDepends(depender_index, dependee,
                              dependee_name.Backtrace, config, emitted);
  }
}

void cmComputeTargetDepends::AddObjectDepends(size_t depender_index,
                                              cmSourceFile const* o,
                                              std::set<cmLinkItem>& emitted)
{
  std::string const& objLib = o->GetObjectLibrary();
  if (objLib.empty()) {
    return;
  }
  cmGeneratorTarget const* depender = this->Targets[depender_index];
  cmLinkItem const& objItem =
    depender->ResolveLinkItem(BT<std::string>(objLib));
  if (emitted.insert(objItem).second) {
    if (depender->GetType() != cmStateEnums::EXECUTABLE &&
        depender->GetType() != cmStateEnums::STATIC_LIBRARY &&
        depender->GetType() != cmStateEnums::SHARED_LIBRARY &&
        depender->GetType() != cmStateEnums::MODULE_LIBRARY &&
        depender->GetType() != cmStateEnums::OBJECT_LIBRARY) {
      this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
        MessageType::FATAL_ERROR,
        "Only executables and libraries may reference target objects.",
        depender->GetBacktrace());
      return;
    }
    const_cast<cmGeneratorTarget*>(depender)->Target->AddUtility(objLib,
                                                                 false);
  }
}

void cmComputeTargetDepends::AddTargetDepend(size_t depender_index,
                                             cmLinkItem const& dependee_name,
                                             bool linking, bool cross)
{
  // Get the depender.
  cmGeneratorTarget const* depender = this->Targets[depender_index];

  // Check the target's makefile first.
  cmGeneratorTarget const* dependee = dependee_name.Target;

  if (!dependee && !linking &&
      (depender->GetType() != cmStateEnums::GLOBAL_TARGET)) {
    MessageType messageType = MessageType::AUTHOR_WARNING;
    bool issueMessage = false;
    std::ostringstream e;
    switch (depender->GetPolicyStatusCMP0046()) {
      case cmPolicies::WARN:
        e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0046) << "\n";
        issueMessage = true;
        CM_FALLTHROUGH;
      case cmPolicies::OLD:
        break;
      case cmPolicies::NEW:
        issueMessage = true;
        messageType = MessageType::FATAL_ERROR;
        break;
    }
    if (issueMessage) {
      cmake* cm = this->GlobalGenerator->GetCMakeInstance();

      e << "The dependency target \"" << dependee_name << "\" of target \""
        << depender->GetName() << "\" does not exist.";

      cm->IssueMessage(messageType, e.str(), dependee_name.Backtrace);
    }
  }

  // Skip targets that will not really be linked.  This is probably a
  // name conflict between an external library and an executable
  // within the project.
  if (linking && dependee && dependee->GetType() == cmStateEnums::EXECUTABLE &&
      !dependee->IsExecutableWithExports()) {
    dependee = nullptr;
  }

  if (dependee) {
    this->AddTargetDepend(depender_index, dependee, dependee_name.Backtrace,
                          linking, cross);
  }
}

void cmComputeTargetDepends::AddTargetDepend(
  size_t depender_index, cmGeneratorTarget const* dependee,
  cmListFileBacktrace const& dependee_backtrace, bool linking, bool cross)
{
  if (!dependee->IsInBuildSystem()) {
    // Skip targets that are not in the buildsystem but follow their
    // utility dependencies.
    std::set<cmLinkItem> const& utils = dependee->GetUtilityItems();
    for (cmLinkItem const& i : utils) {
      if (cmGeneratorTarget const* transitive_dependee = i.Target) {
        this->AddTargetDepend(depender_index, transitive_dependee, i.Backtrace,
                              false, i.Cross);
      }
    }
  } else {
    // Lookup the index for this target.  All targets should be known by
    // this point.
    auto tii = this->TargetIndex.find(dependee);
    assert(tii != this->TargetIndex.end());
    size_t dependee_index = tii->second;

    // Add this entry to the dependency graph.
    this->InitialGraph[depender_index].emplace_back(dependee_index, !linking,
                                                    cross, dependee_backtrace);
  }
}

void cmComputeTargetDepends::CollectSideEffects()
{
  this->SideEffects.resize(0);
  this->SideEffects.resize(this->InitialGraph.size());

  size_t n = this->InitialGraph.size();
  std::set<size_t> visited;
  for (size_t i = 0; i < n; ++i) {
    this->CollectSideEffectsForTarget(visited, i);
  }
}

void cmComputeTargetDepends::CollectSideEffectsForTarget(
  std::set<size_t>& visited, size_t depender_index)
{
  if (!visited.count(depender_index)) {
    auto& se = this->SideEffects[depender_index];
    visited.insert(depender_index);
    this->Targets[depender_index]->AppendCustomCommandSideEffects(
      se.CustomCommandSideEffects);
    this->Targets[depender_index]->AppendLanguageSideEffects(
      se.LanguageSideEffects);

    for (auto const& edge : this->InitialGraph[depender_index]) {
      this->CollectSideEffectsForTarget(visited, edge);
      auto const& dse = this->SideEffects[edge];
      se.CustomCommandSideEffects.insert(dse.CustomCommandSideEffects.cbegin(),
                                         dse.CustomCommandSideEffects.cend());
      for (auto const& it : dse.LanguageSideEffects) {
        se.LanguageSideEffects[it.first].insert(it.second.cbegin(),
                                                it.second.cend());
      }
    }
  }
}

void cmComputeTargetDepends::ComputeIntermediateGraph()
{
  this->IntermediateGraph.resize(0);
  this->IntermediateGraph.resize(this->InitialGraph.size());

  size_t n = this->InitialGraph.size();
  for (size_t i = 0; i < n; ++i) {
    auto const& initialEdges = this->InitialGraph[i];
    auto& intermediateEdges = this->IntermediateGraph[i];
    cmGeneratorTarget const* gt = this->Targets[i];
    if (gt->GetType() != cmStateEnums::STATIC_LIBRARY &&
        gt->GetType() != cmStateEnums::OBJECT_LIBRARY) {
      intermediateEdges = initialEdges;
    } else {
      if (cmValue optimizeDependencies =
            gt->GetProperty("OPTIMIZE_DEPENDENCIES")) {
        if (optimizeDependencies.IsOn()) {
          this->OptimizeLinkDependencies(gt, intermediateEdges, initialEdges);
        } else {
          intermediateEdges = initialEdges;
        }
      } else {
        intermediateEdges = initialEdges;
      }
    }
  }
}

void cmComputeTargetDepends::OptimizeLinkDependencies(
  cmGeneratorTarget const* gt, cmGraphEdgeList& outputEdges,
  cmGraphEdgeList const& inputEdges)
{
  std::set<size_t> emitted;
  for (auto const& edge : inputEdges) {
    if (edge.IsStrong()) {
      // Preserve strong edges
      outputEdges.push_back(edge);
    } else {
      auto const& dse = this->SideEffects[edge];

      // Add edges that have custom command side effects
      for (cmGeneratorTarget const* dep : dse.CustomCommandSideEffects) {
        auto index = this->TargetIndex[dep];
        if (!emitted.count(index)) {
          emitted.insert(index);
          outputEdges.push_back(
            cmGraphEdge(index, false, edge.IsCross(), edge.GetBacktrace()));
        }
      }

      // Add edges that have language side effects for languages we
      // care about
      for (auto const& lang : gt->GetAllConfigCompileLanguages()) {
        auto it = dse.LanguageSideEffects.find(lang);
        if (it != dse.LanguageSideEffects.end()) {
          for (cmGeneratorTarget const* dep : it->second) {
            auto index = this->TargetIndex[dep];
            if (!emitted.count(index)) {
              emitted.insert(index);
              outputEdges.push_back(cmGraphEdge(index, false, edge.IsCross(),
                                                edge.GetBacktrace()));
            }
          }
        }
      }
    }
  }
}

void cmComputeTargetDepends::DisplayGraph(Graph const& graph,
                                          const std::string& name)
{
  fprintf(stderr, "The %s target dependency graph is:\n", name.c_str());
  size_t n = graph.size();
  for (size_t depender_index = 0; depender_index < n; ++depender_index) {
    EdgeList const& nl = graph[depender_index];
    cmGeneratorTarget const* depender = this->Targets[depender_index];
    fprintf(stderr, "target %zu is [%s]\n", depender_index,
            depender->GetName().c_str());
    for (cmGraphEdge const& ni : nl) {
      size_t dependee_index = ni;
      cmGeneratorTarget const* dependee = this->Targets[dependee_index];
      fprintf(stderr, "  depends on target %zu [%s] (%s)\n", dependee_index,
              dependee->GetName().c_str(), ni.IsStrong() ? "strong" : "weak");
    }
  }
  fprintf(stderr, "\n");
}

void cmComputeTargetDepends::DisplaySideEffects()
{
  fprintf(stderr, "The side effects are:\n");
  size_t n = this->SideEffects.size();
  for (size_t depender_index = 0; depender_index < n; ++depender_index) {
    cmGeneratorTarget const* depender = this->Targets[depender_index];
    fprintf(stderr, "target %zu is [%s]\n", depender_index,
            depender->GetName().c_str());
    if (!this->SideEffects[depender_index].CustomCommandSideEffects.empty()) {
      fprintf(stderr, "  custom commands\n");
      for (auto const* gt :
           this->SideEffects[depender_index].CustomCommandSideEffects) {
        fprintf(stderr, "    from target %zu [%s]\n", this->TargetIndex[gt],
                gt->GetName().c_str());
      }
    }
    for (auto const& it :
         this->SideEffects[depender_index].LanguageSideEffects) {
      fprintf(stderr, "  language %s\n", it.first.c_str());
      for (auto const* gt : it.second) {
        fprintf(stderr, "    from target %zu [%s]\n", this->TargetIndex[gt],
                gt->GetName().c_str());
      }
    }
  }
  fprintf(stderr, "\n");
}

void cmComputeTargetDepends::DisplayComponents(
  cmComputeComponentGraph const& ccg, const std::string& name)
{
  fprintf(stderr, "The strongly connected components for the %s graph are:\n",
          name.c_str());
  std::vector<NodeList> const& components = ccg.GetComponents();
  size_t n = components.size();
  for (size_t c = 0; c < n; ++c) {
    NodeList const& nl = components[c];
    fprintf(stderr, "Component (%zu):\n", c);
    for (size_t i : nl) {
      fprintf(stderr, "  contains target %zu [%s]\n", i,
              this->Targets[i]->GetName().c_str());
    }
  }
  fprintf(stderr, "\n");
}

bool cmComputeTargetDepends::CheckComponents(
  cmComputeComponentGraph const& ccg)
{
  // All non-trivial components should consist only of static
  // libraries.
  std::vector<NodeList> const& components = ccg.GetComponents();
  size_t nc = components.size();
  for (size_t c = 0; c < nc; ++c) {
    // Get the current component.
    NodeList const& nl = components[c];

    // Skip trivial components.
    if (nl.size() < 2) {
      continue;
    }

    // Immediately complain if no cycles are allowed at all.
    if (this->NoCycles) {
      this->ComplainAboutBadComponent(ccg, c);
      return false;
    }

    // Make sure the component is all STATIC_LIBRARY targets.
    for (size_t ni : nl) {
      if (this->Targets[ni]->GetType() != cmStateEnums::STATIC_LIBRARY) {
        this->ComplainAboutBadComponent(ccg, c);
        return false;
      }
    }
  }
  return true;
}

void cmComputeTargetDepends::ComplainAboutBadComponent(
  cmComputeComponentGraph const& ccg, size_t c, bool strong)
{
  // Construct the error message.
  std::ostringstream e;
  e << "The inter-target dependency graph contains the following "
    << "strongly connected component (cycle):\n";
  std::vector<NodeList> const& components = ccg.GetComponents();
  std::vector<size_t> const& cmap = ccg.GetComponentMap();
  NodeList const& cl = components[c];
  for (size_t i : cl) {
    // Get the depender.
    cmGeneratorTarget const* depender = this->Targets[i];

    // Describe the depender.
    e << "  \"" << depender->GetName() << "\" of type "
      << cmState::GetTargetTypeName(depender->GetType()) << "\n";

    // List its dependencies that are inside the component.
    EdgeList const& nl = this->InitialGraph[i];
    for (cmGraphEdge const& ni : nl) {
      size_t j = ni;
      if (cmap[j] == c) {
        cmGeneratorTarget const* dependee = this->Targets[j];
        e << "    depends on \"" << dependee->GetName() << "\""
          << " (" << (ni.IsStrong() ? "strong" : "weak") << ")\n";
      }
    }
  }
  if (strong) {
    // Custom command executable dependencies cannot occur within a
    // component of static libraries.  The cycle must appear in calls
    // to add_dependencies.
    e << "The component contains at least one cycle consisting of strong "
      << "dependencies (created by add_dependencies) that cannot be broken.";
  } else if (this->NoCycles) {
    e << "The GLOBAL_DEPENDS_NO_CYCLES global property is enabled, so "
      << "cyclic dependencies are not allowed even among static libraries.";
  } else {
    e << "At least one of these targets is not a STATIC_LIBRARY.  "
      << "Cyclic dependencies are allowed only among static libraries.";
  }
  cmSystemTools::Error(e.str());
}

bool cmComputeTargetDepends::IntraComponent(std::vector<size_t> const& cmap,
                                            size_t c, size_t i, size_t* head,
                                            std::set<size_t>& emitted,
                                            std::set<size_t>& visited)
{
  if (!visited.insert(i).second) {
    // Cycle in utility depends!
    return false;
  }
  if (emitted.insert(i).second) {
    // Honor strong intra-component edges in the final order.
    EdgeList const& el = this->InitialGraph[i];
    for (cmGraphEdge const& edge : el) {
      size_t j = edge;
      if (cmap[j] == c && edge.IsStrong()) {
        this->FinalGraph[i].emplace_back(j, true, edge.IsCross(),
                                         edge.GetBacktrace());
        if (!this->IntraComponent(cmap, c, j, head, emitted, visited)) {
          return false;
        }
      }
    }

    // Prepend to a linear linked-list of intra-component edges.
    if (*head != cmComputeComponentGraph::INVALID_COMPONENT) {
      this->FinalGraph[i].emplace_back(*head, false, false,
                                       cmListFileBacktrace());
    } else {
      this->ComponentTail[c] = i;
    }
    *head = i;
  }
  return true;
}

bool cmComputeTargetDepends::ComputeFinalDepends(
  cmComputeComponentGraph const& ccg)
{
  // Get the component graph information.
  std::vector<NodeList> const& components = ccg.GetComponents();
  Graph const& cgraph = ccg.GetComponentGraph();

  // Allocate the final graph.
  this->FinalGraph.resize(0);
  this->FinalGraph.resize(this->InitialGraph.size());

  // Choose intra-component edges to linearize dependencies.
  std::vector<size_t> const& cmap = ccg.GetComponentMap();
  this->ComponentHead.resize(components.size());
  this->ComponentTail.resize(components.size());
  size_t nc = components.size();
  for (size_t c = 0; c < nc; ++c) {
    size_t head = cmComputeComponentGraph::INVALID_COMPONENT;
    std::set<size_t> emitted;
    NodeList const& nl = components[c];
    for (size_t ni : cmReverseRange(nl)) {
      std::set<size_t> visited;
      if (!this->IntraComponent(cmap, c, ni, &head, emitted, visited)) {
        // Cycle in add_dependencies within component!
        this->ComplainAboutBadComponent(ccg, c, true);
        return false;
      }
    }
    this->ComponentHead[c] = head;
  }

  // Convert inter-component edges to connect component tails to heads.
  size_t n = cgraph.size();
  for (size_t depender_component = 0; depender_component < n;
       ++depender_component) {
    size_t depender_component_tail = this->ComponentTail[depender_component];
    EdgeList const& nl = cgraph[depender_component];
    for (cmGraphEdge const& ni : nl) {
      size_t dependee_component = ni;
      size_t dependee_component_head = this->ComponentHead[dependee_component];
      this->FinalGraph[depender_component_tail].emplace_back(
        dependee_component_head, ni.IsStrong(), ni.IsCross(),
        ni.GetBacktrace());
    }
  }
  return true;
}
