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

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

#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_codecvt_Encoding.hxx"

#include "cmBuildOptions.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalCommonGenerator.h"
#include "cmGlobalGeneratorFactory.h"
#include "cmNinjaTypes.h"
#include "cmPolicies.h"
#include "cmStringAlgorithms.h"
#include "cmTransformDepfile.h"

class cmCustomCommand;
class cmGeneratorTarget;
class cmLinkLineComputer;
class cmLocalGenerator;
class cmMakefile;
class cmOutputConverter;
class cmStateDirectory;
class cmake;
struct cmCxxModuleExportInfo;

/**
 * \class cmGlobalNinjaGenerator
 * \brief Write a build.ninja file.
 *
 * The main differences between this generator and the UnixMakefile
 * generator family are:
 * - We don't care about VERBOSE variable or RULE_MESSAGES property since
 *   it is handle by Ninja's -v option.
 * - We don't care about computing any progress status since Ninja manages
 *   it itself.
 * - We generate one build.ninja and one rules.ninja per project.
 * - We try to minimize the number of generated rules: one per target and
 *   language.
 * - We use Ninja special variable $in and $out to produce nice output.
 * - We extensively use Ninja variable overloading system to minimize the
 *   number of generated rules.
 */
class cmGlobalNinjaGenerator : public cmGlobalCommonGenerator
{
public:
  /// The default name of Ninja's build file. Typically: build.ninja.
  static const char* NINJA_BUILD_FILE;

  /// The default name of Ninja's rules file. Typically: rules.ninja.
  /// It is included in the main build.ninja file.
  static const char* NINJA_RULES_FILE;

  /// The indentation string used when generating Ninja's build file.
  static const char* INDENT;

  /// The shell command used for a no-op.
  static std::string const SHELL_NOOP;

  /// Write @a count times INDENT level to output stream @a os.
  static void Indent(std::ostream& os, int count);

  /// Write a divider in the given output stream @a os.
  static void WriteDivider(std::ostream& os);

  static std::string EncodeRuleName(std::string const& name);
  std::string& EncodeLiteral(std::string& lit) override;
  std::string GetEncodedLiteral(const std::string& lit);
  std::string EncodePath(const std::string& path);

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

  /**
   * Write the given @a comment to the output stream @a os. It
   * handles new line character properly.
   */
  static void WriteComment(std::ostream& os, const std::string& comment);

  /**
   * Utilized by the generator factory to determine if this generator
   * supports toolsets.
   */
  static bool SupportsToolset() { return false; }

  /**
   * Utilized by the generator factory to determine if this generator
   * supports platforms.
   */
  static bool SupportsPlatform() { return false; }

  bool IsIPOSupported() const override { return true; }

  /**
   * Write a build statement @a build to @a os.
   * @warning no escaping of any kind is done here.
   */
  void WriteBuild(std::ostream& os, cmNinjaBuild const& build,
                  int cmdLineLimit = 0, bool* usedResponseFile = nullptr);

  class CCOutputs
  {
    cmGlobalNinjaGenerator* GG;

  public:
    CCOutputs(cmGlobalNinjaGenerator* gg)
      : GG(gg)
    {
    }
    void Add(std::vector<std::string> const& outputs);
    cmNinjaDeps ExplicitOuts;
    cmNinjaDeps WorkDirOuts;
  };

  void WriteCustomCommandBuild(std::string const& command,
                               std::string const& description,
                               std::string const& comment,
                               std::string const& depfile,
                               std::string const& pool, bool uses_terminal,
                               bool restat, std::string const& config,
                               CCOutputs outputs,
                               cmNinjaDeps explicitDeps = cmNinjaDeps(),
                               cmNinjaDeps orderOnlyDeps = cmNinjaDeps());

  void WriteMacOSXContentBuild(std::string input, std::string output,
                               const std::string& config);

  /**
   * Write a rule statement to @a os.
   * @warning no escaping of any kind is done here.
   */
  static void WriteRule(std::ostream& os, cmNinjaRule const& rule);

  /**
   * Write a variable named @a name to @a os with value @a value and an
   * optional @a comment. An @a indent level can be specified.
   * @warning no escaping of any kind is done here.
   */
  static void WriteVariable(std::ostream& os, const std::string& name,
                            const std::string& value,
                            const std::string& comment = "", int indent = 0);

  /**
   * Write an include statement including @a filename with an optional
   * @a comment to the @a os stream.
   */
  static void WriteInclude(std::ostream& os, const std::string& filename,
                           const std::string& comment = "");

  /**
   * Write a default target statement specifying @a targets as
   * the default targets.
   */
  static void WriteDefault(std::ostream& os, const cmNinjaDeps& targets,
                           const std::string& comment = "");

  bool IsGCCOnWindows() const { return this->UsingGCCOnWindows; }
  void MarkAsGCCOnWindows() { this->UsingGCCOnWindows = true; }

  cmGlobalNinjaGenerator(cmake* cm);

  static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory()
  {
    return std::unique_ptr<cmGlobalGeneratorFactory>(
      new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaGenerator>());
  }

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

  std::string GetName() const override
  {
    return cmGlobalNinjaGenerator::GetActualName();
  }

  static std::string GetActualName() { return "Ninja"; }

  bool IsNinja() const override { return true; }

  /** Get encoding used by generator for ninja files */
  codecvt_Encoding GetMakefileEncoding() const override;

  static cmDocumentationEntry GetDocumentation();

  void EnableLanguage(std::vector<std::string> const& languages,
                      cmMakefile* mf, bool optional) override;

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

  // Setup target names
  const char* GetAllTargetName() const override { return "all"; }
  const char* GetInstallTargetName() const override { return "install"; }
  const char* GetInstallLocalTargetName() const override
  {
    return "install/local";
  }
  const char* GetInstallStripTargetName() const override
  {
    return "install/strip";
  }
  const char* GetInstallParallelTargetName() const
  {
    return "install/parallel";
  }
  const char* GetTestTargetName() const override { return "test"; }
  const char* GetPackageTargetName() const override { return "package"; }
  const char* GetPackageSourceTargetName() const override
  {
    return "package_source";
  }
  const char* GetRebuildCacheTargetName() const override
  {
    return "rebuild_cache";
  }
  const char* GetCleanTargetName() const override { return "clean"; }

  bool SupportsCustomCommandDepfile() const override { return true; }
  cm::optional<cmDepfileFormat> DepfileFormat() const override
  {
    return cmDepfileFormat::GccDepfile;
  }

  bool SupportsLinkerDependencyFile() const override { return true; }

  virtual cmGeneratedFileStream* GetImplFileStream(
    const std::string& /*config*/) const
  {
    return this->BuildFileStream.get();
  }

  virtual cmGeneratedFileStream* GetConfigFileStream(
    const std::string& /*config*/) const
  {
    return this->BuildFileStream.get();
  }

  virtual cmGeneratedFileStream* GetDefaultFileStream() const
  {
    return this->BuildFileStream.get();
  }

  virtual cmGeneratedFileStream* GetCommonFileStream() const
  {
    return this->BuildFileStream.get();
  }

  cmGeneratedFileStream* GetRulesFileStream() const
  {
    return this->RulesFileStream.get();
  }

  std::string const& ConvertToNinjaPath(const std::string& path) const;
  std::string ConvertToNinjaAbsPath(std::string path) const;

  struct MapToNinjaPathImpl
  {
    cmGlobalNinjaGenerator* GG;
    MapToNinjaPathImpl(cmGlobalNinjaGenerator* gg)
      : GG(gg)
    {
    }
    std::string operator()(std::string const& path) const
    {
      return this->GG->ConvertToNinjaPath(path);
    }
  };
  MapToNinjaPathImpl MapToNinjaPath() { return { this }; }

#ifdef _WIN32
  std::string const& GetComspec() const { return this->Comspec; }
#endif

  // -- Additional clean files
  void AddAdditionalCleanFile(std::string fileName, const std::string& config);
  const char* GetAdditionalCleanTargetName() const
  {
    return "CMakeFiles/clean.additional";
  }

  static const char* GetByproductsForCleanTargetName()
  {
    return "CMakeFiles/cmake_byproducts_for_clean_target";
  }

  void AddCXXCompileCommand(const std::string& commandLine,
                            const std::string& sourceFile,
                            const std::string& objPath);

  /**
   * Add a rule to the generated build system.
   * Call WriteRule() behind the scene but perform some check before like:
   * - Do not add twice the same rule.
   */
  void AddRule(cmNinjaRule const& rule);

  bool HasRule(const std::string& name);

  void AddCustomCommandRule();
  void AddMacOSXContentRule();

  bool HasCustomCommandOutput(const std::string& output)
  {
    return this->CustomCommandOutputs.find(output) !=
      this->CustomCommandOutputs.end();
  }

  /// Called when we have seen the given custom command.  Returns true
  /// if we has seen it before.
  bool SeenCustomCommand(cmCustomCommand const* cc, const std::string& config)
  {
    return !this->Configs[config].CustomCommands.insert(cc).second;
  }

  /// Called when we have seen the given custom command output.
  void SeenCustomCommandOutput(const std::string& output)
  {
    this->CustomCommandOutputs.insert(output);
    // We don't need the assumed dependencies anymore, because we have
    // an output.
    this->AssumedSourceDependencies.erase(output);
  }

  void AddAssumedSourceDependencies(const std::string& source,
                                    const cmNinjaDeps& deps)
  {
    std::set<std::string>& ASD = this->AssumedSourceDependencies[source];
    // Because we may see the same source file multiple times (same source
    // specified in multiple targets), compute the union of any assumed
    // dependencies.
    ASD.insert(deps.begin(), deps.end());
  }

  virtual std::string OrderDependsTargetForTarget(
    cmGeneratorTarget const* target, const std::string& config) const;

  std::string OrderDependsTargetForTargetPrivate(
    cmGeneratorTarget const* target, const std::string& config) const;

  void AppendTargetOutputs(cmGeneratorTarget const* target,
                           cmNinjaDeps& outputs, const std::string& config,
                           cmNinjaTargetDepends depends) const;
  void AppendTargetDepends(cmGeneratorTarget const* target,
                           cmNinjaDeps& outputs, const std::string& config,
                           const std::string& fileConfig,
                           cmNinjaTargetDepends depends);
  void AppendTargetDependsClosure(cmGeneratorTarget const* target,
                                  std::unordered_set<std::string>& outputs,
                                  const std::string& config,
                                  const std::string& fileConfig,
                                  bool genexOutput, bool omit_self = true);

  void AppendDirectoryForConfig(const std::string& prefix,
                                const std::string& config,
                                const std::string& suffix,
                                std::string& dir) override;

  virtual void AppendNinjaFileArgument(GeneratedMakeCommand& /*command*/,
                                       const std::string& /*config*/) const
  {
  }

  virtual void AddRebuildManifestOutputs(cmNinjaDeps& outputs) const
  {
    outputs.push_back(this->NinjaOutputPath(NINJA_BUILD_FILE));
  }

  int GetRuleCmdLength(const std::string& name)
  {
    return this->RuleCmdLength[name];
  }

  void AddTargetAlias(const std::string& alias, cmGeneratorTarget* target,
                      const std::string& config);

  void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override;

  // Ninja generator uses 'deps' and 'msvc_deps_prefix' introduced in 1.3
  static std::string RequiredNinjaVersion() { return "1.3"; }
  static std::string RequiredNinjaVersionForConsolePool() { return "1.5"; }
  static std::string RequiredNinjaVersionForImplicitOuts() { return "1.7"; }
  static std::string RequiredNinjaVersionForManifestRestat() { return "1.8"; }
  static std::string RequiredNinjaVersionForMultilineDepfile()
  {
    return "1.9";
  }
  static std::string RequiredNinjaVersionForDyndepsCxx() { return "1.11"; }
  static std::string RequiredNinjaVersionForDyndepsFortran() { return "1.10"; }
  static std::string RequiredNinjaVersionForRestatTool() { return "1.10"; }
  static std::string RequiredNinjaVersionForUnconditionalRecompactTool()
  {
    return "1.10";
  }
  static std::string RequiredNinjaVersionForMultipleOutputs()
  {
    return "1.10";
  }
  static std::string RequiredNinjaVersionForMetadataOnRegeneration()
  {
    return "1.10.2";
  }
  static std::string RequiredNinjaVersionForCodePage() { return "1.11"; }
  static std::string RequiredNinjaVersionForCWDDepend() { return "1.7"; }
  bool SupportsDirectConsole() const override;
  bool SupportsImplicitOuts() const;
  bool SupportsManifestRestat() const;
  bool SupportsMultilineDepfile() const;
  bool SupportsCWDDepend() const;

  std::string NinjaOutputPath(std::string const& path) const;
  bool HasOutputPathPrefix() const { return !this->OutputPathPrefix.empty(); }
  void StripNinjaOutputPathPrefixAsSuffix(std::string& path);

  bool WriteDyndepFile(
    std::string const& dir_top_src, std::string const& dir_top_bld,
    std::string const& dir_cur_src, std::string const& dir_cur_bld,
    std::string const& arg_dd, std::vector<std::string> const& arg_ddis,
    std::string const& module_dir,
    std::vector<std::string> const& linked_target_dirs,
    std::vector<std::string> const& forward_modules_from_target_dirs,
    std::string const& arg_lang, std::string const& arg_modmapfmt,
    cmCxxModuleExportInfo const& export_info);

  virtual std::string BuildAlias(const std::string& alias,
                                 const std::string& /*config*/) const
  {
    return alias;
  }

  virtual std::string ConfigDirectory(const std::string& /*config*/) const
  {
    return "";
  }

  cmNinjaDeps& GetByproductsForCleanTarget()
  {
    return this->ByproductsForCleanTarget;
  }

  cmNinjaDeps& GetByproductsForCleanTarget(const std::string& config)
  {
    return this->Configs[config].ByproductsForCleanTarget;
  }

  bool EnableCrossConfigBuild() const;

  std::set<std::string> GetCrossConfigs(const std::string& config) const;

  const std::set<std::string>& GetDefaultConfigs() const
  {
    return this->DefaultConfigs;
  }

  const std::set<std::string>& GetPerConfigUtilityTargets() const
  {
    return this->PerConfigUtilityTargets;
  }

  void AddPerConfigUtilityTarget(const std::string& name)
  {
    this->PerConfigUtilityTargets.insert(name);
  }

  bool IsSingleConfigUtility(cmGeneratorTarget const* target) const;

  bool CheckCxxModuleSupport(CxxModuleSupportQuery query) override;

protected:
  void Generate() override;

  bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const override { return true; }

  virtual bool OpenBuildFileStreams();
  virtual void CloseBuildFileStreams();

  bool OpenFileStream(std::unique_ptr<cmGeneratedFileStream>& stream,
                      const std::string& name);

  static cm::optional<std::set<std::string>> ListSubsetWithAll(
    const std::set<std::string>& all, const std::set<std::string>& defaults,
    const std::vector<std::string>& items);

  std::set<std::string> CrossConfigs;
  std::set<std::string> DefaultConfigs;
  std::string DefaultFileConfig;

private:
  bool FindMakeProgram(cmMakefile* mf) override;
  void CheckNinjaFeatures();
  void CheckNinjaCodePage();
  bool CheckLanguages(std::vector<std::string> const& languages,
                      cmMakefile* mf) const override;
  bool CheckFortran(cmMakefile* mf) const;
  bool CheckISPC(cmMakefile* mf) const;

  void CloseCompileCommandsStream();

  bool OpenRulesFileStream();
  void CloseRulesFileStream();
  void CleanMetaData();

  /// Write the common disclaimer text at the top of each build file.
  void WriteDisclaimer(std::ostream& os) const;

  void WriteAssumedSourceDependencies();

  void WriteTargetAliases(std::ostream& os);
  void WriteFolderTargets(std::ostream& os);
  void WriteUnknownExplicitDependencies(std::ostream& os);

  void WriteBuiltinTargets(std::ostream& os);
  void WriteTargetDefault(std::ostream& os);
  void WriteTargetRebuildManifest(std::ostream& os);
  bool WriteTargetCleanAdditional(std::ostream& os);
  void WriteTargetClean(std::ostream& os);
  void WriteTargetHelp(std::ostream& os);

  void ComputeTargetDependsClosure(
    cmGeneratorTarget const* target,
    std::set<cmGeneratorTarget const*>& depends);

  std::string CMakeCmd() const;
  std::string NinjaCmd() const;

  /// The file containing the build statement. (the relationship of the
  /// compilation DAG).
  std::unique_ptr<cmGeneratedFileStream> BuildFileStream;
  /// The file containing the rule statements. (The action attached to each
  /// edge of the compilation DAG).
  std::unique_ptr<cmGeneratedFileStream> RulesFileStream;
  std::unique_ptr<cmGeneratedFileStream> CompileCommandsStream;

  /// The set of rules added to the generated build system.
  std::unordered_set<std::string> Rules;

  /// Length of rule command, used by rsp file evaluation
  std::unordered_map<std::string, int> RuleCmdLength;

  bool UsingGCCOnWindows = false;

  /// The set of custom command outputs we have seen.
  std::set<std::string> CustomCommandOutputs;

  /// Whether we are collecting known build outputs and needed
  /// dependencies to determine unknown dependencies.
  bool ComputingUnknownDependencies = false;
  cmPolicies::PolicyStatus PolicyCMP0058 = cmPolicies::WARN;

  /// The combined explicit dependencies of custom build commands
  std::set<std::string> CombinedCustomCommandExplicitDependencies;

  /// When combined with CombinedCustomCommandExplicitDependencies it allows
  /// us to detect the set of explicit dependencies that have
  std::set<std::string> CombinedBuildOutputs;

  /// The mapping from source file to assumed dependencies.
  std::map<std::string, std::set<std::string>> AssumedSourceDependencies;

  /// Utility targets which have per-config outputs
  std::set<std::string> PerConfigUtilityTargets;

  struct TargetAlias
  {
    cmGeneratorTarget* GeneratorTarget;
    std::string Config;
  };
  using TargetAliasMap = std::map<std::string, TargetAlias>;
  TargetAliasMap TargetAliases;
  TargetAliasMap DefaultTargetAliases;

  /// the local cache for calls to ConvertToNinjaPath
  mutable std::unordered_map<std::string, std::string> ConvertToNinjaPathCache;

  std::string NinjaCommand;
  std::string NinjaVersion;
  bool NinjaSupportsConsolePool = false;
  bool NinjaSupportsImplicitOuts = false;
  bool NinjaSupportsManifestRestat = false;
  bool NinjaSupportsMultilineDepfile = false;
  bool NinjaSupportsDyndepsCxx = false;
  bool NinjaSupportsDyndepsFortran = false;
  bool NinjaSupportsRestatTool = false;
  bool NinjaSupportsUnconditionalRecompactTool = false;
  bool NinjaSupportsMultipleOutputs = false;
  bool NinjaSupportsMetadataOnRegeneration = false;
  bool NinjaSupportsCodePage = false;
  bool NinjaSupportsCWDDepend = false;

  codecvt_Encoding NinjaExpectedEncoding = codecvt_Encoding::None;

#ifdef _WIN32
  // Windows Command shell.
  std::string Comspec;
#endif

  bool DiagnosedCxxModuleNinjaSupport = false;

  void InitOutputPathPrefix();

  std::string OutputPathPrefix;
  std::string TargetAll;
  std::string CMakeCacheFile;

  struct ByConfig
  {
    std::set<std::string> AdditionalCleanFiles;

    /// The set of custom commands we have seen.
    std::set<cmCustomCommand const*> CustomCommands;

    struct TargetDependsClosureKey
    {
      cmGeneratorTarget const* Target;
      std::string Config;
      bool GenexOutput;
    };

    std::map<TargetDependsClosureKey, std::unordered_set<std::string>>
      TargetDependsClosures;

    TargetAliasMap TargetAliases;

    cmNinjaDeps ByproductsForCleanTarget;
  };
  std::map<std::string, ByConfig> Configs;

  cmNinjaDeps ByproductsForCleanTarget;

  friend bool operator==(const ByConfig::TargetDependsClosureKey& lhs,
                         const ByConfig::TargetDependsClosureKey& rhs);
  friend bool operator!=(const ByConfig::TargetDependsClosureKey& lhs,
                         const ByConfig::TargetDependsClosureKey& rhs);
  friend bool operator<(const ByConfig::TargetDependsClosureKey& lhs,
                        const ByConfig::TargetDependsClosureKey& rhs);
  friend bool operator>(const ByConfig::TargetDependsClosureKey& lhs,
                        const ByConfig::TargetDependsClosureKey& rhs);
  friend bool operator<=(const ByConfig::TargetDependsClosureKey& lhs,
                         const ByConfig::TargetDependsClosureKey& rhs);
  friend bool operator>=(const ByConfig::TargetDependsClosureKey& lhs,
                         const ByConfig::TargetDependsClosureKey& rhs);
};

class cmGlobalNinjaMultiGenerator : public cmGlobalNinjaGenerator
{
public:
  /// The default name of Ninja's common file. Typically: common.ninja.
  static const char* NINJA_COMMON_FILE;
  /// The default file extension to use for per-config Ninja files.
  static const char* NINJA_FILE_EXTENSION;

  cmGlobalNinjaMultiGenerator(cmake* cm);
  bool IsMultiConfig() const override { return true; }
  static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory()
  {
    return std::unique_ptr<cmGlobalGeneratorFactory>(
      new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaMultiGenerator>());
  }

  static cmDocumentationEntry GetDocumentation();

  std::string GetName() const override
  {
    return cmGlobalNinjaMultiGenerator::GetActualName();
  }

  static std::string GetActualName() { return "Ninja Multi-Config"; }

  std::string BuildAlias(const std::string& alias,
                         const std::string& config) const override
  {
    if (config.empty()) {
      return alias;
    }
    return cmStrCat(alias, ":", config);
  }

  std::string ConfigDirectory(const std::string& config) const override
  {
    if (!config.empty()) {
      return cmStrCat('/', config);
    }
    return "";
  }

  const char* GetCMakeCFGIntDir() const override { return "${CONFIGURATION}"; }

  std::string ExpandCFGIntDir(const std::string& str,
                              const std::string& config) const override;

  cmGeneratedFileStream* GetImplFileStream(
    const std::string& config) const override
  {
    return this->ImplFileStreams.at(config).get();
  }

  cmGeneratedFileStream* GetConfigFileStream(
    const std::string& config) const override
  {
    return this->ConfigFileStreams.at(config).get();
  }

  cmGeneratedFileStream* GetDefaultFileStream() const override
  {
    return this->DefaultFileStream.get();
  }

  cmGeneratedFileStream* GetCommonFileStream() const override
  {
    return this->CommonFileStream.get();
  }

  void AppendNinjaFileArgument(GeneratedMakeCommand& command,
                               const std::string& config) const override;

  static std::string GetNinjaImplFilename(const std::string& config);
  static std::string GetNinjaConfigFilename(const std::string& config);

  void AddRebuildManifestOutputs(cmNinjaDeps& outputs) const override;

  void GetQtAutoGenConfigs(std::vector<std::string>& configs) const override;

  bool InspectConfigTypeVariables() override;

  std::string GetDefaultBuildConfig() const override;

  bool SupportsDefaultBuildType() const override { return true; }
  bool SupportsCrossConfigs() const override { return true; }
  bool SupportsDefaultConfigs() const override { return true; }

  std::string OrderDependsTargetForTarget(
    cmGeneratorTarget const* target, const std::string& config) const override;

protected:
  bool OpenBuildFileStreams() override;
  void CloseBuildFileStreams() override;

private:
  std::map<std::string, std::unique_ptr<cmGeneratedFileStream>>
    ImplFileStreams;
  std::map<std::string, std::unique_ptr<cmGeneratedFileStream>>
    ConfigFileStreams;
  std::unique_ptr<cmGeneratedFileStream> CommonFileStream;
  std::unique_ptr<cmGeneratedFileStream> DefaultFileStream;
};
