/* 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 <algorithm>
#include <array>
#include <cassert>
#include <cstring>
#include <sstream>
#include <utility>

#include <cm/memory>
#include <cm/optional>
#include <cmext/string_view>

#include "cmsys/FStream.hxx"

#include "cmComputeLinkInformation.h"
#include "cmExportSet.h"
#include "cmFileSet.h"
#include "cmFindPackageStack.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmLinkItem.h"
#include "cmList.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmPropertyMap.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmValue.h"
#include "cmVersion.h"

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 std::string& cmExportFileGenerator::GetMainExportFileName() const
{
  return this->MainImportFile;
}

bool cmExportFileGenerator::GenerateImportFile()
{
  // Open the output file to generate it.
  std::unique_ptr<cmsys::ofstream> foutPtr;
  if (this->AppendMode) {
    // Open for append.
    auto openmodeApp = std::ios::app;
    foutPtr = cm::make_unique<cmsys::ofstream>(this->MainImportFile.c_str(),
                                               openmodeApp);
  } 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 || !*foutPtr) {
    std::string se = cmSystemTools::GetLastSystemError();
    std::ostringstream e;
    e << "cannot write to file \"" << this->MainImportFile << "\": " << se;
    cmSystemTools::Error(e.str());
    return false;
  }
  std::ostream& os = *foutPtr;
  std::stringstream mainFileWithHeadersAndFootersBuffer;

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

  // Create all the imported targets.
  std::stringstream mainFileBuffer;
  bool result = this->GenerateMainFile(mainFileBuffer);

  // Export find_dependency() calls. Must be done after GenerateMainFile(),
  // because that's when target dependencies are gathered, which we need for
  // the find_dependency() calls.
  if (!this->AppendMode && this->GetExportSet() &&
      this->ExportPackageDependencies) {
    this->SetRequiredCMakeVersion(3, 9, 0);
    this->GenerateFindDependencyCalls(mainFileWithHeadersAndFootersBuffer);
  }

  // Write cached import code.
  mainFileWithHeadersAndFootersBuffer << mainFileBuffer.rdbuf();

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

  // This has to be done last, after the minimum CMake version has been
  // determined.
  this->GeneratePolicyHeaderCode(os);
  os << mainFileWithHeadersAndFootersBuffer.rdbuf();

  return result;
}

void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
                                                 const std::string& config)
{
  // 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);
}

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

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

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

bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty(
  cmGeneratorTarget const* target,
  cmGeneratorExpression::PreprocessContext preprocessRule,
  ImportPropertyMap& properties)
{
  if (!target->IsLinkable()) {
    return false;
  }
  static const std::array<std::string, 3> linkIfaceProps = {
    { "INTERFACE_LINK_LIBRARIES", "INTERFACE_LINK_LIBRARIES_DIRECT",
      "INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE" }
  };
  bool hadINTERFACE_LINK_LIBRARIES = false;
  for (std::string const& linkIfaceProp : linkIfaceProps) {
    if (cmValue input = target->GetProperty(linkIfaceProp)) {
      std::string prepro =
        cmGeneratorExpression::Preprocess(*input, preprocessRule);
      if (!prepro.empty()) {
        this->ResolveTargetsInGeneratorExpressions(prepro, target,
                                                   ReplaceFreeTargets);
        properties[linkIfaceProp] = prepro;
        hadINTERFACE_LINK_LIBRARIES = true;
      }
    }
  }
  return hadINTERFACE_LINK_LIBRARIES;
}

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 const* 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;
    }
    if (cmHasLiteralPrefix(li, "${_IMPORT_PREFIX}")) {
      continue;
    }
    MessageType messageType = MessageType::FATAL_ERROR;
    std::ostringstream e;
    if (genexPos != std::string::npos) {
      if (prop == "INTERFACE_INCLUDE_DIRECTORIES") {
        switch (target->GetPolicyStatusCMP0041()) {
          case cmPolicies::WARN:
            messageType = MessageType::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 (!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) << "\"\n";
              target->GetLocalGenerator()->IssueMessage(
                MessageType::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(
  cmGeneratorTarget const* gt,
  cmGeneratorExpression::PreprocessContext preprocessRule,
  ImportPropertyMap& properties)
{
  assert(preprocessRule == cmGeneratorExpression::InstallInterface);

  const char* 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, true);
  if (!prepro.empty()) {
    this->ResolveTargetsInGeneratorExpressions(prepro, gt);

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

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

  includesDestinationDirs.clear();

  const char* 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, true);
  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;
  }

  prefixItems(exportDirs);
  includesDestinationDirs = 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);

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

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

  const char* 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, true);
  if (!prepro.empty()) {
    this->ResolveTargetsInGeneratorExpressions(prepro, gt);

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

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

  const char* 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, true);
  if (!prepro.empty()) {
    this->ResolveTargetsInGeneratorExpressions(prepro, gt);

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

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

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

static void getCompatibleInterfaceProperties(
  cmGeneratorTarget const* 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(MessageType::FATAL_ERROR, e.str());
    return;
  }

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

  for (auto const& dep : deps) {
    if (!dep.Target || dep.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
      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 const* 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) {
    std::vector<std::string> configNames =
      gtarget->Target->GetMakefile()->GetGeneratorConfigs(
        cmMakefile::IncludeEmptyConfig);

    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 =
      cmStrCat(this->Namespace, 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 const* target,
                                               cmLocalGenerator const* lg)
{
  cmGeneratorTarget::TargetOrString resolved =
    target->ResolveTargetReference(input, lg);

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

  cmFindPackageStack const& pkgStack = tgt->Target->GetFindPackageStack();
  if (!pkgStack.Empty() ||
      tgt->Target->GetProperty("EXPORT_FIND_PACKAGE_NAME")) {
    this->ExternalTargets.emplace(tgt);
  }

  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, target, tgt);
    if (!namespacedTarget.empty()) {
      input = namespacedTarget;
    } else {
      input = tgt->GetName();
    }
  }
  return true;
}

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

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

void cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
  std::string& input, cmGeneratorTarget const* target,
  cmLocalGenerator const* lg)
{
  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 + cmStrLen("$<TARGET_PROPERTY:");
    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, lg)) {
      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 + cmStrLen("$<TARGET_NAME:");
    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, lg)) {
      errorString = "$<TARGET_NAME:...> requires its parameter to be a "
                    "reachable target.";
      break;
    }
    input.replace(pos, endPos - pos + 1, targetName);
    lastPos = pos + targetName.size();
  }

  pos = 0;
  lastPos = pos;
  while (errorString.empty() &&
         (pos = input.find("$<LINK_ONLY:", lastPos)) != std::string::npos) {
    std::string::size_type nameStartPos = pos + cmStrLen("$<LINK_ONLY:");
    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, lg)) {
      input.replace(nameStartPos, endPos - nameStartPos, libName);
    }
    lastPos = nameStartPos + libName.size() + 1;
  }

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

  this->ReplaceInstallPrefix(input);

  if (!errorString.empty()) {
    target->GetLocalGenerator()->IssueMessage(MessageType::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 const* target, ImportPropertyMap& properties)
{
  // 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, ImportLinkPropertyTargetNames::Yes);
    return;
  }

  cmValue propContent;

  if (cmValue prop_suffixed =
        target->GetProperty("LINK_INTERFACE_LIBRARIES" + suffix)) {
    propContent = prop_suffixed;
  } else if (cmValue 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(MessageType::FATAL_ERROR, e.str());
    return;
  }

  if (propContent->empty()) {
    properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix].clear();
    return;
  }

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

void cmExportFileGenerator::SetImportDetailProperties(
  const std::string& config, std::string const& suffix,
  cmGeneratorTarget* target, ImportPropertyMap& properties)
{
  // 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, ImportLinkPropertyTargetNames::No);

    // Export IMPORTED_LINK_DEPENDENT_LIBRARIES to help consuming linkers
    // find private dependencies of shared libraries.
    std::size_t oldMissingTargetsSize = this->MissingTargets.size();
    auto oldExternalTargets = this->ExternalTargets;
    this->SetImportLinkProperty(
      suffix, target, "IMPORTED_LINK_DEPENDENT_LIBRARIES", iface->SharedDeps,
      properties, ImportLinkPropertyTargetNames::Yes);
    // Avoid enforcing shared library private dependencies as public package
    // dependencies by ignoring missing targets added for them.
    this->MissingTargets.resize(oldMissingTargetsSize);
    this->ExternalTargets = std::move(oldExternalTargets);

    if (iface->Multiplicity > 0) {
      std::string prop =
        cmStrCat("IMPORTED_LINK_INTERFACE_MULTIPLICITY", suffix);
      properties[prop] = std::to_string(iface->Multiplicity);
    }
  }

  // Add information if this target is a managed target
  if (target->GetManagedType(config) !=
      cmGeneratorTarget::ManagedType::Native) {
    std::string prop = cmStrCat("IMPORTED_COMMON_LANGUAGE_RUNTIME", suffix);
    std::string propval;
    if (cmValue 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 const* target,
  const std::string& propName, std::vector<T> const& entries,
  ImportPropertyMap& properties, ImportLinkPropertyTargetNames targetNames)
{
  // Skip the property if there are no entries.
  if (entries.empty()) {
    return;
  }

  cmLocalGenerator const* lg = target->GetLocalGenerator();

  // 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 = ";";

    if (targetNames == ImportLinkPropertyTargetNames::Yes) {
      std::string temp = asString(l);
      this->AddTargetNamespace(temp, target, lg);
      link_entries += temp;
    } else {
      link_entries += asString(l);
    }
  }

  // Store the property.
  std::string prop = cmStrCat(propName, 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.8)\n"
     << "   message(FATAL_ERROR \"CMake >= 2.8.0 required\")\n"
     << "endif()\n"
     << "if(CMAKE_VERSION VERSION_LESS \""
     << this->RequiredCMakeVersionMajor << '.'
     << this->RequiredCMakeVersionMinor << '.'
     << this->RequiredCMakeVersionPatch << "\")\n"
     << "   message(FATAL_ERROR \"CMake >= "
     << this->RequiredCMakeVersionMajor << '.'
     << this->RequiredCMakeVersionMinor << '.'
     << this->RequiredCMakeVersionPatch << " required\")\n"
     << "endif()\n";
  /* clang-format on */

  // Isolate the file policy level.
  // Support CMake versions as far back as 2.6 but also support using NEW
  // policy settings for up to CMake 3.27 (this upper limit may be reviewed
  // and increased from time to time). This reduces the opportunity for CMake
  // warnings when an older export file is later used with newer CMake
  // versions.
  /* clang-format off */
  os << "cmake_policy(PUSH)\n"
     << "cmake_policy(VERSION "
     << this->RequiredCMakeVersionMajor << '.'
     << this->RequiredCMakeVersionMinor << '.'
     << this->RequiredCMakeVersionPatch << "...3.27)\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(_cmake_targets_defined \"\")\n"
        "set(_cmake_targets_not_defined \"\")\n"
        "set(_cmake_expected_targets \"\")\n"
        "foreach(_cmake_expected_target IN ITEMS " << expectedTargets << ")\n"
        "  list(APPEND _cmake_expected_targets \"${_cmake_expected_target}\")\n"
        "  if(TARGET \"${_cmake_expected_target}\")\n"
        "    list(APPEND _cmake_targets_defined \"${_cmake_expected_target}\")\n"
        "  else()\n"
        "    list(APPEND _cmake_targets_not_defined \"${_cmake_expected_target}\")\n"
        "  endif()\n"
        "endforeach()\n"
        "unset(_cmake_expected_target)\n"
        "if(_cmake_targets_defined STREQUAL _cmake_expected_targets)\n"
        "  unset(_cmake_targets_defined)\n"
        "  unset(_cmake_targets_not_defined)\n"
        "  unset(_cmake_expected_targets)\n"
        "  unset(CMAKE_IMPORT_FILE_VERSION)\n"
        "  cmake_policy(POP)\n"
        "  return()\n"
        "endif()\n"
        "if(NOT _cmake_targets_defined STREQUAL \"\")\n"
        "  string(REPLACE \";\" \", \" _cmake_targets_defined_text \"${_cmake_targets_defined}\")\n"
        "  string(REPLACE \";\" \", \" _cmake_targets_not_defined_text \"${_cmake_targets_not_defined}\")\n"
        "  message(FATAL_ERROR \"Some (but not all) targets in this export "
        "set were already defined.\\nTargets Defined: ${_cmake_targets_defined_text}\\n"
        "Targets not yet defined: ${_cmake_targets_not_defined_text}\\n\")\n"
        "endif()\n"
        "unset(_cmake_targets_defined)\n"
        "unset(_cmake_targets_not_defined)\n"
        "unset(_cmake_expected_targets)\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() ||
      (target->IsSharedLibraryWithExports() && target->HasImportLibrary(""))) {
    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";
  }

  // generate DEPRECATION
  if (target->IsDeprecated()) {
    os << "set_property(TARGET " << targetName << " PROPERTY DEPRECATION "
       << cmExportFileGeneratorEscape(target->GetDeprecation()) << ")\n";
  }

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

  if (target->GetPropertyAsBool("EXPORT_NO_SYSTEM")) {
    os << "set_property(TARGET " << targetName << " PROPERTY SYSTEM 0)\n";
  }

  os << "\n";
}

void cmExportFileGenerator::GenerateImportPropertyCode(
  std::ostream& os, const std::string& config, const std::string& suffix,
  cmGeneratorTarget const* target, ImportPropertyMap const& properties,
  const std::string& importedXcFrameworkLocation)
{
  // 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";
  std::string importedLocationProp = cmStrCat("IMPORTED_LOCATION", suffix);
  for (auto const& property : properties) {
    if (importedXcFrameworkLocation.empty() ||
        property.first != importedLocationProp) {
      os << "  " << property.first << " "
         << cmExportFileGeneratorEscape(property.second) << "\n";
    }
  }
  os << "  )\n";
  if (!importedXcFrameworkLocation.empty()) {
    auto importedLocationIt = properties.find(importedLocationProp);
    if (importedLocationIt != properties.end()) {
      os << "if(NOT CMAKE_VERSION VERSION_LESS \"3.28\" AND IS_DIRECTORY "
         << cmExportFileGeneratorEscape(importedXcFrameworkLocation)
         << ")\n"
            "  set_property(TARGET "
         << targetName << " PROPERTY " << importedLocationProp << " "
         << cmExportFileGeneratorEscape(importedXcFrameworkLocation)
         << ")\nelse()\n  set_property(TARGET " << targetName << " PROPERTY "
         << importedLocationProp << " "
         << cmExportFileGeneratorEscape(importedLocationIt->second)
         << ")\nendif()\n";
    }
  }
  os << "\n";
}

void cmExportFileGenerator::GenerateFindDependencyCalls(std::ostream& os)
{
  os << "include(CMakeFindDependencyMacro)\n";
  std::map<std::string, cmExportSet::PackageDependency> packageDependencies;
  auto* exportSet = this->GetExportSet();
  if (exportSet) {
    packageDependencies = exportSet->GetPackageDependencies();
  }

  for (cmGeneratorTarget const* gt : this->ExternalTargets) {
    std::string findPackageName;
    auto exportFindPackageName = gt->GetProperty("EXPORT_FIND_PACKAGE_NAME");
    cmFindPackageStack pkgStack = gt->Target->GetFindPackageStack();
    if (!exportFindPackageName.IsEmpty()) {
      findPackageName = *exportFindPackageName;
    } else {
      if (!pkgStack.Empty()) {
        cmFindPackageCall const& fpc = pkgStack.Top();
        findPackageName = fpc.Name;
      }
    }
    if (!findPackageName.empty()) {
      auto& dep = packageDependencies[findPackageName];
      if (!pkgStack.Empty()) {
        dep.FindPackageIndex = pkgStack.Top().Index;
      }
      if (dep.Enabled == cmExportSet::PackageDependencyExportEnabled::Auto) {
        dep.Enabled = cmExportSet::PackageDependencyExportEnabled::On;
      }
    }
  }

  std::vector<std::pair<std::string, cmExportSet::PackageDependency>>
    packageDependenciesSorted(packageDependencies.begin(),
                              packageDependencies.end());
  std::sort(
    packageDependenciesSorted.begin(), packageDependenciesSorted.end(),
    [](const std::pair<std::string, cmExportSet::PackageDependency>& lhs,
       const std::pair<std::string, cmExportSet::PackageDependency>& rhs)
      -> bool {
      if (lhs.second.SpecifiedIndex) {
        if (rhs.second.SpecifiedIndex) {
          return lhs.second.SpecifiedIndex < rhs.second.SpecifiedIndex;
        }
        assert(rhs.second.FindPackageIndex);
        return true;
      }
      assert(lhs.second.FindPackageIndex);
      if (rhs.second.SpecifiedIndex) {
        return false;
      }
      assert(rhs.second.FindPackageIndex);
      return lhs.second.FindPackageIndex < rhs.second.FindPackageIndex;
    });

  for (auto const& it : packageDependenciesSorted) {
    if (it.second.Enabled == cmExportSet::PackageDependencyExportEnabled::On) {
      os << "find_dependency(" << it.first << " REQUIRED";
      for (auto const& arg : it.second.ExtraArguments) {
        os << " " << cmOutputConverter::EscapeForCMake(arg);
      }
      os << ")\n";
    }
  }
  os << "\n\n";
}

void cmExportFileGenerator::GenerateMissingTargetsCheckCode(std::ostream& os)
{
  if (this->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 : this->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(_cmake_target IN LISTS _cmake_import_check_targets)\n"
        "  if(CMAKE_VERSION VERSION_LESS \"3.28\"\n"
        "      OR NOT DEFINED "
        "_cmake_import_check_xcframework_for_${_cmake_target}\n"
        "      OR NOT IS_DIRECTORY "
        "\"${_cmake_import_check_xcframework_for_${_cmake_target}}\")\n"
        "    foreach(_cmake_file IN LISTS "
        "\"_cmake_import_check_files_for_${_cmake_target}\")\n"
        "      if(NOT EXISTS \"${_cmake_file}\")\n"
        "        message(FATAL_ERROR \"The imported target "
        "\\\"${_cmake_target}\\\" references the file\n"
        "   \\\"${_cmake_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"
        "  endif()\n"
        "  unset(_cmake_file)\n"
        "  unset(\"_cmake_import_check_files_for_${_cmake_target}\")\n"
        "endforeach()\n"
        "unset(_cmake_target)\n"
        "unset(_cmake_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,
  const std::string& importedXcFrameworkLocation)
{
  // Construct the imported target name.
  std::string targetName = cmStrCat(this->Namespace, target->GetExportName());

  os << "list(APPEND _cmake_import_check_targets " << targetName << " )\n";
  if (!importedXcFrameworkLocation.empty()) {
    os << "set(_cmake_import_check_xcframework_for_" << targetName << ' '
       << cmExportFileGeneratorEscape(importedXcFrameworkLocation) << ")\n";
  }
  os << "list(APPEND _cmake_import_check_files_for_" << targetName << " ";

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

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

enum class PropertyType
{
  Strings,
  Paths,
  IncludePaths,
};

namespace {
bool PropertyTypeIsForPaths(PropertyType pt)
{
  switch (pt) {
    case PropertyType::Strings:
      return false;
    case PropertyType::Paths:
    case PropertyType::IncludePaths:
      return true;
  }
  return false;
}
}

struct ModulePropertyTable
{
  cm::static_string_view Name;
  PropertyType Type;
};

bool cmExportFileGenerator::PopulateCxxModuleExportProperties(
  cmGeneratorTarget const* gte, ImportPropertyMap& properties,
  cmGeneratorExpression::PreprocessContext ctx,
  std::string const& includesDestinationDirs, std::string& errorMessage)
{
  if (!gte->HaveCxx20ModuleSources(&errorMessage)) {
    return true;
  }

  const cm::static_string_view exportedDirectModuleProperties[] = {
    "CXX_EXTENSIONS"_s,
  };
  for (auto const& propName : exportedDirectModuleProperties) {
    auto const propNameStr = std::string(propName);
    cmValue prop = gte->Target->GetComputedProperty(
      propNameStr, *gte->Target->GetMakefile());
    if (!prop) {
      prop = gte->Target->GetProperty(propNameStr);
    }
    if (prop) {
      properties[propNameStr] = cmGeneratorExpression::Preprocess(*prop, ctx);
    }
  }

  const ModulePropertyTable exportedModuleProperties[] = {
    { "INCLUDE_DIRECTORIES"_s, PropertyType::IncludePaths },
    { "COMPILE_DEFINITIONS"_s, PropertyType::Strings },
    { "COMPILE_OPTIONS"_s, PropertyType::Strings },
    { "COMPILE_FEATURES"_s, PropertyType::Strings },
  };
  for (auto const& propEntry : exportedModuleProperties) {
    auto const propNameStr = std::string(propEntry.Name);
    cmValue prop = gte->Target->GetComputedProperty(
      propNameStr, *gte->Target->GetMakefile());
    if (!prop) {
      prop = gte->Target->GetProperty(propNameStr);
    }
    if (prop) {
      auto const exportedPropName =
        cmStrCat("IMPORTED_CXX_MODULES_", propEntry.Name);
      properties[exportedPropName] =
        cmGeneratorExpression::Preprocess(*prop, ctx);
      if (ctx == cmGeneratorExpression::InstallInterface &&
          PropertyTypeIsForPaths(propEntry.Type)) {
        this->ReplaceInstallPrefix(properties[exportedPropName]);
        prefixItems(properties[exportedPropName]);
        if (propEntry.Type == PropertyType::IncludePaths &&
            !includesDestinationDirs.empty()) {
          if (!properties[exportedPropName].empty()) {
            properties[exportedPropName] += ';';
          }
          properties[exportedPropName] += includesDestinationDirs;
        }
      }
    }
  }

  const cm::static_string_view exportedLinkModuleProperties[] = {
    "LINK_LIBRARIES"_s,
  };
  for (auto const& propName : exportedLinkModuleProperties) {
    auto const propNameStr = std::string(propName);
    cmValue prop = gte->Target->GetComputedProperty(
      propNameStr, *gte->Target->GetMakefile());
    if (!prop) {
      prop = gte->Target->GetProperty(propNameStr);
    }
    if (prop) {
      auto const exportedPropName =
        cmStrCat("IMPORTED_CXX_MODULES_", propName);
      auto value = cmGeneratorExpression::Preprocess(*prop, ctx);
      this->ResolveTargetsInGeneratorExpressions(
        value, gte, cmExportFileGenerator::ReplaceFreeTargets);
      std::vector<std::string> wrappedValues;
      for (auto& item : cmList{ value }) {
        wrappedValues.push_back(cmStrCat("$<COMPILE_ONLY:", item, '>'));
      }
      properties[exportedPropName] = cmJoin(wrappedValues, ";");
    }
  }

  return true;
}

bool cmExportFileGenerator::PopulateExportProperties(
  cmGeneratorTarget const* gte, ImportPropertyMap& properties,
  std::string& errorMessage)
{
  const auto& targetProperties = gte->Target->GetProperties();
  if (cmValue exportProperties =
        targetProperties.GetPropertyValue("EXPORT_PROPERTIES")) {
    for (auto& prop : cmList{ *exportProperties }) {
      /* Black list reserved properties */
      if (cmHasLiteralPrefix(prop, "IMPORTED_") ||
          cmHasLiteralPrefix(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;
      }
      cmValue propertyValue = targetProperties.GetPropertyValue(prop);
      if (!propertyValue) {
        // 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;
}

void cmExportFileGenerator::GenerateTargetFileSets(cmGeneratorTarget* gte,
                                                   std::ostream& os,
                                                   cmTargetExport* te)
{
  auto interfaceFileSets = gte->Target->GetAllInterfaceFileSets();
  if (!interfaceFileSets.empty()) {
    std::string targetName = cmStrCat(this->Namespace, gte->GetExportName());
    os << "if(NOT CMAKE_VERSION VERSION_LESS \"3.23.0\")\n"
          "  target_sources("
       << targetName << "\n";

    for (auto const& name : interfaceFileSets) {
      auto* fileSet = gte->Target->GetFileSet(name);
      if (!fileSet) {
        gte->Makefile->IssueMessage(
          MessageType::FATAL_ERROR,
          cmStrCat("File set \"", name,
                   "\" is listed in interface file sets of ", gte->GetName(),
                   " but has not been created"));
        return;
      }

      os << "    INTERFACE"
         << "\n      FILE_SET " << cmOutputConverter::EscapeForCMake(name)
         << "\n      TYPE "
         << cmOutputConverter::EscapeForCMake(fileSet->GetType())
         << "\n      BASE_DIRS "
         << this->GetFileSetDirectories(gte, fileSet, te) << "\n      FILES "
         << this->GetFileSetFiles(gte, fileSet, te) << "\n";
    }

    os << "  )\nelse()\n  set_property(TARGET " << targetName
       << "\n    APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES";
    for (auto const& name : interfaceFileSets) {
      auto* fileSet = gte->Target->GetFileSet(name);
      if (!fileSet) {
        gte->Makefile->IssueMessage(
          MessageType::FATAL_ERROR,
          cmStrCat("File set \"", name,
                   "\" is listed in interface file sets of ", gte->GetName(),
                   " but has not been created"));
        return;
      }

      os << "\n      " << this->GetFileSetDirectories(gte, fileSet, te);
    }
    os << "\n  )\nendif()\n\n";
  }
}

void cmExportFileGenerator::GenerateCxxModuleInformation(std::ostream& os)
{
  auto const cxx_module_dirname = this->GetCxxModulesDirectory();
  if (cxx_module_dirname.empty()) {
    return;
  }

  // Write the include.
  os << "# Include C++ module properties\n"
     << "include(\"${CMAKE_CURRENT_LIST_DIR}/" << cxx_module_dirname
     << "/cxx-modules.cmake\")\n\n";

  // Get the path to the file we're going to write.
  std::string path = this->MainImportFile;
  path = cmSystemTools::GetFilenamePath(path);
  auto trampoline_path =
    cmStrCat(path, '/', cxx_module_dirname, "/cxx-modules.cmake");

  // Include all configuration-specific include files.
  cmGeneratedFileStream ap(trampoline_path, true);
  ap.SetCopyIfDifferent(true);

  this->GenerateCxxModuleConfigInformation(ap);
}

void cmExportFileGenerator::SetRequiredCMakeVersion(unsigned int major,
                                                    unsigned int minor,
                                                    unsigned int patch)
{
  if (CMake_VERSION_ENCODE(major, minor, patch) >
      CMake_VERSION_ENCODE(this->RequiredCMakeVersionMajor,
                           this->RequiredCMakeVersionMinor,
                           this->RequiredCMakeVersionPatch)) {
    this->RequiredCMakeVersionMajor = major;
    this->RequiredCMakeVersionMinor = minor;
    this->RequiredCMakeVersionPatch = patch;
  }
}
