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

#include <array>
#include <cstddef>
#include <deque>
#include <initializer_list>
#include <limits>
#include <map>
#include <set>
#include <sstream> // for basic_ios, istringstream
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>

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

#include <cm3p/json/value.h>
#include <cm3p/json/writer.h>

#include "cmsys/SystemInformation.hxx"

#include "cmAlgorithms.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
#include "cmEvaluatedTargetProperty.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLinkItem.h"
#include "cmList.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmQtAutoGen.h"
#include "cmQtAutoGenGlobalInitializer.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocationKind.h"
#include "cmSourceGroup.h"
#include "cmStandardLevelResolver.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmValue.h"
#include "cmake.h"

namespace {

unsigned int GetParallelCPUCount()
{
  static unsigned int count = 0;
  // Detect only on the first call
  if (count == 0) {
    cmsys::SystemInformation info;
    info.RunCPUCheck();
    count =
      cm::clamp(info.GetNumberOfPhysicalCPU(), 1u, cmQtAutoGen::ParallelMax);
  }
  return count;
}

std::string FileProjectRelativePath(cmMakefile const* makefile,
                                    std::string const& fileName)
{
  std::string res;
  {
    std::string pSource = cmSystemTools::RelativePath(
      makefile->GetCurrentSourceDirectory(), fileName);
    std::string pBinary = cmSystemTools::RelativePath(
      makefile->GetCurrentBinaryDirectory(), fileName);
    if (pSource.size() < pBinary.size()) {
      res = std::move(pSource);
    } else if (pBinary.size() < fileName.size()) {
      res = std::move(pBinary);
    } else {
      res = fileName;
    }
  }
  return res;
}

/**
 * Tests if targetDepend is a STATIC_LIBRARY and if any of its
 * recursive STATIC_LIBRARY dependencies depends on targetOrigin
 * (STATIC_LIBRARY cycle).
 */
bool StaticLibraryCycle(cmGeneratorTarget const* targetOrigin,
                        cmGeneratorTarget const* targetDepend,
                        std::string const& config)
{
  bool cycle = false;
  if ((targetOrigin->GetType() == cmStateEnums::STATIC_LIBRARY) &&
      (targetDepend->GetType() == cmStateEnums::STATIC_LIBRARY)) {
    std::set<cmGeneratorTarget const*> knownLibs;
    std::deque<cmGeneratorTarget const*> testLibs;

    // Insert initial static_library dependency
    knownLibs.insert(targetDepend);
    testLibs.push_back(targetDepend);

    while (!testLibs.empty()) {
      cmGeneratorTarget const* testTarget = testLibs.front();
      testLibs.pop_front();
      // Check if the test target is the origin target (cycle)
      if (testTarget == targetOrigin) {
        cycle = true;
        break;
      }
      // Collect all static_library dependencies from the test target
      cmLinkImplementationLibraries const* libs =
        testTarget->GetLinkImplementationLibraries(
          config, cmGeneratorTarget::UseTo::Link);
      if (libs) {
        for (cmLinkItem const& item : libs->Libraries) {
          cmGeneratorTarget const* depTarget = item.Target;
          if (depTarget &&
              (depTarget->GetType() == cmStateEnums::STATIC_LIBRARY) &&
              knownLibs.insert(depTarget).second) {
            testLibs.push_back(depTarget);
          }
        }
      }
    }
  }
  return cycle;
}

/** Sanitizes file search paths.  */
class SearchPathSanitizer
{
public:
  SearchPathSanitizer(cmMakefile* makefile)
    : SourcePath_(makefile->GetCurrentSourceDirectory())
  {
  }
  std::vector<std::string> operator()(
    std::vector<std::string> const& paths) const;

private:
  std::string SourcePath_;
};

std::vector<std::string> SearchPathSanitizer::operator()(
  std::vector<std::string> const& paths) const
{
  std::vector<std::string> res;
  res.reserve(paths.size());
  for (std::string const& srcPath : paths) {
    // Collapse relative paths
    std::string path =
      cmSystemTools::CollapseFullPath(srcPath, this->SourcePath_);
    // Remove suffix slashes
    while (cmHasSuffix(path, '/')) {
      path.pop_back();
    }
    // Accept only non empty paths
    if (!path.empty()) {
      res.emplace_back(std::move(path));
    }
  }
  return res;
}

/** @brief Writes a CMake info file.  */
class InfoWriter
{
public:
  // -- Single value
  void Set(std::string const& key, std::string const& value)
  {
    this->Value_[key] = value;
  }
  void SetConfig(std::string const& key,
                 cmQtAutoGenInitializer::ConfigString const& cfgStr);
  void SetBool(std::string const& key, bool value)
  {
    this->Value_[key] = value;
  }
  void SetUInt(std::string const& key, unsigned int value)
  {
    this->Value_[key] = value;
  }

  // -- Array utility
  template <typename CONT>
  static bool MakeArray(Json::Value& jval, CONT const& container);

  template <typename CONT>
  static void MakeStringArray(Json::Value& jval, CONT const& container);

  // -- Array value
  template <typename CONT>
  void SetArray(std::string const& key, CONT const& container);
  template <typename CONT>
  void SetConfigArray(
    std::string const& key,
    cmQtAutoGenInitializer::ConfigStrings<CONT> const& cfgStr);

  // -- Array of arrays
  template <typename CONT, typename FUNC>
  void SetArrayArray(std::string const& key, CONT const& container, FUNC func);

  // -- Save to json file
  bool Save(std::string const& filename);

private:
  Json::Value Value_;
};

void InfoWriter::SetConfig(std::string const& key,
                           cmQtAutoGenInitializer::ConfigString const& cfgStr)
{
  this->Set(key, cfgStr.Default);
  for (auto const& item : cfgStr.Config) {
    this->Set(cmStrCat(key, '_', item.first), item.second);
  }
}

template <typename CONT>
bool InfoWriter::MakeArray(Json::Value& jval, CONT const& container)
{
  jval = Json::arrayValue;
  std::size_t const listSize = cm::size(container);
  if (listSize == 0) {
    return false;
  }
  jval.resize(static_cast<unsigned int>(listSize));
  return true;
}

template <typename CONT>
void InfoWriter::MakeStringArray(Json::Value& jval, CONT const& container)
{
  if (MakeArray(jval, container)) {
    Json::ArrayIndex ii = 0;
    for (std::string const& item : container) {
      jval[ii++] = item;
    }
  }
}

template <typename CONT>
void InfoWriter::SetArray(std::string const& key, CONT const& container)
{
  MakeStringArray(this->Value_[key], container);
}

template <typename CONT, typename FUNC>
void InfoWriter::SetArrayArray(std::string const& key, CONT const& container,
                               FUNC func)
{
  Json::Value& jval = this->Value_[key];
  if (MakeArray(jval, container)) {
    Json::ArrayIndex ii = 0;
    for (auto const& citem : container) {
      Json::Value& aval = jval[ii++];
      aval = Json::arrayValue;
      func(aval, citem);
    }
  }
}

template <typename CONT>
void InfoWriter::SetConfigArray(
  std::string const& key,
  cmQtAutoGenInitializer::ConfigStrings<CONT> const& cfgStr)
{
  this->SetArray(key, cfgStr.Default);
  for (auto const& item : cfgStr.Config) {
    this->SetArray(cmStrCat(key, '_', item.first), item.second);
  }
}

bool InfoWriter::Save(std::string const& filename)
{
  cmGeneratedFileStream fileStream;
  fileStream.SetCopyIfDifferent(true);
  fileStream.Open(filename, false, true);
  if (!fileStream) {
    return false;
  }

  Json::StyledStreamWriter jsonWriter;
  try {
    jsonWriter.write(fileStream, this->Value_);
  } catch (...) {
    return false;
  }

  return fileStream.Close();
}

cmQtAutoGen::ConfigStrings<std::vector<std::string>> generateListOptions(
  cmQtAutoGen::ConfigStrings<cmQtAutoGen::CompilerFeaturesHandle> const&
    executableFeatures,
  bool IsMultiConfig)
{
  cmQtAutoGen::ConfigStrings<std::vector<std::string>> tempListOptions;
  if (IsMultiConfig) {
    for (auto const& executableFeature : executableFeatures.Config) {
      tempListOptions.Config[executableFeature.first] =
        executableFeature.second->ListOptions;
    }
  } else {
    tempListOptions.Default = executableFeatures.Default->ListOptions;
  }

  return tempListOptions;
}

} // End of unnamed namespace

cmQtAutoGenInitializer::cmQtAutoGenInitializer(
  cmQtAutoGenGlobalInitializer* globalInitializer,
  cmGeneratorTarget* genTarget, IntegerVersion const& qtVersion,
  bool mocEnabled, bool uicEnabled, bool rccEnabled, bool globalAutogenTarget,
  bool globalAutoRccTarget)
  : GlobalInitializer(globalInitializer)
  , GenTarget(genTarget)
  , GlobalGen(genTarget->GetGlobalGenerator())
  , LocalGen(genTarget->GetLocalGenerator())
  , Makefile(genTarget->Makefile)
  , PathCheckSum(genTarget->Makefile)
  , QtVersion(qtVersion)
{
  this->AutogenTarget.GlobalTarget = globalAutogenTarget;
  this->Moc.Enabled = mocEnabled;
  this->Uic.Enabled = uicEnabled;
  this->Rcc.Enabled = rccEnabled;
  this->Rcc.GlobalTarget = globalAutoRccTarget;
  this->CrossConfig =
    !this->Makefile->GetSafeDefinition("CMAKE_CROSS_CONFIGS").empty();
  this->UseBetterGraph =
    this->GenTarget->GetProperty("AUTOGEN_BETTER_GRAPH_MULTI_CONFIG").IsSet()
    ? this->GenTarget->GetProperty("AUTOGEN_BETTER_GRAPH_MULTI_CONFIG").IsOn()
    : (this->QtVersion >= IntegerVersion(6, 8));
  // AUTOGEN_BETTER_GRAPH_MULTI_CONFIG is set explicitly because it is read by
  // the qt library
  this->GenTarget->Target->SetProperty("AUTOGEN_BETTER_GRAPH_MULTI_CONFIG",
                                       this->UseBetterGraph ? "ON" : "OFF");
}

void cmQtAutoGenInitializer::AddAutogenExecutableToDependencies(
  cmQtAutoGenInitializer::GenVarsT const& genVars,
  std::vector<std::string>& dependencies) const
{
  if (genVars.ExecutableTarget != nullptr) {
    dependencies.push_back(genVars.ExecutableTarget->Target->GetName());
  } else if (this->MultiConfig && this->UseBetterGraph) {
    cm::string_view const& configGenexWithCommandConfig =
      "$<COMMAND_CONFIG:$<$<CONFIG:";
    cm::string_view const& configGenex = "$<$<CONFIG:";
    cm::string_view const& configGenexEnd = ">";
    cm::string_view const& configGenexEndWithCommandConfig = ">>";
    auto genexBegin =
      this->CrossConfig ? configGenexWithCommandConfig : configGenex;
    auto genexEnd =
      this->CrossConfig ? configGenexEndWithCommandConfig : configGenexEnd;
    for (auto const& config : genVars.Executable.Config) {
      auto executableWithConfig =
        cmStrCat(genexBegin, config.first, ">:", config.second, genexEnd);
      dependencies.emplace_back(std::move(executableWithConfig));
    }
  } else {
    if (!genVars.Executable.Default.empty()) {
      dependencies.push_back(genVars.Executable.Default);
    }
  }
}

bool cmQtAutoGenInitializer::InitCustomTargets()
{
  // Configurations
  this->MultiConfig = this->GlobalGen->IsMultiConfig();
  this->ConfigDefault = this->Makefile->GetDefaultConfiguration();
  this->ConfigsList =
    this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);

  // Verbosity
  {
    std::string const def =
      this->Makefile->GetSafeDefinition("CMAKE_AUTOGEN_VERBOSE");
    if (!def.empty()) {
      unsigned long iVerb = 0;
      if (cmStrToULong(def, &iVerb)) {
        // Numeric verbosity
        this->Verbosity = static_cast<unsigned int>(iVerb);
      } else {
        // Non numeric verbosity
        if (cmIsOn(def)) {
          this->Verbosity = 1;
        }
      }
    }
  }

  // Targets FOLDER
  {
    cmValue folder =
      this->Makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER");
    if (!folder) {
      folder = this->Makefile->GetState()->GetGlobalProperty(
        "AUTOGEN_TARGETS_FOLDER");
    }
    // Inherit FOLDER property from target (#13688)
    if (!folder) {
      folder = this->GenTarget->GetProperty("FOLDER");
    }
    if (folder) {
      this->TargetsFolder = *folder;
    }
  }

  // Check status of policy CMP0071 regarding handling of GENERATED files
  switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0071)) {
    case cmPolicies::WARN:
      // Ignore GENERATED files but warn
      this->CMP0071Warn = true;
      CM_FALLTHROUGH;
    case cmPolicies::OLD:
      // Ignore GENERATED files
      break;
    case cmPolicies::REQUIRED_IF_USED:
    case cmPolicies::REQUIRED_ALWAYS:
    case cmPolicies::NEW:
      // Process GENERATED files
      this->CMP0071Accept = true;
      break;
  }

  // Check status of policy CMP0100 regarding handling of .hh headers
  switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0100)) {
    case cmPolicies::WARN:
      // Ignore but .hh files but warn
      this->CMP0100Warn = true;
      CM_FALLTHROUGH;
    case cmPolicies::OLD:
      // Ignore .hh files
      break;
    case cmPolicies::REQUIRED_IF_USED:
    case cmPolicies::REQUIRED_ALWAYS:
    case cmPolicies::NEW:
      // Process .hh file
      this->CMP0100Accept = true;
      break;
  }

  // Common directories
  std::string relativeBuildDir;
  {
    // Collapsed current binary directory
    std::string const cbd = cmSystemTools::CollapseFullPath(
      std::string(), this->Makefile->GetCurrentBinaryDirectory());

    // Info directory
    this->Dir.Info = cmStrCat(cbd, "/CMakeFiles/", this->GenTarget->GetName(),
                              "_autogen.dir");
    cmSystemTools::ConvertToUnixSlashes(this->Dir.Info);

    // Build directory
    this->Dir.Build = this->GenTarget->GetSafeProperty("AUTOGEN_BUILD_DIR");
    if (this->Dir.Build.empty()) {
      this->Dir.Build =
        cmStrCat(cbd, '/', this->GenTarget->GetName(), "_autogen");
    }
    cmSystemTools::ConvertToUnixSlashes(this->Dir.Build);
    this->Dir.RelativeBuild =
      cmSystemTools::RelativePath(cbd, this->Dir.Build);
    // Cleanup build directory
    this->AddCleanFile(this->Dir.Build);

    // Working directory
    this->Dir.Work = cbd;
    cmSystemTools::ConvertToUnixSlashes(this->Dir.Work);

    // Include directory
    this->ConfigFileNamesAndGenex(this->Dir.Include, this->Dir.IncludeGenExp,
                                  cmStrCat(this->Dir.Build, "/include"), "");
  }

  // Moc, Uic and _autogen target settings
  if (this->MocOrUicEnabled()) {
    // Init moc specific settings
    if (this->Moc.Enabled && !this->InitMoc()) {
      return false;
    }

    // Init uic specific settings
    if (this->Uic.Enabled && !this->InitUic()) {
      return false;
    }

    // Autogen target name
    this->AutogenTarget.Name =
      cmStrCat(this->GenTarget->GetName(), "_autogen");

    // Autogen target parallel processing
    {
      using ParallelType = decltype(this->AutogenTarget.Parallel);
      unsigned long propInt = 0;
      std::string const& prop =
        this->GenTarget->GetSafeProperty("AUTOGEN_PARALLEL");
      if (prop.empty() || (prop == "AUTO")) {
        // Autodetect number of CPUs
        this->AutogenTarget.Parallel = GetParallelCPUCount();
      } else if (cmStrToULong(prop, &propInt) && propInt > 0 &&
                 propInt <= std::numeric_limits<ParallelType>::max()) {
        this->AutogenTarget.Parallel = static_cast<ParallelType>(propInt);
      } else {
        // Warn the project author that AUTOGEN_PARALLEL is not valid.
        this->Makefile->IssueMessage(
          MessageType::AUTHOR_WARNING,
          cmStrCat("AUTOGEN_PARALLEL=\"", prop, "\" for target \"",
                   this->GenTarget->GetName(),
                   "\" is not valid. Using AUTOGEN_PARALLEL=1"));
        this->AutogenTarget.Parallel = 1;
      }
    }

#ifdef _WIN32
    {
      const auto& value =
        this->GenTarget->GetProperty("AUTOGEN_COMMAND_LINE_LENGTH_MAX");
      if (value.IsSet()) {
        using maxCommandLineLengthType =
          decltype(this->AutogenTarget.MaxCommandLineLength);
        unsigned long propInt = 0;
        if (cmStrToULong(value, &propInt) && propInt > 0 &&
            propInt <= std::numeric_limits<maxCommandLineLengthType>::max()) {
          this->AutogenTarget.MaxCommandLineLength =
            static_cast<maxCommandLineLengthType>(propInt);
        } else {
          // Warn the project author that AUTOGEN_PARALLEL is not valid.
          this->Makefile->IssueMessage(
            MessageType::AUTHOR_WARNING,
            cmStrCat("AUTOGEN_COMMAND_LINE_LENGTH_MAX=\"", *value,
                     "\" for target \"", this->GenTarget->GetName(),
                     "\" is not valid. Using no limit for "
                     "AUTOGEN_COMMAND_LINE_LENGTH_MAX"));
          this->AutogenTarget.MaxCommandLineLength =
            std::numeric_limits<maxCommandLineLengthType>::max();
        }
      } else {
        // Actually 32767 (see
        // https://devblogs.microsoft.com/oldnewthing/20031210-00/?p=41553) but
        // we allow for a small margin
        this->AutogenTarget.MaxCommandLineLength = 32000;
      }
    }
#endif

    // Autogen target info and settings files
    {
      // Info file
      this->AutogenTarget.InfoFile =
        cmStrCat(this->Dir.Info, "/AutogenInfo.json");

      // Used settings file
      this->ConfigFileNames(this->AutogenTarget.SettingsFile,
                            cmStrCat(this->Dir.Info, "/AutogenUsed"), ".txt");
      this->ConfigFileClean(this->AutogenTarget.SettingsFile);

      // Parse cache file
      this->ConfigFileNames(this->AutogenTarget.ParseCacheFile,
                            cmStrCat(this->Dir.Info, "/ParseCache"), ".txt");
      this->ConfigFileClean(this->AutogenTarget.ParseCacheFile);
    }

    // Autogen target: Compute user defined dependencies
    {
      this->AutogenTarget.DependOrigin =
        this->GenTarget->GetPropertyAsBool("AUTOGEN_ORIGIN_DEPENDS");

      std::string const& deps =
        this->GenTarget->GetSafeProperty("AUTOGEN_TARGET_DEPENDS");
      if (!deps.empty()) {
        for (auto const& depName : cmList{ deps }) {
          // Allow target and file dependencies
          auto* depTarget = this->Makefile->FindTargetToUse(depName);
          if (depTarget) {
            this->AutogenTarget.DependTargets.insert(depTarget);
          } else {
            this->AutogenTarget.DependFiles.insert(depName);
          }
        }
      }
    }

    if (this->Moc.Enabled) {
      // Path prefix
      if (this->GenTarget->GetProperty("AUTOMOC_PATH_PREFIX").IsOn()) {
        this->Moc.PathPrefix = true;
      }

      // CMAKE_AUTOMOC_RELAXED_MODE
      if (this->Makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE")) {
        this->Moc.RelaxedMode = true;
        this->Makefile->IssueMessage(
          MessageType::AUTHOR_WARNING,
          cmStrCat("AUTOMOC: CMAKE_AUTOMOC_RELAXED_MODE is "
                   "deprecated an will be removed in the future.  Consider "
                   "disabling it and converting the target ",
                   this->GenTarget->GetName(), " to regular mode."));
      }

      // Options
      cmExpandList(this->GenTarget->GetSafeProperty("AUTOMOC_MOC_OPTIONS"),
                   this->Moc.Options);
      // Filters
      cmExpandList(this->GenTarget->GetSafeProperty("AUTOMOC_MACRO_NAMES"),
                   this->Moc.MacroNames);
      this->Moc.MacroNames.erase(cmRemoveDuplicates(this->Moc.MacroNames),
                                 this->Moc.MacroNames.end());
      {
        cmList const filterList = { this->GenTarget->GetSafeProperty(
          "AUTOMOC_DEPEND_FILTERS") };
        if ((filterList.size() % 2) != 0) {
          cmSystemTools::Error(
            cmStrCat("AutoMoc: AUTOMOC_DEPEND_FILTERS predefs size ",
                     filterList.size(), " is not a multiple of 2."));
          return false;
        }
        this->Moc.DependFilters.reserve(1 + (filterList.size() / 2));
        this->Moc.DependFilters.emplace_back(
          "Q_PLUGIN_METADATA",
          "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\("
          "[^\\)]*FILE[ \t]*\"([^\"]+)\"");
        for (cmList::size_type ii = 0; ii != filterList.size(); ii += 2) {
          this->Moc.DependFilters.emplace_back(filterList[ii],
                                               filterList[ii + 1]);
        }
      }
    }
  }

  // Init rcc specific settings
  if (this->Rcc.Enabled && !this->InitRcc()) {
    return false;
  }

  // Add autogen include directory to the origin target INCLUDE_DIRECTORIES
  if (this->MocOrUicEnabled() || (this->Rcc.Enabled && this->MultiConfig)) {
    auto addBefore = false;
    auto const& value =
      this->GenTarget->GetProperty("AUTOGEN_USE_SYSTEM_INCLUDE");
    if (value.IsSet()) {
      if (value.IsOn()) {
        this->GenTarget->AddSystemIncludeDirectory(this->Dir.IncludeGenExp,
                                                   "CXX");
      } else {
        addBefore = true;
      }
    } else {
      switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0151)) {
        case cmPolicies::WARN:
        case cmPolicies::OLD:
          addBefore = true;
          break;
        case cmPolicies::REQUIRED_IF_USED:
        case cmPolicies::REQUIRED_ALWAYS:
        case cmPolicies::NEW:
          this->GenTarget->AddSystemIncludeDirectory(this->Dir.IncludeGenExp,
                                                     "CXX");
          break;
      }
    }
    this->GenTarget->AddIncludeDirectory(this->Dir.IncludeGenExp, addBefore);
  }

  // Scan files
  if (!this->InitScanFiles()) {
    return false;
  }

  // Create autogen target
  if (this->MocOrUicEnabled() && !this->InitAutogenTarget()) {
    return false;
  }

  // Create rcc targets
  if (this->Rcc.Enabled && !this->InitRccTargets()) {
    return false;
  }

  return true;
}

bool cmQtAutoGenInitializer::InitMoc()
{
  // Mocs compilation file
  if (this->GlobalGen->IsXcode()) {
    // XXX(xcode-per-cfg-src): Drop this Xcode-specific code path
    // when the Xcode generator supports per-config sources.
    this->Moc.CompilationFile.Default =
      cmStrCat(this->Dir.Build, "/mocs_compilation.cpp");
    this->Moc.CompilationFileGenex = this->Moc.CompilationFile.Default;
  } else {
    this->ConfigFileNamesAndGenex(
      this->Moc.CompilationFile, this->Moc.CompilationFileGenex,
      cmStrCat(this->Dir.Build, "/mocs_compilation"_s), ".cpp"_s);
  }

  // Moc predefs
  if (this->GenTarget->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") &&
      (this->QtVersion >= IntegerVersion(5, 8))) {
    // Command
    cmList::assign(
      this->Moc.PredefsCmd,
      this->Makefile->GetDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"));
    // Header
    if (!this->Moc.PredefsCmd.empty()) {
      this->ConfigFileNames(this->Moc.PredefsFile,
                            cmStrCat(this->Dir.Build, "/moc_predefs"), ".h");
    }
  }

  // Moc includes
  {
    SearchPathSanitizer const sanitizer(this->Makefile);
    auto getDirs =
      [this, &sanitizer](std::string const& cfg) -> std::vector<std::string> {
      // Get the include dirs for this target, without stripping the implicit
      // include dirs off, see issue #13667.
      std::vector<std::string> dirs;
      bool const appendImplicit = (this->QtVersion.Major >= 5);
      this->LocalGen->GetIncludeDirectoriesImplicit(
        dirs, this->GenTarget, "CXX", cfg, false, appendImplicit);
      return sanitizer(dirs);
    };

    // Other configuration settings
    if (this->MultiConfig) {
      for (std::string const& cfg : this->ConfigsList) {
        std::vector<std::string> dirs = getDirs(cfg);
        if (dirs == this->Moc.Includes.Default) {
          continue;
        }
        this->Moc.Includes.Config[cfg] = std::move(dirs);
      }
    } else {
      // Default configuration include directories
      this->Moc.Includes.Default = getDirs(this->ConfigDefault);
    }
  }

  // Moc compile definitions
  {
    auto getDefs = [this](std::string const& cfg) -> std::set<std::string> {
      std::set<std::string> defines;
      this->LocalGen->GetTargetDefines(this->GenTarget, cfg, "CXX", defines);
      if (this->Moc.PredefsCmd.empty() &&
          this->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") ==
            "Windows") {
        // Add WIN32 definition if we don't have a moc_predefs.h
        defines.insert("WIN32");
      }
      return defines;
    };

    // Other configuration defines
    if (this->MultiConfig) {
      for (std::string const& cfg : this->ConfigsList) {
        std::set<std::string> defines = getDefs(cfg);
        if (defines == this->Moc.Defines.Default) {
          continue;
        }
        this->Moc.Defines.Config[cfg] = std::move(defines);
      }
    } else {
      // Default configuration defines
      this->Moc.Defines.Default = getDefs(this->ConfigDefault);
    }
  }

  // Moc executable
  {
    if (!this->GetQtExecutable(this->Moc, "moc", false)) {
      return false;
    }
    // Let the _autogen target depend on the moc executable
    if (this->Moc.ExecutableTarget) {
      this->AutogenTarget.DependTargets.insert(
        this->Moc.ExecutableTarget->Target);
    }
  }

  return true;
}

bool cmQtAutoGenInitializer::InitUic()
{
  // Uic search paths
  {
    std::string const& usp =
      this->GenTarget->GetSafeProperty("AUTOUIC_SEARCH_PATHS");
    if (!usp.empty()) {
      this->Uic.SearchPaths =
        SearchPathSanitizer(this->Makefile)(cmList{ usp });
    }
  }
  // Uic target options
  {
    auto getOpts = [this](std::string const& cfg) -> std::vector<std::string> {
      std::vector<std::string> opts;
      this->GenTarget->GetAutoUicOptions(opts, cfg);
      return opts;
    };

    // Default options
    this->Uic.Options.Default = getOpts(this->ConfigDefault);
    // Configuration specific options
    if (this->MultiConfig) {
      for (std::string const& cfg : this->ConfigsList) {
        std::vector<std::string> options = getOpts(cfg);
        if (options == this->Uic.Options.Default) {
          continue;
        }
        this->Uic.Options.Config[cfg] = std::move(options);
      }
    }
  }

  // Uic executable
  {
    if (!this->GetQtExecutable(this->Uic, "uic", true)) {
      return false;
    }
    // Let the _autogen target depend on the uic executable
    if (this->Uic.ExecutableTarget) {
      this->AutogenTarget.DependTargets.insert(
        this->Uic.ExecutableTarget->Target);
    }
  }

  return true;
}

bool cmQtAutoGenInitializer::InitRcc()
{
  // Rcc executable
  {
    if (!this->GetQtExecutable(this->Rcc, "rcc", false)) {
      return false;
    }
    // Evaluate test output on demand
    auto& features = this->Rcc.ExecutableFeatures;
    auto checkAndAddOptions = [this](CompilerFeaturesHandle& feature) {
      if (!feature->Evaluated) {
        // Look for list options
        if (this->QtVersion.Major == 5 || this->QtVersion.Major == 6) {
          static std::array<std::string, 2> const listOptions{ { "--list",
                                                                 "-list" } };
          for (std::string const& opt : listOptions) {
            if (feature->HelpOutput.find(opt) != std::string::npos) {
              feature->ListOptions.emplace_back(opt);
              break;
            }
          }
        }
        // Evaluation finished
        feature->Evaluated = true;
      }
    };
    if (this->MultiConfig && this->UseBetterGraph) {
      for (auto const& config : this->ConfigsList) {
        checkAndAddOptions(features.Config[config]);
      }
    } else {
      checkAndAddOptions(features.Default);
    }
  }

  // Disable zstd if it is not supported
  {
    std::string const qtFeatureZSTD = "QT_FEATURE_zstd";
    if (this->GenTarget->Target->GetMakefile()->IsDefinitionSet(
          qtFeatureZSTD)) {
      const auto zstdDef =
        this->GenTarget->Target->GetMakefile()->GetSafeDefinition(
          qtFeatureZSTD);
      const auto zstdVal = cmValue(zstdDef);
      if (zstdVal.IsOff()) {
        auto const& kw = this->GlobalInitializer->kw();
        auto rccOptions = this->GenTarget->GetSafeProperty(kw.AUTORCC_OPTIONS);
        std::string const nozstd = "--no-zstd";
        if (rccOptions.find(nozstd) == std::string::npos) {
          rccOptions.append(";" + nozstd + ";");
        }
        this->GenTarget->Target->SetProperty(kw.AUTORCC_OPTIONS, rccOptions);
      }
    }
  }

  return true;
}

bool cmQtAutoGenInitializer::InitScanFiles()
{
  cmake const* cm = this->Makefile->GetCMakeInstance();
  auto const& kw = this->GlobalInitializer->kw();

  auto makeMUFile = [this, &kw](cmSourceFile* sf, std::string const& fullPath,
                                std::vector<size_t> const& configs,
                                bool muIt) -> MUFileHandle {
    MUFileHandle muf = cm::make_unique<MUFile>();
    muf->FullPath = fullPath;
    muf->SF = sf;
    if (!configs.empty() && configs.size() != this->ConfigsList.size()) {
      muf->Configs = configs;
    }
    muf->Generated = sf->GetIsGenerated();
    bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN);
    muf->SkipMoc = this->Moc.Enabled &&
      (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOMOC));
    muf->SkipUic = this->Uic.Enabled &&
      (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOUIC));
    if (muIt) {
      muf->MocIt = this->Moc.Enabled && !muf->SkipMoc;
      muf->UicIt = this->Uic.Enabled && !muf->SkipUic;
    }
    return muf;
  };

  auto addMUHeader = [this](MUFileHandle&& muf, cm::string_view extension) {
    cmSourceFile* sf = muf->SF;
    const bool muIt = (muf->MocIt || muf->UicIt);
    if (this->CMP0100Accept || (extension != "hh")) {
      // Accept
      if (muIt && muf->Generated) {
        this->AutogenTarget.FilesGenerated.emplace_back(muf.get());
      }
      this->AutogenTarget.Headers.emplace(sf, std::move(muf));
    } else if (muIt && this->CMP0100Warn) {
      // Store file for warning message
      this->AutogenTarget.CMP0100HeadersWarn.push_back(sf);
    }
  };

  auto addMUSource = [this](MUFileHandle&& muf) {
    if ((muf->MocIt || muf->UicIt) && muf->Generated) {
      this->AutogenTarget.FilesGenerated.emplace_back(muf.get());
    }
    this->AutogenTarget.Sources.emplace(muf->SF, std::move(muf));
  };

  // Scan through target files
  {
    // Scan through target files
    for (cmGeneratorTarget::AllConfigSource const& acs :
         this->GenTarget->GetAllConfigSources()) {
      std::string const& fullPath = acs.Source->GetFullPath();
      std::string const& extLower =
        cmSystemTools::LowerCase(acs.Source->GetExtension());

      // Register files that will be scanned by moc or uic
      if (this->MocOrUicEnabled()) {
        if (cm->IsAHeaderExtension(extLower)) {
          addMUHeader(makeMUFile(acs.Source, fullPath, acs.Configs, true),
                      extLower);
        } else if (cm->IsACLikeSourceExtension(extLower)) {
          addMUSource(makeMUFile(acs.Source, fullPath, acs.Configs, true));
        }
      }

      // Register rcc enabled files
      if (this->Rcc.Enabled) {
        if ((extLower == kw.qrc) &&
            !acs.Source->GetPropertyAsBool(kw.SKIP_AUTOGEN) &&
            !acs.Source->GetPropertyAsBool(kw.SKIP_AUTORCC)) {
          // Register qrc file
          Qrc qrc;
          qrc.QrcFile = fullPath;
          qrc.QrcName =
            cmSystemTools::GetFilenameWithoutLastExtension(qrc.QrcFile);
          qrc.Generated = acs.Source->GetIsGenerated();
          // RCC options
          {
            std::string const& opts =
              acs.Source->GetSafeProperty(kw.AUTORCC_OPTIONS);
            if (!opts.empty()) {
              cmExpandList(opts, qrc.Options);
            }
          }
          this->Rcc.Qrcs.push_back(std::move(qrc));
        }
      }
    }
  }
  // cmGeneratorTarget::GetAllConfigSources computes the target's
  // sources meta data cache. Clear it so that OBJECT library targets that
  // are AUTOGEN initialized after this target get their added
  // mocs_compilation.cpp source acknowledged by this target.
  this->GenTarget->ClearSourcesCache();

  // For source files find additional headers and private headers
  if (this->MocOrUicEnabled()) {
    // Header search suffixes and extensions
    static std::initializer_list<cm::string_view> const suffixes{ "", "_p" };
    auto const& exts = cm->GetHeaderExtensions();
    // Scan through sources
    for (auto const& pair : this->AutogenTarget.Sources) {
      MUFile const& muf = *pair.second;
      if (muf.MocIt || muf.UicIt) {
        // Search for the default header file and a private header
        std::string const& srcFullPath = muf.SF->ResolveFullPath();
        std::string const basePath = cmStrCat(
          cmQtAutoGen::SubDirPrefix(srcFullPath),
          cmSystemTools::GetFilenameWithoutLastExtension(srcFullPath));
        for (auto const& suffix : suffixes) {
          std::string const suffixedPath = cmStrCat(basePath, suffix);
          for (auto const& ext : exts) {
            std::string const fullPath = cmStrCat(suffixedPath, '.', ext);

            auto constexpr locationKind = cmSourceFileLocationKind::Known;
            cmSourceFile* sf =
              this->Makefile->GetSource(fullPath, locationKind);
            if (sf) {
              // Check if we know about this header already
              if (cm::contains(this->AutogenTarget.Headers, sf)) {
                continue;
              }
              // We only accept not-GENERATED files that do exist.
              if (!sf->GetIsGenerated() &&
                  !cmSystemTools::FileExists(fullPath)) {
                continue;
              }
            } else if (cmSystemTools::FileExists(fullPath)) {
              // Create a new source file for the existing file
              sf = this->Makefile->CreateSource(fullPath, false, locationKind);
            }

            if (sf) {
              auto eMuf = makeMUFile(sf, fullPath, muf.Configs, true);
              // Only process moc/uic when the parent is processed as well
              if (!muf.MocIt) {
                eMuf->MocIt = false;
              }
              if (!muf.UicIt) {
                eMuf->UicIt = false;
              }
              addMUHeader(std::move(eMuf), ext);
            }
          }
        }
      }
    }
  }

  // Scan through all source files in the makefile to extract moc and uic
  // parameters.  Historically we support non target source file parameters.
  // The reason is that their file names might be discovered from source files
  // at generation time.
  if (this->MocOrUicEnabled()) {
    for (const auto& sf : this->Makefile->GetSourceFiles()) {
      // sf->GetExtension() is only valid after sf->ResolveFullPath() ...
      // Since we're iterating over source files that might be not in the
      // target we need to check for path errors (not existing files).
      std::string pathError;
      std::string const& fullPath = sf->ResolveFullPath(&pathError);
      if (!pathError.empty() || fullPath.empty()) {
        continue;
      }
      std::string const& extLower =
        cmSystemTools::LowerCase(sf->GetExtension());

      if (cm->IsAHeaderExtension(extLower)) {
        if (!cm::contains(this->AutogenTarget.Headers, sf.get())) {
          auto muf = makeMUFile(sf.get(), fullPath, {}, false);
          if (muf->SkipMoc || muf->SkipUic) {
            addMUHeader(std::move(muf), extLower);
          }
        }
      } else if (cm->IsACLikeSourceExtension(extLower)) {
        if (!cm::contains(this->AutogenTarget.Sources, sf.get())) {
          auto muf = makeMUFile(sf.get(), fullPath, {}, false);
          if (muf->SkipMoc || muf->SkipUic) {
            addMUSource(std::move(muf));
          }
        }
      } else if (this->Uic.Enabled && (extLower == kw.ui)) {
        // .ui file
        bool const skipAutogen = sf->GetPropertyAsBool(kw.SKIP_AUTOGEN);
        bool const skipUic =
          (skipAutogen || sf->GetPropertyAsBool(kw.SKIP_AUTOUIC));
        if (!skipUic) {
          // Check if the .ui file has uic options
          std::string const uicOpts = sf->GetSafeProperty(kw.AUTOUIC_OPTIONS);
          if (uicOpts.empty()) {
            this->Uic.UiFilesNoOptions.emplace_back(fullPath);
          } else {
            this->Uic.UiFilesWithOptions.emplace_back(
              fullPath, std::move(cmList{ uicOpts }.data()));
          }

          auto uiHeaderRelativePath = cmSystemTools::RelativePath(
            this->LocalGen->GetCurrentSourceDirectory(),
            cmSystemTools::GetFilenamePath(fullPath));

          // Avoid creating a path containing adjacent slashes
          if (!uiHeaderRelativePath.empty() &&
              uiHeaderRelativePath.back() != '/') {
            uiHeaderRelativePath += '/';
          }

          auto uiHeaderFilePath = cmStrCat(
            '/', uiHeaderRelativePath, "ui_"_s,
            cmSystemTools::GetFilenameWithoutLastExtension(fullPath), ".h"_s);

          ConfigString uiHeader;
          std::string uiHeaderGenex;
          this->ConfigFileNamesAndGenex(
            uiHeader, uiHeaderGenex, cmStrCat(this->Dir.Build, "/include"_s),
            uiHeaderFilePath);

          this->Uic.UiHeaders.emplace_back(uiHeader, uiHeaderGenex);
        } else {
          // Register skipped .ui file
          this->Uic.SkipUi.insert(fullPath);
        }
      }
    }
  }

  // Process GENERATED sources and headers
  if (this->MocOrUicEnabled() && !this->AutogenTarget.FilesGenerated.empty()) {
    if (this->CMP0071Accept) {
      // Let the autogen target depend on the GENERATED files
      if (this->MultiConfig && !this->CrossConfig) {
        for (MUFile const* muf : this->AutogenTarget.FilesGenerated) {
          if (muf->Configs.empty()) {
            this->AutogenTarget.DependFiles.insert(muf->FullPath);
          } else {
            for (size_t ci : muf->Configs) {
              std::string const& config = this->ConfigsList[ci];
              std::string const& pathWithConfig =
                cmStrCat("$<$<CONFIG:", config, ">:", muf->FullPath, '>');
              this->AutogenTarget.DependFiles.insert(pathWithConfig);
            }
          }
        }
      } else {
        for (MUFile const* muf : this->AutogenTarget.FilesGenerated) {
          this->AutogenTarget.DependFiles.insert(muf->FullPath);
        }
      }
    } else if (this->CMP0071Warn) {
      cm::string_view property;
      if (this->Moc.Enabled && this->Uic.Enabled) {
        property = "SKIP_AUTOGEN";
      } else if (this->Moc.Enabled) {
        property = "SKIP_AUTOMOC";
      } else if (this->Uic.Enabled) {
        property = "SKIP_AUTOUIC";
      }
      std::string files;
      for (MUFile const* muf : this->AutogenTarget.FilesGenerated) {
        files += cmStrCat("  ", Quoted(muf->FullPath), '\n');
      }
      this->Makefile->IssueMessage(
        MessageType::AUTHOR_WARNING,
        cmStrCat(
          cmPolicies::GetPolicyWarning(cmPolicies::CMP0071), '\n',
          "For compatibility, CMake is excluding the GENERATED source "
          "file(s):\n",
          files, "from processing by ",
          cmQtAutoGen::Tools(this->Moc.Enabled, this->Uic.Enabled, false),
          ".  If any of the files should be processed, set CMP0071 to NEW.  "
          "If any of the files should not be processed, "
          "explicitly exclude them by setting the source file property ",
          property, ":\n  set_property(SOURCE file.h PROPERTY ", property,
          " ON)\n"));
    }
  }

  // Generate CMP0100 warning
  if (this->MocOrUicEnabled() &&
      !this->AutogenTarget.CMP0100HeadersWarn.empty()) {
    cm::string_view property;
    if (this->Moc.Enabled && this->Uic.Enabled) {
      property = "SKIP_AUTOGEN";
    } else if (this->Moc.Enabled) {
      property = "SKIP_AUTOMOC";
    } else if (this->Uic.Enabled) {
      property = "SKIP_AUTOUIC";
    }
    std::string files;
    for (cmSourceFile const* sf : this->AutogenTarget.CMP0100HeadersWarn) {
      files += cmStrCat("  ", Quoted(sf->GetFullPath()), '\n');
    }
    this->Makefile->IssueMessage(
      MessageType::AUTHOR_WARNING,
      cmStrCat(
        cmPolicies::GetPolicyWarning(cmPolicies::CMP0100), '\n',
        "For compatibility, CMake is excluding the header file(s):\n", files,
        "from processing by ",
        cmQtAutoGen::Tools(this->Moc.Enabled, this->Uic.Enabled, false),
        ".  If any of the files should be processed, set CMP0100 to NEW.  "
        "If any of the files should not be processed, "
        "explicitly exclude them by setting the source file property ",
        property, ":\n  set_property(SOURCE file.hh PROPERTY ", property,
        " ON)\n"));
  }

  // Process qrc files
  if (!this->Rcc.Qrcs.empty()) {
    const bool modernQt = (this->QtVersion.Major >= 5);
    // Target rcc options
    cmList const optionsTarget{ this->GenTarget->GetSafeProperty(
      kw.AUTORCC_OPTIONS) };

    // Check if file name is unique
    for (Qrc& qrc : this->Rcc.Qrcs) {
      qrc.Unique = true;
      for (Qrc const& qrc2 : this->Rcc.Qrcs) {
        if ((&qrc != &qrc2) && (qrc.QrcName == qrc2.QrcName)) {
          qrc.Unique = false;
          break;
        }
      }
    }
    // Path checksum and file names
    for (Qrc& qrc : this->Rcc.Qrcs) {
      // Path checksum
      qrc.QrcPathChecksum = this->PathCheckSum.getPart(qrc.QrcFile);
      // Output file name
      if (this->MultiConfig && !this->GlobalGen->IsXcode() &&
          this->UseBetterGraph) {
        qrc.OutputFile = cmStrCat(this->Dir.Build, '/', qrc.QrcPathChecksum,
                                  "_$<CONFIG>", "/qrc_", qrc.QrcName, ".cpp");
      } else {
        qrc.OutputFile = cmStrCat(this->Dir.Build, '/', qrc.QrcPathChecksum,
                                  "/qrc_", qrc.QrcName, ".cpp");
      }
      std::string const base = cmStrCat(this->Dir.Info, "/AutoRcc_",
                                        qrc.QrcName, '_', qrc.QrcPathChecksum);
      qrc.LockFile = cmStrCat(base, "_Lock.lock");
      qrc.InfoFile = cmStrCat(base, "_Info.json");
      this->ConfigFileNames(qrc.SettingsFile, cmStrCat(base, "_Used"), ".txt");
    }
    // rcc options
    for (Qrc& qrc : this->Rcc.Qrcs) {
      // Target options
      std::vector<std::string> opts = optionsTarget;
      // Merge computed "-name XYZ" option
      {
        std::string name = qrc.QrcName;
        // Replace '-' with '_'. The former is not valid for symbol names.
        std::replace(name.begin(), name.end(), '-', '_');
        if (!qrc.Unique) {
          name += cmStrCat('_', qrc.QrcPathChecksum);
        }
        std::vector<std::string> nameOpts;
        nameOpts.emplace_back("-name");
        nameOpts.emplace_back(std::move(name));
        RccMergeOptions(opts, nameOpts, modernQt);
      }
      // Merge file option
      RccMergeOptions(opts, qrc.Options, modernQt);
      qrc.Options = std::move(opts);
    }
    // rcc resources
    for (Qrc& qrc : this->Rcc.Qrcs) {
      if (!qrc.Generated) {
        std::string error;
        if (this->MultiConfig && this->UseBetterGraph) {
          for (auto const& config : this->ConfigsList) {
            RccLister const lister(
              this->Rcc.Executable.Config[config],
              this->Rcc.ExecutableFeatures.Config[config]->ListOptions);
            if (!lister.list(qrc.QrcFile, qrc.Resources.Config[config],
                             error)) {
              cmSystemTools::Error(error);
              return false;
            }
          }
        } else {
          RccLister const lister(
            this->Rcc.Executable.Default,
            this->Rcc.ExecutableFeatures.Default->ListOptions);
          if (!lister.list(qrc.QrcFile, qrc.Resources.Default, error)) {
            cmSystemTools::Error(error);
            return false;
          }
        }
      }
    }
  }

  return true;
}

bool cmQtAutoGenInitializer::InitAutogenTarget()
{
  // Register info file as generated by CMake
  this->Makefile->AddCMakeOutputFile(this->AutogenTarget.InfoFile);

  // Determine whether to use a depfile for the AUTOGEN target.
  bool const useDepfile = [this]() -> bool {
    auto const& gen = this->GlobalGen->GetName();
    return this->QtVersion >= IntegerVersion(5, 15) &&
      (gen.find("Ninja") != std::string::npos ||
       gen.find("Make") != std::string::npos);
  }();

  // Files provided by the autogen target
  std::vector<std::string> autogenByproducts;
  std::vector<std::string> timestampByproducts;
  if (this->Moc.Enabled) {
    this->AddGeneratedSource(this->Moc.CompilationFile, this->Moc, true);
    if (useDepfile) {
      if (this->CrossConfig &&
          this->GlobalGen->GetName().find("Ninja") != std::string::npos &&
          !this->UseBetterGraph) {
        // Make all mocs_compilation_<CONFIG>.cpp files byproducts of the
        // ${target}_autogen/timestamp custom command.
        // We cannot just use Moc.CompilationFileGenex here, because that
        // custom command runs cmake_autogen for each configuration.
        for (const auto& p : this->Moc.CompilationFile.Config) {
          timestampByproducts.push_back(p.second);
        }
      } else {
        timestampByproducts.push_back(this->Moc.CompilationFileGenex);
      }
    } else {
      autogenByproducts.push_back(this->Moc.CompilationFileGenex);
    }
  }

  if (this->Uic.Enabled) {
    for (const auto& file : this->Uic.UiHeaders) {
      this->AddGeneratedSource(file.first, this->Uic);
      autogenByproducts.push_back(file.second);
    }
  }

  // Compose target comment
  std::string autogenComment;
  {
    std::string tools;
    if (this->Moc.Enabled) {
      tools += "MOC";
    }
    if (this->Uic.Enabled) {
      if (!tools.empty()) {
        tools += " and ";
      }
      tools += "UIC";
    }
    autogenComment = cmStrCat("Automatic ", tools, " for target ",
                              this->GenTarget->GetName());
  }

  // Compose command lines
  // FIXME: Take advantage of our per-config mocs_compilation_$<CONFIG>.cpp
  // instead of fiddling with the include directories

  bool constexpr stdPipesUTF8 = true;
  cmCustomCommandLines commandLines;
  AddCMakeProcessToCommandLines(this->AutogenTarget.InfoFile, "cmake_autogen",
                                commandLines);

  // Use PRE_BUILD on demand
  bool usePRE_BUILD = false;
  if (this->GlobalGen->GetName().find("Visual Studio") != std::string::npos) {
    // Under VS use a PRE_BUILD event instead of a separate target to
    // reduce the number of targets loaded into the IDE.
    // This also works around a VS 11 bug that may skip updating the target:
    //  https://connect.microsoft.com/VisualStudio/feedback/details/769495
    usePRE_BUILD = true;
  }
  // Disable PRE_BUILD in some cases
  if (usePRE_BUILD) {
    // Cannot use PRE_BUILD with file depends
    if (!this->AutogenTarget.DependFiles.empty()) {
      usePRE_BUILD = false;
    }
    // Cannot use PRE_BUILD when a global autogen target is in place
    if (this->AutogenTarget.GlobalTarget) {
      usePRE_BUILD = false;
    }
  }
  // Create the autogen target/command
  if (usePRE_BUILD) {
    // Add additional autogen target dependencies to origin target
    for (cmTarget const* depTarget : this->AutogenTarget.DependTargets) {
      this->GenTarget->Target->AddUtility(depTarget->GetName(), false,
                                          this->Makefile);
    }

    if (!this->Uic.UiFilesNoOptions.empty() ||
        !this->Uic.UiFilesWithOptions.empty()) {
      // Add a generated timestamp file
      ConfigString timestampFile;
      std::string timestampFileGenex;
      ConfigFileNamesAndGenex(timestampFile, timestampFileGenex,
                              cmStrCat(this->Dir.Build, "/autouic"_s),
                              ".stamp"_s);
      this->AddGeneratedSource(timestampFile, this->Uic);

      // Add a step in the pre-build command to touch the timestamp file
      commandLines.push_back(
        cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), "-E", "touch",
                            timestampFileGenex }));

      // UIC needs to be re-run if any of the known UI files change or the
      // executable itself has been updated
      auto uicDependencies = this->Uic.UiFilesNoOptions;
      for (auto const& uiFile : this->Uic.UiFilesWithOptions) {
        uicDependencies.push_back(uiFile.first);
      }
      AddAutogenExecutableToDependencies(this->Uic, uicDependencies);

      // Add a rule file to cause the target to build if a dependency has
      // changed, which will trigger the pre-build command to run autogen
      auto cc = cm::make_unique<cmCustomCommand>();
      cc->SetOutputs(timestampFileGenex);
      cc->SetDepends(uicDependencies);
      cc->SetComment("");
      cc->SetWorkingDirectory(this->Dir.Work.c_str());
      cc->SetEscapeOldStyle(false);
      cc->SetStdPipesUTF8(stdPipesUTF8);
      this->LocalGen->AddCustomCommandToOutput(std::move(cc));
    }

    // Add the pre-build command directly to bypass the OBJECT_LIBRARY
    // rejection in cmMakefile::AddCustomCommandToTarget because we know
    // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case.
    //
    // PRE_BUILD does not support file dependencies!
    cmCustomCommand cc;
    cc.SetByproducts(autogenByproducts);
    cc.SetCommandLines(commandLines);
    cc.SetComment(autogenComment.c_str());
    cc.SetBacktrace(this->Makefile->GetBacktrace());
    cc.SetWorkingDirectory(this->Dir.Work.c_str());
    cc.SetStdPipesUTF8(stdPipesUTF8);
    cc.SetEscapeOldStyle(false);
    cc.SetEscapeAllowMakeVars(true);
    this->GenTarget->Target->AddPreBuildCommand(std::move(cc));
  } else {

    // Add link library target dependencies to the autogen target
    // dependencies
    if (this->AutogenTarget.DependOrigin) {
      // add_dependencies/addUtility do not support generator expressions.
      // We depend only on the libraries found in all configs therefore.
      std::map<cmGeneratorTarget const*, std::size_t> commonTargets;
      for (std::string const& config : this->ConfigsList) {
        cmLinkImplementationLibraries const* libs =
          this->GenTarget->GetLinkImplementationLibraries(
            config, cmGeneratorTarget::UseTo::Link);
        if (libs) {
          for (cmLinkItem const& item : libs->Libraries) {
            cmGeneratorTarget const* libTarget = item.Target;
            if (libTarget &&
                !StaticLibraryCycle(this->GenTarget, libTarget, config)) {
              // Increment target config count
              commonTargets[libTarget]++;
            }
          }
        }
      }
      for (auto const& item : commonTargets) {
        if (item.second == this->ConfigsList.size()) {
          this->AutogenTarget.DependTargets.insert(item.first->Target);
        }
      }
    }

    cmTarget* timestampTarget = nullptr;
    std::vector<std::string> dependencies(
      this->AutogenTarget.DependFiles.begin(),
      this->AutogenTarget.DependFiles.end());
    if (useDepfile) {
      // Create a custom command that generates a timestamp file and
      // has a depfile assigned. The depfile is created by JobDepFilesMergeT.
      //
      // Also create an additional '_autogen_timestamp_deps' that the custom
      // command will depend on. It will have no sources or commands to
      // execute, but it will have dependencies that would originally be
      // assigned to the pre-Qt 5.15 'autogen' target. These dependencies will
      // serve as a list of order-only dependencies for the custom command,
      // without forcing the custom command to re-execute.
      //
      // The dependency tree would then look like
      // '_autogen_timestamp_deps (order-only)' <- '/timestamp' file <-
      // '_autogen' target.
      const auto timestampTargetName =
        cmStrCat(this->GenTarget->GetName(), "_autogen_timestamp_deps");

      auto cc = cm::make_unique<cmCustomCommand>();
      cc->SetWorkingDirectory(this->Dir.Work.c_str());
      cc->SetDepends(dependencies);
      cc->SetEscapeOldStyle(false);
      timestampTarget = this->LocalGen->AddUtilityCommand(timestampTargetName,
                                                          true, std::move(cc));

      this->LocalGen->AddGeneratorTarget(
        cm::make_unique<cmGeneratorTarget>(timestampTarget, this->LocalGen));

      // Set FOLDER property on the timestamp target, so it appears in the
      // appropriate folder in an IDE or in the file api.
      if (!this->TargetsFolder.empty()) {
        timestampTarget->SetProperty("FOLDER", this->TargetsFolder);
      }

      // Make '/timestamp' file depend on '_autogen_timestamp_deps' and on the
      // moc and uic executables (whichever are enabled).
      dependencies.clear();
      dependencies.push_back(timestampTargetName);

      AddAutogenExecutableToDependencies(this->Moc, dependencies);
      AddAutogenExecutableToDependencies(this->Uic, dependencies);
      std::string outputFile;
      std::string depFile;
      // Create the custom command that outputs the timestamp file.
      if (this->MultiConfig && this->UseBetterGraph) {
        // create timestamp file with $<CONFIG> in the name so that
        // every cmake_autogen target has its own timestamp file
        std::string const configView = "$<CONFIG>";
        std::string const timestampFileWithoutConfig = "timestamp_";
        std::string const depFileWithoutConfig =
          cmStrCat(this->Dir.Build, "/deps_");
        std::string const timestampFileName =
          timestampFileWithoutConfig + configView;
        outputFile = cmStrCat(this->Dir.Build, "/", timestampFileName);
        auto const depFileWithConfig =
          cmStrCat(depFileWithoutConfig, configView);
        depFile = depFileWithConfig;
        commandLines.push_back(cmMakeCommandLine(
          { cmSystemTools::GetCMakeCommand(), "-E", "touch", outputFile }));

        ConfigString outputFileWithConfig;
        for (std::string const& config : this->ConfigsList) {
          auto tempTimestampFileName = timestampFileWithoutConfig + config;
          auto tempDepFile = depFileWithoutConfig + config;
          outputFileWithConfig.Config[config] = tempTimestampFileName;
          this->AutogenTarget.DepFileRuleName.Config[config] =
            cmStrCat(this->Dir.RelativeBuild, "/", tempTimestampFileName);
          this->AutogenTarget.DepFile.Config[config] = tempDepFile;
        }
        this->AddGeneratedSource(outputFileWithConfig, this->Moc);
      } else {
        cm::string_view const timestampFileName = "timestamp";
        outputFile = cmStrCat(this->Dir.Build, "/", timestampFileName);
        this->AutogenTarget.DepFile.Default =
          cmStrCat(this->Dir.Build, "/deps");
        depFile = this->AutogenTarget.DepFile.Default;
        this->AutogenTarget.DepFileRuleName.Default =
          cmStrCat(this->Dir.RelativeBuild, "/", timestampFileName);
        commandLines.push_back(cmMakeCommandLine(
          { cmSystemTools::GetCMakeCommand(), "-E", "touch", outputFile }));
        this->AddGeneratedSource(outputFile, this->Moc);
      }
      cc = cm::make_unique<cmCustomCommand>();
      cc->SetOutputs(outputFile);
      cc->SetByproducts(timestampByproducts);
      cc->SetDepends(dependencies);
      cc->SetCommandLines(commandLines);
      cc->SetComment(autogenComment.c_str());
      cc->SetWorkingDirectory(this->Dir.Work.c_str());
      cc->SetEscapeOldStyle(false);
      cc->SetDepfile(depFile);
      cc->SetStdPipesUTF8(stdPipesUTF8);
      this->LocalGen->AddCustomCommandToOutput(std::move(cc));
      dependencies.clear();
      dependencies.emplace_back(std::move(outputFile));
      commandLines.clear();
      autogenComment.clear();
    }

    // Create autogen target
    auto cc = cm::make_unique<cmCustomCommand>();
    cc->SetWorkingDirectory(this->Dir.Work.c_str());
    cc->SetByproducts(autogenByproducts);
    cc->SetDepends(dependencies);
    cc->SetCommandLines(commandLines);
    cc->SetEscapeOldStyle(false);
    cc->SetComment(autogenComment.c_str());
    cmTarget* autogenTarget = this->LocalGen->AddUtilityCommand(
      this->AutogenTarget.Name, true, std::move(cc));
    // Create autogen generator target
    this->LocalGen->AddGeneratorTarget(
      cm::make_unique<cmGeneratorTarget>(autogenTarget, this->LocalGen));

    // Order the autogen target(s) just before the original target.
    cmTarget* orderTarget = timestampTarget ? timestampTarget : autogenTarget;
    // Forward origin utilities to autogen target
    if (this->AutogenTarget.DependOrigin) {
      for (BT<std::pair<std::string, bool>> const& depName :
           this->GenTarget->GetUtilities()) {
        orderTarget->AddUtility(depName.Value.first, false, this->Makefile);
      }
    }

    // Add additional autogen target dependencies to autogen target
    for (cmTarget const* depTarget : this->AutogenTarget.DependTargets) {
      orderTarget->AddUtility(depTarget->GetName(), false, this->Makefile);
    }

    // Set FOLDER property in autogen target
    if (!this->TargetsFolder.empty()) {
      autogenTarget->SetProperty("FOLDER", this->TargetsFolder);
    }

    // Add autogen target to the origin target dependencies
    this->GenTarget->Target->AddUtility(this->AutogenTarget.Name, false,
                                        this->Makefile);

    // Add autogen target to the global autogen target dependencies
    if (this->AutogenTarget.GlobalTarget) {
      this->GlobalInitializer->AddToGlobalAutoGen(this->LocalGen,
                                                  this->AutogenTarget.Name);
    }
  }

  return true;
}

void cmQtAutoGenInitializer::AddCMakeProcessToCommandLines(
  std::string const& infoFile, std::string const& processName,
  cmCustomCommandLines& commandLines)
{
  if (this->CrossConfig && this->UseBetterGraph) {
    commandLines.push_back(cmMakeCommandLine(
      { cmSystemTools::GetCMakeCommand(), "-E", processName, infoFile,
        "$<CONFIG>", "$<COMMAND_CONFIG:$<CONFIG>>" }));
  } else if ((this->MultiConfig && this->GlobalGen->IsXcode()) ||
             this->CrossConfig) {
    for (std::string const& config : this->ConfigsList) {
      commandLines.push_back(
        cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), "-E",
                            processName, infoFile, config }));
    }
  } else {
    std::string autoInfoFileConfig;
    if (this->MultiConfig) {
      autoInfoFileConfig = "$<CONFIG>";
    } else {
      std::vector<std::string> configs;
      this->GlobalGen->GetQtAutoGenConfigs(configs);
      autoInfoFileConfig = configs[0];
    }
    commandLines.push_back(
      cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), "-E", processName,
                          infoFile, autoInfoFileConfig }));
  }
}

bool cmQtAutoGenInitializer::InitRccTargets()
{
  for (Qrc const& qrc : this->Rcc.Qrcs) {
    // Register info file as generated by CMake
    this->Makefile->AddCMakeOutputFile(qrc.InfoFile);
    // Register file at target
    {
      cmSourceFile* sf = this->AddGeneratedSource(qrc.OutputFile, this->Rcc);
      sf->SetProperty("SKIP_UNITY_BUILD_INCLUSION", "On");
    }

    std::vector<std::string> ccOutput;
    ccOutput.push_back(qrc.OutputFile);

    std::vector<std::string> ccDepends;
    // Add the .qrc and info file to the custom command dependencies
    ccDepends.push_back(qrc.QrcFile);
    ccDepends.push_back(qrc.InfoFile);

    cmCustomCommandLines commandLines;
    AddCMakeProcessToCommandLines(qrc.InfoFile, "cmake_autorcc", commandLines);

    std::string const ccComment =
      cmStrCat("Automatic RCC for ",
               FileProjectRelativePath(this->Makefile, qrc.QrcFile));

    auto cc = cm::make_unique<cmCustomCommand>();
    cc->SetWorkingDirectory(this->Dir.Work.c_str());
    cc->SetCommandLines(commandLines);
    cc->SetComment(ccComment.c_str());
    cc->SetStdPipesUTF8(true);

    if (qrc.Generated || this->Rcc.GlobalTarget) {
      // Create custom rcc target
      std::string ccName;
      {
        ccName = cmStrCat(this->GenTarget->GetName(), "_arcc_", qrc.QrcName);
        if (!qrc.Unique) {
          ccName += cmStrCat('_', qrc.QrcPathChecksum);
        }

        cc->SetByproducts(ccOutput);
        cc->SetDepends(ccDepends);
        cc->SetEscapeOldStyle(false);
        cmTarget* autoRccTarget =
          this->LocalGen->AddUtilityCommand(ccName, true, std::move(cc));

        // Create autogen generator target
        this->LocalGen->AddGeneratorTarget(
          cm::make_unique<cmGeneratorTarget>(autoRccTarget, this->LocalGen));

        // Set FOLDER property in autogen target
        if (!this->TargetsFolder.empty()) {
          autoRccTarget->SetProperty("FOLDER", this->TargetsFolder);
        }
        if (!this->Rcc.ExecutableTargetName.empty()) {
          autoRccTarget->AddUtility(this->Rcc.ExecutableTargetName, false,
                                    this->Makefile);
        }
      }
      // Add autogen target to the origin target dependencies
      this->GenTarget->Target->AddUtility(ccName, false, this->Makefile);

      // Add autogen target to the global autogen target dependencies
      if (this->Rcc.GlobalTarget) {
        this->GlobalInitializer->AddToGlobalAutoRcc(this->LocalGen, ccName);
      }
    } else {
      // Create custom rcc command
      {
        // Add the resource files to the dependencies
        if (this->MultiConfig && this->UseBetterGraph) {
          for (auto const& config : this->ConfigsList) {
            // Add resource file to the custom command dependencies
            auto resourceFilesWithConfig = cmStrCat(
              "$<$<CONFIG:", config,
              ">:", cmList{ qrc.Resources.Config.at(config) }.to_string(),
              ">");
            ccDepends.emplace_back(std::move(resourceFilesWithConfig));
          }
        } else {
          for (std::string const& fileName : qrc.Resources.Default) {
            // Add resource file to the custom command dependencies
            ccDepends.push_back(fileName);
          }
        }

        if (!this->Rcc.ExecutableTargetName.empty()) {
          ccDepends.push_back(this->Rcc.ExecutableTargetName);
        }

        AddAutogenExecutableToDependencies(this->Rcc, ccDepends);

        cc->SetOutputs(ccOutput);
        cc->SetDepends(ccDepends);
        this->LocalGen->AddCustomCommandToOutput(std::move(cc));
      }
      // Reconfigure when .qrc file changes
      this->Makefile->AddCMakeDependFile(qrc.QrcFile);
    }
  }

  return true;
}

bool cmQtAutoGenInitializer::SetupCustomTargets()
{
  // Create info directory on demand
  if (!cmSystemTools::MakeDirectory(this->Dir.Info)) {
    cmSystemTools::Error(cmStrCat("AutoGen: Could not create directory: ",
                                  Quoted(this->Dir.Info)));
    return false;
  }

  // Generate autogen target info file
  if (this->MocOrUicEnabled()) {
    // Write autogen target info files
    if (!this->SetupWriteAutogenInfo()) {
      return false;
    }
  }

  // Write AUTORCC info files
  return !this->Rcc.Enabled || this->SetupWriteRccInfo();
}

bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
{
  // Utility lambdas
  auto MfDef = [this](std::string const& key) {
    return this->Makefile->GetSafeDefinition(key);
  };

  // Filtered headers and sources
  std::set<std::string> moc_skip;
  std::set<std::string> uic_skip;
  std::vector<MUFile const*> headers;
  std::vector<MUFile const*> sources;

  // Filter headers
  {
    headers.reserve(this->AutogenTarget.Headers.size());
    for (auto const& pair : this->AutogenTarget.Headers) {
      MUFile const* const muf = pair.second.get();
      if (muf->SkipMoc) {
        moc_skip.insert(muf->FullPath);
      }
      if (muf->SkipUic) {
        uic_skip.insert(muf->FullPath);
      }
      if (muf->Generated && !this->CMP0071Accept) {
        continue;
      }
      if (muf->MocIt || muf->UicIt) {
        headers.emplace_back(muf);
      }
    }
    std::sort(headers.begin(), headers.end(),
              [](MUFile const* a, MUFile const* b) {
                return (a->FullPath < b->FullPath);
              });
  }

  // Filter sources
  {
    sources.reserve(this->AutogenTarget.Sources.size());
    for (auto const& pair : this->AutogenTarget.Sources) {
      MUFile const* const muf = pair.second.get();
      if (muf->Generated && !this->CMP0071Accept) {
        continue;
      }
      if (muf->SkipMoc) {
        moc_skip.insert(muf->FullPath);
      }
      if (muf->SkipUic) {
        uic_skip.insert(muf->FullPath);
      }
      if (muf->MocIt || muf->UicIt) {
        sources.emplace_back(muf);
      }
    }
    std::sort(sources.begin(), sources.end(),
              [](MUFile const* a, MUFile const* b) {
                return (a->FullPath < b->FullPath);
              });
  }

  // Info writer
  InfoWriter info;

  // General
  info.SetBool("MULTI_CONFIG", this->MultiConfig);
  info.SetBool("CROSS_CONFIG", this->CrossConfig);
  info.SetBool("USE_BETTER_GRAPH", this->UseBetterGraph);
  info.SetUInt("PARALLEL", this->AutogenTarget.Parallel);
#ifdef _WIN32
  info.SetUInt("AUTOGEN_COMMAND_LINE_LENGTH_MAX",
               this->AutogenTarget.MaxCommandLineLength);
#endif
  info.SetUInt("VERBOSITY", this->Verbosity);

  // Directories
  info.Set("CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));
  info.Set("CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));
  info.Set("CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR"));
  info.Set("CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR"));
  info.Set("BUILD_DIR", this->Dir.Build);
  info.SetConfig("INCLUDE_DIR", this->Dir.Include);

  info.SetUInt("QT_VERSION_MAJOR", this->QtVersion.Major);
  info.SetUInt("QT_VERSION_MINOR", this->QtVersion.Minor);
  info.SetConfig("QT_MOC_EXECUTABLE", this->Moc.Executable);
  info.SetConfig("QT_UIC_EXECUTABLE", this->Uic.Executable);

  info.Set("CMAKE_EXECUTABLE", cmSystemTools::GetCMakeCommand());
  info.SetConfig("SETTINGS_FILE", this->AutogenTarget.SettingsFile);
  info.SetConfig("PARSE_CACHE_FILE", this->AutogenTarget.ParseCacheFile);
  info.SetConfig("DEP_FILE", this->AutogenTarget.DepFile);
  info.SetConfig("DEP_FILE_RULE_NAME", this->AutogenTarget.DepFileRuleName);
  info.SetArray("CMAKE_LIST_FILES", this->Makefile->GetListFiles());
  info.SetArray("HEADER_EXTENSIONS",
                this->Makefile->GetCMakeInstance()->GetHeaderExtensions());
  auto cfgArray = [this](std::vector<size_t> const& configs) -> Json::Value {
    Json::Value value;
    if (!configs.empty()) {
      value = Json::arrayValue;
      for (size_t ci : configs) {
        value.append(this->ConfigsList[ci]);
      }
    }
    return value;
  };
  info.SetArrayArray("HEADERS", headers,
                     [this, &cfgArray](Json::Value& jval, MUFile const* muf) {
                       jval.resize(4u);
                       jval[0u] = muf->FullPath;
                       jval[1u] = cmStrCat(muf->MocIt ? 'M' : 'm',
                                           muf->UicIt ? 'U' : 'u');
                       jval[2u] = this->GetMocBuildPath(*muf);
                       jval[3u] = cfgArray(muf->Configs);
                     });
  info.SetArrayArray(
    "SOURCES", sources, [&cfgArray](Json::Value& jval, MUFile const* muf) {
      jval.resize(3u);
      jval[0u] = muf->FullPath;
      jval[1u] = cmStrCat(muf->MocIt ? 'M' : 'm', muf->UicIt ? 'U' : 'u');
      jval[2u] = cfgArray(muf->Configs);
    });

  // Write moc settings
  if (this->Moc.Enabled) {
    info.SetArray("MOC_SKIP", moc_skip);
    info.SetConfigArray("MOC_DEFINITIONS", this->Moc.Defines);
    info.SetConfigArray("MOC_INCLUDES", this->Moc.Includes);
    info.SetArray("MOC_OPTIONS", this->Moc.Options);
    info.SetBool("MOC_RELAXED_MODE", this->Moc.RelaxedMode);
    info.SetBool("MOC_PATH_PREFIX", this->Moc.PathPrefix);

    EvaluatedTargetPropertyEntries InterfaceAutoMocMacroNamesEntries;

    if (this->MultiConfig) {
      for (auto const& cfg : this->ConfigsList) {
        if (!cfg.empty()) {
          cmGeneratorExpressionDAGChecker dagChecker(
            this->GenTarget, "AUTOMOC_MACRO_NAMES", nullptr, nullptr,
            this->LocalGen, cfg);
          AddInterfaceEntries(this->GenTarget, cfg,
                              "INTERFACE_AUTOMOC_MACRO_NAMES", "CXX",
                              &dagChecker, InterfaceAutoMocMacroNamesEntries,
                              IncludeRuntimeInterface::Yes);
        }
      }
    } else {
      cmGeneratorExpressionDAGChecker dagChecker(
        this->GenTarget, "AUTOMOC_MACRO_NAMES", nullptr, nullptr,
        this->LocalGen, this->ConfigDefault);
      AddInterfaceEntries(this->GenTarget, this->ConfigDefault,
                          "INTERFACE_AUTOMOC_MACRO_NAMES", "CXX", &dagChecker,
                          InterfaceAutoMocMacroNamesEntries,
                          IncludeRuntimeInterface::Yes);
    }

    for (auto const& entry : InterfaceAutoMocMacroNamesEntries.Entries) {
      this->Moc.MacroNames.insert(this->Moc.MacroNames.end(),
                                  entry.Values.begin(), entry.Values.end());
    }
    this->Moc.MacroNames.erase(cmRemoveDuplicates(this->Moc.MacroNames),
                               this->Moc.MacroNames.end());

    info.SetArray("MOC_MACRO_NAMES", this->Moc.MacroNames);
    info.SetArrayArray(
      "MOC_DEPEND_FILTERS", this->Moc.DependFilters,
      [](Json::Value& jval, std::pair<std::string, std::string> const& pair) {
        jval.resize(2u);
        jval[0u] = pair.first;
        jval[1u] = pair.second;
      });
    info.SetConfig("MOC_COMPILATION_FILE", this->Moc.CompilationFile);
    info.SetConfig("MOC_PREDEFS_FILE", this->Moc.PredefsFile);

    cmStandardLevelResolver const resolver{ this->Makefile };
    auto const CompileOptionFlag =
      resolver.GetCompileOptionDef(this->GenTarget, "CXX", "");

    auto const CompileOptionValue =
      this->GenTarget->Makefile->GetSafeDefinition(CompileOptionFlag);

    if (!CompileOptionValue.empty()) {
      if (this->Moc.PredefsCmd.size() >= 3) {
        this->Moc.PredefsCmd.insert(this->Moc.PredefsCmd.begin() + 1,
                                    CompileOptionValue);
      }
    }
    info.SetArray("MOC_PREDEFS_CMD", this->Moc.PredefsCmd);
  }

  // Write uic settings
  if (this->Uic.Enabled) {
    // Add skipped .ui files
    uic_skip.insert(this->Uic.SkipUi.begin(), this->Uic.SkipUi.end());

    info.SetArray("UIC_SKIP", uic_skip);
    info.SetArrayArray("UIC_UI_FILES", this->Uic.UiFilesWithOptions,
                       [](Json::Value& jval, UicT::UiFileT const& uiFile) {
                         jval.resize(2u);
                         jval[0u] = uiFile.first;
                         InfoWriter::MakeStringArray(jval[1u], uiFile.second);
                       });
    info.SetConfigArray("UIC_OPTIONS", this->Uic.Options);
    info.SetArray("UIC_SEARCH_PATHS", this->Uic.SearchPaths);
  }

  info.Save(this->AutogenTarget.InfoFile);

  return true;
}

bool cmQtAutoGenInitializer::SetupWriteRccInfo()
{
  for (Qrc const& qrc : this->Rcc.Qrcs) {
    // Utility lambdas
    auto MfDef = [this](std::string const& key) {
      return this->Makefile->GetSafeDefinition(key);
    };

    InfoWriter info;

    // General
    info.SetBool("MULTI_CONFIG", this->MultiConfig);
    info.SetBool("CROSS_CONFIG", this->CrossConfig);
    info.SetBool("USE_BETTER_GRAPH", this->UseBetterGraph);
    info.SetUInt("VERBOSITY", this->Verbosity);
    info.Set("GENERATOR", this->GlobalGen->GetName());

    // Files
    info.Set("LOCK_FILE", qrc.LockFile);
    info.SetConfig("SETTINGS_FILE", qrc.SettingsFile);

    // Directories
    info.Set("CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));
    info.Set("CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));
    info.Set("CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR"));
    info.Set("CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR"));
    info.Set("BUILD_DIR", this->Dir.Build);
    info.SetConfig("INCLUDE_DIR", this->Dir.Include);

    // rcc executable
    info.SetConfig("RCC_EXECUTABLE", this->Rcc.Executable);
    info.SetConfigArray(
      "RCC_LIST_OPTIONS",
      generateListOptions(this->Rcc.ExecutableFeatures, this->MultiConfig));

    // qrc file
    info.Set("SOURCE", qrc.QrcFile);
    info.Set("OUTPUT_CHECKSUM", qrc.QrcPathChecksum);
    info.Set("OUTPUT_NAME", cmSystemTools::GetFilenameName(qrc.OutputFile));
    info.SetArray("OPTIONS", qrc.Options);
    info.SetConfigArray("INPUTS", qrc.Resources);

    info.Save(qrc.InfoFile);
  }

  return true;
}

cmSourceFile* cmQtAutoGenInitializer::RegisterGeneratedSource(
  std::string const& filename)
{
  cmSourceFile* gFile = this->Makefile->GetOrCreateSource(filename, true);
  gFile->MarkAsGenerated();
  gFile->SetProperty("SKIP_AUTOGEN", "1");
  gFile->SetProperty("SKIP_LINTING", "ON");
  gFile->SetProperty("CXX_SCAN_FOR_MODULES", "0");
  return gFile;
}

cmSourceFile* cmQtAutoGenInitializer::AddGeneratedSource(
  std::string const& filename, GenVarsT const& genVars, bool prepend)
{
  // Register source at makefile
  cmSourceFile* gFile = this->RegisterGeneratedSource(filename);
  // Add source file to target
  this->GenTarget->AddSource(filename, prepend);

  // Add source file to source group
  this->AddToSourceGroup(filename, genVars.GenNameUpper);

  return gFile;
}

void cmQtAutoGenInitializer::AddGeneratedSource(ConfigString const& filename,
                                                GenVarsT const& genVars,
                                                bool prepend)
{
  // XXX(xcode-per-cfg-src): Drop the Xcode-specific part of the condition
  // when the Xcode generator supports per-config sources.
  if (!this->MultiConfig || this->GlobalGen->IsXcode()) {
    cmSourceFile* sf =
      this->AddGeneratedSource(filename.Default, genVars, prepend);
    handleSkipPch(sf);
    return;
  }
  for (auto const& cfg : this->ConfigsList) {
    std::string const& filenameCfg = filename.Config.at(cfg);
    // Register source at makefile
    cmSourceFile* sf = this->RegisterGeneratedSource(filenameCfg);
    handleSkipPch(sf);
    // Add source file to target for this configuration.
    this->GenTarget->AddSource(
      cmStrCat("$<$<CONFIG:"_s, cfg, ">:"_s, filenameCfg, ">"_s), prepend);
    // Add source file to source group
    this->AddToSourceGroup(filenameCfg, genVars.GenNameUpper);
  }
}

void cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName,
                                              cm::string_view genNameUpper)
{
  cmSourceGroup* sourceGroup = nullptr;
  // Acquire source group
  {
    std::string property;
    std::string groupName;
    {
      // Prefer generator specific source group name
      std::initializer_list<std::string> const props{
        cmStrCat(genNameUpper, "_SOURCE_GROUP"), "AUTOGEN_SOURCE_GROUP"
      };
      for (std::string const& prop : props) {
        cmValue propName = this->Makefile->GetState()->GetGlobalProperty(prop);
        if (cmNonempty(propName)) {
          groupName = *propName;
          property = prop;
          break;
        }
      }
    }
    // Generate a source group on demand
    if (!groupName.empty()) {
      sourceGroup = this->Makefile->GetOrCreateSourceGroup(groupName);
      if (!sourceGroup) {
        cmSystemTools::Error(
          cmStrCat(genNameUpper, " error in ", property,
                   ": Could not find or create the source group ",
                   cmQtAutoGen::Quoted(groupName)));
      }
    }
  }
  if (sourceGroup) {
    sourceGroup->AddGroupFile(fileName);
  }
}

void cmQtAutoGenInitializer::AddCleanFile(std::string const& fileName)
{
  this->GenTarget->Target->AppendProperty("ADDITIONAL_CLEAN_FILES", fileName);
}

void cmQtAutoGenInitializer::ConfigFileNames(ConfigString& configString,
                                             cm::string_view prefix,
                                             cm::string_view suffix)
{
  configString.Default = cmStrCat(prefix, suffix);
  if (this->MultiConfig) {
    for (auto const& cfg : this->ConfigsList) {
      configString.Config[cfg] = cmStrCat(prefix, '_', cfg, suffix);
    }
  }
}

void cmQtAutoGenInitializer::ConfigFileNamesAndGenex(
  ConfigString& configString, std::string& genex, cm::string_view const prefix,
  cm::string_view const suffix)
{
  this->ConfigFileNames(configString, prefix, suffix);
  if (this->MultiConfig) {
    genex = cmStrCat(prefix, "_$<CONFIG>"_s, suffix);
  } else {
    genex = configString.Default;
  }
}

void cmQtAutoGenInitializer::ConfigFileClean(ConfigString& configString)
{
  this->AddCleanFile(configString.Default);
  if (this->MultiConfig) {
    for (auto const& pair : configString.Config) {
      this->AddCleanFile(pair.second);
    }
  }
}

static cmQtAutoGen::IntegerVersion parseMocVersion(std::string str)
{
  cmQtAutoGen::IntegerVersion result;

  static const std::string prelude = "moc ";
  size_t const pos = str.find(prelude);
  if (pos == std::string::npos) {
    return result;
  }

  str.erase(0, prelude.size() + pos);
  std::istringstream iss(str);
  std::string major;
  std::string minor;
  if (!std::getline(iss, major, '.') || !std::getline(iss, minor, '.')) {
    return result;
  }

  result.Major = static_cast<unsigned int>(std::stoi(major));
  result.Minor = static_cast<unsigned int>(std::stoi(minor));
  return result;
}

static cmQtAutoGen::IntegerVersion GetMocVersion(
  const std::string& mocExecutablePath)
{
  std::string capturedStdOut;
  int exitCode;
  if (!cmSystemTools::RunSingleCommand({ mocExecutablePath, "--version" },
                                       &capturedStdOut, nullptr, &exitCode,
                                       nullptr, cmSystemTools::OUTPUT_NONE)) {
    return {};
  }

  if (exitCode != 0) {
    return {};
  }

  return parseMocVersion(capturedStdOut);
}

static std::string FindMocExecutableFromMocTarget(cmMakefile const* makefile,
                                                  unsigned int qtMajorVersion)
{
  std::string result;
  const std::string mocTargetName =
    "Qt" + std::to_string(qtMajorVersion) + "::moc";
  cmTarget const* mocTarget = makefile->FindTargetToUse(mocTargetName);
  if (mocTarget) {
    result = mocTarget->GetSafeProperty("IMPORTED_LOCATION");
  }
  return result;
}

std::pair<cmQtAutoGen::IntegerVersion, unsigned int>
cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target,
                                     std::string mocExecutable)
{
  // Converts a char ptr to an unsigned int value
  auto toUInt = [](const char* const input) -> unsigned int {
    unsigned long tmp = 0;
    if (input && cmStrToULong(input, &tmp)) {
      return static_cast<unsigned int>(tmp);
    }
    return 0u;
  };
  auto toUInt2 = [](cmValue input) -> unsigned int {
    unsigned long tmp = 0;
    if (input && cmStrToULong(*input, &tmp)) {
      return static_cast<unsigned int>(tmp);
    }
    return 0u;
  };

  // Initialize return value to a default
  std::pair<IntegerVersion, unsigned int> res(
    IntegerVersion(),
    toUInt(target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION",
                                                           "")));

  // Acquire known Qt versions
  std::vector<cmQtAutoGen::IntegerVersion> knownQtVersions;
  {
    // Qt version variable prefixes
    static std::initializer_list<
      std::pair<cm::string_view, cm::string_view>> const keys{
      { "Qt6Core_VERSION_MAJOR", "Qt6Core_VERSION_MINOR" },
      { "Qt5Core_VERSION_MAJOR", "Qt5Core_VERSION_MINOR" },
      { "QT_VERSION_MAJOR", "QT_VERSION_MINOR" },
    };

    knownQtVersions.reserve(keys.size() * 2);

    // Adds a version to the result (nullptr safe)
    auto addVersion = [&knownQtVersions, &toUInt2](cmValue major,
                                                   cmValue minor) {
      cmQtAutoGen::IntegerVersion ver(toUInt2(major), toUInt2(minor));
      if (ver.Major != 0) {
        knownQtVersions.emplace_back(ver);
      }
    };

    // Read versions from variables
    for (auto const& keyPair : keys) {
      addVersion(target->Makefile->GetDefinition(std::string(keyPair.first)),
                 target->Makefile->GetDefinition(std::string(keyPair.second)));
    }

    // Read versions from directory properties
    for (auto const& keyPair : keys) {
      addVersion(target->Makefile->GetProperty(std::string(keyPair.first)),
                 target->Makefile->GetProperty(std::string(keyPair.second)));
    }
  }

  // Evaluate known Qt versions
  if (!knownQtVersions.empty()) {
    if (res.second == 0) {
      // No specific version was requested by the target:
      // Use highest known Qt version.
      res.first = knownQtVersions.at(0);
    } else {
      // Pick a version from the known versions:
      for (auto const& it : knownQtVersions) {
        if (it.Major == res.second) {
          res.first = it;
          break;
        }
      }
    }
  }

  if (res.first.Major == 0) {
    // We could not get the version number from variables or directory
    // properties. This might happen if the find_package call for Qt is wrapped
    // in a function. Try to find the moc executable path from the available
    // targets and call "moc --version" to get the Qt version.
    if (mocExecutable.empty()) {
      mocExecutable =
        FindMocExecutableFromMocTarget(target->Makefile, res.second);
    }
    if (!mocExecutable.empty()) {
      res.first = GetMocVersion(mocExecutable);
    }
  }

  return res;
}

std::string cmQtAutoGenInitializer::GetMocBuildPath(MUFile const& muf)
{
  std::string res;
  if (!muf.MocIt) {
    return res;
  }

  std::string basePath =
    cmStrCat(this->PathCheckSum.getPart(muf.FullPath), "/moc_",
             FileNameWithoutLastExtension(muf.FullPath));

  res = cmStrCat(basePath, ".cpp");
  if (this->Moc.EmittedBuildPaths.emplace(res).second) {
    return res;
  }

  // File name already emitted.
  // Try appending the header suffix to the base path.
  basePath = cmStrCat(basePath, '_', muf.SF->GetExtension());
  res = cmStrCat(basePath, ".cpp");
  if (this->Moc.EmittedBuildPaths.emplace(res).second) {
    return res;
  }

  // File name with header extension already emitted.
  // Try adding a number to the base path.
  constexpr std::size_t number_begin = 2;
  constexpr std::size_t number_end = 256;
  for (std::size_t ii = number_begin; ii != number_end; ++ii) {
    res = cmStrCat(basePath, '_', ii, ".cpp");
    if (this->Moc.EmittedBuildPaths.emplace(res).second) {
      return res;
    }
  }

  // Output file name conflict (unlikely, but still...)
  cmSystemTools::Error(
    cmStrCat("moc output file name conflict for ", muf.FullPath));

  return res;
}

bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars,
                                             const std::string& executable,
                                             bool ignoreMissingTarget) const
{
  auto print_err = [this, &genVars](std::string const& err) {
    cmSystemTools::Error(cmStrCat(genVars.GenNameUpper, " for target ",
                                  this->GenTarget->GetName(), ": ", err));
  };

  // Custom executable
  {
    std::string const prop = cmStrCat(genVars.GenNameUpper, "_EXECUTABLE");
    std::string const& val = this->GenTarget->Target->GetSafeProperty(prop);
    if (!val.empty()) {
      // Evaluate generator expression
      {
        cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
        cmGeneratorExpression ge(*this->Makefile->GetCMakeInstance(), lfbt);
        std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(val);
        if (this->MultiConfig && this->UseBetterGraph) {
          for (auto const& config : this->ConfigsList) {
            genVars.Executable.Config[config] =
              cge->Evaluate(this->LocalGen, config);
          }
        } else {
          genVars.Executable.Default = cge->Evaluate(this->LocalGen, "");
        }
      }

      if (genVars.Executable.Default.empty() &&
          genVars.Executable.Config.empty() && !ignoreMissingTarget) {
        print_err(prop + " evaluates to an empty value");
        return false;
      }

      // Create empty compiler features.
      if (this->MultiConfig && this->UseBetterGraph) {
        for (auto const& config : this->ConfigsList) {
          genVars.ExecutableFeatures.Config[config] =
            std::make_shared<cmQtAutoGen::CompilerFeatures>();
        }
      } else {
        genVars.ExecutableFeatures.Default =
          std::make_shared<cmQtAutoGen::CompilerFeatures>();
      }
      return true;
    }
  }

  // Find executable target
  {
    // Find executable target name
    cm::string_view prefix;
    if (this->QtVersion.Major == 4) {
      prefix = "Qt4::";
    } else if (this->QtVersion.Major == 5) {
      prefix = "Qt5::";
    } else if (this->QtVersion.Major == 6) {
      prefix = "Qt6::";
    }
    std::string const targetName = cmStrCat(prefix, executable);

    // Find target
    cmGeneratorTarget* genTarget =
      this->LocalGen->FindGeneratorTargetToUse(targetName);
    if (genTarget) {
      genVars.ExecutableTargetName = targetName;
      genVars.ExecutableTarget = genTarget;
      if (genTarget->IsImported()) {
        if (this->MultiConfig && this->UseBetterGraph) {
          for (auto const& config : this->ConfigsList) {
            genVars.Executable.Config[config] =
              genTarget->ImportedGetLocation(config);
          }
        } else {
          genVars.Executable.Default =
            genTarget->ImportedGetLocation(this->ConfigDefault);
        }

      } else {
        if (this->MultiConfig && this->UseBetterGraph) {
          for (auto const& config : this->ConfigsList) {
            genVars.Executable.Config[config] = genTarget->GetLocation(config);
          }
        } else {
          genVars.Executable.Default =
            genTarget->GetLocation(this->ConfigDefault);
        }
      }
    } else {
      if (ignoreMissingTarget) {
        // Create empty compiler features.
        if (this->MultiConfig && this->UseBetterGraph) {
          for (auto const& config : this->ConfigsList) {
            genVars.ExecutableFeatures.Config[config] =
              std::make_shared<cmQtAutoGen::CompilerFeatures>();
          }
        } else {
          genVars.ExecutableFeatures.Default =
            std::make_shared<cmQtAutoGen::CompilerFeatures>();
        }

        return true;
      }
      print_err(cmStrCat("Could not find ", executable, " executable target ",
                         targetName));
      return false;
    }
  }

  // Get executable features
  {
    std::string err;
    genVars.ExecutableFeatures = this->GlobalInitializer->GetCompilerFeatures(
      executable, genVars.Executable, err, this->MultiConfig,
      this->UseBetterGraph);
    if (this->MultiConfig && this->UseBetterGraph) {
      for (auto const& config : this->ConfigsList) {
        if (!genVars.ExecutableFeatures.Config[config]) {
          if (!genVars.ExecutableFeatures.Config[config]) {
            print_err(err);
            return false;
          }
        }
      }
    } else {
      if (!genVars.ExecutableFeatures.Default) {
        print_err(err);
        return false;
      }
    }
  }

  return true;
}

void cmQtAutoGenInitializer::handleSkipPch(cmSourceFile* sf)
{
  bool skipPch = true;
  for (auto const& pair : this->AutogenTarget.Sources) {
    if (!pair.first->GetIsGenerated() &&
        !pair.first->GetProperty("SKIP_PRECOMPILE_HEADERS")) {
      skipPch = false;
    }
  }

  if (skipPch) {
    sf->SetProperty("SKIP_PRECOMPILE_HEADERS", "ON");
  }
}
