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

#include "cmConfigure.h" // IWYU pragma: keep

#include <cstddef>
#include <functional>
#include <iosfwd>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

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

#include "cmBuildOptions.h"
#include "cmCustomCommandLines.h"
#include "cmDuration.h"
#include "cmExportFileGenerator.h"
#include "cmExportSet.h"
#include "cmLocalGenerator.h"
#include "cmSbomBuilder.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetDepend.h"
#include "cmTargetTypes.h"
#include "cmTestGenerator.h"
#include "cmValue.h"
#include "cmXcFramework.h"

#if !defined(CMAKE_BOOTSTRAP)
#  include <cm3p/json/value.h>

#  include "cmFileLockPool.h"
#endif

#define CMAKE_DIRECTORY_ID_SEP "::@"

enum class cmDepfileFormat;
enum class codecvt_Encoding;

class cmBuildArgs;
class cmDirectoryId;
class cmExportBuildFileGenerator;
class cmExternalMakefileProjectGenerator;
class cmBuildSbomGenerator;
class cmInstallSbomGenerator;
class cmGeneratorTarget;
class cmInstallRuntimeDependencySet;
class cmLinkLineComputer;
class cmMakefile;
class cmOutputConverter;
class cmQtAutoGenGlobalInitializer;
class cmSourceFile;
class cmState;
class cmStateDirectory;
class cmake;

namespace detail {
inline void AppendStrs(std::vector<std::string>&)
{
}
template <typename T, typename... Ts>
inline void AppendStrs(std::vector<std::string>& command, T&& s, Ts&&... ts)
{
  command.emplace_back(std::forward<T>(s));
  AppendStrs(command, std::forward<Ts>(ts)...);
}

struct GeneratedMakeCommand
{
  // Add each argument as a separate element to the vector
  template <typename... T>
  void Add(T&&... args)
  {
    // iterate the args and append each one
    AppendStrs(this->PrimaryCommand, std::forward<T>(args)...);
  }

  // Add each value in the iterators as a separate element to the vector
  void Add(std::vector<std::string>::const_iterator start,
           std::vector<std::string>::const_iterator end)
  {
    cm::append(this->PrimaryCommand, start, end);
  }

  std::string Printable() const { return cmJoin(this->PrimaryCommand, " "); }
  std::string QuotedPrintable() const;

  std::vector<std::string> PrimaryCommand;
};
}
namespace Json {
class StreamWriter;
}

/** \class cmGlobalGenerator
 * \brief Responsible for overseeing the generation process for the entire tree
 *
 * Subclasses of this class generate makefiles for various
 * platforms.
 */
class cmGlobalGenerator
{
public:
  using LocalGeneratorVector = std::vector<std::unique_ptr<cmLocalGenerator>>;
  enum class BuildTryCompile
  {
    No,
    Yes,
  };

  //! Free any memory allocated with the GlobalGenerator
  cmGlobalGenerator(cmake* cm);
  virtual ~cmGlobalGenerator();

  virtual std::unique_ptr<cmLocalGenerator> CreateLocalGenerator(
    cmMakefile* mf);

  //! Get the name for this generator
  virtual std::string GetName() const { return "Generic"; }

  virtual std::vector<std::string> GetTestBuildDependencyPaths(
    std::string const& config,
    cmTestGenerator::BuildDependencies const& deps) const;

  /** Check whether the given name matches the current generator.  */
  virtual bool MatchesGeneratorName(std::string const& name) const
  {
    return this->GetName() == name;
  }

  /** Get encoding used by generator for makefile files */
  virtual codecvt_Encoding GetMakefileEncoding() const;

#if !defined(CMAKE_BOOTSTRAP)
  /** Get a JSON object describing the generator.  */
  virtual Json::Value GetJson() const;
#endif

  /** Tell the generator about the target system.  */
  virtual bool SetSystemName(std::string const&, cmMakefile*) { return true; }

  /** Set the generator-specific instance.  Returns true if supported.  */
  virtual bool SetGeneratorInstance(std::string const& i, cmMakefile* mf);

  /** Set the generator-specific platform name.  Returns true if platform
      is supported and false otherwise.  */
  virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf);

  /** Set the generator-specific toolset name.  Returns true if toolset
      is supported and false otherwise.  */
  virtual bool SetGeneratorToolset(std::string const& ts, bool build,
                                   cmMakefile* mf);

  /** Read any other cache entries needed for cmake --build. */
  virtual bool ReadCacheEntriesForBuild(cmState const& /*state*/)
  {
    return true;
  }

  /**
   * Create LocalGenerators and process the CMakeLists files. This does not
   * actually produce any makefiles, DSPs, etc.
   */
  virtual void Configure();

  virtual bool InspectConfigTypeVariables() { return true; }

  enum class CxxModuleSupportQuery
  {
    // Support is expected at the call site.
    Expected,
    // The call site is querying for support and handles problems by itself.
    Inspect,
  };
  virtual bool CheckCxxModuleSupport(CxxModuleSupportQuery /*query*/)
  {
    return false;
  }

  virtual bool SupportsCustomObjectNames() const { return true; }

  virtual bool SupportsBuildDatabase() const { return false; }
  bool AddBuildDatabaseTargets();
  void AddBuildDatabaseFile(std::string const& lang, std::string const& config,
                            std::string const& path);

  virtual bool IsGNUMakeJobServerAware() const { return false; }

  bool Compute();
  virtual void AddExtraIDETargets() {}

  enum TargetTypes
  {
    AllTargets,
    ImportedOnly
  };

  void CreateImportedGenerationObjects(
    cmMakefile* mf, std::vector<std::string> const& targets,
    std::vector<cmGeneratorTarget const*>& exports);
  void CreateGenerationObjects(TargetTypes targetTypes = AllTargets);

  /**
   * Generate the all required files for building this project/tree. This
   * basically creates a series of LocalGenerators for each directory and
   * requests that they Generate.
   */
  virtual void Generate();

  virtual std::unique_ptr<cmLinkLineComputer> CreateLinkLineComputer(
    cmOutputConverter* outputConverter,
    cmStateDirectory const& stateDir) const;

  std::unique_ptr<cmLinkLineComputer> CreateMSVC60LinkLineComputer(
    cmOutputConverter* outputConverter,
    cmStateDirectory const& stateDir) const;

  /**
   * Set/Get and Clear the enabled languages.
   */
  void SetLanguageEnabled(std::string const&, cmMakefile* mf);
  bool GetLanguageEnabled(std::string const&) const;
  void ClearEnabledLanguages();
  void GetEnabledLanguages(std::vector<std::string>& lang) const;
  /**
   * Try to determine system information such as shared library
   * extension, pthreads, byte order etc.
   */
  virtual void EnableLanguage(std::vector<std::string> const& languages,
                              cmMakefile*, bool optional);

  /**
   * Resolve the CMAKE_<lang>_COMPILER setting for the given language.
   * Intended to be called from EnableLanguage.
   */
  void ResolveLanguageCompiler(std::string const& lang, cmMakefile* mf,
                               bool optional) const;

  void SetupTryCompile(cmGlobalGenerator* gen, cmMakefile* mf);
  /**
   * Try running cmake and building a file. This is used for dynamically
   * loaded commands, not as part of the usual build process.
   */
  int TryCompile(int jobs, std::string const& bindir,
                 std::string const& projectName, std::string const& targetName,
                 bool fast, std::string& output, cmMakefile* mf);

  /**
   * Build a file given the following information. This is a more direct call
   * that is used by both CTest and TryCompile. If target name is NULL or
   * empty then all is assumed. clean indicates if a "make clean" should be
   * done first.
   */
  int Build(
    cmBuildArgs const& buildArgs, std::vector<std::string> const& targetNames,
    std::ostream& ostr, std::string const& makeProgram,
    std::string const& config, cmBuildOptions buildOptions, cmDuration timeout,
    cmSystemTools::OutputOption outputMode,
    std::vector<std::string> const& nativeOptions = std::vector<std::string>(),
    BuildTryCompile isInTryCompile = BuildTryCompile::No);

  /**
   * Open a generated IDE project given the following information.
   */
  virtual bool Open(std::string const& bindir, std::string const& projectName,
                    bool dryRun);

  struct GeneratedMakeCommand final : public detail::GeneratedMakeCommand
  {
  };

  virtual std::vector<GeneratedMakeCommand> GenerateBuildCommand(
    std::string const& makeProgram, std::string const& projectName,
    std::string const& projectDir, std::vector<std::string> const& targetNames,
    std::string const& config, int jobs, bool verbose,
    cmBuildOptions buildOptions = cmBuildOptions(),
    std::vector<std::string> const& makeOptions = std::vector<std::string>(),
    BuildTryCompile isInTryCompile = BuildTryCompile::No);

  virtual void PrintBuildCommandAdvice(std::ostream& os, int jobs) const;

  /**
   * Generate a "cmake --build" call for a given target, config and parallel
   * level.
   */
  std::string GenerateCMakeBuildCommand(std::string const& target,
                                        std::string const& config,
                                        std::string const& parallel,
                                        std::string const& native,
                                        bool ignoreErrors);

  //! Get the CMake instance
  cmake* GetCMakeInstance() const { return this->CMakeInstance; }

  void SetConfiguredFilesPath(cmGlobalGenerator* gen);
  std::vector<std::unique_ptr<cmMakefile>> const& GetMakefiles() const
  {
    return this->Makefiles;
  }
  LocalGeneratorVector const& GetLocalGenerators() const
  {
    return this->LocalGenerators;
  }

  std::vector<cmGeneratorTarget*> GetLocalGeneratorTargetsInOrder(
    cmLocalGenerator* lg) const;

  // Find the single build-system target that produces the given path as a
  // primary custom-command output, or nullptr if there is none or more than
  // one.  Used to resolve file-level test build dependencies.
  cmGeneratorTarget* FindOutputOwningTarget(std::string const& output);

  cmMakefile* GetCurrentMakefile() const
  {
    return this->CurrentConfigureMakefile;
  }

  void SetCurrentMakefile(cmMakefile* mf)
  {
    this->CurrentConfigureMakefile = mf;
  }

  void AddMakefile(std::unique_ptr<cmMakefile> mf);

  //! Set an generator for an "external makefile based project"
  void SetExternalMakefileProjectGenerator(
    std::unique_ptr<cmExternalMakefileProjectGenerator> extraGenerator);

  std::string GetExtraGeneratorName() const;

  void AddInstallComponent(std::string const& component);

  /** Mark the (absolute path to a) file as generated.  */
  void MarkAsGeneratedFile(std::string const& filepath);
  /** Determine if the absolute filepath belongs to a generated file.  */
  bool IsGeneratedFile(std::string const& filepath);

  std::set<std::string> const* GetInstallComponents() const
  {
    return &this->InstallComponents;
  }

  cmExportSetMap& GetExportSets() { return this->ExportSets; }

  cmValue GetGlobalSetting(std::string const& name) const;
  bool GlobalSettingIsOn(std::string const& name) const;
  std::string GetSafeGlobalSetting(std::string const& name) const;

  /** Add a file to the manifest of generated targets for a configuration.  */
  void AddToManifest(std::string const& f);

  void EnableInstallTarget();

  cmDuration TryCompileTimeout;

  bool GetForceUnixPaths() const { return this->ForceUnixPaths; }
  bool GetToolSupportsColor() const { return this->ToolSupportsColor; }

  //! return the language for the given extension
  cm::string_view GetLanguageFromExtension(cm::string_view ext) const;
  //! is an extension to be ignored
  bool IgnoreFile(cm::string_view ext) const;
  //! What is the preference for linkers and this language (None or Preferred)
  int GetLinkerPreference(std::string const& lang) const;
  //! What is the object file extension for a given source file?
  std::string GetLanguageOutputExtension(cmSourceFile const&) const;
  //! What is the object file extension for a given language?
  std::string GetLanguageOutputExtension(std::string const& lang) const;
  //! What is the object file extension for a given --emit option in Rust?
  std::string GetRustEmitOutputExtension(std::string const& emitValue) const;

  //! What is the configurations directory variable called?
  virtual char const* GetCMakeCFGIntDir() const { return "."; }

  //! expand CFGIntDir for a configuration
  virtual std::string ExpandCFGIntDir(std::string const& str,
                                      std::string const& config) const;

  /** Get whether the generator should use a script for link commands.  */
  bool GetUseLinkScript() const { return this->UseLinkScript; }

  /** Get whether the generator should produce special marks on rules
      producing symbolic (non-file) outputs.  */
  bool GetNeedSymbolicMark() const { return this->NeedSymbolicMark; }

  /*
   * Determine what program to use for building the project.
   */
  virtual bool FindMakeProgram(cmMakefile*);

  //! Find a target by name by searching the local generators.
  cmTarget* FindTarget(std::string const& name,
                       cm::TargetDomainSet domains = {
                         cm::TargetDomain::NATIVE,
                         cm::TargetDomain::ALIAS }) const;

  cmGeneratorTarget* FindGeneratorTarget(std::string const& name) const;

  void AddAlias(std::string const& name, std::string const& tgtName);
  bool IsAlias(std::string const& name) const;

  /** Determine if a name resolves to a framework on disk or a built target
      that is a framework. */
  bool NameResolvesToFramework(std::string const& libname) const;
  /** Split a framework path to the directory and name of the framework as well
   * as optional suffix.
   * Returns std::nullopt if the path does not match with framework format
   * when extendedFormat is true, required format is relaxed (i.e. extension
   * `.framework' is optional). Used when FRAMEWORK link feature is
   * specified */
  struct FrameworkDescriptor
  {
    FrameworkDescriptor(std::string directory, std::string name)
      : Directory(std::move(directory))
      , Name(std::move(name))
    {
    }
    FrameworkDescriptor(std::string directory, std::string version,
                        std::string name)
      : Directory(std::move(directory))
      , Version(std::move(version))
      , Name(std::move(name))
    {
    }
    FrameworkDescriptor(std::string directory, std::string version,
                        std::string name, std::string suffix)
      : Directory(std::move(directory))
      , Version(std::move(version))
      , Name(std::move(name))
      , Suffix(std::move(suffix))
    {
    }
    std::string GetLinkName() const
    {
      return this->Suffix.empty() ? this->Name
                                  : cmStrCat(this->Name, ',', this->Suffix);
    }
    std::string GetFullName() const
    {
      return cmStrCat(this->Name, ".framework/"_s, this->Name, this->Suffix);
    }
    std::string GetVersionedName() const
    {
      return this->Version.empty()
        ? this->GetFullName()
        : cmStrCat(this->Name, ".framework/Versions/"_s, this->Version, '/',
                   this->Name, this->Suffix);
    }
    std::string GetFrameworkPath() const
    {
      return this->Directory.empty()
        ? cmStrCat(this->Name, ".framework"_s)
        : cmStrCat(this->Directory, '/', this->Name, ".framework"_s);
    }
    std::string GetFullPath() const
    {
      return this->Directory.empty()
        ? this->GetFullName()
        : cmStrCat(this->Directory, '/', this->GetFullName());
    }
    std::string GetVersionedPath() const
    {
      return this->Directory.empty()
        ? this->GetVersionedName()
        : cmStrCat(this->Directory, '/', this->GetVersionedName());
    }

    std::string const Directory;
    std::string const Version;
    std::string const Name;
    std::string const Suffix;
  };
  enum class FrameworkFormat
  {
    Strict,
    Relaxed,
    Extended
  };
  cm::optional<FrameworkDescriptor> SplitFrameworkPath(
    std::string const& path,
    FrameworkFormat format = FrameworkFormat::Relaxed) const;

  cmMakefile* FindMakefile(std::string const& start_dir) const;
  cmLocalGenerator* FindLocalGenerator(cmDirectoryId const& id) const;

  /** Append the subdirectory for the given configuration.  If anything is
      appended the given prefix and suffix will be appended around it, which
      is useful for leading or trailing slashes.  */
  virtual void AppendDirectoryForConfig(std::string const& prefix,
                                        std::string const& config,
                                        std::string const& suffix,
                                        std::string& dir);

  /** Get the content of a directory.  Directory listings are cached
      and re-loaded from disk only when modified.  During the generation
      step the content will include the target files to be built even if
      they do not yet exist.  */
  std::set<std::string> const& GetDirectoryContent(std::string const& dir,
                                                   bool needDisk = true);

  void IndexTarget(cmTarget* t);
  void IndexGeneratorTarget(cmGeneratorTarget* gt);

  // Index the target using a name that is unique to that target
  // even if other targets have the same name.
  std::string IndexGeneratorTargetUniquely(cmGeneratorTarget const* gt);

  static bool IsReservedTarget(std::string const& name);

  virtual char const* GetAllTargetName() const { return "ALL_BUILD"; }
  virtual char const* GetInstallTargetName() const { return "INSTALL"; }
  virtual char const* GetInstallLocalTargetName() const { return nullptr; }
  virtual char const* GetInstallStripTargetName() const { return nullptr; }
  virtual char const* GetPreinstallTargetName() const { return nullptr; }
  virtual char const* GetTestTargetName() const { return "RUN_TESTS"; }
  virtual char const* GetPackageTargetName() const { return "PACKAGE"; }
  virtual char const* GetPackageSourceTargetName() const { return nullptr; }
  virtual char const* GetEditCacheTargetName() const { return nullptr; }
  virtual char const* GetRebuildCacheTargetName() const { return nullptr; }
  virtual char const* GetCleanTargetName() const { return nullptr; }

  // Lookup edit_cache target command preferred by this generator.
  virtual std::string GetEditCacheCommand() const { return ""; }

  // Default config to use for cmake --build
  virtual std::string GetDefaultBuildConfig() const { return "Debug"; }

  virtual cmValue GetDebuggerWorkingDirectory(cmGeneratorTarget* gt) const;

  // Class to track a set of dependencies.
  using TargetDependSet = cmTargetDependSet;

  // what targets does the specified target depend on directly
  // via a target_link_libraries or add_dependencies
  TargetDependSet const& GetTargetDirectDepends(
    cmGeneratorTarget const* target) const;

  // Return true if target 'l' occurs before 'r' in a global ordering
  // of targets that respects inter-target dependencies.
  bool TargetOrderIndexLess(cmGeneratorTarget const* l,
                            cmGeneratorTarget const* r) const;

  std::map<std::string, std::vector<cmLocalGenerator*>> const& GetProjectMap()
    const
  {
    return this->ProjectMap;
  }

  // track files replaced during a Generate
  void FileReplacedDuringGenerate(std::string const& filename);
  void GetFilesReplacedDuringGenerate(std::vector<std::string>& filenames);

  void AddRuleHash(std::vector<std::string> const& outputs,
                   std::string const& content);

  /** Return whether the given binary directory is unused.  */
  bool BinaryDirectoryIsNew(std::string const& dir)
  {
    return this->BinaryDirectories.insert(dir).second;
  }

  /** Return true if the generated build tree may contain multiple builds.
      i.e. "Can I build Debug and Release in the same tree?" */
  virtual bool IsMultiConfig() const { return false; }

  virtual bool IsXcode() const { return false; }

  virtual bool IsVisualStudio() const { return false; }

  virtual bool IsVisualStudioAtLeast10() const { return false; }

  virtual bool IsNinja() const { return false; }

  virtual bool IsFastbuild() const { return false; }

  /** Return true if we know the exact location of object files for the given
     cmTarget. If false, store the reason in the given string. This is
     meaningful only after EnableLanguage has been called.  */
  virtual bool HasKnownObjectFileLocation(cmTarget const&, std::string*) const
  {
    return true;
  }

  virtual bool UseFolderProperty() const;

  virtual bool IsIPOSupported() const { return false; }

  /** Return whether the generator can import external visual studio project
      using INCLUDE_EXTERNAL_MSPROJECT */
  virtual bool IsIncludeExternalMSProjectSupported() const { return false; }

  /** Return whether the generator should use EFFECTIVE_PLATFORM_NAME. This is
      relevant for mixed macOS and iOS builds. */
  virtual bool UseEffectivePlatformName(cmMakefile*) const { return false; }

  /** Return whether the "Resources" folder prefix should be stripped from
      MacFolder. */
  virtual bool ShouldStripResourcePath(cmMakefile*) const;

  virtual bool SupportsCustomCommandDepfile() const { return false; }
  virtual cm::optional<cmDepfileFormat> DepfileFormat() const
  {
    return cm::nullopt;
  }

  virtual bool SupportsLinkerDependencyFile() const { return false; }

  /** Generate an <output>.rule file path for a given command output.  */
  virtual std::string GenerateRuleFile(std::string const& output) const;

  virtual bool SupportsDefaultBuildType() const { return false; }
  virtual bool SupportsCrossConfigs() const { return false; }
  virtual bool SupportsDefaultConfigs() const { return false; }

  virtual std::string ConvertToOutputPath(std::string path) const
  {
    return path;
  }
  virtual std::string GetConfigDirectory(std::string const& config) const
  {
    if (!this->IsMultiConfig() || config.empty()) {
      return {};
    }
    return cmStrCat('/', config);
  }

  static std::string EscapeJSON(std::string const& s);

  void ProcessEvaluationFiles();

  std::map<std::string, cmExportBuildFileGenerator*>& GetBuildExportSets()
  {
    return this->BuildExportSets;
  }
  /** Scan all build-tree exports in the project and report which of them
   *  reference `target`.  Used both by cmExportBuildFileGenerator (to resolve
   *  out-of-export link references) and by cmSbomBuilder (to record which
   *  export sets a target appears in for SBOM dependency tracking).  */
  cmExportFileGenerator::ExportInfo FindBuildExportInfo(
    cmGeneratorTarget const* target) const;

  /** Same as FindBuildExportInfo, but searches install-tree export sets
   *  (those registered via install(EXPORT ...)). */
  cmExportFileGenerator::ExportInfo FindInstallExportInfo(
    cmGeneratorTarget const* target) const;

  /** Scan all build-tree SBOMs and report which of them cover `target`. */
  cmSbomBuilder::SbomInfo FindBuildSbomInfo(
    cmGeneratorTarget const* target) const;

  /** Same as FindBuildSbomInfo, but searches install-tree SBOMs. */
  cmSbomBuilder::SbomInfo FindInstallSbomInfo(
    cmGeneratorTarget const* target) const;
  void AddBuildExportSet(cmExportBuildFileGenerator* gen);
  void AddBuildExportExportSet(cmExportBuildFileGenerator* gen);
  void AddBuildSbomGenerator(cmBuildSbomGenerator* gen);
  std::vector<cmBuildSbomGenerator*> const& GetBuildSbomGenerators() const
  {
    return this->BuildSbomGenerators;
  }

  // Project-wide registry of install(SBOM) generators.
  void AddInstallSbomGenerator(cmInstallSbomGenerator const* gen);
  std::vector<cmInstallSbomGenerator const*> const& GetInstallSbomGenerators()
    const
  {
    return this->InstallSbomGenerators;
  }

  bool IsExportedTargetsFile(std::string const& filename) const;

  /** True if any registered cmBuildSbomGenerator already targets this
   *  output file path.  Used to diagnose duplicate `export(SBOM ...)`
   *  calls that would otherwise silently clobber each other's output. */
  bool IsBuildSbomFile(std::string const& filepath) const;

  /** True if any registered cmInstallSbomGenerator already targets this
   *  install file path (DESTINATION + filename).  Used to diagnose
   *  duplicate `install(SBOM ...)` calls that would otherwise silently
   *  clobber each other at install time. */
  bool IsInstallSbomFile(std::string const& filepath) const;

  cmExportBuildFileGenerator* GetExportedTargetsFile(
    std::string const& filename) const;
  void AddCMP0068WarnTarget(std::string const& target);

  virtual bool SupportsShortObjectNames() const;
  bool UseShortObjectNames(
    cmStateEnums::IntermediateDirKind kind =
      cmStateEnums::IntermediateDirKind::ObjectFiles) const;
  virtual std::string GetShortBinaryOutputDir() const;
  std::string ComputeTargetShortName(std::string const& bindir,
                                     std::string const& targetName) const;
  struct TargetDirectoryRegistration
  {
    TargetDirectoryRegistration() = default;
    TargetDirectoryRegistration(cmGeneratorTarget const* t, bool w)
      : CollidesWith(t)
      , Warned(w)
    {
    }

    cmGeneratorTarget const* CollidesWith = nullptr;
    bool Warned = false;
  };
  TargetDirectoryRegistration& RegisterTargetDirectory(
    cmGeneratorTarget const* tgt, std::string const& targetDir) const;

  virtual void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const;

  bool GenerateCPackPropertiesFile();

  void SetFilenameTargetDepends(
    cmSourceFile* sf, std::set<cmGeneratorTarget const*> const& tgts);
  std::set<cmGeneratorTarget const*> const& GetFilenameTargetDepends(
    cmSourceFile* sf) const;

#if !defined(CMAKE_BOOTSTRAP)
  cmFileLockPool& GetFileLockPool() { return this->FileLockPool; }
#endif

  std::string MakeSilentFlag;

  size_t RecursionDepth = 0;

  virtual void GetQtAutoGenConfigs(std::vector<std::string>& configs) const
  {
    configs.emplace_back("$<CONFIG>");
  }

  std::string const& GetRealPath(std::string const& dir);

  std::string NewDeferId();

  cmInstallRuntimeDependencySet* CreateAnonymousRuntimeDependencySet();

  cmInstallRuntimeDependencySet* GetNamedRuntimeDependencySet(
    std::string const& name);

  enum class StripCommandStyle
  {
    Default,
    Apple,
  };
  StripCommandStyle GetStripCommandStyle(std::string const& strip);

  std::string GetEncodedLiteral(std::string const& lit);
  virtual std::string& EncodeLiteral(std::string& lit) { return lit; }

  bool CheckCMP0171() const;

  void AddInstallScript(std::string const& file);
  void AddTestFile(std::string const& file);
  void AddCMakeFilesToRebuild(std::vector<std::string>& files) const;

  virtual std::set<std::string> const& GetDefaultConfigs() const
  {
    static std::set<std::string> configs;
    return configs;
  }

  bool ShouldWarnCMP0210(std::string const& lang);

  bool ShouldWarnExperimental(cm::string_view featureName,
                              cm::string_view featureUuid);

  cm::optional<cmXcFrameworkPlist> GetXcFrameworkPListContent(
    std::string const& path) const;
  void SetXcFrameworkPListContent(std::string const& path,
                                  cmXcFrameworkPlist const& content);

protected:
  /** Get all targets produced under the given root, plus the transitive
      closure of targets on which they depend, possibly from other dirs.  */
  TargetDependSet GetTargetsForProject(
    cmLocalGenerator const* root,
    std::vector<cmLocalGenerator*> const& generators) const;

  bool IsRootOnlyTarget(cmGeneratorTarget* target) const;
  void AddTargetDepends(cmGeneratorTarget const* target,
                        TargetDependSet& projectTargets) const;
  void SetLanguageEnabledFlag(std::string const& l, cmMakefile* mf);
  void SetLanguageEnabledMaps(std::string const& l, cmMakefile* mf);
  void FillExtensionToLanguageMap(std::string const& l, cmMakefile* mf);
  virtual bool CheckLanguages(std::vector<std::string> const& languages,
                              cmMakefile* mf) const;
  virtual void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
                                   cmValue envVar) const;

  virtual bool ComputeTargetDepends();

#if !defined(CMAKE_BOOTSTRAP)
  void WriteJsonContent(std::string const& fname,
                        Json::Value const& value) const;
  void WriteInstallJson() const;
#endif

  virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const;

  bool ApplyCXXStdTarget();
  void WriteCxxImportErrorModules();
  bool DiscoverSyntheticTargets();

  bool AddHeaderSetVerification();

  void CreateFileGenerateOutputs();
  bool AddAutomaticSources();

  std::string SelectMakeProgram(std::string const& makeProgram,
                                std::string const& makeDefault = "") const;

  // Fill the ProjectMap, this must be called after LocalGenerators
  // has been populated.
  void FillProjectMap();
  void CheckTargetProperties();
  bool IsExcluded(cmStateSnapshot const& root,
                  cmStateSnapshot const& snp) const;
  bool IsExcluded(cmLocalGenerator const* root,
                  cmLocalGenerator const* gen) const;
  bool IsExcluded(cmLocalGenerator const* root,
                  cmGeneratorTarget const* target) const;
  virtual void InitializeProgressMarks() {}

  struct GlobalTargetInfo
  {
    std::string Name;
    std::string Message;
    cmCustomCommandLines CommandLines;
    std::vector<std::string> Depends;
    std::string WorkingDir;
    bool UsesTerminal = false;
    cmTarget::PerConfig PerConfig = cmTarget::PerConfig::Yes;
    bool StdPipesUTF8 = false;
    std::string Role;
  };

  void CreateDefaultGlobalTargets(std::vector<GlobalTargetInfo>& targets);

  void AddGlobalTarget_Package(std::vector<GlobalTargetInfo>& targets);
  void AddGlobalTarget_PackageSource(std::vector<GlobalTargetInfo>& targets);
  void AddGlobalTarget_Test(std::vector<GlobalTargetInfo>& targets);
  void AddGlobalTarget_EditCache(std::vector<GlobalTargetInfo>& targets) const;
  void AddGlobalTarget_RebuildCache(
    std::vector<GlobalTargetInfo>& targets) const;
  void AddGlobalTarget_Install(std::vector<GlobalTargetInfo>& targets);
  void CreateGlobalTarget(GlobalTargetInfo const& gti, cmMakefile* mf);

  void ReserveGlobalTargetCodegen();

  std::string FindMakeProgramFile;
  std::string ConfiguredFilesPath;
  cmake* CMakeInstance;
  std::vector<std::unique_ptr<cmMakefile>> Makefiles;
  LocalGeneratorVector LocalGenerators;

#ifndef CMAKE_BOOTSTRAP
  std::unique_ptr<cmQtAutoGenGlobalInitializer> QtAutoGen;
#endif

  cmMakefile* CurrentConfigureMakefile;
  // map from project name to vector of local generators in that project
  std::map<std::string, std::vector<cmLocalGenerator*>> ProjectMap;

  // Set of named installation components requested by the project.
  std::set<std::string> InstallComponents;
  // Sets of named target exports
  cmExportSetMap ExportSets;
  std::map<std::string, cmExportBuildFileGenerator*> BuildExportSets;
  std::map<std::string, cmExportBuildFileGenerator*> BuildExportExportSets;
  std::vector<cmBuildSbomGenerator*> BuildSbomGenerators;
  std::vector<cmInstallSbomGenerator const*> InstallSbomGenerators;

  std::map<std::string, std::string> AliasTargets;

  cmTarget* FindTargetImpl(std::string const& name,
                           cm::TargetDomainSet domains) const;

  cmGeneratorTarget* FindGeneratorTargetImpl(std::string const& name) const;

  std::string GetPredefinedTargetsFolder() const;

private:
  using TargetMap = std::unordered_map<std::string, cmTarget*>;
  using GeneratorTargetMap =
    std::unordered_map<std::string, cmGeneratorTarget*>;
  using MakefileMap = std::unordered_map<std::string, cmMakefile*>;
  using LocalGeneratorMap = std::unordered_map<std::string, cmLocalGenerator*>;
  using TargetDirectoryRegistrationMap =
    std::map<cmGeneratorTarget const*, TargetDirectoryRegistration>;
  using TargetDirectoryMap =
    std::unordered_map<std::string, std::set<cmGeneratorTarget const*>>;
  // Map efficiently from target name to cmTarget instance.
  // Do not use this structure for looping over all targets.
  // It contains both normal and globally visible imported targets.
  TargetMap TargetSearchIndex;
  GeneratorTargetMap GeneratorTargetSearchIndex;

  // Map from target to a directory registration.
  mutable TargetDirectoryRegistrationMap TargetDirectoryRegistrations;
  // Map from target directories to targets using it.
  mutable TargetDirectoryMap TargetDirectories;

  // Map efficiently from source directory path to cmMakefile instance.
  // Do not use this structure for looping over all directories.
  // It may not contain all of them (see note in IndexMakefile method).
  MakefileMap MakefileSearchIndex;

  // Map efficiently from source directory path to cmLocalGenerator instance.
  // Do not use this structure for looping over all directories.
  // Its order is not deterministic.
  LocalGeneratorMap LocalGeneratorSearchIndex;

  void ComputeTargetOrder();
  void ComputeTargetOrder(cmGeneratorTarget const* gt, size_t& index);
  std::map<cmGeneratorTarget const*, size_t> TargetOrderIndex;

  cmMakefile* TryCompileOuterMakefile;
  std::map<std::string, bool> IgnoreExtensions;
  std::set<std::string> LanguagesReadyForTryCompile;
  std::set<std::string> LanguagesInProgress;
  std::map<std::string, std::string> OutputExtensions;
  std::map<std::string, std::string> LanguageToOutputExtension;
  std::map<std::string, std::string> RustEmitToOutputExtension;
#if __cplusplus >= 201402L || defined(_MSVC_LANG) && _MSVC_LANG >= 201402L
  std::map<std::string, std::string, std::less<void>> ExtensionToLanguage;
#else
  std::map<std::string, std::string> ExtensionToLanguage;
#endif
  std::map<std::string, int> LanguageToLinkerPreference;

#if !defined(CMAKE_BOOTSTRAP)
  std::unique_ptr<Json::StreamWriter> JsonWriter;
#endif

#ifdef __APPLE__
  std::map<std::string, StripCommandStyle> StripCommandStyleMap;
#endif

  // Deferral id generation.
  size_t NextDeferId = 0;

  // Record hashes for rules and outputs.
  struct RuleHash
  {
    char Data[32];
  };
  std::map<std::string, RuleHash> RuleHashes;
  void CheckRuleHashes();
  void CheckRuleHashes(std::string const& pfile, std::string const& home);
  void WriteRuleHashes(std::string const& pfile);

  void WriteSummary();
  void WriteSummary(cmGeneratorTarget* target);
  void FinalizeTargetConfiguration();

  virtual void ForceLinkerLanguages();

  void CheckTargetLinkLibraries() const;
  bool CheckTargetsForMissingSources() const;
  bool CheckTargetsForType() const;
  void MarkTargetsForPchReuse() const;

  void CreateLocalGenerators();

  void CheckCompilerIdCompatibility(cmMakefile* mf,
                                    std::string const& lang) const;

  void ComputeBuildFileGenerators();

  std::unique_ptr<cmExternalMakefileProjectGenerator> ExtraGenerator;

  // track files replaced during a Generate
  std::vector<std::string> FilesReplacedDuringGenerate;

  // Store computed inter-target dependencies.
  using TargetDependMap = std::map<cmGeneratorTarget const*, TargetDependSet>;
  TargetDependMap TargetDependencies;

  // Map from a custom-command primary output (collapsed full path) to the
  // build-system target(s) that produce it.  Built lazily on first use and
  // cleared with the other generator members.
  std::map<std::string, std::vector<cmGeneratorTarget*>> OutputOwnerIndex;
  bool OutputOwnerIndexComputed = false;
  void ComputeOutputOwnerIndex();

  friend class cmake;
  void CreateGeneratorTargets(
    TargetTypes targetTypes, cmMakefile* mf, cmLocalGenerator* lg,
    std::map<cmTarget*, cmGeneratorTarget*> const& importedMap);
  void CreateGeneratorTargets(TargetTypes targetTypes);

  void ClearGeneratorMembers();

  bool CheckReservedTargetName(std::string const& targetName,
                               std::string const& reason) const;
  bool CheckReservedTargetNamePrefix(std::string const& targetPrefix,
                                     std::string const& reason) const;

  void IndexMakefile(cmMakefile* mf);
  void IndexLocalGenerator(cmLocalGenerator* lg);

  virtual char const* GetBuildIgnoreErrorsFlag() const { return nullptr; }

  bool UnsupportedVariableIsDefined(std::string const& name,
                                    bool supported) const;

  // Cache directory content and target files to be built.
  struct DirectoryContent
  {
    long LastDiskTime = -1;
    std::set<std::string> All;
    std::set<std::string> Generated;
  };
  std::map<std::string, DirectoryContent> DirectoryContentMap;

  // Cache parsed PList files
  std::map<std::string, cmXcFrameworkPlist> XcFrameworkPListContentMap;

  // Set of binary directories on disk.
  std::set<std::string> BinaryDirectories;

  // track targets to issue CMP0068 warning for.
  std::set<std::string> CMP0068WarnTargets;

  std::unordered_set<std::string> WarnedCMP0210Languages;

  std::unordered_set<std::string> WarnedExperimental;

  mutable std::map<cmSourceFile*, std::set<cmGeneratorTarget const*>>
    FilenameTargetDepends;

  std::map<std::string, std::string> RealPaths;

  std::unordered_set<std::string> GeneratedFiles;

  std::vector<std::unique_ptr<cmInstallRuntimeDependencySet>>
    RuntimeDependencySets;
  std::map<std::string, cmInstallRuntimeDependencySet*>
    RuntimeDependencySetsByName;

  std::vector<std::string> InstallScripts;
  std::vector<std::string> TestFiles;

#if !defined(CMAKE_BOOTSTRAP)
  // Pool of file locks
  cmFileLockPool FileLockPool;
#endif

  using PerLanguageModuleDatabases =
    std::map<std::string, std::vector<std::string>>;
  using PerConfigModuleDatabases =
    std::map<std::string, PerLanguageModuleDatabases>;
  PerConfigModuleDatabases PerConfigModuleDbs;
  PerLanguageModuleDatabases PerLanguageModuleDbs;

  enum class IntermediateDirStrategy
  {
    Full,
    Short,
  };
  IntermediateDirStrategy IntDirStrategy = IntermediateDirStrategy::Full;
  IntermediateDirStrategy QtAutogenIntDirStrategy =
    IntermediateDirStrategy::Full;

protected:
  float FirstTimeProgress;
  bool NeedSymbolicMark;
  bool UseLinkScript;
  bool ForceUnixPaths;
  bool ToolSupportsColor;
  bool InstallTargetEnabled;
  bool AllowGlobalTargetCodegen;
};
