/*============================================================================
  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 "cmOrderDirectories.h"

#include "cmGlobalGenerator.h"
#include "cmSystemTools.h"
#include "cmake.h"

#include <assert.h>

#include <algorithm>

/*
Directory ordering computation.
  - Useful to compute a safe runtime library path order
  - Need runtime path for supporting INSTALL_RPATH_USE_LINK_PATH
  - Need runtime path at link time to pickup transitive link dependencies
    for shared libraries.
*/

//----------------------------------------------------------------------------
class cmOrderDirectoriesConstraint
{
public:
  cmOrderDirectoriesConstraint(cmOrderDirectories* od,
                               std::string const& file):
    OD(od), GlobalGenerator(od->GlobalGenerator)
    {
    this->FullPath = file;

    if(file.rfind(".framework") != std::string::npos)
      {
      cmsys::RegularExpression splitFramework;
      splitFramework.compile("^(.*)/(.*).framework/(.*)$");
      if(splitFramework.find(file) &&
        (std::string::npos !=
         splitFramework.match(3).find(splitFramework.match(2))))
        {
        this->Directory = splitFramework.match(1);
        this->FileName =
          std::string(file.begin() + this->Directory.size() + 1, file.end());
        }
      }

    if(this->FileName.empty())
      {
      this->Directory = cmSystemTools::GetFilenamePath(file);
      this->FileName = cmSystemTools::GetFilenameName(file);
      }
    }
  virtual ~cmOrderDirectoriesConstraint() {}

  void AddDirectory()
    {
    this->DirectoryIndex = this->OD->AddOriginalDirectory(this->Directory);
    }

  virtual void Report(std::ostream& e) = 0;

  void FindConflicts(unsigned int index)
    {
    for(unsigned int i=0; i < this->OD->OriginalDirectories.size(); ++i)
      {
      // Check if this directory conflicts with the entry.
      std::string const& dir = this->OD->OriginalDirectories[i];
      if(dir != this->Directory && this->FindConflict(dir))
        {
        // The library will be found in this directory but this is not
        // the directory named for it.  Add an entry to make sure the
        // desired directory comes before this one.
        cmOrderDirectories::ConflictPair p(this->DirectoryIndex, index);
        this->OD->ConflictGraph[i].push_back(p);
        }
      }
    }

  void FindImplicitConflicts(cmOStringStream& w)
    {
    bool first = true;
    for(unsigned int i=0; i < this->OD->OriginalDirectories.size(); ++i)
      {
      // Check if this directory conflicts with the entry.
      std::string const& dir = this->OD->OriginalDirectories[i];
      if(dir != this->Directory && this->FindConflict(dir))
        {
        // The library will be found in this directory but it is
        // supposed to be found in an implicit search directory.
        if(first)
          {
          first = false;
          w << "  ";
          this->Report(w);
          w << " in " << this->Directory << " may be hidden by files in:\n";
          }
        w << "    " << dir << "\n";
        }
      }
    }
protected:
  virtual bool FindConflict(std::string const& dir) = 0;

  bool FileMayConflict(std::string const& dir, std::string const& name);

  cmOrderDirectories* OD;
  cmGlobalGenerator* GlobalGenerator;

  // The location in which the item is supposed to be found.
  std::string FullPath;
  std::string Directory;
  std::string FileName;

  // The index assigned to the directory.
  int DirectoryIndex;
};

//----------------------------------------------------------------------------
bool cmOrderDirectoriesConstraint::FileMayConflict(std::string const& dir,
                                                   std::string const& name)
{
  // Check if the file exists on disk.
  std::string file = dir;
  file += "/";
  file += name;
  if(cmSystemTools::FileExists(file.c_str(), true))
    {
    // The file conflicts only if it is not the same as the original
    // file due to a symlink or hardlink.
    return !cmSystemTools::SameFile(this->FullPath.c_str(), file.c_str());
    }

  // Check if the file will be built by cmake.
  std::set<cmStdString> const& files =
    (this->GlobalGenerator->GetDirectoryContent(dir, false));
  std::set<cmStdString>::const_iterator fi = files.find(name);
  return fi != files.end();
}

//----------------------------------------------------------------------------
class cmOrderDirectoriesConstraintSOName: public cmOrderDirectoriesConstraint
{
public:
  cmOrderDirectoriesConstraintSOName(cmOrderDirectories* od,
                                     std::string const& file,
                                     const char* soname):
    cmOrderDirectoriesConstraint(od, file), SOName(soname? soname : "")
    {
    if(this->SOName.empty())
      {
      // Try to guess the soname.
      std::string soguess;
      if(cmSystemTools::GuessLibrarySOName(file, soguess))
        {
        this->SOName = soguess;
        }
      }
    }

  virtual void Report(std::ostream& e)
    {
    e << "runtime library [";
    if(this->SOName.empty())
      {
      e << this->FileName;
      }
    else
      {
      e << this->SOName;
      }
    e << "]";
    }

  virtual bool FindConflict(std::string const& dir);
private:
  // The soname of the shared library if it is known.
  std::string SOName;
};

//----------------------------------------------------------------------------
bool cmOrderDirectoriesConstraintSOName::FindConflict(std::string const& dir)
{
  // Determine which type of check to do.
  if(!this->SOName.empty())
    {
    // We have the library soname.  Check if it will be found.
    if(this->FileMayConflict(dir, this->SOName))
      {
      return true;
      }
    }
  else
    {
    // We do not have the soname.  Look for files in the directory
    // that may conflict.
    std::set<cmStdString> const& files =
      (this->GlobalGenerator
       ->GetDirectoryContent(dir, true));

    // Get the set of files that might conflict.  Since we do not
    // know the soname just look at all files that start with the
    // file name.  Usually the soname starts with the library name.
    std::string base = this->FileName;
    std::set<cmStdString>::const_iterator first = files.lower_bound(base);
    ++base[base.size()-1];
    std::set<cmStdString>::const_iterator last = files.upper_bound(base);
    if(first != last)
      {
      return true;
      }
    }
  return false;
}

//----------------------------------------------------------------------------
class cmOrderDirectoriesConstraintLibrary: public cmOrderDirectoriesConstraint
{
public:
  cmOrderDirectoriesConstraintLibrary(cmOrderDirectories* od,
                                      std::string const& file):
    cmOrderDirectoriesConstraint(od, file)
    {
    }

  virtual void Report(std::ostream& e)
    {
    e << "link library [" << this->FileName << "]";
    }

  virtual bool FindConflict(std::string const& dir);
};

//----------------------------------------------------------------------------
bool cmOrderDirectoriesConstraintLibrary::FindConflict(std::string const& dir)
{
  // We have the library file name.  Check if it will be found.
  if(this->FileMayConflict(dir, this->FileName))
    {
    return true;
    }

  // Now check if the file exists with other extensions the linker
  // might consider.
  if(!this->OD->LinkExtensions.empty() &&
     this->OD->RemoveLibraryExtension.find(this->FileName))
    {
    cmStdString lib = this->OD->RemoveLibraryExtension.match(1);
    cmStdString ext = this->OD->RemoveLibraryExtension.match(2);
    for(std::vector<std::string>::iterator
          i = this->OD->LinkExtensions.begin();
        i != this->OD->LinkExtensions.end(); ++i)
      {
      if(*i != ext)
        {
        std::string fname = lib;
        fname += *i;
        if(this->FileMayConflict(dir, fname.c_str()))
          {
          return true;
          }
        }
      }
    }
  return false;
}

//----------------------------------------------------------------------------
cmOrderDirectories::cmOrderDirectories(cmGlobalGenerator* gg,
                                       cmTarget const* target,
                                       const char* purpose)
{
  this->GlobalGenerator = gg;
  this->Target = target;
  this->Purpose = purpose;
  this->Computed = false;
}

//----------------------------------------------------------------------------
cmOrderDirectories::~cmOrderDirectories()
{
  for(std::vector<cmOrderDirectoriesConstraint*>::iterator
        i = this->ConstraintEntries.begin();
      i != this->ConstraintEntries.end(); ++i)
    {
    delete *i;
    }
  for(std::vector<cmOrderDirectoriesConstraint*>::iterator
        i = this->ImplicitDirEntries.begin();
      i != this->ImplicitDirEntries.end(); ++i)
    {
    delete *i;
    }
}

//----------------------------------------------------------------------------
std::vector<std::string> const& cmOrderDirectories::GetOrderedDirectories()
{
  if(!this->Computed)
    {
    this->Computed = true;
    this->CollectOriginalDirectories();
    this->FindConflicts();
    this->OrderDirectories();
    }
  return this->OrderedDirectories;
}

//----------------------------------------------------------------------------
void cmOrderDirectories::AddRuntimeLibrary(std::string const& fullPath,
                                           const char* soname)
{
  // Add the runtime library at most once.
  if(this->EmmittedConstraintSOName.insert(fullPath).second)
    {
    // Implicit link directories need special handling.
    if(!this->ImplicitDirectories.empty())
      {
      std::string dir = cmSystemTools::GetFilenamePath(fullPath);

      if(fullPath.rfind(".framework") != std::string::npos)
        {
        cmsys::RegularExpression splitFramework;
        splitFramework.compile("^(.*)/(.*).framework/(.*)$");
        if(splitFramework.find(fullPath) &&
          (std::string::npos !=
           splitFramework.match(3).find(splitFramework.match(2))))
          {
          dir = splitFramework.match(1);
          }
        }

      if(this->ImplicitDirectories.find(dir) !=
         this->ImplicitDirectories.end())
        {
        this->ImplicitDirEntries.push_back(
          new cmOrderDirectoriesConstraintSOName(this, fullPath, soname));
        return;
        }
      }

    // Construct the runtime information entry for this library.
    this->ConstraintEntries.push_back(
      new cmOrderDirectoriesConstraintSOName(this, fullPath, soname));
    }
  else
    {
    // This can happen if the same library is linked multiple times.
    // In that case the runtime information check need be done only
    // once anyway.  For shared libs we could add a check in AddItem
    // to not repeat them.
    }
}

//----------------------------------------------------------------------------
void cmOrderDirectories::AddLinkLibrary(std::string const& fullPath)
{
  // Link extension info is required for library constraints.
  assert(!this->LinkExtensions.empty());

  // Add the link library at most once.
  if(this->EmmittedConstraintLibrary.insert(fullPath).second)
    {
    // Implicit link directories need special handling.
    if(!this->ImplicitDirectories.empty())
      {
      std::string dir = cmSystemTools::GetFilenamePath(fullPath);
      if(this->ImplicitDirectories.find(dir) !=
         this->ImplicitDirectories.end())
        {
        this->ImplicitDirEntries.push_back(
          new cmOrderDirectoriesConstraintLibrary(this, fullPath));
        return;
        }
      }

    // Construct the link library entry.
    this->ConstraintEntries.push_back(
      new cmOrderDirectoriesConstraintLibrary(this, fullPath));
    }
}

//----------------------------------------------------------------------------
void
cmOrderDirectories
::AddUserDirectories(std::vector<std::string> const& extra)
{
  this->UserDirectories.insert(this->UserDirectories.end(),
                               extra.begin(), extra.end());
}

//----------------------------------------------------------------------------
void
cmOrderDirectories
::AddLanguageDirectories(std::vector<std::string> const& dirs)
{
  this->LanguageDirectories.insert(this->LanguageDirectories.end(),
                                   dirs.begin(), dirs.end());
}

//----------------------------------------------------------------------------
void
cmOrderDirectories
::SetImplicitDirectories(std::set<cmStdString> const& implicitDirs)
{
  this->ImplicitDirectories = implicitDirs;
}

//----------------------------------------------------------------------------
void
cmOrderDirectories
::SetLinkExtensionInfo(std::vector<std::string> const& linkExtensions,
                       std::string const& removeExtRegex)
{
  this->LinkExtensions = linkExtensions;
  this->RemoveLibraryExtension.compile(removeExtRegex.c_str());
}

//----------------------------------------------------------------------------
void cmOrderDirectories::CollectOriginalDirectories()
{
  // Add user directories specified for inclusion.  These should be
  // indexed first so their original order is preserved as much as
  // possible subject to the constraints.
  this->AddOriginalDirectories(this->UserDirectories);

  // Add directories containing constraints.
  for(unsigned int i=0; i < this->ConstraintEntries.size(); ++i)
    {
    this->ConstraintEntries[i]->AddDirectory();
    }

  // Add language runtime directories last.
  this->AddOriginalDirectories(this->LanguageDirectories);
}

//----------------------------------------------------------------------------
int cmOrderDirectories::AddOriginalDirectory(std::string const& dir)
{
  // Add the runtime directory with a unique index.
  std::map<cmStdString, int>::iterator i =
    this->DirectoryIndex.find(dir);
  if(i == this->DirectoryIndex.end())
    {
    std::map<cmStdString, int>::value_type
      entry(dir, static_cast<int>(this->OriginalDirectories.size()));
    i = this->DirectoryIndex.insert(entry).first;
    this->OriginalDirectories.push_back(dir);
    }

  return i->second;
}

//----------------------------------------------------------------------------
void
cmOrderDirectories
::AddOriginalDirectories(std::vector<std::string> const& dirs)
{
  for(std::vector<std::string>::const_iterator di = dirs.begin();
      di != dirs.end(); ++di)
    {
    // We never explicitly specify implicit link directories.
    if(this->ImplicitDirectories.find(*di) !=
       this->ImplicitDirectories.end())
      {
      continue;
      }

    // Skip the empty string.
    if(di->empty())
      {
      continue;
      }

    // Add this directory.
    this->AddOriginalDirectory(*di);
    }
}

//----------------------------------------------------------------------------
struct cmOrderDirectoriesCompare
{
  typedef std::pair<int, int> ConflictPair;

  // The conflict pair is unique based on just the directory
  // (first).  The second element is only used for displaying
  // information about why the entry is present.
  bool operator()(ConflictPair const& l,
                  ConflictPair const& r)
    {
    return l.first == r.first;
    }
};

//----------------------------------------------------------------------------
void cmOrderDirectories::FindConflicts()
{
  // Allocate the conflict graph.
  this->ConflictGraph.resize(this->OriginalDirectories.size());
  this->DirectoryVisited.resize(this->OriginalDirectories.size(), 0);

  // Find directories conflicting with each entry.
  for(unsigned int i=0; i < this->ConstraintEntries.size(); ++i)
    {
    this->ConstraintEntries[i]->FindConflicts(i);
    }

  // Clean up the conflict graph representation.
  for(std::vector<ConflictList>::iterator
        i = this->ConflictGraph.begin();
      i != this->ConflictGraph.end(); ++i)
    {
    // Sort the outgoing edges for each graph node so that the
    // original order will be preserved as much as possible.
    std::sort(i->begin(), i->end());

    // Make the edge list unique so cycle detection will be reliable.
    ConflictList::iterator last =
      std::unique(i->begin(), i->end(), cmOrderDirectoriesCompare());
    i->erase(last, i->end());
    }

  // Check items in implicit link directories.
  this->FindImplicitConflicts();
}

//----------------------------------------------------------------------------
void cmOrderDirectories::FindImplicitConflicts()
{
  // Check for items in implicit link directories that have conflicts
  // in the explicit directories.
  cmOStringStream conflicts;
  for(unsigned int i=0; i < this->ImplicitDirEntries.size(); ++i)
    {
    this->ImplicitDirEntries[i]->FindImplicitConflicts(conflicts);
    }

  // Skip warning if there were no conflicts.
  std::string text = conflicts.str();
  if(text.empty())
    {
    return;
    }

  // Warn about the conflicts.
  cmOStringStream w;
  w << "Cannot generate a safe " << this->Purpose
    << " for target " << this->Target->GetName()
    << " because files in some directories may conflict with "
    << " libraries in implicit directories:\n"
    << text
    << "Some of these libraries may not be found correctly.";
  this->GlobalGenerator->GetCMakeInstance()
    ->IssueMessage(cmake::WARNING, w.str(), this->Target->GetBacktrace());
}

//----------------------------------------------------------------------------
void cmOrderDirectories::OrderDirectories()
{
  // Allow a cycle to be diagnosed once.
  this->CycleDiagnosed = false;
  this->WalkId = 0;

  // Iterate through the directories in the original order.
  for(unsigned int i=0; i < this->OriginalDirectories.size(); ++i)
    {
    // Start a new DFS from this node.
    ++this->WalkId;
    this->VisitDirectory(i);
    }
}

//----------------------------------------------------------------------------
void cmOrderDirectories::VisitDirectory(unsigned int i)
{
  // Skip nodes already visited.
  if(this->DirectoryVisited[i])
    {
    if(this->DirectoryVisited[i] == this->WalkId)
      {
      // We have reached a node previously visited on this DFS.
      // There is a cycle.
      this->DiagnoseCycle();
      }
    return;
    }

  // We are now visiting this node so mark it.
  this->DirectoryVisited[i] = this->WalkId;

  // Visit the neighbors of the node first.
  ConflictList const& clist = this->ConflictGraph[i];
  for(ConflictList::const_iterator j = clist.begin();
      j != clist.end(); ++j)
    {
    this->VisitDirectory(j->first);
    }

  // Now that all directories required to come before this one have
  // been emmitted, emit this directory.
  this->OrderedDirectories.push_back(this->OriginalDirectories[i]);
}

//----------------------------------------------------------------------------
void cmOrderDirectories::DiagnoseCycle()
{
  // Report the cycle at most once.
  if(this->CycleDiagnosed)
    {
    return;
    }
  this->CycleDiagnosed = true;

  // Construct the message.
  cmOStringStream e;
  e << "Cannot generate a safe " << this->Purpose
    << " for target " << this->Target->GetName()
    << " because there is a cycle in the constraint graph:\n";

  // Display the conflict graph.
  for(unsigned int i=0; i < this->ConflictGraph.size(); ++i)
    {
    ConflictList const& clist = this->ConflictGraph[i];
    e << "  dir " << i << " is [" << this->OriginalDirectories[i] << "]\n";
    for(ConflictList::const_iterator j = clist.begin();
        j != clist.end(); ++j)
      {
      e << "    dir " << j->first << " must precede it due to ";
      this->ConstraintEntries[j->second]->Report(e);
      e << "\n";
      }
    }
  e << "Some of these libraries may not be found correctly.";
  this->GlobalGenerator->GetCMakeInstance()
    ->IssueMessage(cmake::WARNING, e.str(), this->Target->GetBacktrace());
}
