/* 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 "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;
  bool RequiresOutputForward = false;
};
}
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"; }

  /** 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;

  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,
                       cmStateEnums::TargetDomainSet domains = {
                         cmStateEnums::TargetDomain::NATIVE,
                         cmStateEnums::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();
  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,
                           cmStateEnums::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;

  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;
};
