/* 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::LinkInterfaceFor::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::LinkInterfaceFor::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);

    cmGeneratorExpressionDAGChecker dagChecker(
      this->GenTarget, "AUTOMOC_MACRO_NAMES", nullptr, nullptr);
    EvaluatedTargetPropertyEntries InterfaceAutoMocMacroNamesEntries;

    if (this->MultiConfig) {
      for (auto const& cfg : this->ConfigsList) {
        if (!cfg.empty()) {
          AddInterfaceEntries(this->GenTarget, cfg,
                              "INTERFACE_AUTOMOC_MACRO_NAMES", "CXX",
                              &dagChecker, InterfaceAutoMocMacroNamesEntries,
                              IncludeRuntimeInterface::Yes);
        }
      }
    } else {
      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");
  }
}
