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

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <memory>
#include <set>
#include <sstream>
#include <utility>

#include "cmExportSet.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmInstallTargetGenerator.h"
#include "cmList.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetExport.h"
#include "cmValue.h"
#include "cmake.h"

cmExportInstallFileGenerator::cmExportInstallFileGenerator(
  cmInstallExportGenerator* iegen)
  : IEGen(iegen)
{
}

void cmExportInstallFileGenerator::ReplaceInstallPrefix(
  std::string& input) const
{
  cmGeneratorExpression::ReplaceInstallPrefix(input, this->GetInstallPrefix());
}

void cmExportInstallFileGenerator::PopulateImportProperties(
  std::string const& config, std::string const& suffix,
  cmTargetExport const* targetExport, ImportPropertyMap& properties,
  std::set<std::string>& importedLocations)
{
  this->SetImportLocationProperty(config, suffix,
                                  targetExport->ArchiveGenerator, properties,
                                  importedLocations);
  this->SetImportLocationProperty(config, suffix,
                                  targetExport->LibraryGenerator, properties,
                                  importedLocations);
  this->SetImportLocationProperty(config, suffix,
                                  targetExport->RuntimeGenerator, properties,
                                  importedLocations);
  this->SetImportLocationProperty(config, suffix,
                                  targetExport->ObjectsGenerator, properties,
                                  importedLocations);
  this->SetImportLocationProperty(config, suffix,
                                  targetExport->FrameworkGenerator, properties,
                                  importedLocations);
  this->SetImportLocationProperty(config, suffix,
                                  targetExport->BundleGenerator, properties,
                                  importedLocations);

  // If any file location was set for the target add it to the
  // import file.
  if (!properties.empty()) {
    // Get the rest of the target details.
    cmGeneratorTarget const* const gtgt = targetExport->Target;
    this->SetImportDetailProperties(config, suffix, gtgt, properties);

    // TODO: PUBLIC_HEADER_LOCATION
    // This should wait until the build feature propagation stuff is done.
    // Then this can be a propagated include directory.
    // this->GenerateImportProperty(config, te->HeaderGenerator, properties);
  }
}

std::string cmExportInstallFileGenerator::GetImportXcFrameworkLocation(
  std::string const& config, cmTargetExport const* targetExport) const
{
  std::string importedXcFrameworkLocation = targetExport->XcFrameworkLocation;
  if (!importedXcFrameworkLocation.empty()) {
    importedXcFrameworkLocation = cmGeneratorExpression::Preprocess(
      importedXcFrameworkLocation,
      cmGeneratorExpression::PreprocessContext::InstallInterface,
      this->GetImportPrefixWithSlash());
    importedXcFrameworkLocation = cmGeneratorExpression::Evaluate(
      importedXcFrameworkLocation, targetExport->Target->GetLocalGenerator(),
      config, targetExport->Target, nullptr, targetExport->Target);
    if (!importedXcFrameworkLocation.empty() &&
        !cmSystemTools::FileIsFullPath(importedXcFrameworkLocation) &&
        !cmHasPrefix(importedXcFrameworkLocation,
                     this->GetImportPrefixWithSlash())) {
      return cmStrCat(this->GetImportPrefixWithSlash(),
                      importedXcFrameworkLocation);
    }
  }

  return importedXcFrameworkLocation;
}

bool cmExportInstallFileGenerator::GenerateImportFileConfig(
  std::string const& config)
{
  // Skip configurations not enabled for this export.
  if (!this->IEGen->InstallsForConfig(config)) {
    return true;
  }

  // Construct the name of the file to generate.
  std::string fileName = cmStrCat(this->FileDir, '/', this->FileBase,
                                  this->GetConfigFileNameSeparator());
  if (!config.empty()) {
    fileName += cmSystemTools::LowerCase(config);
  } else {
    fileName += "noconfig";
  }
  fileName += this->FileExt;

  // Open the output file to generate it.
  cmGeneratedFileStream exportFileStream(fileName, true);
  if (!exportFileStream) {
    std::string se = cmSystemTools::GetLastSystemError();
    std::ostringstream e;
    e << "cannot write to file \"" << fileName << "\": " << se;
    cmSystemTools::Error(e.str());
    return false;
  }
  exportFileStream.SetCopyIfDifferent(true);
  std::ostream& os = exportFileStream;

  // Generate the per-config target information.
  this->GenerateImportConfig(os, config);

  // Record this per-config import file.
  this->ConfigImportFiles[config] = fileName;

  return true;
}

void cmExportInstallFileGenerator::SetImportLocationProperty(
  std::string const& config, std::string const& suffix,
  cmInstallTargetGenerator* itgen, ImportPropertyMap& properties,
  std::set<std::string>& importedLocations)
{
  // Skip rules that do not match this configuration.
  if (!(itgen && itgen->InstallsForConfig(config))) {
    return;
  }

  // Get the target to be installed.
  cmGeneratorTarget* target = itgen->GetTarget();

  // Construct the installed location of the target.
  std::string dest = itgen->GetDestination(config);
  std::string value;
  if (!cmSystemTools::FileIsFullPath(dest)) {
    // The target is installed relative to the installation prefix.
    value = std::string{ this->GetImportPrefixWithSlash() };
  }
  value += dest;
  value += "/";

  if (itgen->IsImportLibrary()) {
    // Construct the property name.
    std::string prop = cmStrCat("IMPORTED_IMPLIB", suffix);

    // Append the installed file name.
    value += cmInstallTargetGenerator::GetInstallFilename(
      target, config, cmInstallTargetGenerator::NameImplibReal);

    // Store the property.
    properties[prop] = value;
    importedLocations.insert(prop);
  } else if (itgen->GetTarget()->GetType() == cmStateEnums::OBJECT_LIBRARY) {
    // Construct the property name.
    std::string prop = cmStrCat("IMPORTED_OBJECTS", suffix);

    // Compute all the object files inside this target and setup
    // IMPORTED_OBJECTS as a list of object files
    std::vector<std::string> objects;
    itgen->GetInstallObjectNames(config, objects);
    for (std::string& obj : objects) {
      obj = cmStrCat(value, obj);
    }

    // Store the property.
    properties[prop] = cmList::to_string(objects);
    importedLocations.insert(prop);
  } else {
    if (target->IsFrameworkOnApple() && target->HasImportLibrary(config)) {
      // store as well IMPLIB value
      auto importProp = cmStrCat("IMPORTED_IMPLIB", suffix);
      auto importValue =
        cmStrCat(value,
                 cmInstallTargetGenerator::GetInstallFilename(
                   target, config, cmInstallTargetGenerator::NameImplibReal));

      // Store the property.
      properties[importProp] = importValue;
      importedLocations.insert(importProp);
    }

    // Construct the property name.
    std::string prop = cmStrCat("IMPORTED_LOCATION", suffix);

    // Append the installed file name.
    if (target->IsAppBundleOnApple()) {
      value += cmInstallTargetGenerator::GetInstallFilename(target, config);
      value += ".app/";
      if (!target->Makefile->PlatformIsAppleEmbedded()) {
        value += "Contents/MacOS/";
      }
      value += cmInstallTargetGenerator::GetInstallFilename(target, config);
    } else {
      value += cmInstallTargetGenerator::GetInstallFilename(
        target, config, cmInstallTargetGenerator::NameReal);
    }

    // Store the property.
    properties[prop] = value;
    importedLocations.insert(prop);
  }
}

cmStateEnums::TargetType cmExportInstallFileGenerator::GetExportTargetType(
  cmTargetExport const* targetExport) const
{
  cmStateEnums::TargetType targetType = targetExport->Target->GetType();
  // An OBJECT library installed with no OBJECTS DESTINATION
  // is transformed to an INTERFACE library.
  if (targetType == cmStateEnums::OBJECT_LIBRARY &&
      !targetExport->ObjectsGenerator) {
    targetType = cmStateEnums::INTERFACE_LIBRARY;
  }
  return targetType;
}

std::string const& cmExportInstallFileGenerator::GetExportName() const
{
  return this->GetExportSet()->GetName();
}

void cmExportInstallFileGenerator::HandleMissingTarget(
  std::string& link_libs, cmGeneratorTarget const* depender,
  cmGeneratorTarget* dependee)
{
  auto const& exportInfo = this->FindExportInfo(dependee);

  if (exportInfo.Namespaces.size() == 1 && exportInfo.Sets.size() == 1) {
    std::string missingTarget = *exportInfo.Namespaces.begin();

    missingTarget += dependee->GetExportName();
    link_libs += missingTarget;
    this->MissingTargets.emplace_back(std::move(missingTarget));
  } else {
    // All exported targets should be known here and should be unique.
    // This is probably user-error.
    this->ComplainAboutMissingTarget(depender, dependee, exportInfo);
  }
}

cmExportFileGenerator::ExportInfo cmExportInstallFileGenerator::FindExportInfo(
  cmGeneratorTarget const* target) const
{
  std::vector<std::string> exportFiles;
  std::set<std::string> exportSets;
  std::set<std::string> namespaces;

  auto const& name = target->GetName();
  auto& allExportSets =
    target->GetLocalGenerator()->GetGlobalGenerator()->GetExportSets();

  for (auto const& exp : allExportSets) {
    auto const& exportSet = exp.second;
    auto const& targets = exportSet.GetTargetExports();

    if (std::any_of(targets.begin(), targets.end(),
                    [&name](std::unique_ptr<cmTargetExport> const& te) {
                      return te->TargetName == name;
                    })) {
      std::vector<cmInstallExportGenerator const*> const* installs =
        exportSet.GetInstallations();
      if (!installs->empty()) {
        exportSets.insert(exp.first);
        for (cmInstallExportGenerator const* install : *installs) {
          exportFiles.push_back(install->GetDestinationFile());
          namespaces.insert(install->GetNamespace());
        }
      }
    }
  }
  return { exportFiles, exportSets, namespaces };
}

void cmExportInstallFileGenerator::ComplainAboutMissingTarget(
  cmGeneratorTarget const* depender, cmGeneratorTarget const* dependee,
  ExportInfo const& exportInfo) const
{
  std::ostringstream e;
  e << "install(" << this->IEGen->InstallSubcommand() << " \""
    << this->GetExportName() << "\" ...) "
    << "includes target \"" << depender->GetName()
    << "\" which requires target \"" << dependee->GetName() << "\" ";
  if (exportInfo.Sets.empty()) {
    e << "that is not in any export set.";
  } else {
    if (exportInfo.Sets.size() == 1) {
      e << "that is not in this export set, but in another export set which "
           "is "
           "exported multiple times with different namespaces: ";
    } else {
      e << "that is not in this export set, but in multiple other export "
           "sets: ";
    }
    e << cmJoin(exportInfo.Files, ", ") << ".\n"
      << "An exported target cannot depend upon another target which is "
         "exported in more than one export set or with more than one "
         "namespace. "
         "Consider consolidating the exports of the \""
      << dependee->GetName() << "\" target to a single export.";
  }
  this->ReportError(e.str());
}

void cmExportInstallFileGenerator::ComplainAboutDuplicateTarget(
  std::string const& targetName) const
{
  std::ostringstream e;
  e << "install(" << this->IEGen->InstallSubcommand() << " \""
    << this->GetExportName() << "\" ...) "
    << "includes target \"" << targetName
    << "\" more than once in the export set.";
  this->ReportError(e.str());
}

void cmExportInstallFileGenerator::ReportError(
  std::string const& errorMessage) const
{
  this->IEGen->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
    MessageType::FATAL_ERROR, errorMessage,
    this->IEGen->GetLocalGenerator()->GetMakefile()->GetBacktrace());
}

std::string cmExportInstallFileGenerator::InstallNameDir(
  cmGeneratorTarget const* target, std::string const& config)
{
  std::string install_name_dir;

  cmMakefile* mf = target->Target->GetMakefile();
  if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
    auto const& prefix = this->GetInstallPrefix();
    install_name_dir = target->GetInstallNameDirForInstallTree(config, prefix);
  }

  return install_name_dir;
}

std::string cmExportInstallFileGenerator::GetCxxModuleFile() const
{
  return this->GetCxxModuleFile(this->GetExportSet()->GetName());
}

bool cmExportInstallFileGenerator::CollectExports(
  std::function<void(cmTargetExport const*)> const& visitor)
{
  auto pred = [&](std::unique_ptr<cmTargetExport> const& te) -> bool {
    if (te->NamelinkOnly) {
      return true;
    }
    if (this->ExportedTargets.insert(te->Target).second) {
      visitor(te.get());
      return true;
    }

    this->ComplainAboutDuplicateTarget(te->Target->GetName());
    return false;
  };

  auto const& targets = this->GetExportSet()->GetTargetExports();
  return std::all_of(targets.begin(), targets.end(), pred);
}

bool cmExportInstallFileGenerator::PopulateInterfaceProperties(
  cmTargetExport const* targetExport, ImportPropertyMap& properties)
{
  cmGeneratorTarget const* const gt = targetExport->Target;

  std::string includesDestinationDirs;
  this->PopulateInterfaceProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", gt,
                                  cmGeneratorExpression::InstallInterface,
                                  properties);
  this->PopulateIncludeDirectoriesInterface(
    gt, cmGeneratorExpression::InstallInterface, properties, *targetExport,
    includesDestinationDirs);
  this->PopulateLinkDirectoriesInterface(
    gt, cmGeneratorExpression::InstallInterface, properties);
  this->PopulateLinkDependsInterface(
    gt, cmGeneratorExpression::InstallInterface, properties);
  this->PopulateSourcesInterface(gt, cmGeneratorExpression::InstallInterface,
                                 properties);

  return this->PopulateInterfaceProperties(
    gt, includesDestinationDirs, cmGeneratorExpression::InstallInterface,
    properties);
}

namespace {
bool isSubDirectory(std::string const& a, std::string const& b)
{
  return (cmSystemTools::ComparePath(a, b) ||
          cmSystemTools::IsSubDirectory(a, b));
}
}

bool cmExportInstallFileGenerator::CheckInterfaceDirs(
  std::string const& prepro, cmGeneratorTarget const* target,
  std::string const& prop) const
{
  std::string const& installDir =
    target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
  std::string const& topSourceDir =
    target->GetLocalGenerator()->GetSourceDirectory();
  std::string const& topBinaryDir =
    target->GetLocalGenerator()->GetBinaryDirectory();

  std::vector<std::string> parts;
  cmGeneratorExpression::Split(prepro, parts);

  bool const inSourceBuild = topSourceDir == topBinaryDir;

  bool hadFatalError = false;

  for (std::string const& li : parts) {
    size_t genexPos = cmGeneratorExpression::Find(li);
    if (genexPos == 0) {
      continue;
    }
    if (cmHasPrefix(li, this->GetImportPrefixWithSlash())) {
      continue;
    }
    std::ostringstream e;
    if (genexPos != std::string::npos) {
      hadFatalError = true;
    }
    if (!cmSystemTools::FileIsFullPath(li)) {
      /* clang-format off */
      e << "Target \"" << target->GetName() << "\" " << prop <<
           " property contains relative path:\n"
           "  \"" << li << "\"";
      /* clang-format on */
      target->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
                                                e.str());
    }
    bool inBinary = isSubDirectory(li, topBinaryDir);
    bool inSource = isSubDirectory(li, topSourceDir);
    if (isSubDirectory(li, installDir)) {
      // The include directory is inside the install tree.  If the
      // install tree is inside the source tree or build tree then do not
      // fall through to the checks below that the include directory is not
      // also inside the source tree or build tree.
      if ((!inBinary || isSubDirectory(installDir, topBinaryDir)) &&
          (!inSource || isSubDirectory(installDir, topSourceDir))) {
        continue;
      }
    }
    if (inBinary) {
      /* clang-format off */
      e << "Target \"" << target->GetName() << "\" " << prop <<
           " property contains path:\n"
           "  \"" << li << "\"\nwhich is prefixed in the build directory.";
      /* clang-format on */
      target->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
                                                e.str());
    }
    if (!inSourceBuild) {
      if (inSource) {
        e << "Target \"" << target->GetName() << "\" " << prop
          << " property contains path:\n"
             "  \""
          << li << "\"\nwhich is prefixed in the source directory.";
        target->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
                                                  e.str());
      }
    }
  }
  return !hadFatalError;
}

void cmExportInstallFileGenerator::PopulateSourcesInterface(
  cmGeneratorTarget const* gt,
  cmGeneratorExpression::PreprocessContext preprocessRule,
  ImportPropertyMap& properties)
{
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);

  char const* const propName = "INTERFACE_SOURCES";
  cmValue input = gt->GetProperty(propName);

  if (!input) {
    return;
  }

  if (input->empty()) {
    properties[propName].clear();
    return;
  }

  std::string prepro = cmGeneratorExpression::Preprocess(
    *input, preprocessRule, this->GetImportPrefixWithSlash());
  if (!prepro.empty()) {
    this->ResolveTargetsInGeneratorExpressions(prepro, gt);

    if (!this->CheckInterfaceDirs(prepro, gt, propName)) {
      return;
    }
    properties[propName] = prepro;
  }
}

void cmExportInstallFileGenerator::PopulateIncludeDirectoriesInterface(
  cmGeneratorTarget const* target,
  cmGeneratorExpression::PreprocessContext preprocessRule,
  ImportPropertyMap& properties, cmTargetExport const& te,
  std::string& includesDestinationDirs)
{
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);

  includesDestinationDirs.clear();

  char const* const propName = "INTERFACE_INCLUDE_DIRECTORIES";
  cmValue input = target->GetProperty(propName);

  cmGeneratorExpression ge(*target->Makefile->GetCMakeInstance());

  std::string dirs = cmGeneratorExpression::Preprocess(
    cmList::to_string(target->Target->GetInstallIncludeDirectoriesEntries(te)),
    preprocessRule, this->GetImportPrefixWithSlash());
  this->ReplaceInstallPrefix(dirs);
  std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(dirs);
  std::string exportDirs =
    cge->Evaluate(target->GetLocalGenerator(), "", target);

  if (cge->GetHadContextSensitiveCondition()) {
    cmLocalGenerator* lg = target->GetLocalGenerator();
    std::ostringstream e;
    e << "Target \"" << target->GetName()
      << "\" is installed with "
         "INCLUDES DESTINATION set to a context sensitive path.  Paths which "
         "depend on the configuration, policy values or the link interface "
         "are "
         "not supported.  Consider using target_include_directories instead.";
    lg->IssueMessage(MessageType::FATAL_ERROR, e.str());
    return;
  }

  if (!input && exportDirs.empty()) {
    return;
  }
  if ((input && input->empty()) && exportDirs.empty()) {
    // Set to empty
    properties[propName].clear();
    return;
  }

  this->AddImportPrefix(exportDirs);
  includesDestinationDirs = exportDirs;

  std::string includes = (input ? *input : "");
  char const* const sep = input ? ";" : "";
  includes += sep + exportDirs;
  std::string prepro = cmGeneratorExpression::Preprocess(
    includes, preprocessRule, this->GetImportPrefixWithSlash());
  if (!prepro.empty()) {
    this->ResolveTargetsInGeneratorExpressions(prepro, target);

    if (!this->CheckInterfaceDirs(prepro, target, propName)) {
      return;
    }
    properties[propName] = prepro;
  }
}

void cmExportInstallFileGenerator::PopulateLinkDependsInterface(
  cmGeneratorTarget const* gt,
  cmGeneratorExpression::PreprocessContext preprocessRule,
  ImportPropertyMap& properties)
{
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);

  char const* const propName = "INTERFACE_LINK_DEPENDS";
  cmValue input = gt->GetProperty(propName);

  if (!input) {
    return;
  }

  if (input->empty()) {
    properties[propName].clear();
    return;
  }

  std::string prepro = cmGeneratorExpression::Preprocess(
    *input, preprocessRule, this->GetImportPrefixWithSlash());
  if (!prepro.empty()) {
    this->ResolveTargetsInGeneratorExpressions(prepro, gt);

    if (!this->CheckInterfaceDirs(prepro, gt, propName)) {
      return;
    }
    properties[propName] = prepro;
  }
}

void cmExportInstallFileGenerator::PopulateLinkDirectoriesInterface(
  cmGeneratorTarget const* gt,
  cmGeneratorExpression::PreprocessContext preprocessRule,
  ImportPropertyMap& properties)
{
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);

  char const* const propName = "INTERFACE_LINK_DIRECTORIES";
  cmValue input = gt->GetProperty(propName);

  if (!input) {
    return;
  }

  if (input->empty()) {
    properties[propName].clear();
    return;
  }

  std::string prepro = cmGeneratorExpression::Preprocess(
    *input, preprocessRule, this->GetImportPrefixWithSlash());
  if (!prepro.empty()) {
    this->ResolveTargetsInGeneratorExpressions(prepro, gt);

    if (!this->CheckInterfaceDirs(prepro, gt, propName)) {
      return;
    }
    properties[propName] = prepro;
  }
}
