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

#include <algorithm>
#include <cassert>
#include <functional>
#include <iterator>
#include <map>
#include <set>
#include <sstream>
#include <unordered_map>
#include <unordered_set>

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

#include "cmsys/RegularExpression.hxx"

#include "cmAlgorithms.h"
#include "cmCustomCommand.h"
#include "cmDiagnostics.h"
#include "cmFileSet.h"
#include "cmFileSetMetadata.h"
#include "cmFindPackageStack.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmList.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmProperty.h"
#include "cmPropertyDefinition.h"
#include "cmPropertyMap.h"
#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
#include "cmSourceFileLocationKind.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmSystemTools.h"
#include "cmTargetPropertyComputer.h"
#include "cmValue.h"
#include "cmXcFramework.h"
#include "cmake.h"

template <>
std::string const& cmTargetPropertyComputer::ImportedLocation<cmTarget>(
  cmTarget const* tgt, std::string const& config)
{
  static std::string loc;
  assert(tgt->IsImported());
  loc = tgt->ImportedGetFullPath(config, cmStateEnums::RuntimeBinaryArtifact);
  return loc;
}

template <>
cmValue cmTargetPropertyComputer::GetSources<cmTarget>(cmTarget const* tgt)
{
  cmBTStringRange entries = tgt->GetSourceEntries();
  if (entries.empty()) {
    return nullptr;
  }

  std::ostringstream ss;
  char const* sep = "";
  for (auto const& entry : entries) {
    cmList files{ entry.Value };
    for (std::string const& file : files) {
      if ((cmHasLiteralPrefix(file, "$<TARGET_OBJECTS:") &&
           file.back() == '>') ||
          cmGeneratorExpression::Find(file) == std::string::npos) {
        ss << sep;
        sep = ";";
        ss << file;
      } else {
        cmSourceFile* sf = tgt->GetMakefile()->GetOrCreateSource(file);
        // Construct what is known about this source file location.
        cmSourceFileLocation const& location = sf->GetLocation();
        std::string sname = location.GetDirectory();
        if (!sname.empty()) {
          sname += "/";
        }
        sname += location.GetName();

        ss << sep;
        sep = ";";
        // Append this list entry.
        ss << sname;
      }
    }
  }
  static std::string srcs;
  srcs = ss.str();
  return cmValue(srcs);
}

namespace {
struct FileSetEntries
{
  FileSetEntries(cm::string_view propertyName)
    : PropertyName(propertyName)
  {
  }

  cm::string_view const PropertyName;
  std::vector<BT<std::string>> Entries;
};

struct FileSetType
{
  FileSetType(cm::string_view typeName,
              cm::static_string_view defaultDirectoryProperty,
              cm::static_string_view defaultPathProperty,
              cm::static_string_view directoryPrefix,
              cm::static_string_view pathPrefix,
              cm::static_string_view typeDescription,
              cm::static_string_view defaultDescription,
              cm::static_string_view arbitraryDescription,
              FileSetEntries selfEntries, FileSetEntries interfaceEntries)
    : TypeName(typeName)
    , DefaultDirectoryProperty(defaultDirectoryProperty)
    , DefaultPathProperty(defaultPathProperty)
    , DirectoryPrefix(directoryPrefix)
    , PathPrefix(pathPrefix)
    , TypeDescription(typeDescription)
    , DefaultDescription(defaultDescription)
    , ArbitraryDescription(arbitraryDescription)
    , SelfEntries(std::move(selfEntries))
    , InterfaceEntries(std::move(interfaceEntries))
  {
  }

  cm::string_view const TypeName;
  cm::static_string_view const DefaultDirectoryProperty;
  cm::static_string_view const DefaultPathProperty;
  cm::static_string_view const DirectoryPrefix;
  cm::static_string_view const PathPrefix;
  cm::static_string_view const TypeDescription;
  cm::static_string_view const DefaultDescription;
  cm::static_string_view const ArbitraryDescription;

  FileSetEntries SelfEntries;
  FileSetEntries InterfaceEntries;

  enum class Action
  {
    Set,
    Append,
  };

  template <typename ValueType>
  bool WriteProperties(cmTarget* tgt, cmTargetInternals* impl,
                       std::string const& prop, ValueType value,
                       Action action);
  std::pair<bool, cmValue> ReadProperties(cmTarget const* tgt,
                                          cmTargetInternals const* impl,
                                          std::string const& prop) const;

  void AddFileSet(std::string const& name, cm::FileSetMetadata::Visibility vis,
                  cmListFileBacktrace bt);
};

struct UsageRequirementProperty
{
  enum class AppendEmpty
  {
    Yes,
    No,
  };

  UsageRequirementProperty(cm::static_string_view name,
                           AppendEmpty appendEmpty = AppendEmpty::No)
    : Name(name)
    , AppendBehavior(appendEmpty)
  {
  }

  void CopyFromEntries(cmBTStringRange entries)
  {
    cm::append(this->Entries, entries);
  }

  enum class Action
  {
    Set,
    Prepend,
    Append,
  };

  template <typename ValueType>
  bool Write(cmTargetInternals const* impl,
             cm::optional<cmListFileBacktrace> const& bt,
             std::string const& prop, ValueType value, Action action);
  template <typename ValueType>
  void WriteDirect(cmTargetInternals const* impl,
                   cm::optional<cmListFileBacktrace> const& bt,
                   ValueType value, Action action);
  void WriteDirect(BT<std::string> value, Action action);
  std::pair<bool, cmValue> Read(std::string const& prop) const;

  cm::static_string_view const Name;
  AppendEmpty const AppendBehavior;

  std::vector<BT<std::string>> Entries;
};

struct TargetProperty
{
  enum class InitCondition
  {
    // Always initialize the property.
    Always,
    // Never initialize the property.
    Never,
    // Only initialize if the target can compile sources.
    CanCompileSources,
    // Only apply to Xcode generators.
    NeedsXcode,
    // Only apply to Xcode generators on targets that can compile sources.
    NeedsXcodeAndCanCompileSources,
    // Needs to be a "normal" target (any non-global, non-utility target).
    NormalTarget,
    // Any non-imported target.
    NonImportedTarget,
    // Needs to be a "normal" target (any non-global, non-utility target) that
    // is not `IMPORTED`.
    NormalNonImportedTarget,
    // Needs to be a "normal" target with an artifact (no `INTERFACE`
    // libraries).
    TargetWithArtifact,
    // Needs to be a "normal" target with an artifact that is not an
    // executable.
    NonExecutableWithArtifact,
    // Needs to be a linkable library target (no `OBJECT` or `MODULE`
    // libraries).
    LinkableLibraryTarget,
    // Needs to be an executable.
    ExecutableTarget,
    // Needs to be a shared library (`SHARED`).
    SharedLibraryTarget,
    // Needs to be a target with meaningful symbol exports (`SHARED` or
    // `EXECUTABLE`).
    TargetWithSymbolExports,
    // Targets with "commands" associated with them. Basically everything
    // except global and `INTERFACE` targets.
    TargetWithCommands,
  };

  enum class Repetition
  {
    Once,
    PerConfig,
    PerConfigPrefix,
  };

  TargetProperty(cm::static_string_view name)
    : Name(name)
  {
  }

  TargetProperty(cm::static_string_view name, cm::static_string_view dflt,
                 InitCondition init)
    : Name(name)
    , Default(dflt)
    , InitConditional(init)
  {
  }

  TargetProperty(cm::static_string_view name, InitCondition init)
    : Name(name)
    , InitConditional(init)
  {
  }

  TargetProperty(cm::static_string_view name, InitCondition init,
                 Repetition repeat)
    : Name(name)
    , InitConditional(init)
    , Repeat(repeat)
  {
  }

  cm::static_string_view const Name;
  // Explicit initialization is needed for AppleClang in Xcode 8 and below
  // NOLINTNEXTLINE(readability-redundant-member-init)
  cm::optional<cm::static_string_view> const Default = {};
  InitCondition const InitConditional = InitCondition::Always;
  Repetition const Repeat = Repetition::Once;
};

#define IC TargetProperty::InitCondition
#define R TargetProperty::Repetition

/* clang-format off */
#define COMMON_LANGUAGE_PROPERTIES(lang)                                      \
  { #lang "_COMPILER_LAUNCHER"_s, IC::CanCompileSources },                    \
  { #lang "_STANDARD"_s, IC::CanCompileSources },                             \
  { #lang "_STANDARD_REQUIRED"_s, IC::CanCompileSources },                    \
  { #lang "_EXTENSIONS"_s, IC::CanCompileSources },                           \
  { #lang "_VISIBILITY_PRESET"_s, IC::CanCompileSources }
/* clang-format on */

TargetProperty const StaticTargetProperties[] = {
  /* clang-format off */
  // -- Debugger Properties
  { "DEBUGGER_WORKING_DIRECTORY"_s, IC::ExecutableTarget },
  // Compilation properties
  { "COMPILE_WARNING_AS_ERROR"_s, IC::CanCompileSources },
  { "INTERPROCEDURAL_OPTIMIZATION"_s, IC::CanCompileSources },
  { "INTERPROCEDURAL_OPTIMIZATION_"_s, IC::TargetWithArtifact, R::PerConfig },
  { "NO_SYSTEM_FROM_IMPORTED"_s, IC::CanCompileSources },
  // Set to `True` for `SHARED` and `MODULE` targets.
  { "POSITION_INDEPENDENT_CODE"_s, IC::CanCompileSources },
  { "VISIBILITY_INLINES_HIDDEN"_s, IC::CanCompileSources },
  // -- Features
  // ---- PCH
  { "DISABLE_PRECOMPILE_HEADERS"_s, IC::CanCompileSources },
  { "PCH_WARN_INVALID"_s, "ON"_s, IC::CanCompileSources },
  { "PCH_INSTANTIATE_TEMPLATES"_s, "ON"_s, IC::CanCompileSources },
  // -- Platforms
  // ---- Android
  { "ANDROID_API"_s, IC::CanCompileSources },
  { "ANDROID_API_MIN"_s, IC::CanCompileSources },
  { "ANDROID_ARCH"_s, IC::CanCompileSources },
  { "ANDROID_ASSETS_DIRECTORIES"_s, IC::CanCompileSources },
  { "ANDROID_JAVA_SOURCE_DIR"_s, IC::CanCompileSources },
  { "ANDROID_STL_TYPE"_s, IC::CanCompileSources },
  // ---- macOS
  { "OSX_ARCHITECTURES"_s, IC::CanCompileSources },
  // ---- Windows
  { "MSVC_DEBUG_INFORMATION_FORMAT"_s, IC::CanCompileSources },
  { "MSVC_RUNTIME_CHECKS"_s, IC::CanCompileSources },
  { "MSVC_RUNTIME_LIBRARY"_s, IC::CanCompileSources },
  { "VS_JUST_MY_CODE_DEBUGGING"_s, IC::CanCompileSources },
  { "VS_DEBUGGER_COMMAND"_s, IC::ExecutableTarget },
  { "VS_DEBUGGER_COMMAND_ARGUMENTS"_s, IC::ExecutableTarget },
  { "VS_DEBUGGER_ENVIRONMENT"_s, IC::ExecutableTarget },
  { "VS_DEBUGGER_WORKING_DIRECTORY"_s, IC::ExecutableTarget },
  { "VS_USE_DEBUG_LIBRARIES"_s, IC::NonImportedTarget },
  // ---- OpenWatcom
  { "WATCOM_RUNTIME_LIBRARY"_s, IC::CanCompileSources },
  // ---- AIX
  { "AIX_SHARED_LIBRARY_ARCHIVE"_s, IC::SharedLibraryTarget },
  // -- Language
  // ---- C
  COMMON_LANGUAGE_PROPERTIES(C),
  // ---- C++
  COMMON_LANGUAGE_PROPERTIES(CXX),
  { "CXX_MODULE_STD"_s, IC::CanCompileSources },
  // ---- CSharp
  { "DOTNET_SDK"_s, IC::NonImportedTarget },
  { "DOTNET_TARGET_FRAMEWORK"_s, IC::TargetWithCommands },
  { "DOTNET_TARGET_FRAMEWORK_VERSION"_s, IC::TargetWithCommands },
  // ---- CUDA
  COMMON_LANGUAGE_PROPERTIES(CUDA),
  { "CUDA_SEPARABLE_COMPILATION"_s, IC::CanCompileSources },
  { "CUDA_ARCHITECTURES"_s, IC::CanCompileSources },
  // ---- Fortran
  { "Fortran_FORMAT"_s, IC::CanCompileSources },
  { "Fortran_MODULE_DIRECTORY"_s, IC::CanCompileSources },
  { "Fortran_COMPILER_LAUNCHER"_s, IC::CanCompileSources },
  { "Fortran_PREPROCESS"_s, IC::CanCompileSources },
  { "Fortran_VISIBILITY_PRESET"_s, IC::CanCompileSources },
  // ---- HIP
  COMMON_LANGUAGE_PROPERTIES(HIP),
  { "HIP_ARCHITECTURES"_s, IC::CanCompileSources },
  // ---- ISPC
  { "ISPC_COMPILER_LAUNCHER"_s, IC::CanCompileSources },
  { "ISPC_HEADER_DIRECTORY"_s, IC::CanCompileSources },
  { "ISPC_HEADER_SUFFIX"_s, "_ispc.h"_s, IC::CanCompileSources },
  { "ISPC_INSTRUCTION_SETS"_s, IC::CanCompileSources },
  // ---- Objective C
  COMMON_LANGUAGE_PROPERTIES(OBJC),
  // ---- Objective C++
  COMMON_LANGUAGE_PROPERTIES(OBJCXX),
  // ---- Swift
  { "Swift_LANGUAGE_VERSION"_s, IC::CanCompileSources },
  { "Swift_MODULE_DIRECTORY"_s, IC::CanCompileSources },
  { "Swift_COMPILATION_MODE"_s, IC::CanCompileSources },
  { "Swift_SEPARATE_MODULE_EMISSION"_s, IC::CanCompileSources },
  // ---- Rust
  { "Rust_EDITION"_s, IC::CanCompileSources },
  { "Rust_MAIN_CRATE_ROOT"_s, IC::CanCompileSources },
  // ---- moc
  { "AUTOMOC"_s, IC::CanCompileSources },
  { "AUTOMOC_COMPILER_PREDEFINES"_s, IC::CanCompileSources },
  { "AUTOMOC_INCLUDE_DIRECTORIES"_s, IC::CanCompileSources },
  { "AUTOMOC_MACRO_NAMES"_s, IC::CanCompileSources },
  { "AUTOMOC_MOC_OPTIONS"_s, IC::CanCompileSources },
  { "AUTOMOC_PATH_PREFIX"_s, IC::CanCompileSources },
  { "AUTOMOC_EXECUTABLE"_s, IC::CanCompileSources },
  // ---- uic
  { "AUTOUIC"_s, IC::CanCompileSources },
  { "AUTOUIC_OPTIONS"_s, IC::CanCompileSources },
  { "AUTOUIC_SEARCH_PATHS"_s, IC::CanCompileSources },
  { "AUTOUIC_EXECUTABLE"_s, IC::CanCompileSources },
  // ---- rcc
  { "AUTORCC"_s, IC::CanCompileSources },
  { "AUTORCC_OPTIONS"_s, IC::CanCompileSources },
  { "AUTORCC_EXECUTABLE"_s, IC::CanCompileSources },

  // Linking properties
  { "LINKER_TYPE"_s, IC::CanCompileSources },
  { "LINK_WARNING_AS_ERROR"_s, IC::CanCompileSources },
  { "ENABLE_EXPORTS"_s, IC::TargetWithSymbolExports },
  { "LINK_LIBRARIES_ONLY_TARGETS"_s, IC::NormalNonImportedTarget },
  { "LINK_LIBRARIES_STRATEGY"_s, IC::NormalNonImportedTarget },
  { "LINK_SEARCH_START_STATIC"_s, IC::CanCompileSources },
  { "LINK_SEARCH_END_STATIC"_s, IC::CanCompileSources },
  // Initialize per-configuration name postfix property from the variable only
  // for non-executable targets.  This preserves compatibility with previous
  // CMake versions in which executables did not support this variable.
  // Projects may still specify the property directly.
  { "_POSTFIX"_s, IC::NonExecutableWithArtifact, R::PerConfigPrefix },
  // -- Dependent library lookup
  { "MACOSX_RPATH"_s, IC::CanCompileSources },
  // ---- Build
  { "BUILD_RPATH"_s, IC::CanCompileSources },
  { "BUILD_RPATH_USE_ORIGIN"_s, IC::CanCompileSources },
  { "SKIP_BUILD_RPATH"_s, "OFF"_s, IC::CanCompileSources },
  { "BUILD_WITH_INSTALL_RPATH"_s, "OFF"_s, IC::CanCompileSources },
  { "BUILD_WITH_INSTALL_NAME_DIR"_s, IC::CanCompileSources },
  // ---- Install
  { "INSTALL_NAME_DIR"_s, IC::CanCompileSources },
  { "INSTALL_OBJECT_NAME_STRATEGY"_s, IC::CanCompileSources },
  { "INSTALL_OBJECT_ONLY_USE_DESTINATION"_s, IC::CanCompileSources },
  { "INSTALL_REMOVE_ENVIRONMENT_RPATH"_s, IC::CanCompileSources },
  { "INSTALL_RPATH"_s, ""_s, IC::CanCompileSources },
  { "INSTALL_RPATH_USE_LINK_PATH"_s, "OFF"_s, IC::CanCompileSources },
  // -- Platforms
  // ---- AIX
  { "AIX_EXPORT_ALL_SYMBOLS"_s, IC::TargetWithSymbolExports },
  // ---- Android
  { "ANDROID_GUI"_s, IC::ExecutableTarget },
  { "ANDROID_JAR_DIRECTORIES"_s, IC::CanCompileSources },
  { "ANDROID_JAR_DEPENDENCIES"_s, IC::CanCompileSources },
  { "ANDROID_NATIVE_LIB_DIRECTORIES"_s, IC::CanCompileSources },
  { "ANDROID_NATIVE_LIB_DEPENDENCIES"_s, IC::CanCompileSources },
  { "ANDROID_PROGUARD"_s, IC::CanCompileSources },
  { "ANDROID_PROGUARD_CONFIG_PATH"_s, IC::CanCompileSources },
  { "ANDROID_SECURE_PROPS_PATH"_s, IC::CanCompileSources },
  // ---- iOS
  { "IOS_INSTALL_COMBINED"_s, IC::CanCompileSources },
  // ---- macOS
  { "FRAMEWORK_MULTI_CONFIG_POSTFIX_"_s, IC::LinkableLibraryTarget, R::PerConfig },
  // ---- Windows
  { "DLL_NAME_WITH_SOVERSION"_s, IC::SharedLibraryTarget },
  { "GNUtoMS"_s, IC::CanCompileSources },
  { "WIN32_EXECUTABLE"_s, IC::CanCompileSources },
  { "WINDOWS_EXPORT_ALL_SYMBOLS"_s, IC::TargetWithSymbolExports },
  // -- Languages
  // ---- C
  { "C_LINKER_LAUNCHER"_s, IC::CanCompileSources },
  // ---- C++
  { "CXX_LINKER_LAUNCHER"_s, IC::CanCompileSources },
  // ---- CUDA
  { "CUDA_LINKER_LAUNCHER"_s, IC::CanCompileSources },
  { "CUDA_RESOLVE_DEVICE_SYMBOLS"_s, IC::CanCompileSources },
  { "CUDA_RUNTIME_LIBRARY"_s, IC::CanCompileSources },
  // ---- HIP
  { "HIP_LINKER_LAUNCHER"_s, IC::CanCompileSources },
  { "HIP_RUNTIME_LIBRARY"_s, IC::CanCompileSources },
  // ---- Objective C
  { "OBJC_LINKER_LAUNCHER"_s, IC::CanCompileSources },
  // ---- Objective C++
  { "OBJCXX_LINKER_LAUNCHER"_s, IC::CanCompileSources },
  // ---- Fortran
  { "Fortran_LINKER_LAUNCHER"_s, IC::CanCompileSources },

  // Static analysis
  { "SKIP_LINTING"_s, IC::CanCompileSources },
  // -- C
  { "C_CLANG_TIDY"_s, IC::CanCompileSources },
  { "C_CLANG_TIDY_EXPORT_FIXES_DIR"_s, IC::CanCompileSources },
  { "C_CPPLINT"_s, IC::CanCompileSources },
  { "C_CPPCHECK"_s, IC::CanCompileSources },
  { "C_ICSTAT"_s, IC::CanCompileSources },
  { "C_INCLUDE_WHAT_YOU_USE"_s, IC::CanCompileSources },
  { "C_PVS_STUDIO"_s, IC::CanCompileSources },
  // -- C++
  { "CXX_CLANG_TIDY"_s, IC::CanCompileSources },
  { "CXX_CLANG_TIDY_EXPORT_FIXES_DIR"_s, IC::CanCompileSources },
  { "CXX_CPPLINT"_s, IC::CanCompileSources },
  { "CXX_CPPCHECK"_s, IC::CanCompileSources },
  { "CXX_ICSTAT"_s, IC::CanCompileSources },
  { "CXX_INCLUDE_WHAT_YOU_USE"_s, IC::CanCompileSources },
  { "CXX_PVS_STUDIO"_s, IC::CanCompileSources },
  // -- Objective C
  { "OBJC_CLANG_TIDY"_s, IC::CanCompileSources },
  { "OBJC_CLANG_TIDY_EXPORT_FIXES_DIR"_s, IC::CanCompileSources },
  // -- Objective C++
  { "OBJCXX_CLANG_TIDY"_s, IC::CanCompileSources },
  { "OBJCXX_CLANG_TIDY_EXPORT_FIXES_DIR"_s, IC::CanCompileSources },
  // -- Linking
  { "LINK_WHAT_YOU_USE"_s, IC::CanCompileSources },

  // Build graph properties
  { "LINK_DEPENDS_NO_SHARED"_s, IC::CanCompileSources },
  { "UNITY_BUILD"_s, IC::CanCompileSources },
  { "UNITY_BUILD_UNIQUE_ID"_s, IC::CanCompileSources },
  { "UNITY_BUILD_BATCH_SIZE"_s, "8"_s, IC::CanCompileSources },
  { "UNITY_BUILD_MODE"_s, "BATCH"_s, IC::CanCompileSources },
  { "UNITY_BUILD_RELOCATABLE"_s, IC::CanCompileSources },
  { "OPTIMIZE_DEPENDENCIES"_s, IC::CanCompileSources },
  { "VERIFY_INTERFACE_HEADER_SETS"_s },
  { "VERIFY_PRIVATE_HEADER_SETS"_s },
  // -- Android
  { "ANDROID_ANT_ADDITIONAL_OPTIONS"_s, IC::CanCompileSources },
  { "ANDROID_PROCESS_MAX"_s, IC::CanCompileSources },
  { "ANDROID_SKIP_ANT_STEP"_s, IC::CanCompileSources },
  // -- Autogen
  { "AUTOGEN_COMMAND_LINE_LENGTH_MAX"_s, IC::CanCompileSources },
  { "AUTOGEN_ORIGIN_DEPENDS"_s, IC::CanCompileSources },
  { "AUTOGEN_PARALLEL"_s, IC::CanCompileSources },
  { "AUTOGEN_USE_SYSTEM_INCLUDE"_s, IC::CanCompileSources },
  { "AUTOGEN_BETTER_GRAPH_MULTI_CONFIG"_s, IC::CanCompileSources },
  // -- moc
  { "AUTOMOC_DEPEND_FILTERS"_s, IC::CanCompileSources },
  // -- C++
  { "CXX_SCAN_FOR_MODULES"_s, IC::CanCompileSources },
  // -- Ninja
  { "JOB_POOL_COMPILE"_s, IC::CanCompileSources },
  { "JOB_POOL_LINK"_s, IC::CanCompileSources },
  { "JOB_POOL_PRECOMPILE_HEADER"_s, IC::CanCompileSources },
  // -- Visual Studio
  { "VS_NO_COMPILE_BATCHING"_s, IC::CanCompileSources },
  { "VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION"_s, IC::CanCompileSources},

  // Output location properties
  { "ARCHIVE_OUTPUT_DIRECTORY"_s, IC::CanCompileSources },
  { "ARCHIVE_OUTPUT_DIRECTORY_"_s, IC::TargetWithArtifact, R::PerConfig },
  { "COMPILE_PDB_OUTPUT_DIRECTORY"_s, IC::CanCompileSources },
  { "COMPILE_PDB_OUTPUT_DIRECTORY_"_s, IC::TargetWithArtifact, R::PerConfig },
  { "LIBRARY_OUTPUT_DIRECTORY"_s, IC::CanCompileSources },
  { "LIBRARY_OUTPUT_DIRECTORY_"_s, IC::TargetWithArtifact, R::PerConfig },
  { "PDB_OUTPUT_DIRECTORY"_s, IC::CanCompileSources },
  { "PDB_OUTPUT_DIRECTORY_"_s, IC::TargetWithArtifact, R::PerConfig },
  { "RUNTIME_OUTPUT_DIRECTORY"_s, IC::CanCompileSources },
  { "RUNTIME_OUTPUT_DIRECTORY_"_s, IC::TargetWithArtifact, R::PerConfig },

  // macOS bundle properties
  { "FRAMEWORK"_s, IC::CanCompileSources },
  { "FRAMEWORK_MULTI_CONFIG_POSTFIX"_s, IC::CanCompileSources },
  { "MACOSX_BUNDLE"_s, IC::CanCompileSources },

  // Usage requirement properties
  { "LINK_INTERFACE_LIBRARIES"_s, IC::CanCompileSources },
  { "MAP_IMPORTED_CONFIG_"_s, IC::NormalTarget, R::PerConfig },
  { "EXPORT_FIND_PACKAGE_NAME"_s, IC::NormalTarget },

  // Metadata
  { "CROSSCOMPILING_EMULATOR"_s, IC::ExecutableTarget },
  { "EXPORT_BUILD_DATABASE"_s, IC::CanCompileSources },
  { "EXPORT_COMPILE_COMMANDS"_s, IC::CanCompileSources },
  { "FOLDER"_s },
  { "TEST_LAUNCHER"_s, IC::ExecutableTarget },

  // Xcode properties
  { "XCODE_GENERATE_SCHEME"_s, IC::NeedsXcode },

#ifdef __APPLE__
  { "XCODE_SCHEME_ADDRESS_SANITIZER"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_THREAD_SANITIZER"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_THREAD_SANITIZER_STOP"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_LAUNCH_CONFIGURATION"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_TEST_CONFIGURATION"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_ENABLE_GPU_API_VALIDATION"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_WORKING_DIRECTORY"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_MALLOC_SCRIBBLE"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_MALLOC_GUARD_EDGES"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_GUARD_MALLOC"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_LAUNCH_MODE"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_LLDB_INIT_FILE"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_ZOMBIE_OBJECTS"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_MALLOC_STACK"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_SCHEME_ENVIRONMENT"_s, IC::NeedsXcodeAndCanCompileSources },
  { "XCODE_LINK_BUILD_PHASE_MODE"_s, "NONE"_s, IC::NeedsXcodeAndCanCompileSources },
#endif
  /* clang-format on */
};

#undef COMMON_LANGUAGE_PROPERTIES
#undef IC
#undef R
}

class cmTargetInternals
{
public:
  cmStateEnums::TargetType TargetType;
  cmTarget::Origin Origin = cmTarget::Origin::Unknown;
  cmMakefile* Makefile;
  cmPolicies::PolicyMap PolicyMap;
  cmTarget const* TemplateTarget;
  std::string Name;
  std::string InstallPath;
  std::string RuntimeInstallPath;
  cmPropertyMap Properties;
  bool IsGeneratorProvided;
  bool HaveInstallRule;
  bool IsDLLPlatform;
  bool IsAIX;
  bool IsApple;
  bool IsAndroid;
  bool BuildInterfaceIncludesAppended;
  bool PerConfig;
  bool IsSymbolic;
  bool IsForTryCompile{ false };
  cmTarget::Visibility TargetVisibility;
  std::set<BT<std::pair<std::string, bool>>> Utilities;
  std::set<std::string> CodegenDependencies;
  std::vector<cmCustomCommand> PreBuildCommands;
  std::vector<cmCustomCommand> PreLinkCommands;
  std::vector<cmCustomCommand> PostBuildCommands;
  std::vector<cmInstallTargetGenerator*> InstallGenerators;
  std::set<std::string> SystemIncludeDirectories;
  cmTarget::LinkLibraryVectorType OriginalLinkLibraries;
  std::map<std::string, BTs<std::string>> LanguageStandardProperties;
  std::map<cmTargetExport const*, std::vector<std::string>>
    InstallIncludeDirectoriesEntries;
  std::vector<std::pair<cmTarget::TLLSignature, cmListFileContext>>
    TLLCommands;
  std::map<std::string, cmFileSet> FileSets;
  cmListFileBacktrace Backtrace;
  cmFindPackageStack FindPackageStack;

  UsageRequirementProperty IncludeDirectories;
  UsageRequirementProperty CompileOptions;
  UsageRequirementProperty CompileFeatures;
  UsageRequirementProperty CompileDefinitions;
  UsageRequirementProperty PrecompileHeaders;
  UsageRequirementProperty Sources;
  UsageRequirementProperty LinkOptions;
  UsageRequirementProperty LinkDirectories;
  UsageRequirementProperty LinkLibraries;
  UsageRequirementProperty InterfaceLinkLibraries;
  UsageRequirementProperty InterfaceLinkLibrariesDirect;
  UsageRequirementProperty InterfaceLinkLibrariesDirectExclude;
  UsageRequirementProperty ImportedCxxModulesIncludeDirectories;
  UsageRequirementProperty ImportedCxxModulesCompileDefinitions;
  UsageRequirementProperty ImportedCxxModulesCompileFeatures;
  UsageRequirementProperty ImportedCxxModulesCompileOptions;
  UsageRequirementProperty ImportedCxxModulesLinkLibraries;

  std::unordered_map<cm::string_view, FileSetType> FileSetTypes;

  cmTargetInternals();

  bool IsImported() const;

  bool CheckImportedLibName(std::string const& prop,
                            std::string const& value) const;

  template <typename ValueType>
  void AddDirectoryToFileSet(cmTarget* self, std::string const& fileSetName,
                             ValueType value, cm::string_view fileSetType,
                             cm::string_view description,
                             FileSetType::Action action);
  template <typename ValueType>
  void AddPathToFileSet(cmTarget* self, std::string const& fileSetName,
                        ValueType value, cm::string_view fileSetType,
                        cm::string_view description,
                        FileSetType::Action action);
  cmValue GetFileSetDirectories(cmTarget const* self,
                                std::string const& fileSetName,
                                cm::string_view fileSetType) const;
  cmValue GetFileSetPaths(cmTarget const* self, std::string const& fileSetName,
                          cm::string_view fileSetType) const;

  cmListFileBacktrace GetBacktrace(
    cm::optional<cmListFileBacktrace> const& bt) const
  {
    return bt ? *bt : this->Makefile->GetBacktrace();
  }
};

cmTargetInternals::cmTargetInternals()
  : IncludeDirectories("INCLUDE_DIRECTORIES"_s)
  , CompileOptions("COMPILE_OPTIONS"_s)
  , CompileFeatures("COMPILE_FEATURES"_s)
  , CompileDefinitions("COMPILE_DEFINITIONS"_s)
  , PrecompileHeaders("PRECOMPILE_HEADERS"_s)
  , Sources("SOURCES"_s, UsageRequirementProperty::AppendEmpty::Yes)
  , LinkOptions("LINK_OPTIONS"_s)
  , LinkDirectories("LINK_DIRECTORIES"_s)
  , LinkLibraries("LINK_LIBRARIES"_s)
  , InterfaceLinkLibraries("INTERFACE_LINK_LIBRARIES"_s)
  , InterfaceLinkLibrariesDirect("INTERFACE_LINK_LIBRARIES_DIRECT"_s)
  , InterfaceLinkLibrariesDirectExclude(
      "INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE"_s)
  , ImportedCxxModulesIncludeDirectories(
      "IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES"_s)
  , ImportedCxxModulesCompileDefinitions(
      "IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS"_s)
  , ImportedCxxModulesCompileFeatures(
      "IMPORTED_CXX_MODULES_COMPILE_FEATURES"_s)
  , ImportedCxxModulesCompileOptions("IMPORTED_CXX_MODULES_COMPILE_OPTIONS"_s)
  , ImportedCxxModulesLinkLibraries("IMPORTED_CXX_MODULES_LINK_LIBRARIES"_s)
  , FileSetTypes{ { cm::FileSetMetadata::HEADERS,
                    { cm::FileSetMetadata::HEADERS, "HEADER_DIRS"_s,
                      "HEADER_SET"_s, "HEADER_DIRS_"_s, "HEADER_SET_"_s,
                      "Header"_s, "The default header set"_s, "Header set"_s,
                      FileSetEntries{ "HEADER_SETS"_s },
                      FileSetEntries{ "INTERFACE_HEADER_SETS"_s } } },
                  { cm::FileSetMetadata::SOURCES,
                    { cm::FileSetMetadata::SOURCES, "SOURCE_DIRS"_s,
                      "SOURCE_SET"_s, "SOURCE_DIRS_"_s, "SOURCE_SET_"_s,
                      "Source"_s, "The default source set"_s, "Source set"_s,
                      FileSetEntries{ "SOURCE_SETS"_s },
                      FileSetEntries{ "INTERFACE_SOURCE_SETS"_s } } },
                  { cm::FileSetMetadata::CXX_MODULES,
                    { cm::FileSetMetadata::CXX_MODULES, "CXX_MODULE_DIRS"_s,
                      "CXX_MODULE_SET"_s, "CXX_MODULE_DIRS_"_s,
                      "CXX_MODULE_SET_"_s, "C++ module"_s,
                      "The default C++ module set"_s, "C++ module set"_s,
                      FileSetEntries{ "CXX_MODULE_SETS"_s },
                      FileSetEntries{ "INTERFACE_CXX_MODULE_SETS"_s } } } }
{
}

template <typename ValueType>
bool FileSetType::WriteProperties(cmTarget* tgt, cmTargetInternals* impl,
                                  std::string const& prop, ValueType value,
                                  Action action)
{
  if (prop == this->DefaultDirectoryProperty) {
    impl->AddDirectoryToFileSet(tgt, std::string(this->TypeName), value,
                                this->TypeName, this->DefaultDescription,
                                action);
    return true;
  }
  if (prop == this->DefaultPathProperty) {
    impl->AddPathToFileSet(tgt, std::string(this->TypeName), value,
                           this->TypeName, this->DefaultDescription, action);
    return true;
  }
  if (cmHasPrefix(prop, this->DirectoryPrefix)) {
    auto fileSetName = prop.substr(this->DirectoryPrefix.size());
    if (fileSetName.empty()) {
      impl->Makefile->IssueMessage(
        MessageType::FATAL_ERROR,
        cmStrCat(this->ArbitraryDescription, " name cannot be empty."));
    } else {
      impl->AddDirectoryToFileSet(
        tgt, fileSetName, value, this->TypeName,
        cmStrCat(this->ArbitraryDescription, " \"", fileSetName, '"'), action);
    }
    return true;
  }
  if (cmHasPrefix(prop, this->PathPrefix)) {
    auto fileSetName = prop.substr(this->PathPrefix.size());
    if (fileSetName.empty()) {
      impl->Makefile->IssueMessage(
        MessageType::FATAL_ERROR,
        cmStrCat(this->ArbitraryDescription, " name cannot be empty."));
    } else {
      impl->AddPathToFileSet(
        tgt, fileSetName, value, this->TypeName,
        cmStrCat(this->ArbitraryDescription, " \"", fileSetName, '"'), action);
    }
    return true;
  }
  return false;
}

std::pair<bool, cmValue> FileSetType::ReadProperties(
  cmTarget const* tgt, cmTargetInternals const* impl,
  std::string const& prop) const
{
  bool did_read = false;
  cmValue value = nullptr;
  if (prop == this->DefaultDirectoryProperty) {
    value = impl->GetFileSetDirectories(tgt, std::string(this->TypeName),
                                        this->TypeName);
    did_read = true;
  } else if (prop == this->DefaultPathProperty) {
    value =
      impl->GetFileSetPaths(tgt, std::string(this->TypeName), this->TypeName);
    did_read = true;
  } else if (prop == this->SelfEntries.PropertyName) {
    static std::string output;
    output = cmList::to_string(this->SelfEntries.Entries);
    value = cmValue(output);
    did_read = true;
  } else if (prop == this->InterfaceEntries.PropertyName) {
    static std::string output;
    output = cmList::to_string(this->InterfaceEntries.Entries);
    value = cmValue(output);
    did_read = true;
  } else if (cmHasPrefix(prop, this->DirectoryPrefix)) {
    std::string fileSetName = prop.substr(this->DirectoryPrefix.size());
    if (!fileSetName.empty()) {
      value = impl->GetFileSetDirectories(tgt, fileSetName, this->TypeName);
    }
    did_read = true;
  } else if (cmHasPrefix(prop, this->PathPrefix)) {
    std::string fileSetName = prop.substr(this->PathPrefix.size());
    if (!fileSetName.empty()) {
      value = impl->GetFileSetPaths(tgt, fileSetName, this->TypeName);
    }
    did_read = true;
  }
  return { did_read, value };
}

void FileSetType::AddFileSet(std::string const& name,
                             cm::FileSetMetadata::Visibility vis,
                             cmListFileBacktrace bt)
{
  if (cm::FileSetMetadata::VisibilityIsForSelf(vis)) {
    this->SelfEntries.Entries.emplace_back(name, bt);
  }
  if (cm::FileSetMetadata::VisibilityIsForInterface(vis)) {
    this->InterfaceEntries.Entries.emplace_back(name, std::move(bt));
  }
}

template <typename ValueType>
bool UsageRequirementProperty::Write(
  cmTargetInternals const* impl, cm::optional<cmListFileBacktrace> const& bt,
  std::string const& prop, ValueType value, Action action)
{
  if (prop == this->Name) {
    this->WriteDirect(impl, bt, value, action);
    return true;
  }
  return false;
}

template <typename ValueType>
void UsageRequirementProperty::WriteDirect(
  cmTargetInternals const* impl, cm::optional<cmListFileBacktrace> const& bt,
  ValueType value, Action action)
{
  if (action == Action::Set) {
    this->Entries.clear();
  }
  if (value) {
    cmListFileBacktrace lfbt = impl->GetBacktrace(bt);
    if (action == Action::Prepend) {
      this->Entries.emplace(this->Entries.begin(), value, lfbt);
    } else if (action == Action::Set || cmNonempty(value) ||
               this->AppendBehavior == AppendEmpty::Yes) {
      this->Entries.emplace_back(value, lfbt);
    }
  }
}

void UsageRequirementProperty::WriteDirect(BT<std::string> value,
                                           Action action)
{
  if (action == Action::Set) {
    this->Entries.clear();
  }
  if (action == Action::Prepend) {
    this->Entries.emplace(this->Entries.begin(), std::move(value));
  } else {
    this->Entries.emplace_back(std::move(value));
  }
}

std::pair<bool, cmValue> UsageRequirementProperty::Read(
  std::string const& prop) const
{
  bool did_read = false;
  cmValue value = nullptr;
  if (prop == this->Name) {
    if (!this->Entries.empty()) {
      // Storage to back the returned `cmValue`.
      static std::string output;
      output = cmList::to_string(this->Entries);
      value = cmValue(output);
    }
    did_read = true;
  }
  return { did_read, value };
}

cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
                   Visibility vis, cmMakefile* mf, PerConfig perConfig)
  : impl(cm::make_unique<cmTargetInternals>())
{
  assert(mf);
  this->impl->TargetType = type;
  this->impl->Makefile = mf;
  this->impl->Name = name;
  this->impl->TemplateTarget = nullptr;
  this->impl->IsGeneratorProvided = false;
  this->impl->HaveInstallRule = false;
  this->impl->IsDLLPlatform = false;
  this->impl->IsAIX = false;
  this->impl->IsApple = false;
  this->impl->IsAndroid = false;
  this->impl->IsSymbolic = false;
  this->impl->TargetVisibility = vis;
  this->impl->BuildInterfaceIncludesAppended = false;
  this->impl->PerConfig = (perConfig == PerConfig::Yes);

  // Check whether this is a DLL platform.
  this->impl->IsDLLPlatform =
    !this->impl->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")
       .empty();

  // Check whether we are targeting AIX.
  {
    std::string const& systemName =
      this->impl->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME");
    this->impl->IsAIX = (systemName == "AIX" || systemName == "OS400");
  }

  // Check whether we are targeting Apple.
  this->impl->IsApple = this->impl->Makefile->IsOn("APPLE");

  // Check whether we are targeting an Android platform.
  this->impl->IsAndroid = (this->impl->Makefile->GetSafeDefinition(
                             "CMAKE_SYSTEM_NAME") == "Android");

  // Save the backtrace of target construction.
  this->impl->Backtrace = this->impl->Makefile->GetBacktrace();
  if (this->impl->IsImported()) {
    this->impl->FindPackageStack = this->impl->Makefile->GetFindPackageStack();
  }

  if (this->IsNormal()) {
    // Initialize the INCLUDE_DIRECTORIES property based on the current value
    // of the same directory property:
    this->impl->IncludeDirectories.CopyFromEntries(
      this->impl->Makefile->GetIncludeDirectoriesEntries());

    {
      auto const& sysInc = this->impl->Makefile->GetSystemIncludeDirectories();
      this->impl->SystemIncludeDirectories.insert(sysInc.begin(),
                                                  sysInc.end());
    }

    this->impl->CompileOptions.CopyFromEntries(
      this->impl->Makefile->GetCompileOptionsEntries());
    this->impl->LinkOptions.CopyFromEntries(
      this->impl->Makefile->GetLinkOptionsEntries());
    this->impl->LinkDirectories.CopyFromEntries(
      this->impl->Makefile->GetLinkDirectoriesEntries());
  }

  // Record current policies for later use.
  this->impl->Makefile->RecordPolicies(this->impl->PolicyMap);

  std::set<TargetProperty::InitCondition> metConditions;
  metConditions.insert(TargetProperty::InitCondition::Always);
  if (this->CanCompileSources()) {
    metConditions.insert(TargetProperty::InitCondition::CanCompileSources);
  }
  if (this->GetGlobalGenerator()->IsXcode()) {
    metConditions.insert(TargetProperty::InitCondition::NeedsXcode);
    if (this->CanCompileSources()) {
      metConditions.insert(
        TargetProperty::InitCondition::NeedsXcodeAndCanCompileSources);
    }
  }
  if (!this->IsImported()) {
    metConditions.insert(TargetProperty::InitCondition::NonImportedTarget);
  }
  if (this->impl->TargetType != cmStateEnums::UTILITY &&
      this->impl->TargetType != cmStateEnums::GLOBAL_TARGET) {
    metConditions.insert(TargetProperty::InitCondition::NormalTarget);
    if (this->IsNormal()) {
      metConditions.insert(
        TargetProperty::InitCondition::NormalNonImportedTarget);
    }
    if (this->impl->TargetType != cmStateEnums::INTERFACE_LIBRARY) {
      metConditions.insert(TargetProperty::InitCondition::TargetWithArtifact);
      if (this->impl->TargetType != cmStateEnums::EXECUTABLE) {
        metConditions.insert(
          TargetProperty::InitCondition::NonExecutableWithArtifact);
      }
    }
    if (this->impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
        this->impl->TargetType == cmStateEnums::STATIC_LIBRARY) {
      metConditions.insert(
        TargetProperty::InitCondition::LinkableLibraryTarget);
    }
    if (this->impl->TargetType == cmStateEnums::SHARED_LIBRARY) {
      metConditions.insert(TargetProperty::InitCondition::SharedLibraryTarget);
    }
  }
  if (this->impl->TargetType == cmStateEnums::EXECUTABLE) {
    metConditions.insert(TargetProperty::InitCondition::ExecutableTarget);
  }
  if (this->impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
      this->impl->TargetType == cmStateEnums::EXECUTABLE) {
    metConditions.insert(
      TargetProperty::InitCondition::TargetWithSymbolExports);
  }
  if (this->impl->TargetType <= cmStateEnums::GLOBAL_TARGET) {
    metConditions.insert(TargetProperty::InitCondition::TargetWithCommands);
  }

  std::vector<std::string> configNames =
    mf->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig);
  for (auto& config : configNames) {
    config = cmSystemTools::UpperCase(config);
  }

  std::string defKey;
  defKey.reserve(128);
  defKey += "CMAKE_";
  auto initProperty = [this, mf, &defKey](std::string const& property,
                                          char const* default_value) {
    // special init for ENABLE_EXPORTS
    // For SHARED_LIBRARY, only CMAKE_SHARED_LIBRARY_ENABLE_EXPORTS variable
    // is used
    // For EXECUTABLE, CMAKE_EXECUTABLE_ENABLE_EXPORTS or else
    // CMAKE_ENABLE_EXPORTS variables are used
    if (property == "ENABLE_EXPORTS"_s) {
      // Replace everything after "CMAKE_"
      defKey.replace(
        defKey.begin() + 6, defKey.end(),
        cmStrCat(this->impl->TargetType == cmStateEnums::EXECUTABLE
                   ? "EXECUTABLE"
                   : "SHARED_LIBRARY",
                 '_', property));
      if (cmValue value = mf->GetDefinition(defKey)) {
        this->SetProperty(property, value);
        return;
      }
      if (this->impl->TargetType == cmStateEnums::SHARED_LIBRARY) {
        if (default_value) {
          this->SetProperty(property, default_value);
        }
        return;
      }
    }

    // Imported targets must set AIX_SHARED_LIBRARY_ARCHIVE explicitly.
    if (this->IsImported() && property == "AIX_SHARED_LIBRARY_ARCHIVE"_s) {
      return;
    }

    // Replace everything after "CMAKE_"
    defKey.replace(defKey.begin() + 6, defKey.end(), property);
    if (cmValue value = mf->GetDefinition(defKey)) {
      this->SetProperty(property, value);
    } else if (default_value) {
      this->SetProperty(property, default_value);
    }
  };

  std::string dflt_storage;
  for (auto const& tp : StaticTargetProperties) {
    // Ignore properties that we have not met the condition for.
    if (!metConditions.count(tp.InitConditional)) {
      continue;
    }

    char const* dflt = nullptr;
    if (tp.Default) {
      dflt_storage = std::string(*tp.Default);
      dflt = dflt_storage.c_str();
    }

    if (tp.Repeat == TargetProperty::Repetition::Once) {
      initProperty(std::string(tp.Name), dflt);
    } else {
      std::string propertyName;
      for (auto const& configName : configNames) {
        if (tp.Repeat == TargetProperty::Repetition::PerConfig) {
          propertyName = cmStrCat(tp.Name, configName);
        } else if (tp.Repeat == TargetProperty::Repetition::PerConfigPrefix) {
          propertyName = cmStrCat(configName, tp.Name);
        }
        initProperty(propertyName, dflt);
      }
    }
  }

  // Clean up some property defaults.
  if (this->impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
      this->impl->TargetType == cmStateEnums::MODULE_LIBRARY) {
    this->SetProperty("POSITION_INDEPENDENT_CODE", "True");
  }

  // check for "CMAKE_VS_GLOBALS" variable and set up target properties
  // if any
  cmValue globals = mf->GetDefinition("CMAKE_VS_GLOBALS");
  if (globals) {
    std::string const genName = mf->GetGlobalGenerator()->GetName();
    if (cmHasLiteralPrefix(genName, "Visual Studio")) {
      cmList props{ *globals };
      std::string const vsGlobal = "VS_GLOBAL_";
      for (std::string const& i : props) {
        // split NAME=VALUE
        std::string::size_type const assignment = i.find('=');
        if (assignment != std::string::npos) {
          std::string const propName = vsGlobal + i.substr(0, assignment);
          std::string const propValue = i.substr(assignment + 1);
          initProperty(propName, propValue.c_str());
        }
      }
    }
  }

  if (!this->IsNormal() || mf->GetPropertyAsBool("SYSTEM")) {
    this->SetProperty("SYSTEM", "ON");
  }

  for (auto const& prop : mf->GetState()->GetPropertyDefinitions().GetMap()) {
    auto iter = prop.second.find(cmProperty::TARGET);
    if (iter != prop.second.end()) {
      if (!iter->second.GetInitializeFromVariable().empty()) {
        if (auto value =
              mf->GetDefinition(iter->second.GetInitializeFromVariable())) {
          this->SetProperty(prop.first, value);
        }
      }
    }
  }
}

cmTarget::cmTarget(cmTarget&&) noexcept = default;
cmTarget::~cmTarget() = default;

cmTarget& cmTarget::operator=(cmTarget&&) noexcept = default;

cmStateEnums::TargetType cmTarget::GetType() const
{
  return this->impl->TargetType;
}

void cmTarget::SetOrigin(Origin origin)
{
  assert(origin != cmTarget::Origin::Unknown);
  assert(this->impl->Origin == cmTarget::Origin::Unknown);
  this->impl->Origin = origin;
}

cmTarget::Origin cmTarget::GetOrigin() const
{
  return this->impl->Origin;
}

cmMakefile* cmTarget::GetMakefile() const
{
  return this->impl->Makefile;
}

cmPolicies::PolicyMap const& cmTarget::GetPolicyMap() const
{
  return this->impl->PolicyMap;
}

std::string const& cmTarget::GetName() const
{
  return this->impl->Name;
}

std::string const& cmTarget::GetTemplateName() const
{
  if (this->impl->TemplateTarget) {
    return this->impl->TemplateTarget->GetTemplateName();
  }
  return this->impl->Name;
}

cmPolicies::PolicyStatus cmTarget::GetPolicyStatus(
  cmPolicies::PolicyID policy) const
{
  return this->impl->PolicyMap.Get(policy);
}

cmGlobalGenerator* cmTarget::GetGlobalGenerator() const
{
  return this->impl->Makefile->GetGlobalGenerator();
}

BTs<std::string> const* cmTarget::GetLanguageStandardProperty(
  std::string const& propertyName) const
{
  auto entry = this->impl->LanguageStandardProperties.find(propertyName);
  if (entry != this->impl->LanguageStandardProperties.end()) {
    return &entry->second;
  }

  return nullptr;
}

void cmTarget::SetLanguageStandardProperty(std::string const& lang,
                                           std::string const& value,
                                           std::string const& feature)
{
  cmListFileBacktrace featureBacktrace;
  for (auto const& entry : this->impl->CompileFeatures.Entries) {
    if (entry.Value == feature) {
      featureBacktrace = entry.Backtrace;
      break;
    }
  }

  BTs<std::string>& languageStandardProperty =
    this->impl->LanguageStandardProperties[cmStrCat(lang, "_STANDARD")];
  if (languageStandardProperty.Value != value) {
    languageStandardProperty.Value = value;
    languageStandardProperty.Backtraces.clear();
  }
  languageStandardProperty.Backtraces.emplace_back(featureBacktrace);
}

void cmTarget::AddUtility(std::string const& name, bool cross,
                          cmMakefile const* mf)
{
  this->impl->Utilities.insert(BT<std::pair<std::string, bool>>(
    { name, cross }, mf ? mf->GetBacktrace() : cmListFileBacktrace()));
}

void cmTarget::AddUtility(BT<std::pair<std::string, bool>> util)
{
  this->impl->Utilities.emplace(std::move(util));
}

void cmTarget::AddCodegenDependency(std::string const& name)
{
  this->impl->CodegenDependencies.emplace(name);
}

std::set<std::string> const& cmTarget::GetCodegenDeps() const
{
  return this->impl->CodegenDependencies;
}

std::set<BT<std::pair<std::string, bool>>> const& cmTarget::GetUtilities()
  const
{
  return this->impl->Utilities;
}

cmListFileBacktrace const& cmTarget::GetBacktrace() const
{
  return this->impl->Backtrace;
}

cmFindPackageStack const& cmTarget::GetFindPackageStack() const
{
  return this->impl->FindPackageStack;
}

bool cmTarget::IsExecutableWithExports() const
{
  return (this->GetType() == cmStateEnums::EXECUTABLE &&
          this->GetPropertyAsBool("ENABLE_EXPORTS"));
}

bool cmTarget::IsSharedLibraryWithExports() const
{
  return (this->GetType() == cmStateEnums::SHARED_LIBRARY &&
          this->GetPropertyAsBool("ENABLE_EXPORTS"));
}

bool cmTarget::IsFrameworkOnApple() const
{
  return ((this->GetType() == cmStateEnums::SHARED_LIBRARY ||
           this->GetType() == cmStateEnums::STATIC_LIBRARY) &&
          this->IsApple() && this->GetPropertyAsBool("FRAMEWORK"));
}

bool cmTarget::IsArchivedAIXSharedLibrary() const
{
  if (this->GetType() == cmStateEnums::SHARED_LIBRARY && this->IsAIX()) {
    cmValue value = this->GetProperty("AIX_SHARED_LIBRARY_ARCHIVE");
    if (!value.IsEmpty()) {
      return value.IsOn();
    }
    if (this->IsImported()) {
      return false;
    }
    switch (this->GetPolicyStatusCMP0182()) {
      case cmPolicies::WARN:
      case cmPolicies::OLD:
        // The OLD behavior's default is to disable shared library archives.
        break;
      case cmPolicies::NEW:
        // The NEW behavior's default is to enable shared library archives.
        return true;
    }
  }
  return false;
}

bool cmTarget::IsAppBundleOnApple() const
{
  return (this->GetType() == cmStateEnums::EXECUTABLE && this->IsApple() &&
          this->GetPropertyAsBool("MACOSX_BUNDLE"));
}

bool cmTarget::IsAndroidGuiExecutable() const
{
  return (this->GetType() == cmStateEnums::EXECUTABLE &&
          this->impl->IsAndroid && this->GetPropertyAsBool("ANDROID_GUI"));
}

bool cmTarget::HasKnownObjectFileLocation(std::string* reason) const
{
  return this->GetGlobalGenerator()->HasKnownObjectFileLocation(*this, reason);
}

std::vector<cmCustomCommand> const& cmTarget::GetPreBuildCommands() const
{
  return this->impl->PreBuildCommands;
}

void cmTarget::AddPreBuildCommand(cmCustomCommand const& cmd)
{
  this->impl->PreBuildCommands.push_back(cmd);
}

void cmTarget::AddPreBuildCommand(cmCustomCommand&& cmd)
{
  this->impl->PreBuildCommands.push_back(std::move(cmd));
}

std::vector<cmCustomCommand> const& cmTarget::GetPreLinkCommands() const
{
  return this->impl->PreLinkCommands;
}

void cmTarget::AddPreLinkCommand(cmCustomCommand const& cmd)
{
  this->impl->PreLinkCommands.push_back(cmd);
}

void cmTarget::AddPreLinkCommand(cmCustomCommand&& cmd)
{
  this->impl->PreLinkCommands.push_back(std::move(cmd));
}

std::vector<cmCustomCommand> const& cmTarget::GetPostBuildCommands() const
{
  return this->impl->PostBuildCommands;
}

void cmTarget::AddPostBuildCommand(cmCustomCommand const& cmd)
{
  this->impl->PostBuildCommands.push_back(cmd);
}

void cmTarget::AddPostBuildCommand(cmCustomCommand&& cmd)
{
  this->impl->PostBuildCommands.push_back(std::move(cmd));
}

void cmTarget::AddTracedSources(std::vector<std::string> const& srcs)
{
  if (!srcs.empty()) {
    this->impl->Sources.WriteDirect(this->impl.get(), {},
                                    cmValue(cmJoin(srcs, ";")),
                                    UsageRequirementProperty::Action::Append);
  }
}

void cmTarget::AddSources(std::vector<std::string> const& srcs)
{
  std::vector<std::string> srcFiles;
  for (std::string const& filename : srcs) {
    if (!cmGeneratorExpression::StartsWithGeneratorExpression(filename)) {
      this->impl->Makefile->GetOrCreateSource(filename);
    }
    srcFiles.emplace_back(filename);
  }
  this->AddTracedSources(srcFiles);
}

struct CreateLocation
{
  cmMakefile const* Makefile;

  CreateLocation(cmMakefile const* mf)
    : Makefile(mf)
  {
  }

  cmSourceFileLocation operator()(std::string const& filename) const
  {
    return cmSourceFileLocation(this->Makefile, filename);
  }
};

struct LocationMatcher
{
  cmSourceFileLocation const& Needle;

  LocationMatcher(cmSourceFileLocation const& needle)
    : Needle(needle)
  {
  }

  bool operator()(cmSourceFileLocation& loc)
  {
    return loc.Matches(this->Needle);
  }
};

struct TargetPropertyEntryFinder
{
private:
  cmSourceFileLocation const& Needle;

public:
  TargetPropertyEntryFinder(cmSourceFileLocation const& needle)
    : Needle(needle)
  {
  }

  bool operator()(BT<std::string> const& entry)
  {
    cmList files{ entry.Value };
    std::vector<cmSourceFileLocation> locations;
    locations.reserve(files.size());
    std::transform(files.begin(), files.end(), std::back_inserter(locations),
                   CreateLocation(this->Needle.GetMakefile()));

    return std::find_if(locations.begin(), locations.end(),
                        LocationMatcher(this->Needle)) != locations.end();
  }
};

cmSourceFile* cmTarget::AddSource(std::string const& src, bool before)
{
  cmSourceFileLocation sfl(this->impl->Makefile, src,
                           cmSourceFileLocationKind::Known);
  auto const& sources = this->impl->Sources.Entries;
  if (std::find_if(sources.begin(), sources.end(),
                   TargetPropertyEntryFinder(sfl)) == sources.end()) {
    this->impl->Sources.WriteDirect(
      this->impl.get(), {}, cmValue(src),
      before ? UsageRequirementProperty::Action::Prepend
             : UsageRequirementProperty::Action::Append);
  }
  if (cmGeneratorExpression::Find(src) != std::string::npos) {
    return nullptr;
  }
  return this->impl->Makefile->GetOrCreateSource(
    src, false, cmSourceFileLocationKind::Known);
}

void cmTarget::ClearDependencyInformation(cmMakefile& mf) const
{
  std::string depname = cmStrCat(this->GetName(), "_LIB_DEPENDS");
  mf.RemoveCacheDefinition(depname);
}

std::string cmTarget::GetDebugGeneratorExpressions(
  std::string const& value, cmTargetLinkLibraryType llt) const
{
  if (llt == GENERAL_LibraryType) {
    return value;
  }

  // Get the list of configurations considered to be DEBUG.
  std::vector<std::string> debugConfigs =
    this->impl->Makefile->GetCMakeInstance()->GetDebugConfigs();

  std::string configString = "$<CONFIG:" + debugConfigs[0] + ">";

  if (debugConfigs.size() > 1) {
    for (std::string const& conf : cmMakeRange(debugConfigs).advance(1)) {
      configString += ",$<CONFIG:" + conf + ">";
    }
    configString = "$<OR:" + configString + ">";
  }

  if (llt == OPTIMIZED_LibraryType) {
    configString = "$<NOT:" + configString + ">";
  }
  return "$<" + configString + ":" + value + ">";
}

static std::string targetNameGenex(std::string const& lib)
{
  return "$<TARGET_NAME:" + lib + ">";
}

bool cmTarget::PushTLLCommandTrace(TLLSignature signature,
                                   cmListFileContext const& lfc)
{
  bool ret = true;
  if (!this->impl->TLLCommands.empty()) {
    if (this->impl->TLLCommands.back().first != signature) {
      ret = false;
    }
  }
  if (this->impl->TLLCommands.empty() ||
      this->impl->TLLCommands.back().second != lfc) {
    this->impl->TLLCommands.emplace_back(signature, lfc);
  }
  return ret;
}

void cmTarget::GetTllSignatureTraces(std::ostream& s, TLLSignature sig) const
{
  char const* sigString =
    (sig == cmTarget::KeywordTLLSignature ? "keyword" : "plain");
  s << "The uses of the " << sigString << " signature are here:\n";
  for (auto const& cmd : this->impl->TLLCommands) {
    if (cmd.first == sig) {
      cmListFileContext lfc = cmd.second;
      lfc.FilePath = cmSystemTools::RelativeIfUnder(
        this->impl->Makefile->GetState()->GetSourceDirectory(), lfc.FilePath);
      s << " * " << lfc << '\n';
    }
  }
}

std::string const& cmTarget::GetInstallPath() const
{
  return this->impl->InstallPath;
}

void cmTarget::SetInstallPath(std::string const& name)
{
  this->impl->InstallPath = name;
}

std::string const& cmTarget::GetRuntimeInstallPath() const
{
  return this->impl->RuntimeInstallPath;
}

void cmTarget::SetRuntimeInstallPath(std::string const& name)
{
  this->impl->RuntimeInstallPath = name;
}

bool cmTarget::GetHaveInstallRule() const
{
  return this->impl->HaveInstallRule;
}

void cmTarget::SetHaveInstallRule(bool hir)
{
  this->impl->HaveInstallRule = hir;
}

void cmTarget::AddInstallGenerator(cmInstallTargetGenerator* g)
{
  this->impl->InstallGenerators.emplace_back(g);
}

std::vector<cmInstallTargetGenerator*> const& cmTarget::GetInstallGenerators()
  const
{
  return this->impl->InstallGenerators;
}

bool cmTarget::GetIsGeneratorProvided() const
{
  return this->impl->IsGeneratorProvided;
}

void cmTarget::SetIsGeneratorProvided(bool igp)
{
  this->impl->IsGeneratorProvided = igp;
}

cmTarget::LinkLibraryVectorType const& cmTarget::GetOriginalLinkLibraries()
  const
{
  return this->impl->OriginalLinkLibraries;
}

void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib,
                              cmTargetLinkLibraryType llt)
{
  cmTarget* tgt = mf.FindTargetToUse(lib);
  {
    bool const isNonImportedTarget = tgt && !tgt->IsImported();

    std::string const libName =
      (isNonImportedTarget && llt != GENERAL_LibraryType)
      ? targetNameGenex(lib)
      : lib;
    this->AppendProperty("LINK_LIBRARIES",
                         this->GetDebugGeneratorExpressions(libName, llt),
                         mf.GetBacktrace());
  }

  if (cmGeneratorExpression::Find(lib) != std::string::npos ||
      (tgt &&
       (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
        tgt->GetType() == cmStateEnums::OBJECT_LIBRARY)) ||
      (this->impl->Name == lib)) {
    return;
  }

  this->impl->OriginalLinkLibraries.emplace_back(lib, llt);

  // Add the explicit dependency information for libraries. This is
  // simply a set of libraries separated by ";". There should always
  // be a trailing ";". These library names are not canonical, in that
  // they may be "-framework x", "-ly", "/path/libz.a", etc.
  // We shouldn't remove duplicates here because external libraries
  // may be purposefully duplicated to handle recursive dependencies,
  // and we removing one instance will break the link line. Duplicates
  // will be appropriately eliminated at emit time.
  if (this->impl->TargetType >= cmStateEnums::STATIC_LIBRARY &&
      this->impl->TargetType <= cmStateEnums::MODULE_LIBRARY &&
      (this->GetPolicyStatusCMP0073() == cmPolicies::OLD ||
       this->GetPolicyStatusCMP0073() == cmPolicies::WARN)) {
    std::string targetEntry = cmStrCat(this->impl->Name, "_LIB_DEPENDS");
    std::string dependencies;
    cmValue old_val = mf.GetDefinition(targetEntry);
    if (old_val) {
      dependencies += *old_val;
    }
    switch (llt) {
      case GENERAL_LibraryType:
        dependencies += "general";
        break;
      case DEBUG_LibraryType:
        dependencies += "debug";
        break;
      case OPTIMIZED_LibraryType:
        dependencies += "optimized";
        break;
    }
    dependencies += ";";
    dependencies += lib;
    dependencies += ";";
    mf.AddCacheDefinition(targetEntry, dependencies,
                          "Dependencies for the target", cmStateEnums::STATIC);
  }
}

void cmTarget::AddSystemIncludeDirectories(std::set<std::string> const& incs)
{
  this->impl->SystemIncludeDirectories.insert(incs.begin(), incs.end());
}

std::set<std::string> const& cmTarget::GetSystemIncludeDirectories() const
{
  return this->impl->SystemIncludeDirectories;
}

void cmTarget::AddInstallIncludeDirectories(cmTargetExport const& te,
                                            cmStringRange incs)
{
  std::copy(
    incs.begin(), incs.end(),
    std::back_inserter(this->impl->InstallIncludeDirectoriesEntries[&te]));
}

cmStringRange cmTarget::GetInstallIncludeDirectoriesEntries(
  cmTargetExport const& te) const
{
  auto i = this->impl->InstallIncludeDirectoriesEntries.find(&te);
  if (i == this->impl->InstallIncludeDirectoriesEntries.end()) {
    decltype(i->second) empty;
    return cmMakeRange(empty);
  }
  return cmMakeRange(i->second);
}

cmBTStringRange cmTarget::GetIncludeDirectoriesEntries() const
{
  return cmMakeRange(this->impl->IncludeDirectories.Entries);
}

cmBTStringRange cmTarget::GetCompileOptionsEntries() const
{
  return cmMakeRange(this->impl->CompileOptions.Entries);
}

cmBTStringRange cmTarget::GetCompileFeaturesEntries() const
{
  return cmMakeRange(this->impl->CompileFeatures.Entries);
}

cmBTStringRange cmTarget::GetCompileDefinitionsEntries() const
{
  return cmMakeRange(this->impl->CompileDefinitions.Entries);
}

cmBTStringRange cmTarget::GetPrecompileHeadersEntries() const
{
  return cmMakeRange(this->impl->PrecompileHeaders.Entries);
}

cmBTStringRange cmTarget::GetSourceEntries() const
{
  return cmMakeRange(this->impl->Sources.Entries);
}

cmBTStringRange cmTarget::GetLinkOptionsEntries() const
{
  return cmMakeRange(this->impl->LinkOptions.Entries);
}

cmBTStringRange cmTarget::GetLinkDirectoriesEntries() const
{
  return cmMakeRange(this->impl->LinkDirectories.Entries);
}

cmBTStringRange cmTarget::GetLinkImplementationEntries() const
{
  return cmMakeRange(this->impl->LinkLibraries.Entries);
}

cmBTStringRange cmTarget::GetLinkInterfaceEntries() const
{
  return cmMakeRange(this->impl->InterfaceLinkLibraries.Entries);
}

cmBTStringRange cmTarget::GetLinkInterfaceDirectEntries() const
{
  return cmMakeRange(this->impl->InterfaceLinkLibrariesDirect.Entries);
}

cmBTStringRange cmTarget::GetLinkInterfaceDirectExcludeEntries() const
{
  return cmMakeRange(this->impl->InterfaceLinkLibrariesDirectExclude.Entries);
}

void cmTarget::CopyPolicyStatuses(cmTarget const* tgt)
{
  // Normal targets cannot be the target of a copy.
  assert(!this->IsNormal());
  // Imported targets cannot be the target of a copy.
  assert(!this->IsImported());

  // Only imported or normal targets can be the source of a copy.
  assert(tgt->IsImported() || tgt->IsNormal());

  this->impl->PolicyMap = tgt->impl->PolicyMap;
  this->impl->TemplateTarget = tgt;
}

void cmTarget::CopyCxxModulesEntries(cmTarget const* tgt)
{
  // Normal targets cannot be the target of a copy.
  assert(!this->IsNormal());
  // Imported targets cannot be the target of a copy.
  assert(!this->IsImported());
  // Only imported or normal targets can be the source of a copy.
  assert(tgt->IsImported() || tgt->IsNormal());

  this->impl->IncludeDirectories.Entries.clear();
  this->impl->CompileDefinitions.Entries.clear();
  this->impl->CompileFeatures.Entries.clear();
  this->impl->CompileOptions.Entries.clear();
  this->impl->LinkLibraries.Entries.clear();

  if (tgt->IsImported()) {
    this->impl->IncludeDirectories.CopyFromEntries(
      cmMakeRange(tgt->impl->ImportedCxxModulesIncludeDirectories.Entries));
    this->impl->CompileDefinitions.CopyFromEntries(
      cmMakeRange(tgt->impl->ImportedCxxModulesCompileDefinitions.Entries));
    this->impl->CompileFeatures.CopyFromEntries(
      cmMakeRange(tgt->impl->ImportedCxxModulesCompileFeatures.Entries));
    this->impl->CompileOptions.CopyFromEntries(
      cmMakeRange(tgt->impl->ImportedCxxModulesCompileOptions.Entries));
    this->impl->LinkLibraries.CopyFromEntries(
      cmMakeRange(tgt->impl->ImportedCxxModulesLinkLibraries.Entries));
  } else {
    this->impl->IncludeDirectories.CopyFromEntries(
      cmMakeRange(tgt->impl->IncludeDirectories.Entries));
    this->impl->CompileDefinitions.CopyFromEntries(
      cmMakeRange(tgt->impl->CompileDefinitions.Entries));
    this->impl->CompileFeatures.CopyFromEntries(
      cmMakeRange(tgt->impl->CompileFeatures.Entries));
    this->impl->CompileOptions.CopyFromEntries(
      cmMakeRange(tgt->impl->CompileOptions.Entries));
    this->impl->LinkLibraries.CopyFromEntries(
      cmMakeRange(tgt->impl->LinkLibraries.Entries));
  }

  // Copy the C++ module fileset entries from `tgt`'s `INTERFACE` to this
  // target's `PRIVATE`.
  auto& entries = this->impl->FileSetTypes.at(cm::FileSetMetadata::CXX_MODULES)
                    .SelfEntries.Entries;
  entries.clear();
  entries = tgt->impl->FileSetTypes.at(cm::FileSetMetadata::CXX_MODULES)
              .InterfaceEntries.Entries;
}

void cmTarget::CopyCxxModulesProperties(cmTarget const* tgt)
{
  // Normal targets cannot be the target of a copy.
  assert(!this->IsNormal());
  // Imported targets cannot be the target of a copy.
  assert(!this->IsImported());
  // Only imported or normal targets can be the source of a copy.
  assert(tgt->IsImported() || tgt->IsNormal());

  // The list of properties that are relevant here include:
  // - compilation-specific properties for any language or platform
  // - compilation-specific properties for C++
  // - build graph-specific properties that affect compilation
  // - IDE metadata properties
  // - static analysis properties

  static std::string const propertiesToCopy[] = {
    // Compilation properties
    "DEFINE_SYMBOL",
    "DEPRECATION",
    "NO_SYSTEM_FROM_IMPORTED",
    "POSITION_INDEPENDENT_CODE",
    "VISIBILITY_INLINES_HIDDEN",
    // -- Platforms
    // ---- Android
    "ANDROID_API",
    "ANDROID_API_MIN",
    "ANDROID_ARCH",
    "ANDROID_STL_TYPE",
    // ---- macOS
    "OSX_ARCHITECTURES",
    // ---- Windows
    "MSVC_DEBUG_INFORMATION_FORMAT",
    "MSVC_RUNTIME_CHECKS",
    "MSVC_RUNTIME_LIBRARY",
    "VS_PLATFORM_TOOLSET",
    // ---- OpenWatcom
    "WATCOM_RUNTIME_LIBRARY",
    // -- Language
    // ---- C++
    "CXX_COMPILER_LAUNCHER",
    "CXX_STANDARD",
    "CXX_STANDARD_REQUIRED",
    "CXX_EXTENSIONS",
    "CXX_VISIBILITY_PRESET",
    "CXX_MODULE_STD",

    // Static analysis
    "CXX_CLANG_TIDY",
    "CXX_CLANG_TIDY_EXPORT_FIXES_DIR",
    "CXX_CPPLINT",
    "CXX_CPPCHECK",
    "CXX_ICSTAT",
    "CXX_INCLUDE_WHAT_YOU_USE",
    "CXX_PVS_STUDIO",
    "SKIP_LINTING",

    // Build graph properties
    "EXCLUDE_FROM_ALL",
    "EXCLUDE_FROM_DEFAULT_BUILD",
    "OPTIMIZE_DEPENDENCIES",
    // -- Ninja
    "JOB_POOL_COMPILE",
    // -- Visual Studio
    "VS_NO_COMPILE_BATCHING",
    "VS_PROJECT_IMPORT",

    // Metadata
    "EchoString",
    "EXPORT_COMPILE_COMMANDS",
    // Do *not* copy this property; it should be re-initialized at synthesis
    // time from the `CMAKE_EXPORT_BUILD_DATABASE` variable as `IMPORTED`
    // targets ignore the property initialization.
    // "EXPORT_BUILD_DATABASE",
    "FOLDER",
    "LABELS",
    "PROJECT_LABEL",
    "SYSTEM",
  };

  auto copyProperty = [this, tgt](std::string const& prop) -> cmValue {
    cmValue value = tgt->GetProperty(prop);
    // Always set the property; it may have been explicitly unset.
    this->SetProperty(prop, value);
    return value;
  };

  for (auto const& prop : propertiesToCopy) {
    copyProperty(prop);
  }

  static cm::static_string_view const perConfigPropertiesToCopy[] = {
    "EXCLUDE_FROM_DEFAULT_BUILD_"_s,
    "IMPORTED_CXX_MODULES_"_s,
    "MAP_IMPORTED_CONFIG_"_s,
    "OSX_ARCHITECTURES_"_s,
  };

  std::vector<std::string> configNames =
    this->impl->Makefile->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig);
  for (std::string const& configName : configNames) {
    std::string configUpper = cmSystemTools::UpperCase(configName);
    for (auto const& perConfigProp : perConfigPropertiesToCopy) {
      copyProperty(cmStrCat(perConfigProp, configUpper));
    }
  }

  if (this->GetGlobalGenerator()->IsXcode()) {
    cmValue xcodeGenerateScheme = copyProperty("XCODE_GENERATE_SCHEME");

    // TODO: Make sure these show up on the imported target in the first place
    // XCODE_ATTRIBUTE_???

    if (xcodeGenerateScheme.IsOn()) {
#ifdef __APPLE__
      static std::string const xcodeSchemePropertiesToCopy[] = {
        // FIXME: Do all of these apply? Do they matter?
        "XCODE_SCHEME_ADDRESS_SANITIZER",
        "XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN",
        "XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER",
        "XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS",
        "XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE",
        "XCODE_SCHEME_ENABLE_GPU_API_VALIDATION",
        "XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION",
        "XCODE_SCHEME_GUARD_MALLOC",
        "XCODE_SCHEME_LAUNCH_CONFIGURATION",
        "XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP",
        "XCODE_SCHEME_MALLOC_GUARD_EDGES",
        "XCODE_SCHEME_MALLOC_SCRIBBLE",
        "XCODE_SCHEME_MALLOC_STACK",
        "XCODE_SCHEME_THREAD_SANITIZER",
        "XCODE_SCHEME_THREAD_SANITIZER_STOP",
        "XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER",
        "XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP",
        "XCODE_SCHEME_ZOMBIE_OBJECTS",
      };

      for (auto const& xcodeProperty : xcodeSchemePropertiesToCopy) {
        copyProperty(xcodeProperty);
      }
#endif
    }
  }
}

namespace {
std::vector<BT<std::string>> EmptyEntries;
}

cmBTStringRange cmTarget::GetFileSetsEntries(cm::string_view type) const
{
  if (cm::contains(this->impl->FileSetTypes, type)) {
    return cmMakeRange(this->impl->FileSetTypes.at(type).SelfEntries.Entries);
  }
  return cmMakeRange(EmptyEntries);
}

cmBTStringRange cmTarget::GetInterfaceFileSetsEntries(
  cm::string_view type) const
{
  if (cm::contains(this->impl->FileSetTypes, type)) {
    return cmMakeRange(
      this->impl->FileSetTypes.at(type).InterfaceEntries.Entries);
  }
  return cmMakeRange(EmptyEntries);
}

namespace {
#define MAKE_PROP(PROP) const std::string prop##PROP = #PROP
MAKE_PROP(C_STANDARD);
MAKE_PROP(CXX_STANDARD);
MAKE_PROP(CUDA_STANDARD);
MAKE_PROP(HIP_STANDARD);
MAKE_PROP(OBJC_STANDARD);
MAKE_PROP(OBJCXX_STANDARD);
MAKE_PROP(COMPILE_DEFINITIONS);
MAKE_PROP(COMPILE_FEATURES);
MAKE_PROP(COMPILE_OPTIONS);
MAKE_PROP(PRECOMPILE_HEADERS);
MAKE_PROP(CUDA_CUBIN_COMPILATION);
MAKE_PROP(CUDA_FATBIN_COMPILATION);
MAKE_PROP(CUDA_OPTIX_COMPILATION);
MAKE_PROP(CUDA_PTX_COMPILATION);
MAKE_PROP(IMPORTED);
MAKE_PROP(IMPORTED_GLOBAL);
MAKE_PROP(INCLUDE_DIRECTORIES);
MAKE_PROP(LINK_OPTIONS);
MAKE_PROP(IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES);
MAKE_PROP(IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS);
MAKE_PROP(IMPORTED_CXX_MODULES_COMPILE_FEATURES);
MAKE_PROP(IMPORTED_CXX_MODULES_COMPILE_OPTIONS);
MAKE_PROP(IMPORTED_CXX_MODULES_LINK_LIBRARIES);
MAKE_PROP(LINK_DIRECTORIES);
MAKE_PROP(LINK_LIBRARIES);
MAKE_PROP(MANUALLY_ADDED_DEPENDENCIES);
MAKE_PROP(NAME);
MAKE_PROP(SOURCES);
MAKE_PROP(SYMBOLIC);
MAKE_PROP(TYPE);
MAKE_PROP(BINARY_DIR);
MAKE_PROP(SOURCE_DIR);
MAKE_PROP(FALSE);
MAKE_PROP(TRUE);
MAKE_PROP(INTERFACE_LINK_LIBRARIES);
MAKE_PROP(INTERFACE_LINK_LIBRARIES_DIRECT);
MAKE_PROP(INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE);
#undef MAKE_PROP
}

namespace {

enum class ReadOnlyCondition
{
  All,
  Imported,
  NonImported,
};

struct ReadOnlyProperty
{
  ReadOnlyProperty(ReadOnlyCondition cond)
    : Condition{ cond }
  {
  }
  ReadOnlyProperty(ReadOnlyCondition cond, cmPolicies::PolicyID id)
    : Condition{ cond }
    , Policy{ id }
  {
  }

  ReadOnlyCondition Condition;
  cm::optional<cmPolicies::PolicyID> Policy;

  std::string message(std::string const& prop, cmTarget* target) const
  {
    std::string msg;
    if (this->Condition == ReadOnlyCondition::All) {
      msg = " property is read-only for target(\"";
    } else if (this->Condition == ReadOnlyCondition::Imported) {
      msg = " property can't be set on imported targets(\"";
    } else if (this->Condition == ReadOnlyCondition::NonImported) {
      msg = " property can't be set on non-imported targets(\"";
    }
    return cmStrCat(prop, msg, target->GetName(), "\")\n");
  }

  bool isReadOnly(std::string const& prop, cmMakefile* context,
                  cmTarget* target) const
  {
    auto importedTarget = target->IsImported();
    bool matchingCondition = true;
    if ((!importedTarget && this->Condition == ReadOnlyCondition::Imported) ||
        (importedTarget &&
         this->Condition == ReadOnlyCondition::NonImported)) {
      matchingCondition = false;
    }
    if (!matchingCondition) {
      // Not read-only in this scenario
      return false;
    }

    bool readOnly = true;
    if (!this->Policy) {
      // No policy associated, so is always read-only
      context->IssueMessage(MessageType::FATAL_ERROR,
                            this->message(prop, target));
    } else {
      switch (target->GetPolicyStatus(*this->Policy)) {
        case cmPolicies::WARN:
          context->IssueDiagnostic(
            cmDiagnostics::CMD_AUTHOR,
            cmPolicies::GetPolicyWarning(cmPolicies::CMP0160) + "\n" +
              this->message(prop, target));
          CM_FALLTHROUGH;
        case cmPolicies::OLD:
          readOnly = false;
          break;
        case cmPolicies::NEW:
          context->IssueMessage(MessageType::FATAL_ERROR,
                                this->message(prop, target));
          break;
      }
    }
    return readOnly;
  }
};

bool IsSettableProperty(cmMakefile* context, cmTarget* target,
                        std::string const& prop)
{
  using ROC = ReadOnlyCondition;
  static std::unordered_map<std::string, ReadOnlyProperty> const readOnlyProps{
    { "EXPORT_NAME", { ROC::Imported } },
    { "HEADER_SETS", { ROC::All } },
    { "IMPORTED_GLOBAL", { ROC::NonImported } },
    { "INTERFACE_HEADER_SETS", { ROC::All } },
    { "MANUALLY_ADDED_DEPENDENCIES", { ROC::All } },
    { "NAME", { ROC::All } },
    { "SOURCES", { ROC::Imported } },
    { "SYMBOLIC", { ROC::All } },
    { "TYPE", { ROC::All } },
    { "ALIAS_GLOBAL", { ROC::All, cmPolicies::CMP0160 } },
    { "BINARY_DIR", { ROC::All, cmPolicies::CMP0160 } },
    { "CXX_MODULE_SETS", { ROC::All, cmPolicies::CMP0160 } },
    { "IMPORTED", { ROC::All, cmPolicies::CMP0160 } },
    { "INTERFACE_CXX_MODULE_SETS", { ROC::All, cmPolicies::CMP0160 } },
    { "LOCATION", { ROC::All, cmPolicies::CMP0160 } },
    { "LOCATION_CONFIG", { ROC::All, cmPolicies::CMP0160 } },
    { "SOURCE_DIR", { ROC::All, cmPolicies::CMP0160 } }
  };

  auto it = readOnlyProps.find(prop);

  if (it != readOnlyProps.end()) {
    return !(it->second.isReadOnly(prop, context, target));
  }
  return true;
}
}

void cmTarget::SetSymbolic(bool const value)
{
  this->impl->IsSymbolic = value;
}

void cmTarget::SetProperty(std::string const& prop, cmValue value)
{
  if (!IsSettableProperty(this->impl->Makefile, this, prop)) {
    return;
  }

  UsageRequirementProperty* usageRequirements[] = {
    &this->impl->IncludeDirectories,
    &this->impl->CompileOptions,
    &this->impl->CompileFeatures,
    &this->impl->CompileDefinitions,
    &this->impl->PrecompileHeaders,
    &this->impl->Sources,
    &this->impl->LinkOptions,
    &this->impl->LinkDirectories,
    &this->impl->LinkLibraries,
    &this->impl->InterfaceLinkLibraries,
    &this->impl->InterfaceLinkLibrariesDirect,
    &this->impl->InterfaceLinkLibrariesDirectExclude,
    &this->impl->ImportedCxxModulesIncludeDirectories,
    &this->impl->ImportedCxxModulesCompileDefinitions,
    &this->impl->ImportedCxxModulesCompileFeatures,
    &this->impl->ImportedCxxModulesCompileOptions,
    &this->impl->ImportedCxxModulesLinkLibraries,
  };

  for (auto* usageRequirement : usageRequirements) {
    if (usageRequirement->Write(this->impl.get(), {}, prop, value,
                                UsageRequirementProperty::Action::Set)) {
      return;
    }
  }

  for (auto& fileSetType : this->impl->FileSetTypes) {
    if (fileSetType.second.WriteProperties(this, this->impl.get(), prop, value,
                                           FileSetType::Action::Set)) {
      return;
    }
  }

  if (prop == propIMPORTED_GLOBAL) {
    if (!value.IsOn()) {
      std::ostringstream e;
      e << "IMPORTED_GLOBAL property can't be set to FALSE on targets (\""
        << this->impl->Name << "\")\n";
      this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
      return;
    }
    /* no need to change anything if value does not change */
    if (!this->IsImportedGloballyVisible()) {
      this->impl->TargetVisibility = Visibility::ImportedGlobally;
      this->GetGlobalGenerator()->IndexTarget(this);
    }
  } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME") &&
             !this->impl->CheckImportedLibName(
               prop,
               value ? value
                     : std::string{})) { // NOLINT(bugprone-branch-clone)
    /* error was reported by check method */
  } else if (prop == propCUDA_CUBIN_COMPILATION ||
             prop == propCUDA_FATBIN_COMPILATION ||
             prop == propCUDA_OPTIX_COMPILATION ||
             prop == propCUDA_PTX_COMPILATION) {
    auto const& compiler =
      this->impl->Makefile->GetSafeDefinition("CMAKE_CUDA_COMPILER_ID");
    auto const& compilerVersion =
      this->impl->Makefile->GetSafeDefinition("CMAKE_CUDA_COMPILER_VERSION");
    if (this->GetType() != cmStateEnums::OBJECT_LIBRARY) {
      auto e =
        cmStrCat(prop, " property can only be applied to OBJECT targets(",
                 this->impl->Name, ")\n");
      this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e);
      return;
    }
    bool const flag_found =
      (prop == propCUDA_PTX_COMPILATION &&
       this->impl->Makefile->GetDefinition("_CMAKE_CUDA_PTX_FLAG")) ||
      (prop == propCUDA_CUBIN_COMPILATION &&
       this->impl->Makefile->GetDefinition("_CMAKE_CUDA_CUBIN_FLAG")) ||
      (prop == propCUDA_FATBIN_COMPILATION &&
       this->impl->Makefile->GetDefinition("_CMAKE_CUDA_FATBIN_FLAG")) ||
      (prop == propCUDA_OPTIX_COMPILATION &&
       this->impl->Makefile->GetDefinition("_CMAKE_CUDA_OPTIX_FLAG"));
    if (flag_found) {
      this->impl->Properties.SetProperty(prop, value);
    } else {
      auto e = cmStrCat(prop, " property is not supported by ", compiler,
                        "  compiler version ", compilerVersion, '.');
      this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e);
      return;
    }
  } else if (prop == propC_STANDARD || prop == propCXX_STANDARD ||
             prop == propCUDA_STANDARD || prop == propHIP_STANDARD ||
             prop == propOBJC_STANDARD || prop == propOBJCXX_STANDARD) {
    if (value) {
      this->impl->LanguageStandardProperties[prop] =
        BTs<std::string>(value, this->impl->Makefile->GetBacktrace());
    } else {
      this->impl->LanguageStandardProperties.erase(prop);
    }
  } else {
    this->impl->Properties.SetProperty(prop, value);
  }
}

void cmTarget::AppendProperty(std::string const& prop,
                              std::string const& value,
                              cm::optional<cmListFileBacktrace> const& bt,
                              bool asString)
{
  if (!IsSettableProperty(this->impl->Makefile, this, prop)) {
    return;
  }
  if (prop == "IMPORTED_GLOBAL") {
    this->impl->Makefile->IssueMessage(
      MessageType::FATAL_ERROR,
      cmStrCat("IMPORTED_GLOBAL property can't be appended, only set on "
               "imported targets (\"",
               this->impl->Name, "\")\n"));
  }

  UsageRequirementProperty* usageRequirements[] = {
    &this->impl->IncludeDirectories,
    &this->impl->CompileOptions,
    &this->impl->CompileFeatures,
    &this->impl->CompileDefinitions,
    &this->impl->PrecompileHeaders,
    &this->impl->Sources,
    &this->impl->LinkOptions,
    &this->impl->LinkDirectories,
    &this->impl->LinkLibraries,
    &this->impl->InterfaceLinkLibraries,
    &this->impl->InterfaceLinkLibrariesDirect,
    &this->impl->InterfaceLinkLibrariesDirectExclude,
    &this->impl->ImportedCxxModulesIncludeDirectories,
    &this->impl->ImportedCxxModulesCompileDefinitions,
    &this->impl->ImportedCxxModulesCompileFeatures,
    &this->impl->ImportedCxxModulesCompileOptions,
    &this->impl->ImportedCxxModulesLinkLibraries,
  };

  for (auto* usageRequirement : usageRequirements) {
    if (usageRequirement->Write(this->impl.get(), bt, prop, cmValue(value),
                                UsageRequirementProperty::Action::Append)) {
      return;
    }
  }

  for (auto& fileSetType : this->impl->FileSetTypes) {
    if (fileSetType.second.WriteProperties(this, this->impl.get(), prop, value,
                                           FileSetType::Action::Append)) {
      return;
    }
  }

  if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME")) {
    this->impl->Makefile->IssueMessage(
      MessageType::FATAL_ERROR, prop + " property may not be APPENDed.");
  } else if (prop == "C_STANDARD" || prop == "CXX_STANDARD" ||
             prop == "CUDA_STANDARD" || prop == "HIP_STANDARD" ||
             prop == "OBJC_STANDARD" || prop == "OBJCXX_STANDARD") {
    this->impl->Makefile->IssueMessage(
      MessageType::FATAL_ERROR, prop + " property may not be appended.");
  } else {
    this->impl->Properties.AppendProperty(prop, value, asString);
  }
}

template <typename ValueType>
void cmTargetInternals::AddDirectoryToFileSet(cmTarget* self,
                                              std::string const& fileSetName,
                                              ValueType value,
                                              cm::string_view fileSetType,
                                              cm::string_view description,
                                              FileSetType::Action action)
{
  auto* fileSet = self->GetFileSet(fileSetName);
  if (!fileSet) {
    this->Makefile->IssueMessage(
      MessageType::FATAL_ERROR,
      cmStrCat(description, "has not yet been created."));
    return;
  }
  if (fileSet->GetType() != fileSetType) {
    this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
                                 cmStrCat("File set \"", fileSetName,
                                          "\" is not of type \"", fileSetType,
                                          "\"."));
    return;
  }
  if (action == FileSetType::Action::Set) {
    fileSet->ClearDirectoryEntries();
  }
  if (cmNonempty(value)) {
    fileSet->AddDirectoryEntry(
      BT<std::string>(value, this->Makefile->GetBacktrace()));
  }
}

template <typename ValueType>
void cmTargetInternals::AddPathToFileSet(cmTarget* self,
                                         std::string const& fileSetName,
                                         ValueType value,
                                         cm::string_view fileSetType,
                                         cm::string_view description,
                                         FileSetType::Action action)
{
  auto* fileSet = self->GetFileSet(fileSetName);
  if (!fileSet) {
    this->Makefile->IssueMessage(
      MessageType::FATAL_ERROR,
      cmStrCat(description, "has not yet been created."));
    return;
  }
  if (fileSet->GetType() != fileSetType) {
    this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
                                 cmStrCat("File set \"", fileSetName,
                                          "\" is not of type \"", fileSetType,
                                          "\"."));
    return;
  }
  if (action == FileSetType::Action::Set) {
    fileSet->ClearFileEntries();
  }
  if (cmNonempty(value)) {
    fileSet->AddFileEntry(
      BT<std::string>(value, this->Makefile->GetBacktrace()));
  }
}

cmValue cmTargetInternals::GetFileSetDirectories(
  cmTarget const* self, std::string const& fileSetName,
  cm::string_view fileSetType) const
{
  auto const* fileSet = self->GetFileSet(fileSetName);
  if (!fileSet) {
    return nullptr;
  }
  if (fileSet->GetType() != fileSetType) {
    this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
                                 cmStrCat("File set \"", fileSetName,
                                          "\" is not of type \"", fileSetType,
                                          "\"."));
    return nullptr;
  }
  static std::string output;
  output = cmList::to_string(fileSet->GetDirectoryEntries());
  return cmValue(output);
}

cmValue cmTargetInternals::GetFileSetPaths(cmTarget const* self,
                                           std::string const& fileSetName,
                                           cm::string_view fileSetType) const
{
  auto const* fileSet = self->GetFileSet(fileSetName);
  if (!fileSet) {
    return nullptr;
  }
  if (fileSet->GetType() != fileSetType) {
    this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
                                 cmStrCat("File set \"", fileSetName,
                                          "\" is not of type \"", fileSetType,
                                          "\"."));
    return nullptr;
  }
  static std::string output;
  output = cmList::to_string(fileSet->GetFileEntries());
  return cmValue(output);
}

void cmTarget::AppendBuildInterfaceIncludes()
{
  if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
      this->GetType() != cmStateEnums::STATIC_LIBRARY &&
      this->GetType() != cmStateEnums::MODULE_LIBRARY &&
      this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
      !this->IsExecutableWithExports()) {
    return;
  }
  if (this->impl->BuildInterfaceIncludesAppended) {
    return;
  }
  this->impl->BuildInterfaceIncludesAppended = true;

  if (this->impl->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE")) {
    std::string dirs = this->impl->Makefile->GetCurrentBinaryDirectory();
    if (!dirs.empty()) {
      dirs += ';';
    }
    dirs += this->impl->Makefile->GetCurrentSourceDirectory();
    if (!dirs.empty()) {
      this->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES",
                           ("$<BUILD_INTERFACE:" + dirs + ">"));
    }
  }
}

namespace {
bool CheckLinkLibraryPattern(UsageRequirementProperty const& usage,
                             cmake* context)
{
  // Look for <LINK_LIBRARY:> and </LINK_LIBRARY:> internal tags
  static cmsys::RegularExpression linkPattern(
    "(^|;)(</?LINK_(LIBRARY|GROUP):[^;>]*>)(;|$)");

  bool isValid = true;

  for (auto const& item : usage.Entries) {
    if (!linkPattern.find(item.Value)) {
      continue;
    }

    isValid = false;

    // Report an error.
    context->IssueMessage(
      MessageType::FATAL_ERROR,
      cmStrCat(
        "Property ", usage.Name, " contains the invalid item \"",
        linkPattern.match(2), "\". The ", usage.Name,
        " property may contain the generator-expression \"$<LINK_",
        linkPattern.match(3),
        ":...>\" which may be used to specify how the libraries are linked."),
      item.Backtrace);
  }

  return isValid;
}
}

void cmTarget::FinalizeTargetConfiguration(cmBTStringRange compileDefinitions)
{
  if (this->GetType() == cmStateEnums::GLOBAL_TARGET) {
    return;
  }

  if (!CheckLinkLibraryPattern(this->impl->LinkLibraries,
                               this->GetMakefile()->GetCMakeInstance()) ||
      !CheckLinkLibraryPattern(this->impl->InterfaceLinkLibraries,
                               this->GetMakefile()->GetCMakeInstance()) ||
      !CheckLinkLibraryPattern(this->impl->InterfaceLinkLibrariesDirect,
                               this->GetMakefile()->GetCMakeInstance())) {
    return;
  }

  this->AppendBuildInterfaceIncludes();

  if (this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
    return;
  }

  for (auto const& def : compileDefinitions) {
    this->InsertCompileDefinition(def);
  }
}

void cmTarget::InsertInclude(BT<std::string> const& entry, bool before)
{
  this->impl->IncludeDirectories.WriteDirect(
    entry,
    before ? UsageRequirementProperty::Action::Prepend
           : UsageRequirementProperty::Action::Append);
}

void cmTarget::InsertCompileOption(BT<std::string> const& entry, bool before)
{
  this->impl->CompileOptions.WriteDirect(
    entry,
    before ? UsageRequirementProperty::Action::Prepend
           : UsageRequirementProperty::Action::Append);
}

void cmTarget::InsertCompileDefinition(BT<std::string> const& entry)
{
  this->impl->CompileDefinitions.WriteDirect(
    entry, UsageRequirementProperty::Action::Append);
}

void cmTarget::InsertLinkOption(BT<std::string> const& entry, bool before)
{
  this->impl->LinkOptions.WriteDirect(
    entry,
    before ? UsageRequirementProperty::Action::Prepend
           : UsageRequirementProperty::Action::Append);
}

void cmTarget::InsertLinkDirectory(BT<std::string> const& entry, bool before)
{
  this->impl->LinkDirectories.WriteDirect(
    entry,
    before ? UsageRequirementProperty::Action::Prepend
           : UsageRequirementProperty::Action::Append);
}

void cmTarget::InsertPrecompileHeader(BT<std::string> const& entry)
{
  this->impl->PrecompileHeaders.WriteDirect(
    entry, UsageRequirementProperty::Action::Append);
}

namespace {
void CheckLINK_INTERFACE_LIBRARIES(std::string const& prop,
                                   std::string const& value,
                                   cmMakefile* context, bool imported)
{
  // Support imported and non-imported versions of the property.
  char const* base = (imported ? "IMPORTED_LINK_INTERFACE_LIBRARIES"
                               : "LINK_INTERFACE_LIBRARIES");

  // Look for link-type keywords in the value.
  static cmsys::RegularExpression keys("(^|;)(debug|optimized|general)(;|$)");
  if (keys.find(value)) {
    // Report an error.
    std::ostringstream e;
    e << "Property " << prop << " may not contain link-type keyword \""
      << keys.match(2) << "\".  "
      << "The " << base << " property has a per-configuration "
      << "version called " << base << "_<CONFIG> which may be "
      << "used to specify per-configuration rules.";
    if (!imported) {
      e << "  "
        << "Alternatively, an IMPORTED library may be created, configured "
        << "with a per-configuration location, and then named in the "
        << "property value.  "
        << "See the add_library command's IMPORTED mode for details."
        << "\n"
        << "If you have a list of libraries that already contains the "
        << "keyword, use the target_link_libraries command with its "
        << "LINK_INTERFACE_LIBRARIES mode to set the property.  "
        << "The command automatically recognizes link-type keywords and sets "
        << "the LINK_INTERFACE_LIBRARIES and LINK_INTERFACE_LIBRARIES_DEBUG "
        << "properties accordingly.";
    }
    context->IssueMessage(MessageType::FATAL_ERROR, e.str());
  }
}

void CheckINTERFACE_LINK_LIBRARIES(std::string const& value,
                                   cmMakefile* context)
{
  // Look for link-type keywords in the value.
  static cmsys::RegularExpression keys("(^|;)(debug|optimized|general)(;|$)");
  if (keys.find(value)) {
    // Report an error.
    std::ostringstream e;

    e << "Property INTERFACE_LINK_LIBRARIES may not contain link-type "
         "keyword \""
      << keys.match(2)
      << "\".  The INTERFACE_LINK_LIBRARIES "
         "property may contain configuration-sensitive generator-expressions "
         "which may be used to specify per-configuration rules.";

    context->IssueMessage(MessageType::FATAL_ERROR, e.str());
  }
}

void CheckIMPORTED_GLOBAL(cmTarget const* target, cmMakefile* context)
{
  auto const& targets = context->GetOwnedImportedTargets();
  auto it =
    std::find_if(targets.begin(), targets.end(),
                 [&](std::unique_ptr<cmTarget> const& importTarget) -> bool {
                   return target == importTarget.get();
                 });
  if (it == targets.end()) {
    std::ostringstream e;
    e << "Attempt to promote imported target \"" << target->GetName()
      << "\" to global scope (by setting IMPORTED_GLOBAL) "
         "which is not built in this directory.";
    context->IssueMessage(MessageType::FATAL_ERROR, e.str());
  }
}
}

void cmTarget::CheckProperty(std::string const& prop,
                             cmMakefile* context) const
{
  // Certain properties need checking.
  if (cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES")) {
    if (cmValue value = this->GetProperty(prop)) {
      CheckLINK_INTERFACE_LIBRARIES(prop, *value, context, false);
    }
  } else if (cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES")) {
    if (cmValue value = this->GetProperty(prop)) {
      CheckLINK_INTERFACE_LIBRARIES(prop, *value, context, true);
    }
  } else if (prop == "INTERFACE_LINK_LIBRARIES") {
    if (cmValue value = this->GetProperty(prop)) {
      CheckINTERFACE_LINK_LIBRARIES(*value, context);
    }
  } else if (prop == "IMPORTED_GLOBAL") {
    if (this->IsImported()) {
      CheckIMPORTED_GLOBAL(this, context);
    }
  }
}

cmValue cmTarget::GetComputedProperty(std::string const& prop,
                                      cmMakefile& mf) const
{
  return cmTargetPropertyComputer::GetProperty(this, prop, mf);
}

cmValue cmTarget::GetProperty(std::string const& prop) const
{
  static std::unordered_set<std::string> const specialProps{
    propC_STANDARD,
    propCXX_STANDARD,
    propCUDA_STANDARD,
    propHIP_STANDARD,
    propOBJC_STANDARD,
    propOBJCXX_STANDARD,
    propLINK_LIBRARIES,
    propTYPE,
    propINCLUDE_DIRECTORIES,
    propCOMPILE_FEATURES,
    propCOMPILE_OPTIONS,
    propCOMPILE_DEFINITIONS,
    propPRECOMPILE_HEADERS,
    propLINK_OPTIONS,
    propLINK_DIRECTORIES,
    propIMPORTED,
    propIMPORTED_GLOBAL,
    propMANUALLY_ADDED_DEPENDENCIES,
    propNAME,
    propBINARY_DIR,
    propSOURCE_DIR,
    propSOURCES,
    propSYMBOLIC,
    propINTERFACE_LINK_LIBRARIES,
    propINTERFACE_LINK_LIBRARIES_DIRECT,
    propINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE,
    propIMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES,
    propIMPORTED_CXX_MODULES_COMPILE_DEFINITIONS,
    propIMPORTED_CXX_MODULES_COMPILE_FEATURES,
    propIMPORTED_CXX_MODULES_COMPILE_OPTIONS,
    propIMPORTED_CXX_MODULES_LINK_LIBRARIES,
  };
  if (specialProps.count(prop)) {
    if (prop == propC_STANDARD || prop == propCXX_STANDARD ||
        prop == propCUDA_STANDARD || prop == propHIP_STANDARD ||
        prop == propOBJC_STANDARD || prop == propOBJCXX_STANDARD) {
      auto propertyIter = this->impl->LanguageStandardProperties.find(prop);
      if (propertyIter == this->impl->LanguageStandardProperties.end()) {
        return nullptr;
      }
      return cmValue(propertyIter->second.Value);
    }

    if (prop == propSYMBOLIC) {
      return this->IsSymbolic() ? cmValue(propTRUE) : cmValue(propFALSE);
    }

    UsageRequirementProperty const* usageRequirements[] = {
      &this->impl->IncludeDirectories,
      &this->impl->CompileOptions,
      &this->impl->CompileFeatures,
      &this->impl->CompileDefinitions,
      &this->impl->PrecompileHeaders,
      &this->impl->Sources,
      &this->impl->LinkOptions,
      &this->impl->LinkDirectories,
      &this->impl->LinkLibraries,
      &this->impl->InterfaceLinkLibraries,
      &this->impl->InterfaceLinkLibrariesDirect,
      &this->impl->InterfaceLinkLibrariesDirectExclude,
      &this->impl->ImportedCxxModulesIncludeDirectories,
      &this->impl->ImportedCxxModulesCompileDefinitions,
      &this->impl->ImportedCxxModulesCompileFeatures,
      &this->impl->ImportedCxxModulesCompileOptions,
      &this->impl->ImportedCxxModulesLinkLibraries,
    };

    for (auto const* usageRequirement : usageRequirements) {
      auto value = usageRequirement->Read(prop);
      if (value.first) {
        return value.second;
      }
    }

    // the type property returns what type the target is
    if (prop == propTYPE) {
      return cmValue(cmState::GetTargetTypeName(this->GetType()));
    }
    if (prop == propMANUALLY_ADDED_DEPENDENCIES) {
      if (this->impl->Utilities.empty()) {
        return nullptr;
      }

      static std::string output;
      static std::vector<std::string> utilities;
      utilities.resize(this->impl->Utilities.size());
      std::transform(
        this->impl->Utilities.cbegin(), this->impl->Utilities.cend(),
        utilities.begin(),
        [](const BT<std::pair<std::string, bool>>& item) -> std::string {
          return item.Value.first;
        });
      output = cmList::to_string(utilities);
      return cmValue(output);
    }
    if (prop == propIMPORTED) {
      return this->IsImported() ? cmValue(propTRUE) : cmValue(propFALSE);
    }
    if (prop == propIMPORTED_GLOBAL) {
      return this->IsImportedGloballyVisible() ? cmValue(propTRUE)
                                               : cmValue(propFALSE);
    }
    if (prop == propNAME) {
      return cmValue(this->GetName());
    }
    if (prop == propBINARY_DIR) {
      return cmValue(this->impl->Makefile->GetStateSnapshot()
                       .GetDirectory()
                       .GetCurrentBinary());
    }
    if (prop == propSOURCE_DIR) {
      return cmValue(this->impl->Makefile->GetStateSnapshot()
                       .GetDirectory()
                       .GetCurrentSource());
    }
  }

  // Check fileset properties.
  {
    for (auto const& fileSetType : this->impl->FileSetTypes) {
      auto value =
        fileSetType.second.ReadProperties(this, this->impl.get(), prop);
      if (value.first) {
        return value.second;
      }
    }
  }

  cmValue retVal = this->impl->Properties.GetPropertyValue(prop);
  if (!retVal) {
    bool const chain = this->impl->Makefile->GetState()->IsPropertyChained(
      prop, cmProperty::TARGET);
    if (chain) {
      return this->impl->Makefile->GetStateSnapshot()
        .GetDirectory()
        .GetProperty(prop, chain);
    }
    return nullptr;
  }
  return retVal;
}

std::string const& cmTarget::GetSafeProperty(std::string const& prop) const
{
  cmValue ret = this->GetProperty(prop);
  if (ret) {
    return *ret;
  }

  static std::string const s_empty;
  return s_empty;
}

bool cmTarget::GetPropertyAsBool(std::string const& prop) const
{
  return this->GetProperty(prop).IsOn();
}

cmPropertyMap const& cmTarget::GetProperties() const
{
  return this->impl->Properties;
}

bool cmTarget::IsDLLPlatform() const
{
  return this->impl->IsDLLPlatform;
}

bool cmTarget::IsAIX() const
{
  return this->impl->IsAIX;
}
bool cmTarget::IsApple() const
{
  return this->impl->IsApple;
}

bool cmTarget::IsSymbolic() const
{
  return this->impl->IsSymbolic;
}

bool cmTarget::IsNormal() const
{
  switch (this->impl->TargetVisibility) {
    case Visibility::Normal:
      return true;
    case Visibility::Generated:
    case Visibility::Imported:
    case Visibility::ImportedGlobally:
    case Visibility::Foreign:
      return false;
  }
  assert(false && "unknown visibility (IsNormal)");
  return false;
}

bool cmTarget::IsSynthetic() const
{
  switch (this->impl->TargetVisibility) {
    case Visibility::Generated:
      return true;
    case Visibility::Normal:
    case Visibility::Imported:
    case Visibility::ImportedGlobally:
    case Visibility::Foreign:
      return false;
  }
  assert(false && "unknown visibility (IsSynthetic)");
  return false;
}

bool cmTargetInternals::IsImported() const
{
  switch (this->TargetVisibility) {
    case cmTarget::Visibility::Imported:
    case cmTarget::Visibility::ImportedGlobally:
    case cmTarget::Visibility::Foreign:
      return true;
    case cmTarget::Visibility::Normal:
    case cmTarget::Visibility::Generated:
      return false;
  }
  assert(false && "unknown visibility (IsImported)");
  return false;
}

bool cmTarget::IsImported() const
{
  return this->impl->IsImported();
}

bool cmTarget::IsImportedGloballyVisible() const
{
  switch (this->impl->TargetVisibility) {
    case Visibility::ImportedGlobally:
      return true;
    case Visibility::Normal:
    case Visibility::Generated:
    case Visibility::Imported:
    case Visibility::Foreign:
      return false;
  }
  assert(false && "unknown visibility (IsImportedGloballyVisible)");
  return false;
}

bool cmTarget::IsForeign() const
{
  switch (this->impl->TargetVisibility) {
    case Visibility::Foreign:
      return true;
    case Visibility::Normal:
    case Visibility::Generated:
    case Visibility::Imported:
    case Visibility::ImportedGlobally:
      return false;
  }
  assert(false && "unknown visibility (isForeign)");
  return false;
}

bool cmTarget::IsPerConfig() const
{
  return this->impl->PerConfig;
}

bool cmTarget::IsRuntimeBinary() const
{
  switch (this->GetType()) {
    case cmStateEnums::EXECUTABLE:
    case cmStateEnums::SHARED_LIBRARY:
    case cmStateEnums::MODULE_LIBRARY:
      return true;
    case cmStateEnums::OBJECT_LIBRARY:
    case cmStateEnums::STATIC_LIBRARY:
    case cmStateEnums::UTILITY:
    case cmStateEnums::INTERFACE_LIBRARY:
    case cmStateEnums::GLOBAL_TARGET:
    case cmStateEnums::UNKNOWN_LIBRARY:
      break;
  }
  return false;
}

bool cmTarget::CanCompileSources() const
{
  if (this->IsImported()) {
    return false;
  }
  if (this->IsSynthetic()) {
    return true;
  }
  switch (this->GetType()) {
    case cmStateEnums::EXECUTABLE:
    case cmStateEnums::STATIC_LIBRARY:
    case cmStateEnums::SHARED_LIBRARY:
    case cmStateEnums::MODULE_LIBRARY:
    case cmStateEnums::OBJECT_LIBRARY:
      return true;
    case cmStateEnums::UTILITY:
    case cmStateEnums::INTERFACE_LIBRARY:
    case cmStateEnums::GLOBAL_TARGET:
    case cmStateEnums::UNKNOWN_LIBRARY:
      break;
  }
  return false;
}

void cmTarget::SetIsForTryCompile()
{
  this->impl->IsForTryCompile = true;
}

bool cmTarget::IsForTryCompile() const
{
  return this->impl->IsForTryCompile;
}

char const* cmTarget::GetSuffixVariableInternal(
  cmStateEnums::ArtifactType artifact) const
{
  switch (this->GetType()) {
    case cmStateEnums::STATIC_LIBRARY:
      return "CMAKE_STATIC_LIBRARY_SUFFIX";
    case cmStateEnums::SHARED_LIBRARY:
      switch (artifact) {
        case cmStateEnums::RuntimeBinaryArtifact:
          return this->IsArchivedAIXSharedLibrary()
            ? "CMAKE_SHARED_LIBRARY_ARCHIVE_SUFFIX"
            : "CMAKE_SHARED_LIBRARY_SUFFIX";
        case cmStateEnums::ImportLibraryArtifact:
          return this->IsApple() ? "CMAKE_APPLE_IMPORT_FILE_SUFFIX"
                                 : "CMAKE_IMPORT_LIBRARY_SUFFIX";
      }
      break;
    case cmStateEnums::MODULE_LIBRARY:
      switch (artifact) {
        case cmStateEnums::RuntimeBinaryArtifact:
          return "CMAKE_SHARED_MODULE_SUFFIX";
        case cmStateEnums::ImportLibraryArtifact:
          return "CMAKE_IMPORT_LIBRARY_SUFFIX";
      }
      break;
    case cmStateEnums::EXECUTABLE:
      switch (artifact) {
        case cmStateEnums::RuntimeBinaryArtifact:
          // Android GUI application packages store the native
          // binary as a shared library.
          return (this->IsAndroidGuiExecutable()
                    ? "CMAKE_SHARED_LIBRARY_SUFFIX"
                    : "CMAKE_EXECUTABLE_SUFFIX");
        case cmStateEnums::ImportLibraryArtifact:
          return (this->impl->IsAIX ? "CMAKE_AIX_IMPORT_FILE_SUFFIX"
                                    : "CMAKE_IMPORT_LIBRARY_SUFFIX");
      }
      break;
    default:
      break;
  }
  return "";
}

char const* cmTarget::GetPrefixVariableInternal(
  cmStateEnums::ArtifactType artifact) const
{
  switch (this->GetType()) {
    case cmStateEnums::STATIC_LIBRARY:
      return "CMAKE_STATIC_LIBRARY_PREFIX";
    case cmStateEnums::SHARED_LIBRARY:
      switch (artifact) {
        case cmStateEnums::RuntimeBinaryArtifact:
          return "CMAKE_SHARED_LIBRARY_PREFIX";
        case cmStateEnums::ImportLibraryArtifact:
          return this->IsApple() ? "CMAKE_APPLE_IMPORT_FILE_PREFIX"
                                 : "CMAKE_IMPORT_LIBRARY_PREFIX";
      }
      break;
    case cmStateEnums::MODULE_LIBRARY:
      switch (artifact) {
        case cmStateEnums::RuntimeBinaryArtifact:
          return "CMAKE_SHARED_MODULE_PREFIX";
        case cmStateEnums::ImportLibraryArtifact:
          return "CMAKE_IMPORT_LIBRARY_PREFIX";
      }
      break;
    case cmStateEnums::EXECUTABLE:
      switch (artifact) {
        case cmStateEnums::RuntimeBinaryArtifact:
          // Android GUI application packages store the native
          // binary as a shared library.
          return (this->IsAndroidGuiExecutable()
                    ? "CMAKE_SHARED_LIBRARY_PREFIX"
                    : "");
        case cmStateEnums::ImportLibraryArtifact:
          return (this->impl->IsAIX ? "CMAKE_AIX_IMPORT_FILE_PREFIX"
                                    : "CMAKE_IMPORT_LIBRARY_PREFIX");
      }
      break;
    default:
      break;
  }
  return "";
}

std::string cmTarget::ImportedGetFullPath(
  std::string const& config, cmStateEnums::ArtifactType artifact,
  ImportArtifactMissingOk missingOk) const
{
  assert(this->IsImported());

  // Lookup/compute/cache the import information for this
  // configuration.
  std::string desired_config = config;
  if (config.empty()) {
    desired_config = "NOCONFIG";
  }

  std::string result;

  cmValue loc = nullptr;
  cmValue imp = nullptr;
  std::string suffix;

  if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
      this->GetMappedConfig(desired_config, loc, imp, suffix)) {
    switch (artifact) {
      case cmStateEnums::RuntimeBinaryArtifact:
        if (loc) {
          result = *loc;
        } else if (imp) {
          result = *imp;
        } else {
          std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix);
          if (cmValue config_location = this->GetProperty(impProp)) {
            result = *config_location;
          } else if (cmValue location =
                       this->GetProperty("IMPORTED_LOCATION")) {
            result = *location;
          }
          if (result.empty() &&
              (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
               this->IsExecutableWithExports())) {
            impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
            if (cmValue config_implib = this->GetProperty(impProp)) {
              result = *config_implib;
            } else if (cmValue implib = this->GetProperty("IMPORTED_IMPLIB")) {
              result = *implib;
            }
          }
        }
        if (this->IsApple() &&
            (this->impl->TargetType == cmStateEnums::SHARED_LIBRARY ||
             this->impl->TargetType == cmStateEnums::STATIC_LIBRARY ||
             this->impl->TargetType == cmStateEnums::UNKNOWN_LIBRARY) &&
            cmSystemTools::IsPathToXcFramework(result)) {
          auto plist = cmParseXcFrameworkPlist(result, *this->impl->Makefile,
                                               this->impl->Backtrace);
          if (!plist) {
            return "";
          }
          auto const* library = plist->SelectSuitableLibrary(
            *this->impl->Makefile, this->impl->Backtrace);
          if (library) {
            result = cmStrCat(result, '/', library->LibraryIdentifier, '/',
                              library->LibraryPath);
          } else {
            return "";
          }
        }
        break;

      case cmStateEnums::ImportLibraryArtifact:
        if (imp) {
          result = *imp;
        } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
                   this->IsExecutableWithExports()) {
          std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
          if (cmValue config_implib = this->GetProperty(impProp)) {
            result = *config_implib;
          } else if (cmValue implib = this->GetProperty("IMPORTED_IMPLIB")) {
            result = *implib;
          }
        }
        break;
    }
  }

  if (result.empty() && missingOk != ImportArtifactMissingOk::Yes) {
    if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
      auto message = [&]() -> std::string {
        std::string unset;
        std::string configuration;

        if (this->GetType() == cmStateEnums::SHARED_LIBRARY &&
            artifact == cmStateEnums::RuntimeBinaryArtifact) {
          unset = "IMPORTED_LOCATION or IMPORTED_IMPLIB";
        } else if (artifact == cmStateEnums::RuntimeBinaryArtifact) {
          unset = "IMPORTED_LOCATION";
        } else if (artifact == cmStateEnums::ImportLibraryArtifact) {
          unset = "IMPORTED_IMPLIB";
        }

        if (!config.empty()) {
          configuration = cmStrCat(" configuration \"", config, '"');
        }

        return cmStrCat(unset, " not set for imported target \"",
                        this->GetName(), '"', configuration, '.');
      };

      switch (this->GetPolicyStatus(cmPolicies::CMP0111)) {
        case cmPolicies::WARN:
          this->impl->Makefile->IssueDiagnostic(
            cmDiagnostics::CMD_AUTHOR,
            cmPolicies::GetPolicyWarning(cmPolicies::CMP0111) + "\n" +
              message());
          CM_FALLTHROUGH;
        case cmPolicies::OLD:
          break;
        default:
          this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
                                             message());
      }
    }

    result = cmStrCat(this->GetName(), "-NOTFOUND");
  }
  return result;
}

cmFileSet const* cmTarget::GetFileSet(std::string const& name) const
{
  auto it = this->impl->FileSets.find(name);
  return it == this->impl->FileSets.end() ? nullptr : &it->second;
}

cmFileSet* cmTarget::GetFileSet(std::string const& name)
{
  auto it = this->impl->FileSets.find(name);
  return it == this->impl->FileSets.end() ? nullptr : &it->second;
}

std::pair<cmFileSet*, bool> cmTarget::GetOrCreateFileSet(
  std::string const& name, std::string const& type,
  cm::FileSetMetadata::Visibility vis)
{
  auto result = this->impl->FileSets.emplace(
    name, cmFileSet(this->GetMakefile(), this, name, type, vis));
  if (result.second) {
    auto bt = this->impl->Makefile->GetBacktrace();
    if (cm::contains(this->impl->FileSetTypes, type)) {
      this->impl->FileSetTypes.at(type).AddFileSet(name, vis, std::move(bt));
    }
  }
  return std::make_pair(&result.first->second, result.second);
}

std::string cmTarget::GetFileSetsPropertyName(std::string const& type) const
{
  if (cm::contains(this->impl->FileSetTypes, type)) {
    return std::string{
      this->impl->FileSetTypes.at(type).SelfEntries.PropertyName
    };
  }
  return "";
}

std::string cmTarget::GetInterfaceFileSetsPropertyName(
  std::string const& type) const
{
  if (cm::contains(this->impl->FileSetTypes, type)) {
    return std::string{
      this->impl->FileSetTypes.at(type).InterfaceEntries.PropertyName
    };
  }
  return "";
}

std::vector<std::string> cmTarget::GetAllFileSetNames() const
{
  std::vector<std::string> result;

  for (auto const& it : this->impl->FileSets) {
    result.push_back(it.first);
  }

  return result;
}

namespace {
std::vector<std::string> RetrieveFileSetNames(
  std::unordered_map<cm::string_view, FileSetType> const& fileSetTypes,
  std::function<
    std::vector<BT<std::string>> const&(FileSetType const& fileSetType)>
    GetFileSets)
{
  std::vector<std::string> result;
  auto inserter = std::back_inserter(result);

  auto appendEntries = [=](std::vector<BT<std::string>> const& entries) {
    for (auto const& entry : entries) {
      cmList expanded{ entry.Value };
      std::copy(expanded.begin(), expanded.end(), inserter);
    }
  };

  for (auto const& fileSetType : fileSetTypes) {
    appendEntries(GetFileSets(fileSetType.second));
  }

  return result;
}
}

std::vector<std::string> cmTarget::GetAllPrivateFileSets() const
{
  return RetrieveFileSetNames(
    this->impl->FileSetTypes,
    [](FileSetType const& fileSetType) -> std::vector<BT<std::string>> const& {
      return fileSetType.SelfEntries.Entries;
    });
}

std::vector<std::string> cmTarget::GetAllInterfaceFileSets() const
{
  return RetrieveFileSetNames(
    this->impl->FileSetTypes,
    [](FileSetType const& fileSetType) -> std::vector<BT<std::string>> const& {
      return fileSetType.InterfaceEntries.Entries;
    });
}

bool cmTarget::HasFileSets() const
{
  return !this->impl->FileSets.empty();
}

bool cmTargetInternals::CheckImportedLibName(std::string const& prop,
                                             std::string const& value) const
{
  if (this->TargetType != cmStateEnums::INTERFACE_LIBRARY ||
      !this->IsImported()) {
    this->Makefile->IssueMessage(
      MessageType::FATAL_ERROR,
      prop +
        " property may be set only on imported INTERFACE library targets.");
    return false;
  }
  if (!value.empty()) {
    if (value[0] == '-') {
      this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
                                   prop + " property value\n  " + value +
                                     "\nmay not start with '-'.");
      return false;
    }
    std::string::size_type bad = value.find_first_of(":/\\;");
    if (bad != std::string::npos) {
      this->Makefile->IssueMessage(MessageType::FATAL_ERROR,
                                   prop + " property value\n  " + value +
                                     "\nmay not contain '" +
                                     value.substr(bad, 1) + "'.");
      return false;
    }
  }
  return true;
}

bool cmTarget::GetMappedConfig(std::string const& desiredConfig, cmValue& loc,
                               cmValue& imp, std::string& suffix) const
{
  switch (this->GetPolicyStatusCMP0200()) {
    case cmPolicies::WARN:
      if (this->GetMakefile()->PolicyOptionalWarningEnabled(
            "CMAKE_POLICY_WARNING_CMP0200")) {
        break;
      }
      CM_FALLTHROUGH;
    case cmPolicies::OLD:
      return this->GetMappedConfigOld(desiredConfig, loc, imp, suffix);
    case cmPolicies::NEW:
      return this->GetMappedConfigNew(desiredConfig, loc, imp, suffix);
  }

  cmValue newLoc;
  cmValue newImp;
  std::string newSuffix;

  bool const newResult =
    this->GetMappedConfigNew(desiredConfig, newLoc, newImp, newSuffix);

  auto configFromSuffix = [](cm::string_view s) -> cm::string_view {
    return s.empty() ? "(none)"_s : s.substr(1);
  };

  if (!this->GetMappedConfigOld(desiredConfig, loc, imp, suffix)) {
    if (newResult) {
      // NEW policy found a configuration, OLD did not.
      cm::string_view newConfig = configFromSuffix(newSuffix);
      std::string const err = cmStrCat(
        cmPolicies::GetPolicyWarning(cmPolicies::CMP0200),
        "\nConfiguration selection for imported target \"", this->GetName(),
        "\" failed, but would select configuration \"", newConfig,
        "\" under the NEW policy.\n");
      this->GetMakefile()->IssueDiagnostic(cmDiagnostics::CMD_AUTHOR, err);
    }

    return false;
  }

  cm::string_view oldConfig = configFromSuffix(suffix);
  if (!newResult) {
    // NEW policy did not find a configuration, OLD did.
    std::string const err =
      cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0200),
               "\nConfiguration selection for imported target \"",
               this->GetName(), "\" selected configuration \"", oldConfig,
               "\", but would fail under the NEW policy.\n");
    this->GetMakefile()->IssueDiagnostic(cmDiagnostics::CMD_AUTHOR, err);
  } else if (suffix != newSuffix) {
    // OLD and NEW policies found different configurations.
    cm::string_view newConfig = configFromSuffix(newSuffix);
    std::string const err =
      cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0200),
               "\nConfiguration selection for imported target \"",
               this->GetName(), "\" selected configuration \"", oldConfig,
               "\", but would select configuration \"", newConfig,
               "\" under the NEW policy.\n");
    this->GetMakefile()->IssueDiagnostic(cmDiagnostics::CMD_AUTHOR, err);
  }

  return true;
}

bool cmTarget::GetMappedConfigOld(std::string const& desired_config,
                                  cmValue& loc, cmValue& imp,
                                  std::string& suffix) const
{
  std::string config_upper;
  if (!desired_config.empty()) {
    config_upper = cmSystemTools::UpperCase(desired_config);
  }

  std::string locPropBase;
  if (this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
    locPropBase = "IMPORTED_LIBNAME";
  } else if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
    locPropBase = "IMPORTED_OBJECTS";
  } else {
    locPropBase = "IMPORTED_LOCATION";
  }

  // Track the configuration-specific property suffix.
  suffix = cmStrCat('_', config_upper);

  cmList mappedConfigs;
  {
    std::string mapProp = cmStrCat("MAP_IMPORTED_CONFIG_", config_upper);
    if (cmValue mapValue = this->GetProperty(mapProp)) {
      mappedConfigs.assign(*mapValue, cmList::EmptyElements::Yes);
    }
  }

  // If we needed to find one of the mapped configurations but did not
  // There may be only IMPORTED_IMPLIB for a shared library or an executable
  // with exports.
  bool allowImp = (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
                   this->IsExecutableWithExports()) ||
    (this->IsAIX() && this->IsExecutableWithExports()) ||
    (this->GetMakefile()->PlatformSupportsAppleTextStubs() &&
     this->IsSharedLibraryWithExports());

  // If a mapping was found, check its configurations.
  for (auto mci = mappedConfigs.begin();
       !loc && !imp && mci != mappedConfigs.end(); ++mci) {
    // Look for this configuration.
    if (mci->empty()) {
      // An empty string in the mapping has a special meaning:
      // look up the config-less properties.
      loc = this->GetProperty(locPropBase);
      if (allowImp) {
        imp = this->GetProperty("IMPORTED_IMPLIB");
      }
      // If it was found, set the suffix.
      if (loc || imp) {
        suffix.clear();
      }
    } else {
      std::string mcUpper = cmSystemTools::UpperCase(*mci);
      std::string locProp = cmStrCat(locPropBase, '_', mcUpper);
      loc = this->GetProperty(locProp);
      if (allowImp) {
        std::string impProp = cmStrCat("IMPORTED_IMPLIB_", mcUpper);
        imp = this->GetProperty(impProp);
      }

      // If it was found, use it for all properties below.
      if (loc || imp) {
        suffix = cmStrCat('_', mcUpper);
      }
    }
  }

  // If we needed to find one of the mapped configurations but did not
  // then the target location is not found.  The project does not want
  // any other configuration.
  if (!mappedConfigs.empty() && !loc && !imp) {
    // Interface libraries are always available because their
    // library name is optional so it is okay to leave loc empty.
    return this->GetType() == cmStateEnums::INTERFACE_LIBRARY;
  }

  // If we have not yet found it then there are no mapped
  // configurations.  Look for an exact-match.
  if (!loc && !imp) {
    std::string locProp = cmStrCat(locPropBase, suffix);
    loc = this->GetProperty(locProp);
    if (allowImp) {
      std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
      imp = this->GetProperty(impProp);
    }
  }

  // If we have not yet found it then there are no mapped
  // configurations and no exact match.
  if (!loc && !imp) {
    // The suffix computed above is not useful.
    suffix.clear();

    // Look for a configuration-less location.  This may be set by
    // manually-written code.
    loc = this->GetProperty(locPropBase);
    if (allowImp) {
      imp = this->GetProperty("IMPORTED_IMPLIB");
    }
  }

  // If we have not yet found it then the project is willing to try
  // any available configuration.
  if (!loc && !imp) {
    cmList availableConfigs;
    if (cmValue iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS")) {
      availableConfigs.assign(*iconfigs);
    }
    for (auto it = availableConfigs.begin();
         !loc && !imp && it != availableConfigs.end(); ++it) {
      suffix = cmStrCat('_', cmSystemTools::UpperCase(*it));
      std::string locProp = cmStrCat(locPropBase, suffix);
      loc = this->GetProperty(locProp);
      if (allowImp) {
        std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
        imp = this->GetProperty(impProp);
      }
    }
  }
  // If we have not yet found it then the target location is not available.
  if (!loc && !imp) {
    // Interface libraries are always available because their
    // library name is optional so it is okay to leave loc empty.
    return this->GetType() == cmStateEnums::INTERFACE_LIBRARY;
  }

  return true;
}

cmValue cmTarget::GetLocation(std::string const& base,
                              std::string const& suffix) const
{
  cmValue value = this->GetProperty(cmStrCat(base, suffix));
  if (value || suffix.empty()) {
    return value;
  }
  return this->GetProperty(base);
}

bool cmTarget::GetLocation(std::string const& config, cmValue& loc,
                           cmValue& imp, std::string& suffix) const
{
  suffix = (config.empty() ? std::string{} : cmStrCat('_', config));

  // There may be only IMPORTED_IMPLIB for a shared library or an executable
  // with exports.
  bool const allowImp = (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
                         this->IsExecutableWithExports()) ||
    (this->IsAIX() && this->IsExecutableWithExports()) ||
    (this->GetMakefile()->PlatformSupportsAppleTextStubs() &&
     this->IsSharedLibraryWithExports());

  if (allowImp) {
    imp = this->GetLocation("IMPORTED_IMPLIB", suffix);
  }

  switch (this->GetType()) {
    case cmStateEnums::INTERFACE_LIBRARY:
      loc = this->GetLocation("IMPORTED_LIBNAME", suffix);
      break;
    case cmStateEnums::OBJECT_LIBRARY:
      loc = this->GetLocation("IMPORTED_OBJECTS", suffix);
      break;
    default:
      loc = this->GetLocation("IMPORTED_LOCATION", suffix);
      break;
  }

  return loc || imp || (this->GetType() == cmStateEnums::INTERFACE_LIBRARY);
}

bool cmTarget::GetMappedConfigNew(std::string desiredConfig, cmValue& loc,
                                  cmValue& imp, std::string& suffix) const
{
  desiredConfig = cmSystemTools::UpperCase(desiredConfig);

  // Get configuration mapping, if present.
  cmList mappedConfigs;
  if (!desiredConfig.empty()) {
    std::string mapProp = cmStrCat("MAP_IMPORTED_CONFIG_", desiredConfig);
    if (cmValue mapValue = this->GetProperty(mapProp)) {
      mappedConfigs.assign(cmSystemTools::UpperCase(*mapValue),
                           cmList::EmptyElements::Yes);
    }
  }

  // Get imported configurations, if specified.
  if (cmValue iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS")) {
    cmList const availableConfigs{ cmSystemTools::UpperCase(*iconfigs) };

    if (!mappedConfigs.empty()) {
      for (auto const& c : mappedConfigs) {
        if (cm::contains(availableConfigs, c)) {
          this->GetLocation(c, loc, imp, suffix);
          return true;
        }
      }

      // If a configuration mapping was specified, but no matching
      // configuration was found, we don't want to try anything else.
      return false;
    }

    // There is no mapping; try the requested configuration first.
    if (cm::contains(availableConfigs, desiredConfig)) {
      this->GetLocation(desiredConfig, loc, imp, suffix);
      return true;
    }

    // If there is no mapping and the requested configuration is not one of
    // the available configurations, just take the first available
    // configuration.
    this->GetLocation(availableConfigs[0], loc, imp, suffix);
    return true;
  }

  if (!mappedConfigs.empty()) {
    for (auto const& c : mappedConfigs) {
      if (this->GetLocation(c, loc, imp, suffix)) {
        return true;
      }
    }

    // If a configuration mapping was specified, but no matching
    // configuration was found, we don't want to try anything else.
    return false;
  }

  // There is no mapping and no explicit list of configurations; the only
  // configuration left to try is the requested configuration.
  if (this->GetLocation(desiredConfig, loc, imp, suffix)) {
    return true;
  }

  return false;
}
