/* 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&)
{
  if (!gte->HaveCxx20ModuleSources()) {
    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;
}
