/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium

  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/
#include "cmComputeTargetDepends.h"

#include "cmComputeComponentGraph.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmSystemTools.h"
#include "cmSourceFile.h"
#include "cmTarget.h"
#include "cmake.h"

#include <algorithm>

#include <assert.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()
{
}

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

  // Identify components.
  cmComputeComponentGraph ccg(this->InitialGraph);
  if(this->DebugMode)
    {
    this->DisplayComponents(ccg);
    }
  if(!this->CheckComponents(ccg))
    {
    return false;
    }

  // Compute the final dependency graph.
  if(!this->ComputeFinalDepends(ccg))
    {
    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.
  std::map<cmGeneratorTarget const*, int>::const_iterator tii
                                                  = this->TargetIndex.find(t);
  assert(tii != this->TargetIndex.end());
  int i = tii->second;

  // Get its final dependencies.
  EdgeList const& nl = this->FinalGraph[i];
  for(EdgeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
    {
    cmGeneratorTarget const* dep = this->Targets[*ni];
    cmTargetDependSet::iterator di = deps.insert(dep).first;
    di->SetType(ni->IsStrong());
    }
}

//----------------------------------------------------------------------------
void cmComputeTargetDepends::CollectTargets()
{
  // Collect all targets from all generators.
  std::vector<cmLocalGenerator*> const& lgens =
    this->GlobalGenerator->GetLocalGenerators();
  for(unsigned int i = 0; i < lgens.size(); ++i)
    {
    const std::vector<cmGeneratorTarget*> targets =
        lgens[i]->GetGeneratorTargets();
    for(std::vector<cmGeneratorTarget*>::const_iterator ti = targets.begin();
        ti != targets.end(); ++ti)
      {
      cmGeneratorTarget* gt = *ti;
      int index = static_cast<int>(this->Targets.size());
      this->TargetIndex[gt] = index;
      this->Targets.push_back(gt);
      }
    }
}

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

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

//----------------------------------------------------------------------------
void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
{
  // Get the depender.
  cmGeneratorTarget const* depender = this->Targets[depender_index];
  if (depender->GetType() == cmState::INTERFACE_LIBRARY)
    {
    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<std::string> emitted;

  std::vector<std::string> configs;
  depender->Makefile->GetConfigurations(configs);
  if (configs.empty())
    {
    configs.push_back("");
    }
  for (std::vector<std::string>::const_iterator it = configs.begin();
    it != configs.end(); ++it)
    {
    std::vector<cmSourceFile const*> objectFiles;
    depender->GetExternalObjects(objectFiles, *it);
    for(std::vector<cmSourceFile const*>::const_iterator
        oi = objectFiles.begin(); oi != objectFiles.end(); ++oi)
      {
      std::string objLib = (*oi)->GetObjectLibrary();
      if (!objLib.empty() && emitted.insert(objLib).second)
        {
        if(depender->GetType() != cmState::EXECUTABLE &&
            depender->GetType() != cmState::STATIC_LIBRARY &&
            depender->GetType() != cmState::SHARED_LIBRARY &&
            depender->GetType() != cmState::MODULE_LIBRARY)
          {
          this->GlobalGenerator->GetCMakeInstance()
            ->IssueMessage(cmake::FATAL_ERROR,
                            "Only executables and non-OBJECT libraries may "
                            "reference target objects.",
                            depender->GetBacktrace());
          return;
          }
        const_cast<cmGeneratorTarget*>(depender)->Target->AddUtility(objLib);
        }
      }

    cmLinkImplementation const* impl = depender->GetLinkImplementation(*it);

    // A target should not depend on itself.
    emitted.insert(depender->GetName());
    for(std::vector<cmLinkImplItem>::const_iterator
          lib = impl->Libraries.begin();
        lib != impl->Libraries.end(); ++lib)
      {
      // Don't emit the same library twice for this target.
      if(emitted.insert(*lib).second)
        {
        this->AddTargetDepend(depender_index, *lib, true);
        this->AddInterfaceDepends(depender_index, *lib, emitted);
        }
      }
    }
  }

  // Loop over all utility dependencies.
  {
  std::set<cmLinkItem> const& tutils = depender->GetUtilityItems();
  std::set<std::string> emitted;
  // A target should not depend on itself.
  emitted.insert(depender->GetName());
  for(std::set<cmLinkItem>::const_iterator util = tutils.begin();
      util != tutils.end(); ++util)
    {
    // Don't emit the same utility twice for this target.
    if(emitted.insert(*util).second)
      {
      this->AddTargetDepend(depender_index, *util, false);
      }
    }
  }
}

//----------------------------------------------------------------------------
void cmComputeTargetDepends::AddInterfaceDepends(int depender_index,
                                             const cmGeneratorTarget* dependee,
                                             const std::string& config,
                                             std::set<std::string> &emitted)
{
  cmGeneratorTarget const* depender = this->Targets[depender_index];
  if(cmLinkInterface const* iface =
                                dependee->GetLinkInterface(config,
                                                           depender))
    {
    for(std::vector<cmLinkItem>::const_iterator
        lib = iface->Libraries.begin();
        lib != iface->Libraries.end(); ++lib)
      {
      // Don't emit the same library twice for this target.
      if(emitted.insert(*lib).second)
        {
        this->AddTargetDepend(depender_index, *lib, true);
        this->AddInterfaceDepends(depender_index, *lib, emitted);
        }
      }
    }
}

//----------------------------------------------------------------------------
void cmComputeTargetDepends::AddInterfaceDepends(int depender_index,
                                             cmLinkItem const& dependee_name,
                                             std::set<std::string> &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() == cmState::EXECUTABLE &&
     !dependee->IsExecutableWithExports())
    {
    dependee = 0;
    }

  if(dependee)
    {
    this->AddInterfaceDepends(depender_index, dependee, "", emitted);
    std::vector<std::string> configs;
    depender->Makefile->GetConfigurations(configs);
    for (std::vector<std::string>::const_iterator it = configs.begin();
      it != configs.end(); ++it)
      {
      // A target should not depend on itself.
      emitted.insert(depender->GetName());
      this->AddInterfaceDepends(depender_index, dependee, *it, emitted);
      }
    }
}

//----------------------------------------------------------------------------
void cmComputeTargetDepends::AddTargetDepend(
  int depender_index, cmLinkItem const& dependee_name,
  bool linking)
{
  // 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() != cmState::GLOBAL_TARGET))
    {
    cmake::MessageType messageType = cmake::AUTHOR_WARNING;
    bool issueMessage = false;
    std::ostringstream e;
    switch(depender->GetPolicyStatusCMP0046())
      {
      case cmPolicies::WARN:
        e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0046) << "\n";
        issueMessage = true;
      case cmPolicies::OLD:
        break;
      case cmPolicies::NEW:
      case cmPolicies::REQUIRED_IF_USED:
      case cmPolicies::REQUIRED_ALWAYS:
        issueMessage = true;
        messageType = cmake::FATAL_ERROR;
      }
    if(issueMessage)
      {
      cmake* cm = this->GlobalGenerator->GetCMakeInstance();

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

      cmListFileBacktrace const* backtrace =
        depender->GetUtilityBacktrace(dependee_name);
      if(backtrace)
        {
        cm->IssueMessage(messageType, e.str(), *backtrace);
        }
      else
        {
        cm->IssueMessage(messageType, e.str());
        }

      }
    }

  // 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() == cmState::EXECUTABLE &&
     !dependee->IsExecutableWithExports())
    {
    dependee = 0;
    }

  if(dependee)
    {
    this->AddTargetDepend(depender_index, dependee, linking);
    }
}

//----------------------------------------------------------------------------
void cmComputeTargetDepends::AddTargetDepend(int depender_index,
                                             const cmGeneratorTarget* dependee,
                                             bool linking)
{
  if(dependee->IsImported() ||
     dependee->GetType() == cmState::INTERFACE_LIBRARY)
    {
    // Skip IMPORTED and INTERFACE targets but follow their utility
    // dependencies.
    std::set<cmLinkItem> const& utils = dependee->GetUtilityItems();
    for(std::set<cmLinkItem>::const_iterator i = utils.begin();
        i != utils.end(); ++i)
      {
      if(cmGeneratorTarget const* transitive_dependee = i->Target)
        {
        this->AddTargetDepend(depender_index, transitive_dependee, false);
        }
      }
    }
  else
    {
    // Lookup the index for this target.  All targets should be known by
    // this point.
    std::map<cmGeneratorTarget const*, int>::const_iterator tii =
      this->TargetIndex.find(dependee);
    assert(tii != this->TargetIndex.end());
    int dependee_index = tii->second;

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

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

//----------------------------------------------------------------------------
void
cmComputeTargetDepends
::DisplayComponents(cmComputeComponentGraph const& ccg)
{
  fprintf(stderr, "The strongly connected components are:\n");
  std::vector<NodeList> const& components = ccg.GetComponents();
  int n = static_cast<int>(components.size());
  for(int c = 0; c < n; ++c)
    {
    NodeList const& nl = components[c];
    fprintf(stderr, "Component (%d):\n", c);
    for(NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
      {
      int i = *ni;
      fprintf(stderr, "  contains target %d [%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();
  int nc = static_cast<int>(components.size());
  for(int 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(NodeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
      {
      if(this->Targets[*ni]->GetType() != cmState::STATIC_LIBRARY)
        {
        this->ComplainAboutBadComponent(ccg, c);
        return false;
        }
      }
    }
  return true;
}

//----------------------------------------------------------------------------
void
cmComputeTargetDepends
::ComplainAboutBadComponent(cmComputeComponentGraph const& ccg, int 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<int> const& cmap = ccg.GetComponentMap();
  NodeList const& cl = components[c];
  for(NodeList::const_iterator ci = cl.begin(); ci != cl.end(); ++ci)
    {
    // Get the depender.
    int i = *ci;
    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(EdgeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
      {
      int 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().c_str());
}

//----------------------------------------------------------------------------
bool
cmComputeTargetDepends
::IntraComponent(std::vector<int> const& cmap, int c, int i, int* head,
                 std::set<int>& emitted, std::set<int>& 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(EdgeList::const_iterator ei = el.begin(); ei != el.end(); ++ei)
      {
      int j = *ei;
      if(cmap[j] == c && ei->IsStrong())
        {
        this->FinalGraph[i].push_back(cmGraphEdge(j, true));
        if(!this->IntraComponent(cmap, c, j, head, emitted, visited))
          {
          return false;
          }
        }
      }

    // Prepend to a linear linked-list of intra-component edges.
    if(*head >= 0)
      {
      this->FinalGraph[i].push_back(cmGraphEdge(*head, false));
      }
    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<int> const& cmap = ccg.GetComponentMap();
  this->ComponentHead.resize(components.size());
  this->ComponentTail.resize(components.size());
  int nc = static_cast<int>(components.size());
  for(int c=0; c < nc; ++c)
    {
    int head = -1;
    std::set<int> emitted;
    NodeList const& nl = components[c];
    for(NodeList::const_reverse_iterator ni = nl.rbegin();
        ni != nl.rend(); ++ni)
      {
      std::set<int> 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.
  int n = static_cast<int>(cgraph.size());
  for(int depender_component=0; depender_component < n; ++depender_component)
    {
    int depender_component_tail = this->ComponentTail[depender_component];
    EdgeList const& nl = cgraph[depender_component];
    for(EdgeList::const_iterator ni = nl.begin(); ni != nl.end(); ++ni)
      {
      int dependee_component = *ni;
      int dependee_component_head = this->ComponentHead[dependee_component];
      this->FinalGraph[depender_component_tail]
        .push_back(cmGraphEdge(dependee_component_head, ni->IsStrong()));
      }
    }
  return true;
}
