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

#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmLinkItem.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmProperty.h"
#include "cmPropertyMap.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetExport.h"
#include "cmake.h"

#include "cmsys/FStream.hxx"
#include <assert.h>
#include <memory> // IWYU pragma: keep
#include <sstream>
#include <string.h>
#include <utility>

static std::string cmExportFileGeneratorEscape(std::string const& str)
{
  // Escape a property value for writing into a .cmake file.
  std::string result = cmOutputConverter::EscapeForCMake(str);
  // Un-escape variable references generated by our own export code.
  cmSystemTools::ReplaceString(result, "\\${_IMPORT_PREFIX}",
                               "${_IMPORT_PREFIX}");
  cmSystemTools::ReplaceString(result, "\\${CMAKE_IMPORT_LIBRARY_SUFFIX}",
                               "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
  return result;
}

cmExportFileGenerator::cmExportFileGenerator()
{
  this->AppendMode = false;
  this->ExportOld = false;
}

void cmExportFileGenerator::AddConfiguration(const std::string& config)
{
  this->Configurations.push_back(config);
}

void cmExportFileGenerator::SetExportFile(const char* mainFile)
{
  this->MainImportFile = mainFile;
  this->FileDir = cmSystemTools::GetFilenamePath(this->MainImportFile);
  this->FileBase =
    cmSystemTools::GetFilenameWithoutLastExtension(this->MainImportFile);
  this->FileExt =
    cmSystemTools::GetFilenameLastExtension(this->MainImportFile);
}

const char* cmExportFileGenerator::GetMainExportFileName() const
{
  return this->MainImportFile.c_str();
}

bool cmExportFileGenerator::GenerateImportFile()
{
  // Open the output file to generate it.
  std::unique_ptr<cmsys::ofstream> foutPtr;
  if (this->AppendMode) {
    // Open for append.
    foutPtr = cm::make_unique<cmsys::ofstream>(this->MainImportFile.c_str(),
                                               std::ios::app);
  } else {
    // Generate atomically and with copy-if-different.
    std::unique_ptr<cmGeneratedFileStream> ap(
      new cmGeneratedFileStream(this->MainImportFile, true));
    ap->SetCopyIfDifferent(true);
    foutPtr = std::move(ap);
  }
  if (!foutPtr.get() || !*foutPtr) {
    std::string se = cmSystemTools::GetLastSystemError();
    std::ostringstream e;
    e << "cannot write to file \"" << this->MainImportFile << "\": " << se;
    cmSystemTools::Error(e.str().c_str());
    return false;
  }
  std::ostream& os = *foutPtr;

  // Start with the import file header.
  this->GeneratePolicyHeaderCode(os);
  this->GenerateImportHeaderCode(os);

  // Create all the imported targets.
  bool result = this->GenerateMainFile(os);

  // End with the import file footer.
  this->GenerateImportFooterCode(os);
  this->GeneratePolicyFooterCode(os);

  return result;
}

void cmExportFileGenerator::GenerateImportConfig(
  std::ostream& os, const std::string& config,
  std::vector<std::string>& missingTargets)
{
  // Construct the property configuration suffix.
  std::string suffix = "_";
  if (!config.empty()) {
    suffix += cmSystemTools::UpperCase(config);
  } else {
    suffix += "NOCONFIG";
  }

  // Generate the per-config target information.
  this->GenerateImportTargetsConfig(os, config, suffix, missingTargets);
}

void cmExportFileGenerator::PopulateInterfaceProperty(
  const std::string& propName, cmGeneratorTarget* target,
  ImportPropertyMap& properties)
{
  const char* input = target->GetProperty(propName);
  if (input) {
    properties[propName] = input;
  }
}

void cmExportFileGenerator::PopulateInterfaceProperty(
  const std::string& propName, const std::string& outputName,
  cmGeneratorTarget* target,
  cmGeneratorExpression::PreprocessContext preprocessRule,
  ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
  const char* input = target->GetProperty(propName);
  if (input) {
    if (!*input) {
      // Set to empty
      properties[outputName].clear();
      return;
    }

    std::string prepro =
      cmGeneratorExpression::Preprocess(input, preprocessRule);
    if (!prepro.empty()) {
      this->ResolveTargetsInGeneratorExpressions(prepro, target,
                                                 missingTargets);
      properties[outputName] = prepro;
    }
  }
}

void cmExportFileGenerator::GenerateRequiredCMakeVersion(
  std::ostream& os, const char* versionString)
{
  /* clang-format off */
  os << "if(CMAKE_VERSION VERSION_LESS " << versionString << ")\n"
        "  message(FATAL_ERROR \"This file relies on consumers using "
        "CMake " << versionString << " or greater.\")\n"
        "endif()\n\n";
  /* clang-format on */
}

bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty(
  cmGeneratorTarget* target,
  cmGeneratorExpression::PreprocessContext preprocessRule,
  ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
  if (!target->IsLinkable()) {
    return false;
  }
  const char* input = target->GetProperty("INTERFACE_LINK_LIBRARIES");
  if (input) {
    std::string prepro =
      cmGeneratorExpression::Preprocess(input, preprocessRule);
    if (!prepro.empty()) {
      this->ResolveTargetsInGeneratorExpressions(
        prepro, target, missingTargets, ReplaceFreeTargets);
      properties["INTERFACE_LINK_LIBRARIES"] = prepro;
      return true;
    }
  }
  return false;
}

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

static bool checkInterfaceDirs(const std::string& prepro,
                               cmGeneratorTarget* target,
                               const std::string& prop)
{
  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);

  const bool inSourceBuild = topSourceDir == topBinaryDir;

  bool hadFatalError = false;

  for (std::string const& li : parts) {
    size_t genexPos = cmGeneratorExpression::Find(li);
    if (genexPos == 0) {
      continue;
    }
    cmake::MessageType messageType = cmake::FATAL_ERROR;
    std::ostringstream e;
    if (genexPos != std::string::npos) {
      if (prop == "INTERFACE_INCLUDE_DIRECTORIES") {
        switch (target->GetPolicyStatusCMP0041()) {
          case cmPolicies::WARN:
            messageType = cmake::WARNING;
            e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0041) << "\n";
            break;
          case cmPolicies::OLD:
            continue;
          case cmPolicies::REQUIRED_IF_USED:
          case cmPolicies::REQUIRED_ALWAYS:
          case cmPolicies::NEW:
            hadFatalError = true;
            break; // Issue fatal message.
        }
      } else {
        hadFatalError = true;
      }
    }
    if (cmHasLiteralPrefix(li, "${_IMPORT_PREFIX}")) {
      continue;
    }
    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, 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 not inside the source tree or build tree then
      // fall through to the checks below that the include directory is not
      // also inside the source tree or build tree.
      bool shouldContinue =
        (!inBinary || isSubDirectory(installDir, topBinaryDir)) &&
        (!inSource || isSubDirectory(installDir, topSourceDir));

      if (prop == "INTERFACE_INCLUDE_DIRECTORIES") {
        if (!shouldContinue) {
          switch (target->GetPolicyStatusCMP0052()) {
            case cmPolicies::WARN: {
              std::ostringstream s;
              s << cmPolicies::GetPolicyWarning(cmPolicies::CMP0052) << "\n";
              s << "Directory:\n    \"" << li
                << "\"\nin "
                   "INTERFACE_INCLUDE_DIRECTORIES of target \""
                << target->GetName()
                << "\" is a subdirectory of the install "
                   "directory:\n    \""
                << installDir
                << "\"\nhowever it is also "
                   "a subdirectory of the "
                << (inBinary ? "build" : "source") << " tree:\n    \""
                << (inBinary ? topBinaryDir : topSourceDir) << "\""
                << std::endl;
              target->GetLocalGenerator()->IssueMessage(cmake::AUTHOR_WARNING,
                                                        s.str());
              CM_FALLTHROUGH;
            }
            case cmPolicies::OLD:
              shouldContinue = true;
              break;
            case cmPolicies::REQUIRED_ALWAYS:
            case cmPolicies::REQUIRED_IF_USED:
            case cmPolicies::NEW:
              break;
          }
        }
      }
      if (shouldContinue) {
        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, 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, e.str());
      }
    }
  }
  return !hadFatalError;
}

static void prefixItems(std::string& exportDirs)
{
  std::vector<std::string> entries;
  cmGeneratorExpression::Split(exportDirs, entries);
  exportDirs.clear();
  const char* sep = "";
  for (std::string const& e : entries) {
    exportDirs += sep;
    sep = ";";
    if (!cmSystemTools::FileIsFullPath(e) &&
        e.find("${_IMPORT_PREFIX}") == std::string::npos) {
      exportDirs += "${_IMPORT_PREFIX}/";
    }
    exportDirs += e;
  }
}

void cmExportFileGenerator::PopulateSourcesInterface(
  cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule,
  ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
  cmGeneratorTarget* gt = tei->Target;
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);

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

  if (!input) {
    return;
  }

  if (!*input) {
    properties[propName].clear();
    return;
  }

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

    if (!checkInterfaceDirs(prepro, gt, propName)) {
      return;
    }
    properties[propName] = prepro;
  }
}

void cmExportFileGenerator::PopulateIncludeDirectoriesInterface(
  cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule,
  ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
  cmGeneratorTarget* target = tei->Target;
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);

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

  cmGeneratorExpression ge;

  std::string dirs = cmGeneratorExpression::Preprocess(
    tei->InterfaceIncludeDirectories, preprocessRule, true);
  this->ReplaceInstallPrefix(dirs);
  std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(dirs);
  std::string exportDirs =
    cge->Evaluate(target->GetLocalGenerator(), "", false, 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(cmake::FATAL_ERROR, e.str());
    return;
  }

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

  prefixItems(exportDirs);

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

    if (!checkInterfaceDirs(prepro, target, propName)) {
      return;
    }
    properties[propName] = prepro;
  }
}

void cmExportFileGenerator::PopulateLinkDependsInterface(
  cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule,
  ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
  cmGeneratorTarget* gt = tei->Target;
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);

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

  if (!input) {
    return;
  }

  if (!*input) {
    properties[propName].clear();
    return;
  }

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

    if (!checkInterfaceDirs(prepro, gt, propName)) {
      return;
    }
    properties[propName] = prepro;
  }
}

void cmExportFileGenerator::PopulateLinkDirectoriesInterface(
  cmTargetExport* tei, cmGeneratorExpression::PreprocessContext preprocessRule,
  ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
  cmGeneratorTarget* gt = tei->Target;
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);

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

  if (!input) {
    return;
  }

  if (!*input) {
    properties[propName].clear();
    return;
  }

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

    if (!checkInterfaceDirs(prepro, gt, propName)) {
      return;
    }
    properties[propName] = prepro;
  }
}

void cmExportFileGenerator::PopulateInterfaceProperty(
  const std::string& propName, cmGeneratorTarget* target,
  cmGeneratorExpression::PreprocessContext preprocessRule,
  ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
  this->PopulateInterfaceProperty(propName, propName, target, preprocessRule,
                                  properties, missingTargets);
}

void getPropertyContents(cmGeneratorTarget const* tgt, const std::string& prop,
                         std::set<std::string>& ifaceProperties)
{
  const char* p = tgt->GetProperty(prop);
  if (!p) {
    return;
  }
  std::vector<std::string> content;
  cmSystemTools::ExpandListArgument(p, content);
  ifaceProperties.insert(content.begin(), content.end());
}

void getCompatibleInterfaceProperties(cmGeneratorTarget* target,
                                      std::set<std::string>& ifaceProperties,
                                      const std::string& config)
{
  if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
    // object libraries have no link information, so nothing to compute
    return;
  }

  cmComputeLinkInformation* info = target->GetLinkInformation(config);

  if (!info) {
    cmLocalGenerator* lg = target->GetLocalGenerator();
    std::ostringstream e;
    e << "Exporting the target \"" << target->GetName()
      << "\" is not "
         "allowed since its linker language cannot be determined";
    lg->IssueMessage(cmake::FATAL_ERROR, e.str());
    return;
  }

  const cmComputeLinkInformation::ItemVector& deps = info->GetItems();

  for (auto const& dep : deps) {
    if (!dep.Target) {
      continue;
    }
    getPropertyContents(dep.Target, "COMPATIBLE_INTERFACE_BOOL",
                        ifaceProperties);
    getPropertyContents(dep.Target, "COMPATIBLE_INTERFACE_STRING",
                        ifaceProperties);
    getPropertyContents(dep.Target, "COMPATIBLE_INTERFACE_NUMBER_MIN",
                        ifaceProperties);
    getPropertyContents(dep.Target, "COMPATIBLE_INTERFACE_NUMBER_MAX",
                        ifaceProperties);
  }
}

void cmExportFileGenerator::PopulateCompatibleInterfaceProperties(
  cmGeneratorTarget* gtarget, ImportPropertyMap& properties)
{
  this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_BOOL", gtarget,
                                  properties);
  this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_STRING", gtarget,
                                  properties);
  this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_NUMBER_MIN", gtarget,
                                  properties);
  this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_NUMBER_MAX", gtarget,
                                  properties);

  std::set<std::string> ifaceProperties;

  getPropertyContents(gtarget, "COMPATIBLE_INTERFACE_BOOL", ifaceProperties);
  getPropertyContents(gtarget, "COMPATIBLE_INTERFACE_STRING", ifaceProperties);
  getPropertyContents(gtarget, "COMPATIBLE_INTERFACE_NUMBER_MIN",
                      ifaceProperties);
  getPropertyContents(gtarget, "COMPATIBLE_INTERFACE_NUMBER_MAX",
                      ifaceProperties);

  if (gtarget->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
    getCompatibleInterfaceProperties(gtarget, ifaceProperties, "");

    std::vector<std::string> configNames;
    gtarget->Target->GetMakefile()->GetConfigurations(configNames);

    for (std::string const& cn : configNames) {
      getCompatibleInterfaceProperties(gtarget, ifaceProperties, cn);
    }
  }

  for (std::string const& ip : ifaceProperties) {
    this->PopulateInterfaceProperty("INTERFACE_" + ip, gtarget, properties);
  }
}

void cmExportFileGenerator::GenerateInterfaceProperties(
  const cmGeneratorTarget* target, std::ostream& os,
  const ImportPropertyMap& properties)
{
  if (!properties.empty()) {
    std::string targetName = this->Namespace;
    targetName += target->GetExportName();
    os << "set_target_properties(" << targetName << " PROPERTIES\n";
    for (auto const& property : properties) {
      os << "  " << property.first << " "
         << cmExportFileGeneratorEscape(property.second) << "\n";
    }
    os << ")\n\n";
  }
}

bool cmExportFileGenerator::AddTargetNamespace(
  std::string& input, cmGeneratorTarget* target,
  std::vector<std::string>& missingTargets)
{
  cmGeneratorTarget::TargetOrString resolved =
    target->ResolveTargetReference(input);

  cmGeneratorTarget* tgt = resolved.Target;
  if (!tgt) {
    input = resolved.String;
    return false;
  }

  if (tgt->IsImported()) {
    input = tgt->GetName();
    return true;
  }
  if (this->ExportedTargets.find(tgt) != this->ExportedTargets.end()) {
    input = this->Namespace + tgt->GetExportName();
  } else {
    std::string namespacedTarget;
    this->HandleMissingTarget(namespacedTarget, missingTargets, target, tgt);
    if (!namespacedTarget.empty()) {
      input = namespacedTarget;
    } else {
      input = tgt->GetName();
    }
  }
  return true;
}

void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
  std::string& input, cmGeneratorTarget* target,
  std::vector<std::string>& missingTargets, FreeTargetsReplace replace)
{
  if (replace == NoReplaceFreeTargets) {
    this->ResolveTargetsInGeneratorExpression(input, target, missingTargets);
    return;
  }
  std::vector<std::string> parts;
  cmGeneratorExpression::Split(input, parts);

  std::string sep;
  input.clear();
  for (std::string& li : parts) {
    if (cmGeneratorExpression::Find(li) == std::string::npos) {
      this->AddTargetNamespace(li, target, missingTargets);
    } else {
      this->ResolveTargetsInGeneratorExpression(li, target, missingTargets);
    }
    input += sep + li;
    sep = ";";
  }
}

void cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
  std::string& input, cmGeneratorTarget* target,
  std::vector<std::string>& missingTargets)
{
  std::string::size_type pos = 0;
  std::string::size_type lastPos = pos;

  while ((pos = input.find("$<TARGET_PROPERTY:", lastPos)) !=
         std::string::npos) {
    std::string::size_type nameStartPos =
      pos + sizeof("$<TARGET_PROPERTY:") - 1;
    std::string::size_type closePos = input.find('>', nameStartPos);
    std::string::size_type commaPos = input.find(',', nameStartPos);
    std::string::size_type nextOpenPos = input.find("$<", nameStartPos);
    if (commaPos == std::string::npos    // Implied 'this' target
        || closePos == std::string::npos // Incomplete expression.
        || closePos < commaPos           // Implied 'this' target
        || nextOpenPos < commaPos)       // Non-literal
    {
      lastPos = nameStartPos;
      continue;
    }

    std::string targetName =
      input.substr(nameStartPos, commaPos - nameStartPos);

    if (this->AddTargetNamespace(targetName, target, missingTargets)) {
      input.replace(nameStartPos, commaPos - nameStartPos, targetName);
    }
    lastPos = nameStartPos + targetName.size() + 1;
  }

  std::string errorString;
  pos = 0;
  lastPos = pos;
  while ((pos = input.find("$<TARGET_NAME:", lastPos)) != std::string::npos) {
    std::string::size_type nameStartPos = pos + sizeof("$<TARGET_NAME:") - 1;
    std::string::size_type endPos = input.find('>', nameStartPos);
    if (endPos == std::string::npos) {
      errorString = "$<TARGET_NAME:...> expression incomplete";
      break;
    }
    std::string targetName = input.substr(nameStartPos, endPos - nameStartPos);
    if (targetName.find("$<") != std::string::npos) {
      errorString = "$<TARGET_NAME:...> requires its parameter to be a "
                    "literal.";
      break;
    }
    if (!this->AddTargetNamespace(targetName, target, missingTargets)) {
      errorString = "$<TARGET_NAME:...> requires its parameter to be a "
                    "reachable target.";
      break;
    }
    input.replace(pos, endPos - pos + 1, targetName);
    lastPos = endPos;
  }

  pos = 0;
  lastPos = pos;
  while (errorString.empty() &&
         (pos = input.find("$<LINK_ONLY:", lastPos)) != std::string::npos) {
    std::string::size_type nameStartPos = pos + sizeof("$<LINK_ONLY:") - 1;
    std::string::size_type endPos = input.find('>', nameStartPos);
    if (endPos == std::string::npos) {
      errorString = "$<LINK_ONLY:...> expression incomplete";
      break;
    }
    std::string libName = input.substr(nameStartPos, endPos - nameStartPos);
    if (cmGeneratorExpression::IsValidTargetName(libName) &&
        this->AddTargetNamespace(libName, target, missingTargets)) {
      input.replace(nameStartPos, endPos - nameStartPos, libName);
    }
    lastPos = nameStartPos + libName.size() + 1;
  }

  this->ReplaceInstallPrefix(input);

  if (!errorString.empty()) {
    target->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, errorString);
  }
}

void cmExportFileGenerator::ReplaceInstallPrefix(std::string& /*unused*/)
{
  // Do nothing
}

void cmExportFileGenerator::SetImportLinkInterface(
  const std::string& config, std::string const& suffix,
  cmGeneratorExpression::PreprocessContext preprocessRule,
  cmGeneratorTarget* target, ImportPropertyMap& properties,
  std::vector<std::string>& missingTargets)
{
  // Add the transitive link dependencies for this configuration.
  cmLinkInterface const* iface = target->GetLinkInterface(config, target);
  if (!iface) {
    return;
  }

  if (iface->ImplementationIsInterface) {
    // Policy CMP0022 must not be NEW.
    this->SetImportLinkProperty(suffix, target,
                                "IMPORTED_LINK_INTERFACE_LIBRARIES",
                                iface->Libraries, properties, missingTargets);
    return;
  }

  const char* propContent;

  if (const char* prop_suffixed =
        target->GetProperty("LINK_INTERFACE_LIBRARIES" + suffix)) {
    propContent = prop_suffixed;
  } else if (const char* prop =
               target->GetProperty("LINK_INTERFACE_LIBRARIES")) {
    propContent = prop;
  } else {
    return;
  }

  const bool newCMP0022Behavior =
    target->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
    target->GetPolicyStatusCMP0022() != cmPolicies::OLD;

  if (newCMP0022Behavior && !this->ExportOld) {
    cmLocalGenerator* lg = target->GetLocalGenerator();
    std::ostringstream e;
    e << "Target \"" << target->GetName()
      << "\" has policy CMP0022 enabled, "
         "but also has old-style LINK_INTERFACE_LIBRARIES properties "
         "populated, but it was exported without the "
         "EXPORT_LINK_INTERFACE_LIBRARIES to export the old-style properties";
    lg->IssueMessage(cmake::FATAL_ERROR, e.str());
    return;
  }

  if (!*propContent) {
    properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix].clear();
    return;
  }

  std::string prepro =
    cmGeneratorExpression::Preprocess(propContent, preprocessRule);
  if (!prepro.empty()) {
    this->ResolveTargetsInGeneratorExpressions(prepro, target, missingTargets,
                                               ReplaceFreeTargets);
    properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = prepro;
  }
}

void cmExportFileGenerator::SetImportDetailProperties(
  const std::string& config, std::string const& suffix,
  cmGeneratorTarget* target, ImportPropertyMap& properties,
  std::vector<std::string>& missingTargets)
{
  // Get the makefile in which to lookup target information.
  cmMakefile* mf = target->Makefile;

  // Add the soname for unix shared libraries.
  if (target->GetType() == cmStateEnums::SHARED_LIBRARY ||
      target->GetType() == cmStateEnums::MODULE_LIBRARY) {
    if (!target->IsDLLPlatform()) {
      std::string prop;
      std::string value;
      if (target->HasSOName(config)) {
        if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
          value = this->InstallNameDir(target, config);
        }
        prop = "IMPORTED_SONAME";
        value += target->GetSOName(config);
      } else {
        prop = "IMPORTED_NO_SONAME";
        value = "TRUE";
      }
      prop += suffix;
      properties[prop] = value;
    }
  }

  // Add the transitive link dependencies for this configuration.
  if (cmLinkInterface const* iface =
        target->GetLinkInterface(config, target)) {
    this->SetImportLinkProperty(suffix, target,
                                "IMPORTED_LINK_INTERFACE_LANGUAGES",
                                iface->Languages, properties, missingTargets);

    std::vector<std::string> dummy;
    this->SetImportLinkProperty(suffix, target,
                                "IMPORTED_LINK_DEPENDENT_LIBRARIES",
                                iface->SharedDeps, properties, dummy);
    if (iface->Multiplicity > 0) {
      std::string prop = "IMPORTED_LINK_INTERFACE_MULTIPLICITY";
      prop += suffix;
      std::ostringstream m;
      m << iface->Multiplicity;
      properties[prop] = m.str();
    }
  }

  // Add information if this target is a managed target
  if (target->GetManagedType(config) !=
      cmGeneratorTarget::ManagedType::Native) {
    std::string prop = "IMPORTED_COMMON_LANGUAGE_RUNTIME";
    prop += suffix;
    std::string propval;
    if (auto* p = target->GetProperty("COMMON_LANGUAGE_RUNTIME")) {
      propval = p;
    } else if (target->IsCSharpOnly()) {
      // C# projects do not have the /clr flag, so we set the property
      // here to mark the target as (only) managed (i.e. no .lib file
      // to link to). Otherwise the  COMMON_LANGUAGE_RUNTIME target
      // property would have to be set manually for C# targets to make
      // exporting/importing work.
      propval = "CSharp";
    }
    properties[prop] = propval;
  }
}

static std::string const& asString(std::string const& l)
{
  return l;
}

static std::string const& asString(cmLinkItem const& l)
{
  return l.AsStr();
}

template <typename T>
void cmExportFileGenerator::SetImportLinkProperty(
  std::string const& suffix, cmGeneratorTarget* target,
  const std::string& propName, std::vector<T> const& entries,
  ImportPropertyMap& properties, std::vector<std::string>& missingTargets)
{
  // Skip the property if there are no entries.
  if (entries.empty()) {
    return;
  }

  // Construct the property value.
  std::string link_entries;
  const char* sep = "";
  for (T const& l : entries) {
    // Separate this from the previous entry.
    link_entries += sep;
    sep = ";";

    std::string temp = asString(l);
    this->AddTargetNamespace(temp, target, missingTargets);
    link_entries += temp;
  }

  // Store the property.
  std::string prop = propName;
  prop += suffix;
  properties[prop] = link_entries;
}

void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os)
{
  // Protect that file against use with older CMake versions.
  /* clang-format off */
  os << "# Generated by CMake\n\n";
  os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n"
     << "   message(FATAL_ERROR \"CMake >= 2.6.0 required\")\n"
     << "endif()\n";
  /* clang-format on */

  // Isolate the file policy level.
  // We use 2.6 here instead of the current version because newer
  // versions of CMake should be able to export files imported by 2.6
  // until the import format changes.
  /* clang-format off */
  os << "cmake_policy(PUSH)\n"
     << "cmake_policy(VERSION 2.6)\n";
  /* clang-format on */
}

void cmExportFileGenerator::GeneratePolicyFooterCode(std::ostream& os)
{
  os << "cmake_policy(POP)\n";
}

void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os,
                                                     const std::string& config)
{
  os << "#----------------------------------------------------------------\n"
     << "# Generated CMake target import file";
  if (!config.empty()) {
    os << " for configuration \"" << config << "\".\n";
  } else {
    os << ".\n";
  }
  os << "#----------------------------------------------------------------\n"
     << "\n";
  this->GenerateImportVersionCode(os);
}

void cmExportFileGenerator::GenerateImportFooterCode(std::ostream& os)
{
  os << "# Commands beyond this point should not need to know the version.\n"
     << "set(CMAKE_IMPORT_FILE_VERSION)\n";
}

void cmExportFileGenerator::GenerateImportVersionCode(std::ostream& os)
{
  // Store an import file format version.  This will let us change the
  // format later while still allowing old import files to work.
  /* clang-format off */
  os << "# Commands may need to know the format version.\n"
     << "set(CMAKE_IMPORT_FILE_VERSION 1)\n"
     << "\n";
  /* clang-format on */
}

void cmExportFileGenerator::GenerateExpectedTargetsCode(
  std::ostream& os, const std::string& expectedTargets)
{
  /* clang-format off */
  os << "# Protect against multiple inclusion, which would fail when already "
        "imported targets are added once more.\n"
        "set(_targetsDefined)\n"
        "set(_targetsNotDefined)\n"
        "set(_expectedTargets)\n"
        "foreach(_expectedTarget " << expectedTargets << ")\n"
        "  list(APPEND _expectedTargets ${_expectedTarget})\n"
        "  if(NOT TARGET ${_expectedTarget})\n"
        "    list(APPEND _targetsNotDefined ${_expectedTarget})\n"
        "  endif()\n"
        "  if(TARGET ${_expectedTarget})\n"
        "    list(APPEND _targetsDefined ${_expectedTarget})\n"
        "  endif()\n"
        "endforeach()\n"
        "if(\"${_targetsDefined}\" STREQUAL \"${_expectedTargets}\")\n"
        "  unset(_targetsDefined)\n"
        "  unset(_targetsNotDefined)\n"
        "  unset(_expectedTargets)\n"
        "  set(CMAKE_IMPORT_FILE_VERSION)\n"
        "  cmake_policy(POP)\n"
        "  return()\n"
        "endif()\n"
        "if(NOT \"${_targetsDefined}\" STREQUAL \"\")\n"
        "  message(FATAL_ERROR \"Some (but not all) targets in this export "
        "set were already defined.\\nTargets Defined: ${_targetsDefined}\\n"
        "Targets not yet defined: ${_targetsNotDefined}\\n\")\n"
        "endif()\n"
        "unset(_targetsDefined)\n"
        "unset(_targetsNotDefined)\n"
        "unset(_expectedTargets)\n"
        "\n\n";
  /* clang-format on */
}

void cmExportFileGenerator::GenerateImportTargetCode(
  std::ostream& os, cmGeneratorTarget const* target,
  cmStateEnums::TargetType targetType)
{
  // Construct the imported target name.
  std::string targetName = this->Namespace;

  targetName += target->GetExportName();

  // Create the imported target.
  os << "# Create imported target " << targetName << "\n";
  switch (targetType) {
    case cmStateEnums::EXECUTABLE:
      os << "add_executable(" << targetName << " IMPORTED)\n";
      break;
    case cmStateEnums::STATIC_LIBRARY:
      os << "add_library(" << targetName << " STATIC IMPORTED)\n";
      break;
    case cmStateEnums::SHARED_LIBRARY:
      os << "add_library(" << targetName << " SHARED IMPORTED)\n";
      break;
    case cmStateEnums::MODULE_LIBRARY:
      os << "add_library(" << targetName << " MODULE IMPORTED)\n";
      break;
    case cmStateEnums::UNKNOWN_LIBRARY:
      os << "add_library(" << targetName << " UNKNOWN IMPORTED)\n";
      break;
    case cmStateEnums::OBJECT_LIBRARY:
      os << "add_library(" << targetName << " OBJECT IMPORTED)\n";
      break;
    case cmStateEnums::INTERFACE_LIBRARY:
      os << "add_library(" << targetName << " INTERFACE IMPORTED)\n";
      break;
    default: // should never happen
      break;
  }

  // Mark the imported executable if it has exports.
  if (target->IsExecutableWithExports()) {
    os << "set_property(TARGET " << targetName
       << " PROPERTY ENABLE_EXPORTS 1)\n";
  }

  // Mark the imported library if it is a framework.
  if (target->IsFrameworkOnApple()) {
    os << "set_property(TARGET " << targetName << " PROPERTY FRAMEWORK 1)\n";
  }

  // Mark the imported executable if it is an application bundle.
  if (target->IsAppBundleOnApple()) {
    os << "set_property(TARGET " << targetName
       << " PROPERTY MACOSX_BUNDLE 1)\n";
  }

  if (target->IsCFBundleOnApple()) {
    os << "set_property(TARGET " << targetName << " PROPERTY BUNDLE 1)\n";
  }
  os << "\n";
}

void cmExportFileGenerator::GenerateImportPropertyCode(
  std::ostream& os, const std::string& config, cmGeneratorTarget const* target,
  ImportPropertyMap const& properties)
{
  // Construct the imported target name.
  std::string targetName = this->Namespace;

  targetName += target->GetExportName();

  // Set the import properties.
  os << "# Import target \"" << targetName << "\" for configuration \""
     << config << "\"\n";
  os << "set_property(TARGET " << targetName
     << " APPEND PROPERTY IMPORTED_CONFIGURATIONS ";
  if (!config.empty()) {
    os << cmSystemTools::UpperCase(config);
  } else {
    os << "NOCONFIG";
  }
  os << ")\n";
  os << "set_target_properties(" << targetName << " PROPERTIES\n";
  for (auto const& property : properties) {
    os << "  " << property.first << " "
       << cmExportFileGeneratorEscape(property.second) << "\n";
  }
  os << "  )\n"
     << "\n";
}

void cmExportFileGenerator::GenerateMissingTargetsCheckCode(
  std::ostream& os, const std::vector<std::string>& missingTargets)
{
  if (missingTargets.empty()) {
    /* clang-format off */
    os << "# This file does not depend on other imported targets which have\n"
          "# been exported from the same project but in a separate "
            "export set.\n\n";
    /* clang-format on */
    return;
  }
  /* clang-format off */
  os << "# Make sure the targets which have been exported in some other \n"
        "# export set exist.\n"
        "unset(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)\n"
        "foreach(_target ";
  /* clang-format on */
  std::set<std::string> emitted;
  for (std::string const& missingTarget : missingTargets) {
    if (emitted.insert(missingTarget).second) {
      os << "\"" << missingTarget << "\" ";
    }
  }
  /* clang-format off */
  os << ")\n"
        "  if(NOT TARGET \"${_target}\" )\n"
        "    set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets \""
        "${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets} ${_target}\")"
        "\n"
        "  endif()\n"
        "endforeach()\n"
        "\n"
        "if(DEFINED ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)\n"
        "  if(CMAKE_FIND_PACKAGE_NAME)\n"
        "    set( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)\n"
        "    set( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "
        "\"The following imported targets are "
        "referenced, but are missing: "
                 "${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets}\")\n"
        "  else()\n"
        "    message(FATAL_ERROR \"The following imported targets are "
        "referenced, but are missing: "
                "${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets}\")\n"
        "  endif()\n"
        "endif()\n"
        "unset(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)\n"
        "\n";
  /* clang-format on */
}

void cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os)
{
  // Add code which verifies at cmake time that the file which is being
  // imported actually exists on disk. This should in theory always be theory
  // case, but still when packages are split into normal and development
  // packages this might get broken (e.g. the Config.cmake could be part of
  // the non-development package, something similar happened to me without
  // on SUSE with a mysql pkg-config file, which claimed everything is fine,
  // but the development package was not installed.).
  /* clang-format off */
  os << "# Loop over all imported files and verify that they actually exist\n"
        "foreach(target ${_IMPORT_CHECK_TARGETS} )\n"
        "  foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} )\n"
        "    if(NOT EXISTS \"${file}\" )\n"
        "      message(FATAL_ERROR \"The imported target \\\"${target}\\\""
        " references the file\n"
        "   \\\"${file}\\\"\n"
        "but this file does not exist.  Possible reasons include:\n"
        "* The file was deleted, renamed, or moved to another location.\n"
        "* An install or uninstall procedure did not complete successfully.\n"
        "* The installation package was faulty and contained\n"
        "   \\\"${CMAKE_CURRENT_LIST_FILE}\\\"\n"
        "but not all the files it references.\n"
        "\")\n"
        "    endif()\n"
        "  endforeach()\n"
        "  unset(_IMPORT_CHECK_FILES_FOR_${target})\n"
        "endforeach()\n"
        "unset(_IMPORT_CHECK_TARGETS)\n"
        "\n";
  /* clang-format on */
}

void cmExportFileGenerator::GenerateImportedFileChecksCode(
  std::ostream& os, cmGeneratorTarget* target,
  ImportPropertyMap const& properties,
  const std::set<std::string>& importedLocations)
{
  // Construct the imported target name.
  std::string targetName = this->Namespace;
  targetName += target->GetExportName();

  os << "list(APPEND _IMPORT_CHECK_TARGETS " << targetName
     << " )\n"
        "list(APPEND _IMPORT_CHECK_FILES_FOR_"
     << targetName << " ";

  for (std::string const& li : importedLocations) {
    ImportPropertyMap::const_iterator pi = properties.find(li);
    if (pi != properties.end()) {
      os << cmExportFileGeneratorEscape(pi->second) << " ";
    }
  }

  os << ")\n\n";
}

bool cmExportFileGenerator::PopulateExportProperties(
  cmGeneratorTarget* gte, ImportPropertyMap& properties,
  std::string& errorMessage)
{
  auto& targetProperties = gte->Target->GetProperties();
  const auto& exportProperties = targetProperties.find("EXPORT_PROPERTIES");
  if (exportProperties != targetProperties.end()) {
    std::vector<std::string> propsToExport;
    cmSystemTools::ExpandListArgument(exportProperties->second.GetValue(),
                                      propsToExport);
    for (auto& prop : propsToExport) {
      /* Black list reserved properties */
      if (cmSystemTools::StringStartsWith(prop, "IMPORTED_") ||
          cmSystemTools::StringStartsWith(prop, "INTERFACE_")) {
        std::ostringstream e;
        e << "Target \"" << gte->Target->GetName() << "\" contains property \""
          << prop << "\" in EXPORT_PROPERTIES but IMPORTED_* and INTERFACE_* "
          << "properties are reserved.";
        errorMessage = e.str();
        return false;
      }
      auto propertyValue = targetProperties.GetPropertyValue(prop);
      if (propertyValue == nullptr) {
        // Asked to export a property that isn't defined on the target. Do not
        // consider this an error, there's just nothing to export.
        continue;
      }
      std::string evaluatedValue = cmGeneratorExpression::Preprocess(
        propertyValue, cmGeneratorExpression::StripAllGeneratorExpressions);
      if (evaluatedValue != propertyValue) {
        std::ostringstream e;
        e << "Target \"" << gte->Target->GetName() << "\" contains property \""
          << prop << "\" in EXPORT_PROPERTIES but this property contains a "
          << "generator expression. This is not allowed.";
        errorMessage = e.str();
        return false;
      }
      properties[prop] = propertyValue;
    }
  }
  return true;
}
