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

#include "cmGlobalFastbuildGenerator.h"

#include <algorithm>
#include <cstdlib>
#include <initializer_list>
#include <iterator>
#include <queue>
#include <sstream>

#include <cm/memory>

#include "cmsys/FStream.hxx"
#include "cmsys/RegularExpression.hxx"

#include "cmFastbuildLinkLineComputer.h"
#include "cmFastbuildTargetGenerator.h" // IWYU pragma: keep
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobCacheEntry.h"
#include "cmGlobalGenerator.h"
#include "cmGlobalGeneratorFactory.h"
#include "cmList.h"
#include "cmLocalFastbuildGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmValue.h"
#include "cmVersion.h"
#include "cmake.h"

#if defined(_WIN32)
#  include <future>

#  include <objbase.h>
#  include <shellapi.h>

#endif

#define FASTBUILD_REBUILD_BFF_TARGET_NAME "rebuild-bff"
#define FASTBUILD_GLOB_CHECK_TARGET "glob-check"
#define FASTBUILD_ENV_VAR_NAME "LocalEnv"

// IDE support
#define FASTBUILD_XCODE_BASE_PATH "XCode/Projects"
#define FASTBUILD_VS_BASE_PATH "VisualStudio/Projects"
#define FASTBUILD_VS_PROJECT_SUFFIX "-vcxproj"

#define FASTBUILD_IDE_VS_COMMAND_PREFIX "cd ^$(SolutionDir).. && "
#define FASTBUILD_DEFAULT_IDE_BUILD_ARGS " -ide -cache -summary -dist "

constexpr auto FASTBUILD_CAPTURE_SYSTEM_ENV =
  "CMAKE_FASTBUILD_CAPTURE_SYSTEM_ENV";
constexpr auto FASTBUILD_ENV_OVERRIDES = "CMAKE_FASTBUILD_ENV_OVERRIDES";

// Inherits from "CMAKE_FASTBUILD_VERBOSE_GENERATOR" env variable.
constexpr auto FASTBUILD_VERBOSE_GENERATOR =
  "CMAKE_FASTBUILD_VERBOSE_GENERATOR";
constexpr auto FASTBUILD_CACHE_PATH = "CMAKE_FASTBUILD_CACHE_PATH";
// Compiler settings.
constexpr auto FASTBUILD_COMPILER_EXTRA_FILES =
  "CMAKE_FASTBUILD_COMPILER_EXTRA_FILES";
constexpr auto FASTBUILD_USE_LIGHTCACHE = "CMAKE_FASTBUILD_USE_LIGHTCACHE";
constexpr auto FASTBUILD_USE_RELATIVE_PATHS =
  "CMAKE_FASTBUILD_USE_RELATIVE_PATHS";
constexpr auto FASTBUILD_USE_DETERMINISTIC_PATHS =
  "CMAKE_FASTBUILD_USE_DETERMINISTIC_PATHS";
constexpr auto FASTBUILD_SOURCE_MAPPING = "CMAKE_FASTBUILD_SOURCE_MAPPING";
constexpr auto FASTBUILD_CLANG_REWRITE_INCLUDES =
  "CMAKE_FASTBUILD_CLANG_REWRITE_INCLUDES";
constexpr auto FASTBUILD_CLANG_GCC_UPDATE_XLANG_ARG =
  "CMAKE_FASTBUILD_CLANG_GCC_UPDATE_XLANG_ARG";
constexpr auto FASTBUILD_ALLOW_RESPONSE_FILE =
  "CMAKE_FASTBUILD_ALLOW_RESPONSE_FILE";
constexpr auto FASTBUILD_FORCE_RESPONSE_FILE =
  "CMAKE_FASTBUILD_FORCE_RESPONSE_FILE";

constexpr auto FASTBUILD_IDE_ARGS = "CMAKE_FASTBUILD_IDE_ARGS";

static std::map<std::string, std::string> const compilerIdToFastbuildFamily = {
  { "MSVC", "msvc" }, { "Clang", "clang" },      { "AppleClang", "clang" },
  { "GNU", "gcc" },   { "NVIDIA", "cuda-nvcc" }, { "Clang-cl", "clang-cl" },
};

static std::set<std::string> const supportedLanguages = { "C", "CXX", "CUDA",
                                                          "OBJC", "OBJCXX" };

template <class T>
FastbuildAliasNode generateAlias(std::string const& name, char const* postfix,
                                 T const& nodes)
{
  FastbuildAliasNode alias;
  alias.Name = name + postfix;
  for (auto const& node : nodes) {
    alias.PreBuildDependencies.emplace(node.Name);
  }
  return alias;
}

void FastbuildTarget::GenerateAliases()
{
  // -deps
  this->DependenciesAlias.Name =
    this->Name + FASTBUILD_DEPS_ARTIFACTS_ALIAS_POSTFIX;
  for (auto const& dep : this->PreBuildDependencies) {
    if (dep.Type != FastbuildTargetDepType::ORDER_ONLY) {
      this->DependenciesAlias.PreBuildDependencies.emplace(dep);
    }
  }

  // PRE/POST/REST
  if (!this->PreBuildExecNodes.PreBuildDependencies.empty()) {
    this->PreBuildExecNodes.Name =
      this->Name + FASTBUILD_PRE_BUILD_ALIAS_POSTFIX;
  }
  if (!this->PreLinkExecNodes.Nodes.empty()) {
    this->PreLinkExecNodes.Alias =
      generateAlias(this->Name, FASTBUILD_PRE_LINK_ALIAS_POSTFIX,
                    this->PreLinkExecNodes.Nodes);
  }
  if (!this->PostBuildExecNodes.Alias.PreBuildDependencies.empty()) {
    this->PostBuildExecNodes.Alias.Name =
      this->Name + FASTBUILD_POST_BUILD_ALIAS_POSTFIX;
  }
  if (!this->ExecNodes.PreBuildDependencies.empty()) {
    this->ExecNodes.Name = this->Name + FASTBUILD_CUSTOM_COMMAND_ALIAS_POSTFIX;
  }

  // If we don't have any node that we can build by name (e.g. no static /
  // dynamic lib or executable) -> create an alias so that we can build this
  // target by name.
  if (LinkerNode.empty()) {
    FastbuildAliasNode alias;
    alias.Name = this->Name;
    if (LinkerNode.empty()) {
      for (FastbuildObjectListNode const& objListNode : ObjectListNodes) {
        alias.PreBuildDependencies.emplace(objListNode.Name);
      }
    } else {
      for (FastbuildLinkerNode const& linkerNode : LinkerNode) {
        alias.PreBuildDependencies.emplace(linkerNode.Name);
      }
    }
    AliasNodes.emplace_back(std::move(alias));
  }

  // Link artifacts (should not be added to all
  // since on Windows it might contain Import Lib and FASTBuild doesn't know
  // how to create it, so "-all" will fail).
  AliasNodes.emplace_back(generateAlias(
    this->Name, FASTBUILD_OBJECTS_ALIAS_POSTFIX, this->ObjectListNodes));

  for (auto const& linkerNode : this->LinkerNode) {
    if (linkerNode.Type == FastbuildLinkerNode::SHARED_LIBRARY ||
        linkerNode.Type == FastbuildLinkerNode::STATIC_LIBRARY ||
        linkerNode.Type == FastbuildLinkerNode::EXECUTABLE) {
      std::string postfix = FASTBUILD_LINK_ARTIFACTS_ALIAS_POSTFIX;
      if (!linkerNode.Arch.empty()) {
        postfix += cmStrCat('-', linkerNode.Arch);
      }
#ifdef _WIN32
      // On Windows DLL and Executables must be linked via Import Lib file
      // (.lib).
      if (linkerNode.Type == FastbuildLinkerNode::SHARED_LIBRARY ||
          linkerNode.Type == FastbuildLinkerNode::EXECUTABLE) {
        FastbuildAliasNode linkAlias;
        linkAlias.Name = this->Name + FASTBUILD_LINK_ARTIFACTS_ALIAS_POSTFIX;
        linkAlias.PreBuildDependencies.emplace(
          FASTBUILD_DOLLAR_TAG "TargetOutputImplib" FASTBUILD_DOLLAR_TAG);
        AliasNodes.emplace_back(std::move(linkAlias));
        continue;
      }
#endif
      FastbuildAliasNode alias;
      alias.Name = this->Name + postfix;
      alias.PreBuildDependencies.emplace(linkerNode.LinkerOutput);
      AliasNodes.emplace_back(std::move(alias));
    }
  }
}

cmGlobalFastbuildGenerator::cmGlobalFastbuildGenerator(cmake* cm)
  : cmGlobalCommonGenerator(cm)
  , BuildFileStream(nullptr)
{
#ifdef _WIN32
  cm->GetState()->SetWindowsShell(true);
#endif
  this->FindMakeProgramFile = "CMakeFastbuildFindMake.cmake";
  cm->GetState()->SetFastbuildMake(true);
  cm->GetState()->SetIsGeneratorMultiConfig(false);
}

void cmGlobalFastbuildGenerator::ReadCompilerOptions(
  FastbuildCompiler& compiler, cmMakefile* mf)
{
  if (compiler.CompilerFamily == "custom") {
    return;
  }

  if (cmIsOn(mf->GetSafeDefinition(FASTBUILD_USE_LIGHTCACHE))) {
    compiler.UseLightCache = true;
  }
  if (cmIsOn(mf->GetSafeDefinition(FASTBUILD_USE_RELATIVE_PATHS))) {
    compiler.UseRelativePaths = true;
    UsingRelativePaths = true;
  }
  if (cmIsOn(mf->GetSafeDefinition(FASTBUILD_USE_DETERMINISTIC_PATHS))) {
    compiler.UseDeterministicPaths = true;
  }
  std::string sourceMapping = mf->GetSafeDefinition(FASTBUILD_SOURCE_MAPPING);
  if (!sourceMapping.empty()) {
    compiler.SourceMapping = std::move(sourceMapping);
  }
  auto const clangRewriteIncludesDef =
    mf->GetDefinition(FASTBUILD_CLANG_REWRITE_INCLUDES);
  if (clangRewriteIncludesDef.IsSet() && clangRewriteIncludesDef.IsOff()) {
    compiler.ClangRewriteIncludes = false;
  }
  if (cmIsOn(mf->GetSafeDefinition(FASTBUILD_CLANG_GCC_UPDATE_XLANG_ARG))) {
    compiler.ClangGCCUpdateXLanguageArg = true;
  }
  if (cmIsOn(mf->GetSafeDefinition(FASTBUILD_ALLOW_RESPONSE_FILE))) {
    compiler.AllowResponseFile = true;
  }
  if (cmIsOn(mf->GetSafeDefinition(FASTBUILD_FORCE_RESPONSE_FILE))) {
    compiler.ForceResponseFile = true;
  }
}

void cmGlobalFastbuildGenerator::ProcessEnvironment()
{
  bool const CaptureSystemEnv =
    !this->GetGlobalSetting(FASTBUILD_CAPTURE_SYSTEM_ENV).IsSet() ||
    this->GetGlobalSetting(FASTBUILD_CAPTURE_SYSTEM_ENV).IsOn();
  // On Windows environment is needed for MSVC, but preserve ability to discard
  // it from the generated file if requested.
  if (CaptureSystemEnv) {
    LocalEnvironment = cmSystemTools::GetEnvironmentVariables();
  }
  // FASTBuild strips off "-isysroot" command line option (see :
  // https://github.com/fastbuild/fastbuild/issues/1066).
  // If 'SDK_ROOT' is not set via env and '-isysroot' is absent, AppleClang
  // seems to use MacOS SDK by default (even though FBuild flattens includes
  // before compiling). It breaks cross-compilation for iOS. Tested in
  // "RunCMake.Framework" test.
  std::string const osxRoot = this->GetSafeGlobalSetting("CMAKE_OSX_SYSROOT");
  if (!osxRoot.empty()) {
    LocalEnvironment.emplace_back("SDKROOT=" + osxRoot);
  }

  auto const EnvOverrides =
    this->GetSafeGlobalSetting(FASTBUILD_ENV_OVERRIDES);

  if (!EnvOverrides.empty()) {
    auto const overrideEnvVar = [this](std::string const& prefix,
                                       std::string val) {
      auto const iter =
        std::find_if(LocalEnvironment.begin(), LocalEnvironment.end(),
                     [&prefix](std::string const& value) {
                       return cmSystemTools::StringStartsWith(value.c_str(),
                                                              prefix.c_str());
                     });
      if (iter != LocalEnvironment.end()) {
        *iter = std::move(val);
      } else {
        LocalEnvironment.emplace_back(std::move(val));
      }
    };
    for (auto const& val : cmList{ EnvOverrides }) {
      auto const pos = val.find('=');
      if (pos != std::string::npos && ((pos + 1) < val.size())) {
        overrideEnvVar(val.substr(0, pos + 1), val);
      }
    }
  }

  // Empty strings are not allowed.
  LocalEnvironment.erase(
    std::remove_if(LocalEnvironment.begin(), LocalEnvironment.end(),
                   [](std::string const& s) { return s.empty(); }),
    LocalEnvironment.end());
}

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

void cmGlobalFastbuildGenerator::EnableLanguage(
  std::vector<std::string> const& lang, cmMakefile* mf, bool optional)
{
  this->cmGlobalGenerator::EnableLanguage(lang, mf, optional);
  for (std::string const& l : lang) {
    if (l == "NONE") {
      continue;
    }
    this->ResolveLanguageCompiler(l, mf, optional);
  }
}

bool cmGlobalFastbuildGenerator::FindMakeProgram(cmMakefile* mf)
{
  if (!cmGlobalGenerator::FindMakeProgram(mf)) {
    return false;
  }
  if (auto fastbuildCommand = mf->GetDefinition("CMAKE_MAKE_PROGRAM")) {
    this->FastbuildCommand = *fastbuildCommand;
    std::vector<std::string> command;
    command.push_back(this->FastbuildCommand);
    command.emplace_back("-version");
    std::string version;
    std::string error;
    if (!cmSystemTools::RunSingleCommand(command, &version, &error, nullptr,
                                         nullptr,
                                         cmSystemTools::OUTPUT_NONE)) {
      mf->IssueMessage(MessageType::FATAL_ERROR,
                       "Running\n '" + cmJoin(command, "' '") +
                         "'\n"
                         "failed with:\n " +
                         error);
      cmSystemTools::SetFatalErrorOccurred();
      return false;
    }
    cmsys::RegularExpression versionRegex(R"(^FASTBuild v([0-9]+\.[0-9]+))");
    versionRegex.find(version);
    this->FastbuildVersion = versionRegex.match(1);
  }
  return true;
}

std::unique_ptr<cmLocalGenerator>
cmGlobalFastbuildGenerator::CreateLocalGenerator(cmMakefile* makefile)
{
  return std::unique_ptr<cmLocalGenerator>(
    cm::make_unique<cmLocalFastbuildGenerator>(this, makefile));
}

std::vector<cmGlobalGenerator::GeneratedMakeCommand>
cmGlobalFastbuildGenerator::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*/, std::vector<std::string> const& makeOptions,
  BuildTryCompile isInTryCompile)
{
  GeneratedMakeCommand makeCommand;
  this->FastbuildCommand = this->SelectMakeProgram(makeProgram);
  makeCommand.Add(this->FastbuildCommand);
  // A build command for fastbuild looks like this:
  // fbuild.exe [make-options] [-config projectName.bff] <target>

  std::string configFile = cmStrCat(projectDir, '/', FASTBUILD_BUILD_FILE);

  // Push in the make options
  makeCommand.Add(makeOptions.begin(), makeOptions.end());

  if (!configFile.empty()) {
    makeCommand.Add("-config", configFile);
  }
  // Tested in "RunCMake.SymlinkTrees" test.
  makeCommand.Add("-continueafterdbmove");

  // Tested in RunCMake.LinkWhatYouUse on Linux. (We need to see output of
  // LinkerStampExe process).
  // In general, it might be useful to see output of external processes
  // regardless of their outcome.
  makeCommand.Add("-showcmdoutput");

  // Add the target-config to the command
  for (auto const& tname : targetNames) {
    if (!tname.empty()) {
      makeCommand.Add(tname);
    }
  }
  if (verbose) {
    makeCommand.Add("-verbose");
  }

  // Don't do extra work during "TryCompile".
  if (isInTryCompile == BuildTryCompile::Yes) {
    return { std::move(makeCommand) };
  }

  // Make "rebuild-bff" target up-to-date before running the build.
  std::string output;
  ExecuteFastbuildTarget(projectDir, FASTBUILD_REBUILD_BFF_TARGET_NAME, output,
                         { "-why" });

  // If fbuild.bff was re-generated we need to "restat" it.
  if (output.find("Need to build") != std::string::npos) {
    // Let the user know that re-generation happened (and why it
    // happened).
    cmSystemTools::Stdout(output);
    // FASTBuild will consider the target out-of-date in case some of the
    // inputs have changes after re-generation which might happen if, for
    // example, configuration depends on some files generated during
    // the configuration itself.
    AskCMakeToMakeRebuildBFFUpToDate(projectDir);
  }

  return { std::move(makeCommand) };
}

void cmGlobalFastbuildGenerator::ComputeTargetObjectDirectory(
  cmGeneratorTarget* gt) const
{
  // Compute full path to object file directory for this target.
  std::string dir =
    cmStrCat(gt->GetSupportDirectory(), '/', this->GetCMakeCFGIntDir(), '/');
  gt->ObjectDirectory = std::move(dir);
}

void cmGlobalFastbuildGenerator::AppendDirectoryForConfig(
  std::string const& prefix, std::string const& config,
  std::string const& suffix, std::string& dir)
{
  if (!config.empty() && this->IsMultiConfig()) {
    dir += cmStrCat(prefix, config, suffix);
  }
}

cmDocumentationEntry cmGlobalFastbuildGenerator::GetDocumentation()
{
  return { cmGlobalFastbuildGenerator::GetActualName(),
           "Generates fbuild.bff files." };
}

void cmGlobalFastbuildGenerator::Generate()
{
  // Check minimum Fastbuild version.
  if (cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
                                    this->FastbuildVersion,
                                    RequiredFastbuildVersion())) {
    std::ostringstream msg;
    msg << "The detected version of Fastbuild (" << this->FastbuildVersion;
    msg << ") is less than the version of Fastbuild required by CMake (";
    msg << this->RequiredFastbuildVersion() << ").";
    this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
                                           msg.str());
    return;
  }
  this->ProcessEnvironment();

  this->OpenBuildFileStream();

  this->WriteSettings();
  this->WriteEnvironment();

  // Execute the standard generate process
  cmGlobalGenerator::Generate();

  // Write compilers
  this->WriteCompilers();

  this->WriteTargets();

  this->CloseBuildFileStream();

  if (cmSystemTools::GetErrorOccurredFlag()) {
    return;
  }

  this->RemoveUnknownClangTidyExportFixesFiles();

  if (this->GetCMakeInstance()->GetRegenerateDuringBuild() ||
      this->GetCMakeInstance()->GetIsInTryCompile()) {
    return;
  }
  std::string const workingDir =
    this->GetCMakeInstance()->GetHomeOutputDirectory();
  //  Make "rebuild-bff" target up-to-date after the generation.
  //  This is actually a noop, it just asks CMake to touch the generated file
  //  so FASTBuild would consider the target as up-to-date.
  AskCMakeToMakeRebuildBFFUpToDate(workingDir);

  if (this->GlobalSettingIsOn("CMAKE_EXPORT_COMPILE_COMMANDS")) {
    std::string output;
    ExecuteFastbuildTarget(workingDir, FASTBUILD_ALL_TARGET_NAME, output,
                           { "-compdb" });
  }
}

void cmGlobalFastbuildGenerator::AskCMakeToMakeRebuildBFFUpToDate(
  std::string const& workingDir) const
{
  // "restat" the generated build file.
  // The idea here is to mimic what Ninja's "restat" command does.
  // We need to make the "rebuild.bff" target up-to-date, so the regeneration
  // will only be triggered when CMake files have actually changed.
  // Tested in "RunCMake.Configure" test.
  cmsys::ofstream{
    cmStrCat(workingDir, '/', FASTBUILD_RESTAT_FILE).c_str(),
    std::ios::out | std::ios::binary
  } << cmStrCat(workingDir, '/', FASTBUILD_BUILD_FILE);
  std::string output;
  ExecuteFastbuildTarget(workingDir, FASTBUILD_REBUILD_BFF_TARGET_NAME,
                         output);
}

void cmGlobalFastbuildGenerator::ExecuteFastbuildTarget(
  std::string const& dir, std::string const& target, std::string& output,
  std::vector<std::string> const& fbuildOptions) const
{
  std::vector<std::string> command;

  command.emplace_back(this->FastbuildCommand);
  command.emplace_back("-config");
  std::string const file = cmStrCat(dir, '/', FASTBUILD_BUILD_FILE);
  command.emplace_back(file);
  command.emplace_back(target);
  if (!fbuildOptions.empty()) {
    command.emplace_back(cmJoin(fbuildOptions, " "));
  }

  int retVal = 0;
  if (!cmSystemTools::RunSingleCommand(command, &output, nullptr, &retVal,
                                       dir.c_str(),
                                       cmSystemTools::OUTPUT_NONE) ||
      retVal != 0) {
    cmSystemTools::Error(cmStrCat("Failed to run FASTBuild command:\n  '",
                                  cmJoin(command, "' '"), "'\nOutput:\n",
                                  output));
    cmSystemTools::Stdout(output);
    std::exit(retVal);
  }
}

void cmGlobalFastbuildGenerator::WriteSettings()
{
  // Define some placeholder
  WriteDivider();
  *this->BuildFileStream << "// Helper variables\n\n";

  WriteVariable("FB_INPUT_1_PLACEHOLDER", Quote("\"%1\""));
  WriteVariable("FB_INPUT_1_0_PLACEHOLDER", Quote("\"%1[0]\""));
  WriteVariable("FB_INPUT_1_1_PLACEHOLDER", Quote("\"%1[1]\""));
  WriteVariable("FB_INPUT_2_PLACEHOLDER", Quote("\"%2\""));
  WriteVariable("FB_INPUT_3_PLACEHOLDER", Quote("\"%3\""));

  std::string cacheDir;
  // If explicitly set from CMake.
  auto val = this->GetSafeGlobalSetting(FASTBUILD_CACHE_PATH);
  if (!val.empty()) {
    cacheDir = std::move(val);
    cmSystemTools::ConvertToOutputSlashes(cacheDir);
  }

  WriteDivider();
  *this->BuildFileStream << "// Settings\n\n";

  WriteCommand("Settings");
  *this->BuildFileStream << "{\n";
  if (!cacheDir.empty()) {
    WriteVariable("CachePath", Quote(cacheDir), 1);
  }
  // Concurrency groups.
  WriteStruct(
    FASTBUILD_UTIL_CONCURRENCY_GROUP_NAME,
    { { "ConcurrencyGroupName", Quote(FASTBUILD_UTIL_CONCURRENCY_GROUP_NAME) },
      { "ConcurrencyLimit", "1" } },
    1);

  WriteArray("ConcurrencyGroups",
             { "." FASTBUILD_UTIL_CONCURRENCY_GROUP_NAME }, 1);

  *this->BuildFileStream << "}\n";
}

void cmGlobalFastbuildGenerator::WriteEnvironment()
{
  if (!LocalEnvironment.empty()) {
    WriteArray(FASTBUILD_ENV_VAR_NAME, Wrap(LocalEnvironment), 0);
  }
}

void cmGlobalFastbuildGenerator::WriteDivider()
{
  *this->BuildFileStream << "// ======================================"
                            "=======================================\n";
}

void cmGlobalFastbuildGenerator::Indent(int count)
{
  for (int i = 0; i < count; ++i) {
    *this->BuildFileStream << "  ";
  }
}

void cmGlobalFastbuildGenerator::WriteComment(std::string const& comment,
                                              int indent)
{
  if (comment.empty()) {
    return;
  }

  std::string::size_type lpos = 0;
  std::string::size_type rpos;
  *this->BuildFileStream << "\n";
  Indent(indent);
  *this->BuildFileStream << "/////////////////////////////////////////////\n";
  while ((rpos = comment.find('\n', lpos)) != std::string::npos) {
    Indent(indent);
    *this->BuildFileStream << "// " << comment.substr(lpos, rpos - lpos)
                           << "\n";
    lpos = rpos + 1;
  }
  Indent(indent);
  *this->BuildFileStream << "// " << comment.substr(lpos) << "\n\n";
}

void cmGlobalFastbuildGenerator::WriteVariable(std::string const& key,
                                               std::string const& value,
                                               int indent)
{
  WriteVariable(key, value, "=", indent);
}

void cmGlobalFastbuildGenerator::WriteVariable(std::string const& key,
                                               std::string const& value,
                                               std::string const& op,
                                               int indent)
{
  Indent(indent);
  *this->BuildFileStream << "." << key << " " + op + (value.empty() ? "" : " ")
                         << value << "\n";
}

void cmGlobalFastbuildGenerator::WriteCommand(std::string const& command,
                                              std::string const& value,
                                              int indent)
{
  Indent(indent);
  *this->BuildFileStream << command;
  if (!value.empty()) {
    *this->BuildFileStream << "(" << value << ")";
  }
  *this->BuildFileStream << "\n";
}

void cmGlobalFastbuildGenerator::WriteArray(
  std::string const& key, std::vector<std::string> const& values, int indent)
{
  WriteArray(key, values, "=", indent);
}

void cmGlobalFastbuildGenerator::WriteArray(
  std::string const& key, std::vector<std::string> const& values,
  std::string const& op, int indent)
{
  WriteVariable(key, "", op, indent);
  Indent(indent);
  *this->BuildFileStream << "{\n";
  char const* sep = "";
  for (std::string const& value : values) {
    *this->BuildFileStream << sep;
    sep = ",\n";
    Indent(indent + 1);
    *this->BuildFileStream << value;
  }
  *this->BuildFileStream << "\n";
  Indent(indent);
  *this->BuildFileStream << "}\n";
}

void cmGlobalFastbuildGenerator::WriteStruct(
  std::string const& name,
  std::vector<std::pair<std::string, std::string>> const& variables,
  int indent)
{
  WriteVariable(name, "", "=", indent);
  Indent(indent);
  *this->BuildFileStream << "[\n";
  for (auto const& val : variables) {
    auto const& key = val.first;
    auto const& value = val.second;
    WriteVariable(key, value, "=", indent + 1);
  }
  Indent(indent);
  *this->BuildFileStream << "]\n";
}

std::string cmGlobalFastbuildGenerator::Quote(std::string const& str,
                                              std::string const& quotation)
{
  std::string result = str;
  cmSystemTools::ReplaceString(result, quotation, "^" + quotation);
  cmSystemTools::ReplaceString(result, FASTBUILD_DOLLAR_TAG, "$");
  return quotation + result + quotation;
}
std::string cmGlobalFastbuildGenerator::QuoteIfHasSpaces(std::string str)
{
  if (str.find(' ') != std::string::npos) {
    return cmStrCat('"', str, '"');
  }
  return str;
}

struct WrapHelper
{
  std::string Prefix;
  std::string Suffix;
  bool EscapeDollar;

  std::string operator()(std::string in)
  {
    // If we have ^ in env variable - need to escape it.
    cmSystemTools::ReplaceString(in, "^", "^^");
    // Those all are considered as line ends by FASTBuild.
    cmSystemTools::ReplaceString(in, "\n", "\\n");
    cmSystemTools::ReplaceString(in, "\r", "\\r");
    // Escaping of single quotes tested in "RunCMake.CompilerArgs" test.
    cmSystemTools::ReplaceString(in, "'", "^'");
    std::string result = Prefix + in + Suffix;
    if (EscapeDollar) {
      cmSystemTools::ReplaceString(result, "$", "^$");
      cmSystemTools::ReplaceString(result, FASTBUILD_DOLLAR_TAG, "$");
    }
    return result;
  }
  std::string operator()(FastbuildTargetDep const& in)
  {
    return (*this)(in.Name);
  }
};
template <class T>
std::vector<std::string> cmGlobalFastbuildGenerator::Wrap(
  T const& in, std::string const& prefix, std::string const& suffix,
  bool const escape_dollar)
{

  std::vector<std::string> result;

  WrapHelper helper = { prefix, suffix, escape_dollar };

  std::transform(in.begin(), in.end(), std::back_inserter(result), helper);

  return result;
}

void cmGlobalFastbuildGenerator::TopologicalSort(
  std::vector<FastbuildTargetPtrT>& nodes)
{
  std::unordered_map<std::string, int> inDegree;
  std::unordered_map<std::string, std::set<std::string>> reverseDeps;
  std::unordered_map<std::string, std::size_t> originalIndex;

  // Track original positions
  for (std::size_t i = 0; i < nodes.size(); ++i) {
    auto const& node = nodes[i];
    inDegree[node->Name] = 0;
    originalIndex[node->Name] = i;
  }

  // Build reverse dependency graph and in-degree map
  for (auto const& node : nodes) {
    for (auto const& dep : node->PreBuildDependencies) {
      if (inDegree.count(dep.Name)) {
        reverseDeps[dep.Name].insert(node->Name);
        ++inDegree[node->Name];
      }
    }
  }

  // Min-heap based on original position
  auto const cmp = [&](std::string const& a, std::string const& b) {
    return originalIndex[a] > originalIndex[b];
  };
  std::priority_queue<std::string, std::vector<std::string>, decltype(cmp)>
    zeroInDegree(cmp);

  for (auto const& val : inDegree) {
    auto const& degree = val.second;
    auto const& name = val.first;
    if (degree == 0) {
      zeroInDegree.push(name);
    }
  }

  std::vector<std::string> sorted;
  while (!zeroInDegree.empty()) {
    std::string node = zeroInDegree.top();
    zeroInDegree.pop();
    sorted.push_back(node);
    for (auto const& dep : reverseDeps[node]) {
      if (--inDegree[dep] == 0) {
        zeroInDegree.push(dep);
      }
    }
  }

  if (sorted.size() != nodes.size()) {
    cmSystemTools::Error("Failed to sort (Cyclic dependency)");
    cmSystemTools::Error(cmStrCat("Sorted size: ", sorted.size()));
    cmSystemTools::Error(cmStrCat("nodes size: ", nodes.size()));
    for (auto const& node : nodes) {
      cmSystemTools::Error("Node: " + node->Name);
      for (auto const& dep : reverseDeps[node->Name]) {
        cmSystemTools::Error("\tReverse dep: " + dep);
      }
      for (auto const& child : node->PreBuildDependencies) {
        cmSystemTools::Error("\tChild: " + child.Name);
      }
    }
    for (auto const& node : sorted) {
      cmSystemTools::Error("Sorted: " + node);
    }
    for (auto const& node : nodes) {
      cmSystemTools::Error("In node: " + node->Name);
    }
  }

  // Reconstruct sorted nodes
  std::vector<FastbuildTargetPtrT> result;
  for (auto const& name : sorted) {
    auto it = std::find_if(
      nodes.begin(), nodes.end(), [&name](FastbuildTargetPtrT const& node) {
        return node /* the node might be in moved-from state*/ &&
          node->Name == name;
      });
    if (it != nodes.end()) {
      result.emplace_back(std::move(*it));
    }
  }

  std::swap(result, nodes);
}

void cmGlobalFastbuildGenerator::WriteDisclaimer()
{
  *this->BuildFileStream << "// CMAKE generated file: DO NOT EDIT!\n"
                         << "// Generated by \"" << this->GetName() << "\""
                         << " Generator, CMake Version "
                         << cmVersion::GetMajorVersion() << "."
                         << cmVersion::GetMinorVersion() << "\n\n";
}

void cmGlobalFastbuildGenerator::OpenBuildFileStream()
{
  // Compute Fastbuild's build file path.
  std::string buildFilePath =
    this->GetCMakeInstance()->GetHomeOutputDirectory();
  buildFilePath += "/";
  buildFilePath += FASTBUILD_BUILD_FILE;

  // Get a stream where to generate things.
  if (!this->BuildFileStream) {
    this->BuildFileStream = cm::make_unique<cmGeneratedFileStream>(
      buildFilePath, false, this->GetMakefileEncoding());
    if (!this->BuildFileStream) {
      // An error message is generated by the constructor if it cannot
      // open the file.
      return;
    }
  }

  // Write the do not edit header.
  this->WriteDisclaimer();

  // Write a comment about this file.
  *this->BuildFileStream
    << "// This file contains all the build statements\n\n";
}

void cmGlobalFastbuildGenerator::CloseBuildFileStream()
{
  if (this->BuildFileStream) {
    this->BuildFileStream.reset();
  } else {
    cmSystemTools::Error("Build file stream was not open.");
  }
}

void cmGlobalFastbuildGenerator::WriteCompilers()
{
  WriteDivider();
  *this->BuildFileStream << "// Compilers\n\n";
  for (auto const& val : Compilers) {
    auto const& compilerDef = val.second;

    std::string compilerPath = compilerDef.Executable;

    // Write out the compiler that has been configured
    WriteCommand("Compiler", Quote(compilerDef.Name));
    *this->BuildFileStream << "{\n";
    for (auto const& extra : compilerDef.ExtraVariables) {
      auto const& extraKey = extra.first;
      auto const& extraVal = extra.second;
      WriteVariable(extraKey, Quote(extraVal), 1);
    }
    WriteVariable("Executable", Quote(compilerPath), 1);
    WriteVariable("CompilerFamily", Quote(compilerDef.CompilerFamily), 1);
    if (this->GetCMakeInstance()->GetIsInTryCompile()) {
      WriteVariable("AllowCaching", "false", 1);
      WriteVariable("AllowDistribution", "false", 1);
    }

    if (compilerDef.UseLightCache &&
        (compilerDef.CompilerFamily == "msvc" ||
         // FASTBuild supports Light Cache for non-MSVC compilers starting from
         // version 1.19
         cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER_EQUAL,
                                       this->FastbuildVersion, "1.19"))) {
      WriteVariable("UseLightCache_Experimental", "true", 1);
    }
    if (compilerDef.UseRelativePaths) {
      WriteVariable("UseRelativePaths_Experimental", "true", 1);
    }
    if (compilerDef.UseDeterministicPaths) {
      WriteVariable("UseDeterministicPaths_Experimental", "true", 1);
    }

    if (!compilerDef.SourceMapping.empty()) {
      WriteVariable("SourceMapping_Experimental",
                    Quote(compilerDef.SourceMapping), 1);
    }

    auto const isClang = [&compilerDef] {
      return compilerDef.CompilerFamily == "clang" ||
        compilerDef.CompilerFamily == "clang-cl";
    };

    if (!compilerDef.ClangRewriteIncludes && isClang()) {
      WriteVariable("ClangRewriteIncludes", "false", 1);
    }
    if (compilerDef.ClangGCCUpdateXLanguageArg &&
        (isClang() || compilerDef.CompilerFamily == "gcc")) {
      WriteVariable("ClangGCCUpdateXLanguageArg", "true", 1);
    }

    if (compilerDef.AllowResponseFile) {
      WriteVariable("AllowResponseFile", "true", 1);
    }
    if (compilerDef.ForceResponseFile) {

      WriteVariable("ForceResponseFile", "true", 1);
    }

    if (compilerDef.DontUseEnv) {
      LogMessage("Not using system environment");
    } else {
      if (!LocalEnvironment.empty()) {
        WriteVariable("Environment", "." FASTBUILD_ENV_VAR_NAME, 1);
      }
    }
    if (!compilerDef.ExtraFiles.empty()) {
      // Do not escape '$' sign, CMAKE_${LANG}_FASTBUILD_EXTRA_FILES might
      // contain FB variables to be expanded (we do use some internally).
      // Besides a path cannot contain a '$'
      WriteArray("ExtraFiles", Wrap(compilerDef.ExtraFiles, "'", "'", false),
                 1);
    }
    *this->BuildFileStream << "}\n";

    auto const compilerId = compilerDef.Name;
    WriteVariable(compilerId, Quote(compilerDef.Name));
    *this->BuildFileStream << "\n";
  }
  // We need this because the Library command needs a compiler
  // even if don't compile anything
  if (!this->Compilers.empty()) {
    WriteVariable("Compiler_dummy",
                  Quote(this->Compilers.begin()->second.Name));
  }
}

void cmGlobalFastbuildGenerator::AddCompiler(std::string const& language,
                                             cmMakefile* mf)
{
  if (this->Compilers.find(FASTBUILD_COMPILER_PREFIX + language) !=
      this->Compilers.end()) {
    return;
  }

  // Calculate the root location of the compiler
  std::string const variableString = cmStrCat("CMAKE_", language, "_COMPILER");
  std::string const compilerLocation = mf->GetSafeDefinition(variableString);
  if (compilerLocation.empty()) {
    return;
  }

  // Add the language to the compiler's name
  FastbuildCompiler compilerDef;
  compilerDef.ExtraVariables["Root"] =
    cmSystemTools::GetFilenamePath(compilerLocation);
  compilerDef.Name = FASTBUILD_COMPILER_PREFIX + language;
  compilerDef.Executable = compilerLocation;
  compilerDef.CmakeCompilerID =
    mf->GetSafeDefinition(cmStrCat("CMAKE_", language, "_COMPILER_ID"));
  if (compilerDef.CmakeCompilerID == "Clang" &&
      mf->GetSafeDefinition(cmStrCat(
        "CMAKE_", language, "_COMPILER_FRONTEND_VARIANT")) == "MSVC") {
    compilerDef.CmakeCompilerID = "Clang-cl";
  }

  compilerDef.CmakeCompilerVersion =
    mf->GetSafeDefinition(cmStrCat("CMAKE_", language, "_COMPILER_VERSION"));
  compilerDef.Language = language;

  cmExpandList(mf->GetSafeDefinition(FASTBUILD_COMPILER_EXTRA_FILES),
               compilerDef.ExtraFiles);

  if (supportedLanguages.find(language) != supportedLanguages.end()) {
    auto const iter =
      compilerIdToFastbuildFamily.find(compilerDef.CmakeCompilerID);
    if (iter != compilerIdToFastbuildFamily.end()) {
      compilerDef.CompilerFamily = iter->second;
    }
  }

  // Has to be called after we determined 'CompilerFamily'.
  ReadCompilerOptions(compilerDef, mf);

  // If FASTBUILD_COMPILER_EXTRA_FILES is not set - automatically add extra
  // files based on compiler (see
  // https://fastbuild.org/docs/functions/compiler.html)
  if (!this->GetCMakeInstance()->GetIsInTryCompile() &&
      compilerDef.ExtraFiles.empty() &&
      (language == "C" || language == "CXX") &&
      compilerDef.CmakeCompilerID == "MSVC") {
    // https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html

    // Calculate the i18n number.
    std::string const i18nNum =
      mf->GetSafeDefinition(cmStrCat("CMAKE_", language, "_MSVC_I18N_DIR"));

    // Visual Studio 17 (19.30 to 19.39)
    // TODO

    // Visual Studio 16 (19.20 to 19.29)
    if (cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER_EQUAL,
                                      compilerDef.CmakeCompilerVersion,
                                      "19.20")) {
      compilerDef.ExtraFiles.push_back("$Root$/c1.dll");
      compilerDef.ExtraFiles.push_back("$Root$/c1xx.dll");
      compilerDef.ExtraFiles.push_back("$Root$/c2.dll");
      compilerDef.ExtraFiles.push_back(
        "$Root$/atlprov.dll"); // Only needed if using ATL
      compilerDef.ExtraFiles.push_back("$Root$/msobj140.dll");
      compilerDef.ExtraFiles.push_back("$Root$/mspdb140.dll");
      compilerDef.ExtraFiles.push_back("$Root$/mspdbcore.dll");
      compilerDef.ExtraFiles.push_back("$Root$/mspdbsrv.exe");
      compilerDef.ExtraFiles.push_back("$Root$/mspft140.dll");
      compilerDef.ExtraFiles.push_back("$Root$/msvcp140.dll");
      compilerDef.ExtraFiles.push_back(
        "$Root$/msvcp140_atomic_wait.dll"); // Required circa 16.8.3
                                            // (14.28.29333)
      compilerDef.ExtraFiles.push_back(
        "$Root$/tbbmalloc.dll"); // Required as of 16.2 (14.22.27905)
      compilerDef.ExtraFiles.push_back("$Root$/vcruntime140.dll");
      compilerDef.ExtraFiles.push_back(
        "$Root$/vcruntime140_1.dll"); // Required as of 16.5.1 (14.25.28610)
      compilerDef.ExtraFiles.push_back(
        cmStrCat("$Root$/", i18nNum, "/clui.dll"));
      compilerDef.ExtraFiles.push_back(cmStrCat(
        "$Root$/", i18nNum, "/mspft140ui.dll")); // Localized messages for
                                                 // static analysis
    }
    // Visual Studio 15 (19.10 to 19.19)
    else if (cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER_EQUAL,
                                           compilerDef.CmakeCompilerVersion,
                                           "19.10")) {
      compilerDef.ExtraFiles.push_back("$Root$/c1.dll");
      compilerDef.ExtraFiles.push_back("$Root$/c1xx.dll");
      compilerDef.ExtraFiles.push_back("$Root$/c2.dll");
      compilerDef.ExtraFiles.push_back(
        "$Root$/atlprov.dll"); // Only needed if using ATL
      compilerDef.ExtraFiles.push_back("$Root$/msobj140.dll");
      compilerDef.ExtraFiles.push_back("$Root$/mspdb140.dll");
      compilerDef.ExtraFiles.push_back("$Root$/mspdbcore.dll");
      compilerDef.ExtraFiles.push_back("$Root$/mspdbsrv.exe");
      compilerDef.ExtraFiles.push_back("$Root$/mspft140.dll");
      compilerDef.ExtraFiles.push_back("$Root$/msvcp140.dll");
      compilerDef.ExtraFiles.push_back("$Root$/vcruntime140.dll");
      compilerDef.ExtraFiles.push_back("$Root$/" + i18nNum + "/clui.dll");
    }
  }
  // TODO: Handle Intel compiler

  this->Compilers[compilerDef.Name] = std::move(compilerDef);
}

void cmGlobalFastbuildGenerator::AddLauncher(std::string const& prefix,
                                             std::string const& launcher,
                                             std::string const& language,
                                             std::string const& args)
{
  if (this->Compilers.find(prefix + language) != this->Compilers.end()) {
    return;
  }
  LogMessage("Launcher: " + launcher);
  LogMessage("Launcher args: " + args);
  FastbuildCompiler compilerDef;
  compilerDef.Name = prefix + language;
  compilerDef.Args = args;
  if (cmSystemTools::FileIsFullPath(launcher)) {
    compilerDef.Executable = launcher;
  } else {
    // FASTBuild needs an absolute path to the executable.
    compilerDef.Executable = cmSystemTools::FindProgram(launcher);
    if (compilerDef.Executable.empty()) {
      cmSystemTools::Error("Failed to find path to " + launcher);
      return;
    }
  }
  // When CTest is used as a launcher, there is an interesting env variable
  // "CTEST_LAUNCH_LOGS" which is set by parent CTest process and is expected
  // to be read from global (sic!) env by the launched CTest process. So we
  // will need to make this global env available for CTest executable used as a
  // "launcher". Tested in RunCMake.ctest_labels_for_subprojects test..
  compilerDef.DontUseEnv = true;
  this->Compilers[compilerDef.Name] = std::move(compilerDef);
}

std::string cmGlobalFastbuildGenerator::ConvertToFastbuildPath(
  std::string const& path) const
{
  cmLocalGenerator const* root = LocalGenerators[0].get();
  return root->MaybeRelativeToWorkDir(cmSystemTools::FileIsFullPath(path)
                                        ? cmSystemTools::CollapseFullPath(path)
                                        : path);
}

std::unique_ptr<cmLinkLineComputer>
cmGlobalFastbuildGenerator::CreateLinkLineComputer(
  cmOutputConverter* outputConverter,
  cmStateDirectory const& /* stateDir */) const
{
  return cm::make_unique<cmFastbuildLinkLineComputer>(
    outputConverter,
    this->LocalGenerators[0]->GetStateSnapshot().GetDirectory(), this);
}

void cmGlobalFastbuildGenerator::WriteExec(FastbuildExecNode const& Exec,
                                           int indent)
{
  auto const identPlus1 = indent + 1;
  WriteCommand("Exec", Exec.Name.empty() ? std::string{} : Quote(Exec.Name),
               indent);
  Indent(indent);
  *BuildFileStream << "{\n";
  {
    if (!Exec.PreBuildDependencies.empty()) {
      WriteArray("PreBuildDependencies", Wrap(Exec.PreBuildDependencies),
                 identPlus1);
    }
    WriteVariable("ExecExecutable", Quote(Exec.ExecExecutable), identPlus1);
    if (!Exec.ExecArguments.empty()) {
      WriteVariable("ExecArguments", Quote(Exec.ExecArguments), identPlus1);
    }
    if (!Exec.ExecWorkingDir.empty()) {
      WriteVariable("ExecWorkingDir", Quote(Exec.ExecWorkingDir), identPlus1);
    }
    if (!Exec.ExecInput.empty()) {
      WriteArray("ExecInput", Wrap(Exec.ExecInput), identPlus1);
    }
    if (Exec.ExecUseStdOutAsOutput) {
      WriteVariable("ExecUseStdOutAsOutput", "true", identPlus1);
    }
    if (!Exec.ExecInputPath.empty()) {
      WriteArray("ExecInputPath", Wrap(Exec.ExecInputPath), identPlus1);
    }
    if (!Exec.ExecInputPattern.empty()) {
      WriteArray("ExecInputPattern", Wrap(Exec.ExecInputPattern), identPlus1);
    }
    WriteVariable("ExecAlwaysShowOutput", "true", identPlus1);
    WriteVariable("ExecOutput", Quote(Exec.ExecOutput), identPlus1);
    WriteVariable("ExecAlways", Exec.ExecAlways ? "true" : "false",
                  identPlus1);
    if (!Exec.ConcurrencyGroupName.empty()) {
      WriteVariable("ConcurrencyGroupName", Quote(Exec.ConcurrencyGroupName),
                    identPlus1);
    }
  }
  Indent(indent);
  *BuildFileStream << "}\n";
  static bool const verbose = GlobalSettingIsOn(FASTBUILD_VERBOSE_GENERATOR) ||
    cmSystemTools::HasEnv(FASTBUILD_VERBOSE_GENERATOR);
  // Those aliases are only used for troubleshooting the generated file.
  if (verbose) {
    WriteAlias(Exec.OutputsAlias);
    WriteAlias(Exec.ByproductsAlias);
  }
}

void cmGlobalFastbuildGenerator::WriteUnity(FastbuildUnityNode const& Unity)
{
  WriteCommand("Unity", Quote(Unity.Name), 1);
  Indent(1);
  *BuildFileStream << "{\n";
  {
    WriteVariable("UnityOutputPath", Quote(Unity.UnityOutputPath), 2);
    WriteVariable("UnityOutputPattern", Quote(Unity.UnityOutputPattern), 2);
    WriteArray("UnityInputFiles", Wrap(Unity.UnityInputFiles), 2);
    if (!Unity.UnityInputIsolatedFiles.empty()) {
      WriteArray("UnityInputIsolatedFiles",
                 Wrap(Unity.UnityInputIsolatedFiles), 2);
    }
    if (UsingRelativePaths) {
      WriteVariable("UseRelativePaths_Experimental", "true", 2);
    }
  }
  Indent(1);
  *BuildFileStream << "}\n";
}

void cmGlobalFastbuildGenerator::WriteObjectList(
  FastbuildObjectListNode const& ObjectList, bool allowDistribution)
{
  WriteCommand("ObjectList", Quote(ObjectList.Name), 1);
  Indent(1);
  *BuildFileStream << "{\n";
  {
    if (!allowDistribution) {
      WriteVariable("AllowDistribution", "false", 2);
    }
    if (!ObjectList.PreBuildDependencies.empty()) {
      WriteArray("PreBuildDependencies", Wrap(ObjectList.PreBuildDependencies),
                 2);
    }
    WriteVariable("Compiler", ObjectList.Compiler, 2);
    // If only PCH output is present - this node reuses existing PCH.
    if (!ObjectList.PCHOutputFile.empty()) {
      WriteVariable("PCHOutputFile", Quote(ObjectList.PCHOutputFile), 2);
    }
    // If PCHInputFile and PCHOptions are present  - this node creates PCH.
    if (!ObjectList.PCHInputFile.empty() && !ObjectList.PCHOptions.empty()) {
      WriteVariable("PCHInputFile", Quote(ObjectList.PCHInputFile), 2);
      WriteVariable("PCHOptions", Quote(ObjectList.PCHOptions), 2);
    }
    WriteVariable("CompilerOptions", Quote(ObjectList.CompilerOptions), 2);
    WriteVariable("CompilerOutputPath", Quote(ObjectList.CompilerOutputPath),
                  2);
    WriteVariable("CompilerOutputExtension",
                  Quote(ObjectList.CompilerOutputExtension), 2);
    WriteVariable("CompilerOutputKeepBaseExtension", "true", 2);
    if (!ObjectList.CompilerInputUnity.empty()) {
      WriteArray("CompilerInputUnity", Wrap(ObjectList.CompilerInputUnity), 2);
    }
    if (!ObjectList.CompilerInputFiles.empty()) {
      WriteArray("CompilerInputFiles", Wrap(ObjectList.CompilerInputFiles), 2);
    }
    if (!ObjectList.AllowCaching) {
      WriteVariable("AllowCaching", "false", 2);
    }
    if (!ObjectList.AllowDistribution) {
      WriteVariable("AllowDistribution", "false", 2);
    }
    if (ObjectList.Hidden) {
      WriteVariable("Hidden", "true", 2);
    }
  }
  Indent(1);
  *BuildFileStream << "}\n";
}

void cmGlobalFastbuildGenerator::WriteLinker(
  FastbuildLinkerNode const& LinkerNode, bool allowDistribution)
{
  WriteCommand(
    LinkerNode.Type == FastbuildLinkerNode::EXECUTABLE         ? "Executable"
      : LinkerNode.Type == FastbuildLinkerNode::SHARED_LIBRARY ? "DLL"
                                                               : "Library",
    (!LinkerNode.Name.empty() && LinkerNode.Name != LinkerNode.LinkerOutput)
      ? Quote(LinkerNode.Name)
      : "",
    1);
  Indent(1);
  *BuildFileStream << "{\n";
  {
    if (!LinkerNode.PreBuildDependencies.empty()) {
      WriteArray("PreBuildDependencies", Wrap(LinkerNode.PreBuildDependencies),
                 2);
    }
    if (!allowDistribution) {
      WriteVariable("AllowDistribution", "false", 2);
    }

    if (!LinkerNode.Compiler.empty() &&
        LinkerNode.Type == FastbuildLinkerNode::STATIC_LIBRARY) {
      WriteVariable("Compiler", LinkerNode.Compiler, 2);
      WriteVariable("CompilerOptions", Quote(LinkerNode.CompilerOptions), 2);
      WriteVariable("CompilerOutputPath", Quote("."), 2);
    }
    if (!LocalEnvironment.empty()) {
      WriteVariable("Environment", "." FASTBUILD_ENV_VAR_NAME, 2);
    }

    WriteVariable(LinkerNode.Type == FastbuildLinkerNode::STATIC_LIBRARY
                    ? "Librarian"
                    : "Linker",
                  Quote(LinkerNode.Linker), 2);

    WriteVariable(LinkerNode.Type == FastbuildLinkerNode::STATIC_LIBRARY
                    ? "LibrarianOptions"
                    : "LinkerOptions",
                  Quote(LinkerNode.LinkerOptions), 2);

    WriteVariable(LinkerNode.Type == FastbuildLinkerNode::STATIC_LIBRARY
                    ? "LibrarianOutput"
                    : "LinkerOutput",
                  Quote(LinkerNode.LinkerOutput), 2);

    if (!LinkerNode.LibrarianAdditionalInputs.empty()) {
      WriteArray(LinkerNode.Type == FastbuildLinkerNode::STATIC_LIBRARY
                   ? "LibrarianAdditionalInputs"
                   : "Libraries",
                 Wrap(LinkerNode.LibrarianAdditionalInputs), 2);
    }
    if (!LinkerNode.Libraries2.empty()) {
      WriteArray("Libraries2", Wrap(LinkerNode.Libraries2), 2);
    }
    if (!LinkerNode.LibrarianAdditionalInputs.empty()) {

      if (!LinkerNode.LinkerType.empty()) {
        WriteVariable("LinkerType", Quote(LinkerNode.LinkerType), 2);
      }
    }
    if (LinkerNode.Type == FastbuildLinkerNode::EXECUTABLE ||
        LinkerNode.Type == FastbuildLinkerNode::SHARED_LIBRARY) {
      WriteVariable("LinkerLinkObjects",
                    LinkerNode.LinkerLinkObjects ? "true" : "false", 2);

      if (!LinkerNode.LinkerStampExe.empty()) {
        WriteVariable("LinkerStampExe", Quote(LinkerNode.LinkerStampExe), 2);
        if (!LinkerNode.LinkerStampExeArgs.empty()) {
          WriteVariable("LinkerStampExeArgs",
                        Quote(LinkerNode.LinkerStampExeArgs), 2);
        }
      }
    }
    Indent(1);
    *BuildFileStream << "}\n";
  }
}

void cmGlobalFastbuildGenerator::WriteAlias(FastbuildAliasNode const& Alias,
                                            int indent)
{
  if (Alias.PreBuildDependencies.empty()) {
    return;
  }
  auto const identPlus1 = indent + 1;
  WriteCommand("Alias", Quote(Alias.Name), indent);
  Indent(indent);
  *BuildFileStream << "{\n";
  WriteArray("Targets", Wrap(Alias.PreBuildDependencies), identPlus1);
  if (Alias.Hidden) {
    WriteVariable("Hidden", "true", identPlus1);
  }
  Indent(indent);
  *BuildFileStream << "}\n";
}

void cmGlobalFastbuildGenerator::WriteCopy(FastbuildCopyNode const& Copy)
{
  cmGlobalFastbuildGenerator::WriteCommand(
    Copy.CopyDir ? "CopyDir" : "Copy",
    cmGlobalFastbuildGenerator::Quote(Copy.Name), 1);
  cmGlobalFastbuildGenerator::Indent(1);

  *BuildFileStream << "{\n";
  WriteVariable("PreBuildDependencies",
                cmGlobalFastbuildGenerator::Quote(Copy.PreBuildDependencies),
                2);
  WriteVariable(Copy.CopyDir ? "SourcePaths" : "Source",
                cmGlobalFastbuildGenerator::Quote(Copy.Source), 2);
  WriteVariable("Dest", cmGlobalFastbuildGenerator::Quote(Copy.Dest), 2);
  cmGlobalFastbuildGenerator::Indent(1);
  *BuildFileStream << "}\n";
}

void cmGlobalFastbuildGenerator::WriteTarget(FastbuildTarget const& target)
{
  for (auto const& val : target.Variables) {
    auto const& key = val.first;
    auto const& value = val.second;
    WriteVariable(key, cmGlobalFastbuildGenerator::Quote(value), 1);
  }
  // add_custom_commands(...)
  for (auto const& alias : { target.ExecNodes }) {
    this->WriteAlias(alias);
  }

  // -deps Alias.
  this->WriteAlias(target.DependenciesAlias);

  // PRE_BUILD.
  for (auto const& alias : { target.PreBuildExecNodes }) {
    this->WriteAlias(alias);
  }

  // Copy commands.

  for (FastbuildCopyNode const& node : target.CopyNodes) {
    this->WriteCopy(node);
  }

  // Unity.
  for (FastbuildUnityNode const& unity : target.UnityNodes) {
    this->WriteUnity(unity);
  }

  // Objects.
  for (FastbuildObjectListNode const& objectList : target.ObjectListNodes) {
    this->WriteObjectList(objectList, target.AllowDistribution);
  }

  if (!target.PreLinkExecNodes.Nodes.empty()) {
    for (auto const& exec : target.PreLinkExecNodes.Nodes) {
      this->WriteExec(exec);
    }
    this->WriteAlias(target.PreLinkExecNodes.Alias);
  }

  // Libraries / executables.
  if (!target.LinkerNode.empty()) {
    for (auto const& cudaDeviceLinkNode : target.CudaDeviceLinkNode) {
      this->WriteLinker(cudaDeviceLinkNode, target.AllowDistribution);
    }
    for (auto const& linkerNode : target.LinkerNode) {
      this->WriteLinker(linkerNode, target.AllowDistribution);
    }
  }

  if (!target.PostBuildExecNodes.Nodes.empty()) {
    for (auto const& exec : target.PostBuildExecNodes.Nodes) {
      this->WriteExec(exec);
    }
    this->WriteAlias(target.PostBuildExecNodes.Alias);
  }

  // Aliases (if any).
  for (FastbuildAliasNode const& alias : target.AliasNodes) {
    this->WriteAlias(alias);
  }
}
void cmGlobalFastbuildGenerator::WriteIDEProjects()
{
#if defined(_WIN32)
  std::string platformToolset;
  std::string const toolset =
    this->GetSafeGlobalSetting("MSVC_TOOLSET_VERSION");
  if (!toolset.empty()) {
    platformToolset = cmStrCat('v', toolset);
  }
#endif
  for (auto const& proj : IDEProjects) {
    (void)proj;
    // VS
#if defined(_WIN32)
    auto const& VSProj = proj.second.first;
    WriteCommand("VCXProject", Quote(VSProj.Alias));
    *this->BuildFileStream << "{\n";
    WriteVariable("ProjectOutput", Quote(VSProj.ProjectOutput), 1);
    if (!platformToolset.empty()) {
      WriteVariable("PlatformToolset", Quote(platformToolset), 1);
    }
    WriteIDEProjectConfig(VSProj.ProjectConfigs);
    WriteVSBuildCommands();
    WriteIDEProjectCommon(VSProj);
    *this->BuildFileStream << "}\n\n";

    // XCode
#elif defined(__APPLE__)
    auto const& XCodeProj = proj.second.second;
    WriteCommand("XCodeProject", Quote(XCodeProj.Alias), 0);
    *this->BuildFileStream << "{\n";
    WriteVariable("ProjectOutput", Quote(XCodeProj.ProjectOutput), 1);
    WriteIDEProjectConfig(XCodeProj.ProjectConfigs);
    WriteXCodeBuildCommands();
    WriteIDEProjectCommon(XCodeProj);
    *this->BuildFileStream << "}\n\n";
#endif
  }

#if defined(_WIN32)
  this->WriteSolution();
#elif defined(__APPLE__)
  this->WriteXCodeTopLevelProject();
#endif
}

std::string cmGlobalFastbuildGenerator::GetIDEBuildArgs() const
{
  cmValue const ideArgs = this->GetGlobalSetting(FASTBUILD_IDE_ARGS);
  if (ideArgs) {
    return cmStrCat(' ', ideArgs, ' ');
  }
  return FASTBUILD_DEFAULT_IDE_BUILD_ARGS;
}

void cmGlobalFastbuildGenerator::WriteVSBuildCommands()
{
  std::string const ideArgs = this->GetIDEBuildArgs();
  WriteVariable(
    "ProjectBuildCommand",
    Quote(cmStrCat(FASTBUILD_IDE_VS_COMMAND_PREFIX, this->FastbuildCommand,
                   ideArgs, " ^$(ProjectName)")),
    1);
  WriteVariable(
    "ProjectRebuildCommand",
    Quote(cmStrCat(FASTBUILD_IDE_VS_COMMAND_PREFIX, this->FastbuildCommand,
                   ideArgs, "-clean ^$(ProjectName)")),
    1);
  WriteVariable("ProjectCleanCommand",
                Quote(cmStrCat(FASTBUILD_IDE_VS_COMMAND_PREFIX,
                               this->FastbuildCommand, ideArgs, " clean")),
                1);
}
void cmGlobalFastbuildGenerator::WriteXCodeBuildCommands()
{
  std::string const ideArgs = this->GetIDEBuildArgs();
  WriteVariable("XCodeBuildToolPath", Quote(this->FastbuildCommand), 1);
  WriteVariable("XCodeBuildToolArgs",
                Quote(cmStrCat(ideArgs, "^$(FASTBUILD_TARGET)")), 1);
  WriteVariable("XCodeBuildWorkingDir",
                Quote(this->CMakeInstance->GetHomeOutputDirectory()), 1);
}

void cmGlobalFastbuildGenerator::WriteIDEProjectCommon(
  IDEProjectCommon const& project)
{
  WriteVariable("ProjectBasePath", Quote(project.ProjectBasePath), 1);
  // So Fastbuild will pick up files relative to CMakeLists.txt
  WriteVariable("ProjectInputPaths", Quote(project.ProjectBasePath), 1);
}

void cmGlobalFastbuildGenerator::WriteIDEProjectConfig(
  std::vector<IDEProjectConfig> const& configs, std::string const& keyName)
{
  std::vector<std::string> allConfigVariables;
  for (auto const& config : configs) {
    std::string configName = "Config" + config.Config;
    WriteVariable(configName, "", 1);
    Indent(1);
    *this->BuildFileStream << "[\n";
    WriteVariable("Config", Quote(config.Config), 2);
    if (!config.Target.empty()) {
      WriteVariable("Target", Quote(config.Target), 2);
    }
    if (!config.Platform.empty()) {
      WriteVariable("Platform", Quote(config.Platform), 2);
    }
    Indent(1);
    *this->BuildFileStream << "]\n";
    allConfigVariables.emplace_back(std::move(configName));
  }
  WriteArray(keyName, Wrap(allConfigVariables, ".", ""), 1);
}

void cmGlobalFastbuildGenerator::AddTargetAll()
{
  FastbuildAliasNode allAliasNode;
  allAliasNode.Name = FASTBUILD_ALL_TARGET_NAME;

  for (auto const& targetBase : FastbuildTargets) {
    if (targetBase->Type == FastbuildTargetType::LINK) {
      auto const& target = static_cast<FastbuildTarget const&>(*targetBase);
      // Add non-global and non-excluded targets to "all"
      if (!target.IsGlobal && !target.ExcludeFromAll) {
        allAliasNode.PreBuildDependencies.emplace(target.Name);
      }
    } else if (targetBase->Type == FastbuildTargetType::ALIAS) {
      auto const& target = static_cast<FastbuildAliasNode const&>(*targetBase);
      if (!target.ExcludeFromAll) {
        allAliasNode.PreBuildDependencies.emplace(target.Name);
      }
    }
  }
  if (allAliasNode.PreBuildDependencies.empty()) {
    allAliasNode.PreBuildDependencies.emplace(FASTBUILD_NOOP_FILE_NAME);
  }
  this->AddTarget(std::move(allAliasNode));
}

void cmGlobalFastbuildGenerator::AddGlobCheckExec()
{
  // Tested in "RunCMake.file" test.
  std::string const globScript =
    this->GetCMakeInstance()->GetGlobVerifyScript();
  if (!globScript.empty()) {

    FastbuildExecNode globCheck;
    globCheck.Name = FASTBUILD_GLOB_CHECK_TARGET;
    globCheck.ExecExecutable = cmSystemTools::GetCMakeCommand();
    globCheck.ExecArguments =
      cmStrCat("-P ", this->ConvertToFastbuildPath(globScript));
    globCheck.ExecAlways = false;
    globCheck.ExecUseStdOutAsOutput = false;
    auto const cache = this->GetCMakeInstance()->GetGlobCacheEntries();
    for (auto const& entry : cache) {
      auto path = cmSystemTools::GetFilenamePath(entry.Expression);
      auto expression = cmSystemTools::GetFilenameName(entry.Expression);
      if (std::find(globCheck.ExecInputPath.begin(),
                    globCheck.ExecInputPath.end(),
                    path) == globCheck.ExecInputPath.end()) {
        globCheck.ExecInputPath.emplace_back(std::move(path));
      }
      if (std::find(globCheck.ExecInputPattern.begin(),
                    globCheck.ExecInputPattern.end(),
                    expression) == globCheck.ExecInputPattern.end()) {
        globCheck.ExecInputPattern.emplace_back(std::move(expression));
      }
    }
    globCheck.ExecOutput = this->ConvertToFastbuildPath(
      this->GetCMakeInstance()->GetGlobVerifyStamp());
    this->AddTarget(std::move(globCheck));
  }
}
void cmGlobalFastbuildGenerator::WriteSolution()
{
  std::string const solutionName = LocalGenerators[0]->GetProjectName();
  std::unordered_map<std::string /*folder*/, std::vector<std::string>>
    VSProjectFolders;
  std::unordered_map<std::string /*project*/,
                     std::vector<std::string> /*deps*/>
    VSProjectDeps;
  std::vector<std::string> VSProjectsWithoutFolder;

  for (auto const& IDEProj : IDEProjects) {
    auto const VSProj = IDEProj.second.first;
    VSProjectFolders[VSProj.folder].emplace_back(VSProj.Alias);
    auto& deps = VSProjectDeps[VSProj.Alias];
    deps.reserve(VSProj.deps.size());
    for (auto const& dep : VSProj.deps) {
      if (dep.Type == FastbuildTargetDepType::REGULAR) {
        deps.push_back(cmStrCat(dep.Name, FASTBUILD_VS_PROJECT_SUFFIX));
      }
    }
  }

  WriteCommand("VSSolution", Quote("solution"));
  *this->BuildFileStream << "{\n";

  WriteVariable("SolutionOutput",
                Quote(cmJoin({ "VisualStudio", solutionName + ".sln" }, "/")),
                1);

  auto const& configs = IDEProjects.begin()->second.first.ProjectConfigs;
  WriteIDEProjectConfig(configs, "SolutionConfigs");
  int folderNumber = 0;
  std::vector<std::string> folders;
  for (auto& item : VSProjectFolders) {
    auto const& pathToFolder = item.first;
    auto& projectsInFolder = item.second;
    if (pathToFolder.empty()) {
      std::move(projectsInFolder.begin(), projectsInFolder.end(),
                std::back_inserter(VSProjectsWithoutFolder));
    } else {
      std::string folderName = cmStrCat("Folder_", ++folderNumber);
      WriteStruct(
        folderName,
        { { "Path", Quote(pathToFolder) },
          { "Projects",
            cmStrCat('{', cmJoin(Wrap(projectsInFolder), ","), '}') } },
        1);
      folders.emplace_back(std::move(folderName));
    }
  }
  if (!folders.empty()) {
    WriteArray("SolutionFolders ", Wrap(folders, ".", ""), 1);
  }

  int depNumber = 0;
  std::vector<std::string> dependencies;
  for (auto const& dep : VSProjectDeps) {
    std::string const& projectName = dep.first;
    std::vector<std::string> const& projectDeps = dep.second;
    // This project has some deps.
    if (!projectDeps.empty()) {
      std::string depName = cmStrCat("Deps_", ++depNumber);
      WriteStruct(depName,
                  {
                    { "Projects", Quote(projectName) },
                    { "Dependencies",
                      cmStrCat('{', cmJoin(Wrap(projectDeps), ","), '}') },
                  },
                  1);
      dependencies.emplace_back(std::move(depName));
    }
  }

  if (!dependencies.empty()) {
    WriteArray("SolutionDependencies  ", Wrap(dependencies, ".", ""), 1);
  }
  if (!VSProjectsWithoutFolder.empty()) {
    WriteArray("SolutionProjects", Wrap(VSProjectsWithoutFolder), 1);
  }

  *this->BuildFileStream << "}\n";
}

void cmGlobalFastbuildGenerator::WriteXCodeTopLevelProject()
{
  std::string const projectName = LocalGenerators[0]->GetProjectName();
  std::vector<std::string> XCodeProjects;
  for (auto const& IDEProj : IDEProjects) {
    auto const XCodeProj = IDEProj.second.second;
    XCodeProjects.emplace_back(XCodeProj.Alias);
  }

  WriteCommand("XCodeProject", Quote("xcode"));
  *this->BuildFileStream << "{\n";

  WriteVariable(
    "ProjectOutput",
    Quote(
      cmJoin({ "XCode", projectName + ".xcodeproj", "project.pbxproj" }, "/")),
    1);
  WriteVariable("ProjectBasePath", Quote(FASTBUILD_XCODE_BASE_PATH), 1);

  auto const& configs = IDEProjects.begin()->second.second.ProjectConfigs;
  WriteIDEProjectConfig(configs);
  WriteArray("ProjectFiles", Wrap(XCodeProjects), 1);

  *this->BuildFileStream << "}\n";
}

void cmGlobalFastbuildGenerator::LogMessage(std::string const& m) const
{
  static bool const verbose = GlobalSettingIsOn(FASTBUILD_VERBOSE_GENERATOR) ||
    cmSystemTools::HasEnv(FASTBUILD_VERBOSE_GENERATOR);
  if (verbose) {
    cmSystemTools::Message(m);
  }
}
void cmGlobalFastbuildGenerator::AddFileToClean(std::string const& file)
{
  AllFilesToClean.insert(file);
}

std::string cmGlobalFastbuildGenerator::GetExternalShellExecutable()
{
  // FindProgram is expensive - touches filesystem and makes syscalls, so cache
  // it.
  static std::string const cached =
#ifdef _WIN32
    cmSystemTools::FindProgram(
      "cmd.exe", std::vector<std::string>{ "C:\\Windows\\System32" });
#else
    cmSystemTools::FindProgram("sh", std::vector<std::string>{ "/bin" });
#endif
  return cached;
}

void cmGlobalFastbuildGenerator::WriteTargetRebuildBFF()
{
  std::vector<std::string> implicitDeps;
  for (auto& lg : LocalGenerators) {
    std::vector<std::string> const& lf = lg->GetMakefile()->GetListFiles();
    for (auto const& dep : lf) {
      implicitDeps.push_back(this->ConvertToFastbuildPath(dep));
    }
  }
  auto const* cmake = this->GetCMakeInstance();
  std::string outDir = cmake->GetHomeOutputDirectory() + '/';

  implicitDeps.push_back(outDir + "CMakeCache.txt");

  FastbuildExecNode rebuildBFF;
  rebuildBFF.Name = FASTBUILD_REBUILD_BFF_TARGET_NAME;
  if (!this->GetCMakeInstance()->GetGlobVerifyScript().empty()) {
    implicitDeps.emplace_back(this->GetCMakeInstance()->GetGlobVerifyStamp());
  }

  std::sort(implicitDeps.begin(), implicitDeps.end());
  implicitDeps.erase(std::unique(implicitDeps.begin(), implicitDeps.end()),
                     implicitDeps.end());
  std::string args =
    cmStrCat("--regenerate-during-build",
             (this->GetCMakeInstance()->GetIgnoreCompileWarningAsError()
                ? " --compile-no-warning-as-error"
                : ""),
             (this->GetCMakeInstance()->GetIgnoreLinkWarningAsError()
                ? " --link-no-warning-as-error"
                : ""),
             " -S", QuoteIfHasSpaces(cmake->GetHomeDirectory()), " -B",
             QuoteIfHasSpaces(cmake->GetHomeOutputDirectory()));

  rebuildBFF.ExecArguments = std::move(args);
  rebuildBFF.ExecInput = implicitDeps;
  rebuildBFF.ExecExecutable = cmSystemTools::GetCMakeCommand();
  rebuildBFF.ExecWorkingDir = outDir;
  rebuildBFF.ExecOutput = outDir + FASTBUILD_BUILD_FILE;
  this->WriteExec(rebuildBFF, 0);
}

void cmGlobalFastbuildGenerator::WriteCleanScript()
{
  std::string const path =
    cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), '/',
             FASTBUILD_CLEAN_SCRIPT_NAME);
  cmsys::ofstream scriptFile(path.c_str(), std::ios::out | std::ios::binary);
  if (!scriptFile.is_open()) {
    cmSystemTools::Error("Failed to open: " FASTBUILD_CLEAN_SCRIPT_NAME);
    return;
  }
  for (std::string const& file : AllFilesToClean) {
#if defined(_WIN32)
    scriptFile << "del /f /q "
               << cmSystemTools::ConvertToWindowsOutputPath(file) << "\n";
#else
    scriptFile << "rm -f " << file << '\n';
#endif
  }
}

void cmGlobalFastbuildGenerator::WriteTargetClean()
{
  if (AllFilesToClean.empty()) {
    FastbuildAliasNode clean;
    clean.Name = FASTBUILD_CLEAN_TARGET_NAME;
    clean.PreBuildDependencies.emplace(FASTBUILD_CLEAN_FILE_NAME);
    WriteAlias(clean, 0);
    return;
  }
  WriteCleanScript();
  FastbuildExecNode clean;
  clean.Name = FASTBUILD_CLEAN_TARGET_NAME;
  clean.ExecExecutable = GetExternalShellExecutable();
  clean.ExecArguments =
    FASTBUILD_SCRIPT_FILE_ARG FASTBUILD_1_INPUT_PLACEHOLDER;
  clean.ExecInput = { FASTBUILD_CLEAN_SCRIPT_NAME };
  clean.ExecAlways = true;
  clean.ExecUseStdOutAsOutput = true;
  clean.ExecOutput = FASTBUILD_CLEAN_FILE_NAME;
  clean.ExecWorkingDir = this->GetCMakeInstance()->GetHomeOutputDirectory();
  WriteExec(clean, 0);
}

void cmGlobalFastbuildGenerator::WriteTargets()
{
  std::string const outputDir = this->CMakeInstance->GetHomeOutputDirectory();
  LogMessage("GetHomeOutputDirectory: " + outputDir);
  // Noop file that 'all' can alias to if we don't have any other targets...
  // The exact location of the "noop" file is verified in one of the tests in
  // "RunCMake.CMakePresetsPackage" test suite.
  cmSystemTools::Touch(cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(),
                                '/', FASTBUILD_NOOP_FILE_NAME),
                       true);
  cmSystemTools::Touch(cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(),
                                '/', FASTBUILD_CLEAN_FILE_NAME),
                       true);
  // Add "all" utility target before sorting, so we can correctly sort
  // targets that depend on it
  AddTargetAll();
  TopologicalSort(FastbuildTargets);

  AddGlobCheckExec();

  for (auto const& targetBase : FastbuildTargets) {
    this->WriteComment("Target definition: " + targetBase->Name);
    // Target start.
    *BuildFileStream << "{\n";

    if (targetBase->Type == FastbuildTargetType::EXEC) {
      this->WriteExec(static_cast<FastbuildExecNode const&>(*targetBase));
    } else if (targetBase->Type == FastbuildTargetType::ALIAS) {
      this->WriteAlias(static_cast<FastbuildAliasNode const&>(*targetBase));
    } else if (targetBase->Type == FastbuildTargetType::LINK) {
      auto const& target = static_cast<FastbuildTarget const&>(*targetBase);
      this->WriteTarget(target);
    }
    // Target end.
    *BuildFileStream << "}\n";
  }

  if (!this->GetCMakeInstance()->GetIsInTryCompile()) {
    if (!IDEProjects.empty()) {
      this->WriteIDEProjects();
    }
  }
  this->WriteTargetClean();
  this->WriteTargetRebuildBFF();
}

std::string cmGlobalFastbuildGenerator::GetTargetName(
  cmGeneratorTarget const* GeneratorTarget) const
{
  std::string targetName =
    GeneratorTarget->GetLocalGenerator()->GetCurrentBinaryDirectory();
  targetName += "/";
  targetName += GeneratorTarget->GetName();
  targetName = this->ConvertToFastbuildPath(targetName);
  return targetName;
}

cm::optional<FastbuildTarget>
cmGlobalFastbuildGenerator::GetTargetByOutputName(
  std::string const& output) const
{
  for (auto const& targetBase : FastbuildTargets) {
    if (targetBase->Type == FastbuildTargetType::LINK) {
      auto const& target = static_cast<FastbuildTarget const&>(*targetBase);
      if (std::any_of(target.LinkerNode.begin(), target.LinkerNode.end(),
                      [&output](FastbuildLinkerNode const& target_) {
                        return target_.LinkerOutput == output;
                      })) {
        return target;
      }
    }
  }
  return cm::nullopt;
}

void cmGlobalFastbuildGenerator::AddIDEProject(
  FastbuildTargetBase const& target, std::string const& config)
{
  auto const& configs = GetConfigNames();
  if (std::find(configs.begin(), configs.end(), config) == configs.end()) {
    LogMessage("Config " + config + " doesn't exist, IDE projest for " +
               target.Name + " won't be generated");
    return;
  }
  auto& IDEProject = IDEProjects[target.BaseName];
  auto const relativeSubdir = cmSystemTools::RelativePath(
    this->GetCMakeInstance()->GetHomeDirectory(), target.BasePath);
  // VS
  auto& VSProject = IDEProject.first;
  VSProject.Alias = cmStrCat(target.BaseName, FASTBUILD_VS_PROJECT_SUFFIX);
  VSProject.ProjectOutput = cmStrCat("VisualStudio/Projects/", relativeSubdir,
                                     '/', target.BaseName + ".vcxproj");
  VSProject.ProjectBasePath = target.BasePath;
  VSProject.folder = relativeSubdir;
  VSProject.deps = target.PreBuildDependencies;
  // XCode
  auto& XCodeProject = IDEProject.second;
  XCodeProject.Alias = target.BaseName + "-xcodeproj";
  XCodeProject.ProjectOutput =
    cmStrCat("XCode/Projects/", relativeSubdir, '/',
             target.BaseName + ".xcodeproj/project.pbxproj");
  XCodeProject.ProjectBasePath = target.BasePath;

  IDEProjectConfig VSConfig;
  VSConfig.Platform = "X64";
  IDEProjectConfig XCodeConfig;
  VSConfig.Target = XCodeConfig.Target = target.Name;
  VSConfig.Config = XCodeConfig.Config = config.empty() ? "DEFAULT" : config;

  VSProject.ProjectConfigs.emplace_back(std::move(VSConfig));
  XCodeProject.ProjectConfigs.emplace_back(std::move(XCodeConfig));
}

bool cmGlobalFastbuildGenerator::IsExcluded(cmGeneratorTarget* target)
{
  return cmGlobalGenerator::IsExcluded(LocalGenerators[0].get(), target);
}
std::vector<std::string> const& cmGlobalFastbuildGenerator::GetConfigNames()
  const
{
  return static_cast<cmLocalFastbuildGenerator const*>(
           this->LocalGenerators.front().get())
    ->GetConfigNames();
}

bool cmGlobalFastbuildGenerator::Open(std::string const& bindir,
                                      std::string const& projectName,
                                      bool dryRun)
{
#ifdef _WIN32
  std::string sln = bindir + "/VisualStudio/" + projectName + ".sln";

  if (dryRun) {
    return cmSystemTools::FileExists(sln, true);
  }

  sln = cmSystemTools::ConvertToOutputPath(sln);

  auto OpenSolution = [](std::string pathToSolution) {
    HRESULT comInitialized =
      CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
    if (FAILED(comInitialized)) {
      return false;
    }

    HINSTANCE hi = ShellExecuteA(NULL, "open", pathToSolution.c_str(), NULL,
                                 NULL, SW_SHOWNORMAL);

    CoUninitialize();

    return reinterpret_cast<intptr_t>(hi) > 32;
  };

  return std::async(std::launch::async, OpenSolution, sln).get();
#else
  return cmGlobalCommonGenerator::Open(bindir, projectName, dryRun);
#endif
}
