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

#include <array>
#include <cstddef>
#include <sstream>
#include <utility>

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

#include "cmsys/FStream.hxx"

#include "cmComputeLinkInformation.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 "cmPropertyMap.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmValue.h"

cmExportFileGenerator::cmExportFileGenerator() = default;

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

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

std::string const& 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;
  }

  return this->GenerateImportFile(*foutPtr);
}

std::string cmExportFileGenerator::PropertyConfigSuffix(
  std::string const& config)
{
  // Construct the property configuration suffix.
  if (config.empty()) {
    return "_NOCONFIG";
  }
  return cmStrCat('_', cmSystemTools::UpperCase(config));
}

void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
                                                 std::string const& config)
{
  // Generate the per-config target information.
  this->GenerateImportTargetsConfig(os, config, PropertyConfigSuffix(config));
}

bool cmExportFileGenerator::PopulateInterfaceProperties(
  cmGeneratorTarget const* target, std::string const& includesDestinationDirs,
  cmGeneratorExpression::PreprocessContext preprocessRule,
  ImportPropertyMap& properties)
{
  this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", target,
                                  preprocessRule, properties);
  this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", target,
                                  preprocessRule, properties);
  this->PopulateInterfaceProperty("INTERFACE_PRECOMPILE_HEADERS", target,
                                  preprocessRule, properties);
  this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", target,
                                  preprocessRule, properties);
  this->PopulateInterfaceProperty("INTERFACE_AUTOMOC_MACRO_NAMES", target,
                                  preprocessRule, properties);
  this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES", target,
                                  preprocessRule, properties);
  this->PopulateInterfaceProperty("INTERFACE_LINK_OPTIONS", target,
                                  preprocessRule, properties);
  this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
                                  target, properties);

  this->PopulateInterfaceProperty("SPDX_LICENSE", target, preprocessRule,
                                  properties);

  std::string errorMessage;
  if (!this->PopulateCxxModuleExportProperties(
        target, properties, preprocessRule, includesDestinationDirs,
        errorMessage)) {
    this->ReportError(errorMessage);
    return false;
  }

  if (!this->PopulateExportProperties(target, properties, errorMessage)) {
    this->ReportError(errorMessage);
    return false;
  }
  this->PopulateCompatibleInterfaceProperties(target, properties);
  this->PopulateCustomTransitiveInterfaceProperties(target, preprocessRule,
                                                    properties);

  return true;
}

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

void cmExportFileGenerator::PopulateInterfaceProperty(
  std::string const& propName, std::string const& 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;
    }
  }
}

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

bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty(
  cmGeneratorTarget const* target,
  cmGeneratorExpression::PreprocessContext preprocessRule,
  ImportPropertyMap& properties)
{
  if (!target->IsLinkable()) {
    return false;
  }
  static std::array<std::string, 3> const 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;
}

void cmExportFileGenerator::AddImportPrefix(std::string& exportDirs) const
{
  std::vector<std::string> entries;
  cmGeneratorExpression::Split(exportDirs, entries);
  exportDirs.clear();
  char const* sep = "";
  cm::string_view const& prefixWithSlash = this->GetImportPrefixWithSlash();
  for (std::string const& e : entries) {
    exportDirs += sep;
    sep = ";";
    if (!cmSystemTools::FileIsFullPath(e) &&
        !cmHasPrefix(e, prefixWithSlash)) {
      exportDirs += prefixWithSlash;
    }
    exportDirs += e;
  }
}

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

void getCompatibleInterfaceProperties(cmGeneratorTarget const* target,
                                      std::set<std::string>& ifaceProperties,
                                      std::string const& 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;
  }

  cmComputeLinkInformation::ItemVector const& 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) const
{
  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::PopulateCustomTransitiveInterfaceProperties(
  cmGeneratorTarget const* target,
  cmGeneratorExpression::PreprocessContext preprocessRule,
  ImportPropertyMap& properties)
{
  this->PopulateInterfaceProperty("TRANSITIVE_COMPILE_PROPERTIES", target,
                                  properties);
  this->PopulateInterfaceProperty("TRANSITIVE_LINK_PROPERTIES", target,
                                  properties);
  cmGeneratorTarget::CheckLinkLibrariesSuppressionRAII suppress;
  std::set<std::string> ifaceProperties;
  for (std::string const& config : this->Configurations) {
    for (auto const& i : target->GetCustomTransitiveProperties(
           config, cmGeneratorTarget::PropertyFor::Interface)) {
      ifaceProperties.emplace(i.second.InterfaceName);
    }
  }
  for (std::string const& ip : ifaceProperties) {
    this->PopulateInterfaceProperty(ip, target, preprocessRule, properties);
  }
}

bool cmExportFileGenerator::NoteLinkedTarget(
  cmGeneratorTarget const* /*target*/, std::string const& /*linkedName*/,
  cmGeneratorTarget const* /*linkedTarget*/)
{
  // Default implementation does nothing; only needed by some generators.
  return true;
}

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 this->NoteLinkedTarget(target, input, tgt);
  }

  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 this->NoteLinkedTarget(target, input, tgt);
}

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*/) const
{
  // Do nothing
}

void cmExportFileGenerator::SetImportDetailProperties(
  std::string const& config, std::string const& suffix,
  cmGeneratorTarget const* 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;
  }
}

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

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

template <typename T>
void cmExportFileGenerator::SetImportLinkProperty(
  std::string const& suffix, cmGeneratorTarget const* target,
  std::string const& 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;
  char const* 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;
}

template void cmExportFileGenerator::SetImportLinkProperty<std::string>(
  std::string const&, cmGeneratorTarget const*, std::string const&,
  std::vector<std::string> const&, ImportPropertyMap& properties,
  ImportLinkPropertyTargetNames);

template void cmExportFileGenerator::SetImportLinkProperty<cmLinkItem>(
  std::string const&, cmGeneratorTarget const*, std::string const&,
  std::vector<cmLinkItem> const&, ImportPropertyMap& properties,
  ImportLinkPropertyTargetNames);

namespace {
enum class ExportWhen
{
  Defined,
  Always,
};

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

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

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

  struct ModuleTargetPropertyTable
  {
    cm::static_string_view Name;
    ExportWhen Cond;
  };

  ModuleTargetPropertyTable const exportedDirectModuleProperties[] = {
    { "CXX_EXTENSIONS"_s, ExportWhen::Defined },
    // Always define this property as it is an intrinsic property of the target
    // and should not be inherited from the in-scope `CMAKE_CXX_MODULE_STD`
    // variable.
    //
    // TODO(cxxmodules): A future policy may make this "ON" based on the target
    // policies if unset. Add a new `ExportWhen` condition to handle it when
    // this happens.
    { "CXX_MODULE_STD"_s, ExportWhen::Always },
  };
  for (auto const& prop : exportedDirectModuleProperties) {
    auto const propNameStr = std::string(prop.Name);
    cmValue propValue = gte->Target->GetComputedProperty(
      propNameStr, *gte->Target->GetMakefile());
    if (!propValue) {
      propValue = gte->Target->GetProperty(propNameStr);
    }
    if (propValue) {
      properties[propNameStr] =
        cmGeneratorExpression::Preprocess(*propValue, ctx);
    } else if (prop.Cond == ExportWhen::Always) {
      properties[propNameStr] = "";
    }
  }

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

  ModulePropertyTable const 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]);
        this->AddImportPrefix(properties[exportedPropName]);
        if (propEntry.Type == PropertyType::IncludePaths &&
            !includesDestinationDirs.empty()) {
          if (!properties[exportedPropName].empty()) {
            properties[exportedPropName] += ';';
          }
          properties[exportedPropName] += includesDestinationDirs;
        }
      }
    }
  }

  cm::static_string_view const 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,
                                                 ReplaceFreeTargets);
      properties[exportedPropName] = value;
    }
  }

  return true;
}

bool cmExportFileGenerator::PopulateExportProperties(
  cmGeneratorTarget const* gte, ImportPropertyMap& properties,
  std::string& errorMessage) const
{
  auto const& 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;
}
