/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file LICENSE.rst 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) {
    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::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::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
    // TODO: Split this? `AutogenInfo.json` is expected to always be under the
    // `CMakeFiles` directory, but not all generators places its `<tgt>.dir`
    // directories there.
    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
    {
      auto const& 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::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
  {
    // If the property AUTOMOC_INCLUDE_DIRECTORIES is set on the target,
    // use its value for moc include paths instead of gathering all
    // include directories from the target.
    cmValue autoIncDirs =
      this->GenTarget->GetProperty("AUTOMOC_INCLUDE_DIRECTORIES");
    if (autoIncDirs) {
      cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
      cmGeneratorExpression ge(*this->Makefile->GetCMakeInstance(), lfbt);
      auto cge = ge.Parse(*autoIncDirs);

      // Build a single list of configs to iterate, whether single or multi
      std::vector<std::string> configs = this->MultiConfig
        ? this->ConfigsList
        : std::vector<std::string>{ this->ConfigDefault };

      for (auto const& cfg : configs) {
        std::string eval = cge->Evaluate(this->LocalGen, cfg);
        std::vector<std::string> incList = cmList(eval);

        // Validate absolute paths
        for (auto const& path : incList) {
          if (!cmGeneratorExpression::StartsWithGeneratorExpression(path) &&
              !cmSystemTools::FileIsFullPath(path)) {
            this->Makefile->IssueMessage(
              MessageType::FATAL_ERROR,
              cmStrCat("AUTOMOC_INCLUDE_DIRECTORIES: path '", path,
                       "' is not absolute."));
            return false;
          }
        }
        if (this->MultiConfig) {
          this->Moc.Includes.Config[cfg] = std::move(incList);
        } else {
          this->Moc.Includes.Default = std::move(incList);
        }
      }
    } else {
      // Otherwise, discover include directories from the target for moc.
      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
  {
    if (this->QtVersion.Major >= 6) {
      std::string const qtFeatureZSTD = "QT_FEATURE_zstd";
      if (this->GenTarget->Target->GetMakefile()->IsDefinitionSet(
            qtFeatureZSTD)) {
        auto const zstdDef =
          this->GenTarget->Target->GetMakefile()->GetSafeDefinition(
            qtFeatureZSTD);
        auto const 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;
    bool const 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 (auto const& 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()) {
    bool const 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 (auto const& 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 (auto const& 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> targetsPartOfAllConfigs;
      for (std::string const& config : this->ConfigsList) {
        // The same target might appear multiple times in a config, but we
        // should only count it once.
        std::set<cmGeneratorTarget const*> seenTargets;
        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) &&
                seenTargets.insert(libTarget).second) {
              // Increment target config count
              targetsPartOfAllConfigs[libTarget]++;
            }
          }
        }
      }
      for (auto const& item : targetsPartOfAllConfigs) {
        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.
      auto const 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)
{
  std::vector<std::string> autogenConfigs;
  this->GlobalGen->GetQtAutoGenConfigs(autogenConfigs);
  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) {
    auto const& configs =
      processName == "cmake_autorcc" ? this->ConfigsList : autogenConfigs;
    for (std::string const& config : configs) {
      commandLines.push_back(
        cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), "-E",
                            processName, infoFile, config }));
    }
  } else {
    std::string autoInfoFileConfig;
    if (this->MultiConfig) {
      autoInfoFileConfig = "$<CONFIG>";
    } else {
      autoInfoFileConfig = autogenConfigs[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{ qrc.OutputFile };

    // Add the .qrc and info file to the custom command dependencies
    std::vector<std::string> ccDepends{ qrc.QrcFile, 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 std::string const 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(
  std::string const& 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;
  std::string const mocTargetName = cmStrCat("Qt", 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 = [](char const* 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,
                                             std::string const& 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");
  }
}
