/* 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 "cmQtAutoGen.h"
#include "cmQtAutoGenGlobalInitializer.h"

#include "cmAlgorithms.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
#include "cmFilePathChecksum.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLinkItem.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocationKind.h"
#include "cmSourceGroup.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmake.h"
#include "cmsys/SystemInformation.hxx"

#include <algorithm>
#include <array>
#include <deque>
#include <map>
#include <set>
#include <string>
#include <utility>
#include <vector>

static std::size_t GetParallelCPUCount()
{
  static std::size_t count = 0;
  // Detect only on the first call
  if (count == 0) {
    cmsys::SystemInformation info;
    info.RunCPUCheck();
    count = info.GetNumberOfPhysicalCPU();
    count = std::max<std::size_t>(count, 1);
    count = std::min<std::size_t>(count, cmQtAutoGen::ParallelMax);
  }
  return count;
}

static void AddCleanFile(cmMakefile* makefile, std::string const& fileName)
{
  makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", fileName.c_str(),
                           false);
}

static std::string FileProjectRelativePath(cmMakefile* 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;
}

/* @brief Tests if targetDepend is a STATIC_LIBRARY and if any of its
 * recursive STATIC_LIBRARY dependencies depends on targetOrigin
 * (STATIC_LIBRARY cycle).
 */
static 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);
      if (libs != nullptr) {
        for (cmLinkItem const& item : libs->Libraries) {
          cmGeneratorTarget const* depTarget = item.Target;
          if ((depTarget != nullptr) &&
              (depTarget->GetType() == cmStateEnums::STATIC_LIBRARY) &&
              knownLibs.insert(depTarget).second) {
            testLibs.push_back(depTarget);
          }
        }
      }
    }
  }
  return cycle;
}

cmQtAutoGenInitializer::InfoWriter::InfoWriter(std::string const& filename)
{
  Ofs_.SetCopyIfDifferent(true);
  Ofs_.Open(filename, false, true);
}

template <class IT>
std::string cmQtAutoGenInitializer::InfoWriter::ListJoin(IT it_begin,
                                                         IT it_end)
{
  std::string res;
  for (IT it = it_begin; it != it_end; ++it) {
    if (it != it_begin) {
      res += ';';
    }
    for (const char* c = it->c_str(); *c; ++c) {
      if (*c == '"') {
        // Escape the double quote to avoid ending the argument.
        res += "\\\"";
      } else if (*c == '$') {
        // Escape the dollar to avoid expanding variables.
        res += "\\$";
      } else if (*c == '\\') {
        // Escape the backslash to avoid other escapes.
        res += "\\\\";
      } else if (*c == ';') {
        // Escape the semicolon to avoid list expansion.
        res += "\\;";
      } else {
        // Other characters will be parsed correctly.
        res += *c;
      }
    }
  }
  return res;
}

std::string cmQtAutoGenInitializer::InfoWriter::ConfigKey(
  const char* key, std::string const& config)
{
  std::string ckey = key;
  ckey += '_';
  ckey += config;
  return ckey;
}

void cmQtAutoGenInitializer::InfoWriter::Write(const char* key,
                                               std::string const& value)
{
  Ofs_ << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value)
       << ")\n";
};

void cmQtAutoGenInitializer::InfoWriter::WriteUInt(const char* key,
                                                   unsigned int value)
{
  Ofs_ << "set(" << key << " " << value << ")\n";
};

template <class C>
void cmQtAutoGenInitializer::InfoWriter::WriteStrings(const char* key,
                                                      C const& container)
{
  Ofs_ << "set(" << key << " \""
       << ListJoin(container.begin(), container.end()) << "\")\n";
}

void cmQtAutoGenInitializer::InfoWriter::WriteConfig(
  const char* key, std::map<std::string, std::string> const& map)
{
  for (auto const& item : map) {
    Write(ConfigKey(key, item.first).c_str(), item.second);
  }
};

template <class C>
void cmQtAutoGenInitializer::InfoWriter::WriteConfigStrings(
  const char* key, std::map<std::string, C> const& map)
{
  for (auto const& item : map) {
    WriteStrings(ConfigKey(key, item.first).c_str(), item.second);
  }
}

void cmQtAutoGenInitializer::InfoWriter::WriteNestedLists(
  const char* key, std::vector<std::vector<std::string>> const& lists)
{
  std::vector<std::string> seplist;
  for (const std::vector<std::string>& list : lists) {
    std::string blist = "{";
    blist += ListJoin(list.begin(), list.end());
    blist += "}";
    seplist.push_back(std::move(blist));
  }
  Write(key, cmJoin(seplist, cmQtAutoGen::ListSep));
};

cmQtAutoGenInitializer::cmQtAutoGenInitializer(
  cmQtAutoGenGlobalInitializer* globalInitializer, cmGeneratorTarget* target,
  IntegerVersion const& qtVersion, bool mocEnabled, bool uicEnabled,
  bool rccEnabled, bool globalAutogenTarget, bool globalAutoRccTarget)
  : GlobalInitializer(globalInitializer)
  , Target(target)
  , QtVersion(qtVersion)
{
  AutogenTarget.GlobalTarget = globalAutogenTarget;
  Moc.Enabled = mocEnabled;
  Uic.Enabled = uicEnabled;
  Rcc.Enabled = rccEnabled;
  Rcc.GlobalTarget = globalAutoRccTarget;
}

bool cmQtAutoGenInitializer::InitCustomTargets()
{
  cmMakefile* makefile = this->Target->Target->GetMakefile();
  cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
  cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator();

  // Configurations
  this->MultiConfig = globalGen->IsMultiConfig();
  this->ConfigDefault = makefile->GetConfigurations(this->ConfigsList);
  if (this->ConfigsList.empty()) {
    this->ConfigsList.push_back(this->ConfigDefault);
  }

  // Verbosity
  this->Verbosity = makefile->GetSafeDefinition("CMAKE_AUTOGEN_VERBOSE");
  if (!this->Verbosity.empty()) {
    unsigned long iVerb = 0;
    if (!cmSystemTools::StringToULong(this->Verbosity.c_str(), &iVerb)) {
      // Non numeric verbosity
      this->Verbosity = cmSystemTools::IsOn(this->Verbosity) ? "1" : "0";
    }
  }

  // Targets FOLDER
  {
    const char* folder =
      makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER");
    if (folder == nullptr) {
      folder =
        makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER");
    }
    // Inherit FOLDER property from target (#13688)
    if (folder == nullptr) {
      folder = this->Target->GetProperty("FOLDER");
    }
    if (folder != nullptr) {
      this->TargetsFolder = folder;
    }
  }

  // Check status of policy CMP0071
  {
    cmPolicies::PolicyStatus const CMP0071_status =
      makefile->GetPolicyStatus(cmPolicies::CMP0071);
    switch (CMP0071_status) {
      case cmPolicies::WARN:
        this->CMP0071Warn = true;
        CM_FALLTHROUGH;
      case cmPolicies::OLD:
        // Ignore GENERATED file
        break;
      case cmPolicies::REQUIRED_IF_USED:
      case cmPolicies::REQUIRED_ALWAYS:
      case cmPolicies::NEW:
        // Process GENERATED file
        this->CMP0071Accept = true;
        break;
    }
  }

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

    // Info directory
    this->Dir.Info = cbd;
    this->Dir.Info += "/CMakeFiles";
    this->Dir.Info += '/';
    this->Dir.Info += this->Target->GetName();
    this->Dir.Info += "_autogen";
    this->Dir.Info += ".dir";
    cmSystemTools::ConvertToUnixSlashes(this->Dir.Info);

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

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

    // Include directory
    this->Dir.Include = this->Dir.Build;
    this->Dir.Include += "/include";
    if (this->MultiConfig) {
      this->Dir.Include += "_$<CONFIG>";
    }
    // Per config include directories
    if (this->MultiConfig) {
      for (std::string const& cfg : this->ConfigsList) {
        std::string& dir = this->Dir.ConfigInclude[cfg];
        dir = this->Dir.Build;
        dir += "/include_";
        dir += cfg;
      }
    }
  }

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

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

    // Autogen target name
    this->AutogenTarget.Name = this->Target->GetName();
    this->AutogenTarget.Name += "_autogen";

    // Autogen target parallel processing
    this->AutogenTarget.Parallel =
      this->Target->GetSafeProperty("AUTOGEN_PARALLEL");
    if (this->AutogenTarget.Parallel.empty() ||
        (this->AutogenTarget.Parallel == "AUTO")) {
      // Autodetect number of CPUs
      this->AutogenTarget.Parallel = std::to_string(GetParallelCPUCount());
    }

    // Autogen target info and settings files
    {
      this->AutogenTarget.InfoFile = this->Dir.Info;
      this->AutogenTarget.InfoFile += "/AutogenInfo.cmake";

      this->AutogenTarget.SettingsFile = this->Dir.Info;
      this->AutogenTarget.SettingsFile += "/AutogenOldSettings.txt";

      if (this->MultiConfig) {
        for (std::string const& cfg : this->ConfigsList) {
          std::string& filename = this->AutogenTarget.ConfigSettingsFile[cfg];
          filename =
            AppendFilenameSuffix(this->AutogenTarget.SettingsFile, "_" + cfg);
          AddCleanFile(makefile, filename);
        }
      } else {
        AddCleanFile(makefile, this->AutogenTarget.SettingsFile);
      }
    }

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

      std::string const deps =
        this->Target->GetSafeProperty("AUTOGEN_TARGET_DEPENDS");
      if (!deps.empty()) {
        std::vector<std::string> extraDeps;
        cmSystemTools::ExpandListArgument(deps, extraDeps);
        for (std::string const& depName : extraDeps) {
          // Allow target and file dependencies
          auto* depTarget = makefile->FindTargetToUse(depName);
          if (depTarget != nullptr) {
            this->AutogenTarget.DependTargets.insert(depTarget);
          } else {
            this->AutogenTarget.DependFiles.insert(depName);
          }
        }
      }
    }
  }

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

  // Add autogen include directory to the origin target INCLUDE_DIRECTORIES
  if (this->MocOrUicEnabled() || (this->Rcc.Enabled && this->MultiConfig)) {
    this->Target->AddIncludeDirectory(this->Dir.Include, true);
  }

  // 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()
{
  cmMakefile* makefile = this->Target->Target->GetMakefile();
  cmLocalGenerator* localGen = this->Target->GetLocalGenerator();

  // Mocs compilation file
  this->Moc.MocsCompilation = this->Dir.Build;
  this->Moc.MocsCompilation += "/mocs_compilation.cpp";

  // Moc predefs command
  if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") &&
      (this->QtVersion >= IntegerVersion(5, 8))) {
    this->Moc.PredefsCmd =
      makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND");
  }

  // Moc includes
  {
    bool const appendImplicit = (this->QtVersion.Major >= 5);
    auto GetIncludeDirs =
      [this, localGen,
       appendImplicit](std::string const& cfg) -> std::vector<std::string> {
      // Get the include dirs for this target, without stripping the implicit
      // include dirs off, see
      // https://gitlab.kitware.com/cmake/cmake/issues/13667
      std::vector<std::string> dirs;
      localGen->GetIncludeDirectoriesImplicit(dirs, this->Target, "CXX", cfg,
                                              false, appendImplicit);
      return dirs;
    };

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

  // Moc compile definitions
  {
    auto GetCompileDefinitions =
      [this, localGen](std::string const& cfg) -> std::set<std::string> {
      std::set<std::string> defines;
      localGen->GetTargetDefines(this->Target, cfg, "CXX", defines);
#ifdef _WIN32
      if (this->Moc.PredefsCmd.empty()) {
        // Add WIN32 definition if we don't have a moc_predefs.h
        defines.insert("WIN32");
      }
#endif
      return defines;
    };

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

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

  return true;
}

bool cmQtAutoGenInitializer::InitUic()
{
  cmMakefile* makefile = this->Target->Target->GetMakefile();

  // Uic search paths
  {
    std::string const usp =
      this->Target->GetSafeProperty("AUTOUIC_SEARCH_PATHS");
    if (!usp.empty()) {
      cmSystemTools::ExpandListArgument(usp, this->Uic.SearchPaths);
      std::string const& srcDir = makefile->GetCurrentSourceDirectory();
      for (std::string& path : this->Uic.SearchPaths) {
        path = cmSystemTools::CollapseFullPath(path, srcDir);
      }
    }
  }
  // Uic target options
  {
    auto UicGetOpts =
      [this](std::string const& cfg) -> std::vector<std::string> {
      std::vector<std::string> opts;
      this->Target->GetAutoUicOptions(opts, cfg);
      return opts;
    };

    // Default settings
    this->Uic.Options = UicGetOpts(this->ConfigDefault);

    // Configuration specific settings
    if (this->MultiConfig) {
      for (std::string const& cfg : this->ConfigsList) {
        std::vector<std::string> options = UicGetOpts(cfg);
        if (options != this->Uic.Options) {
          this->Uic.ConfigOptions[cfg] = std::move(options);
        }
      }
    }
  }

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

  return true;
}

bool cmQtAutoGenInitializer::InitRcc()
{
  // Rcc executable
  {
    std::string stdOut;
    if (!this->GetQtExecutable(this->Rcc, "rcc", false, &stdOut)) {
      return false;
    }
    // Evaluate test output
    if (this->QtVersion.Major == 5 || this->QtVersion.Major == 6) {
      if (stdOut.find("--list") != std::string::npos) {
        this->Rcc.ListOptions.emplace_back("--list");
      } else if (stdOut.find("-list") != std::string::npos) {
        this->Rcc.ListOptions.emplace_back("-list");
      }
    }
  }

  return true;
}

bool cmQtAutoGenInitializer::InitScanFiles()
{
  cmMakefile* makefile = this->Target->Target->GetMakefile();
  auto const& kw = this->GlobalInitializer->kw();

  auto makeMUFile = [this, &kw](cmSourceFile* sf, std::string const& fullPath,
                                bool muIt) -> MUFileHandle {
    MUFileHandle muf = cm::make_unique<MUFile>();
    muf->RealPath = cmSystemTools::GetRealPath(fullPath);
    muf->SF = sf;
    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 addMUFile = [&](MUFileHandle&& muf, bool isHeader) {
    if ((muf->MocIt || muf->UicIt) && muf->Generated) {
      this->AutogenTarget.FilesGenerated.emplace_back(muf.get());
    }
    if (isHeader) {
      this->AutogenTarget.Headers.emplace(muf->SF, std::move(muf));
    } else {
      this->AutogenTarget.Sources.emplace(muf->SF, std::move(muf));
    }
  };

  // Scan through target files
  {
    // Scan through target files
    std::vector<cmSourceFile*> srcFiles;
    this->Target->GetConfigCommonSourceFiles(srcFiles);
    for (cmSourceFile* sf : srcFiles) {
      // sf->GetExtension() is only valid after sf->GetFullPath() ...
      // 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->GetFullPath(&pathError);
      if (!pathError.empty() || fullPath.empty()) {
        continue;
      }
      std::string const& ext = sf->GetExtension();

      // Register files that will be scanned by moc or uic
      if (this->MocOrUicEnabled()) {
        switch (cmSystemTools::GetFileFormat(ext)) {
          case cmSystemTools::HEADER_FILE_FORMAT:
            addMUFile(makeMUFile(sf, fullPath, true), true);
            break;
          case cmSystemTools::CXX_FILE_FORMAT:
            addMUFile(makeMUFile(sf, fullPath, true), false);
            break;
          default:
            break;
        }
      }

      // Register rcc enabled files
      if (this->Rcc.Enabled) {
        if ((ext == kw.qrc) && !sf->GetPropertyAsBool(kw.SKIP_AUTOGEN) &&
            !sf->GetPropertyAsBool(kw.SKIP_AUTORCC)) {
          // Register qrc file
          Qrc qrc;
          qrc.QrcFile = cmSystemTools::GetRealPath(fullPath);
          qrc.QrcName =
            cmSystemTools::GetFilenameWithoutLastExtension(qrc.QrcFile);
          qrc.Generated = sf->GetIsGenerated();
          // RCC options
          {
            std::string const opts = sf->GetSafeProperty(kw.AUTORCC_OPTIONS);
            if (!opts.empty()) {
              cmSystemTools::ExpandListArgument(opts, qrc.Options);
            }
          }
          this->Rcc.Qrcs.push_back(std::move(qrc));
        }
      }
    }
  }
  // cmGeneratorTarget::GetConfigCommonSourceFiles 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->Target->ClearSourcesCache();

  // For source files find additional headers and private headers
  if (this->MocOrUicEnabled()) {
    std::vector<MUFileHandle> extraHeaders;
    extraHeaders.reserve(this->AutogenTarget.Sources.size() * 2);
    // Header search suffixes and extensions
    std::array<std::string, 2> const suffixes{ { "", "_p" } };
    auto const& exts = makefile->GetCMakeInstance()->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& realPath = muf.RealPath;
        std::string basePath = cmQtAutoGen::SubDirPrefix(realPath);
        basePath += cmSystemTools::GetFilenameWithoutLastExtension(realPath);
        for (auto const& suffix : suffixes) {
          std::string const suffixedPath = basePath + suffix;
          for (auto const& ext : exts) {
            std::string fullPath = suffixedPath;
            fullPath += '.';
            fullPath += ext;

            auto constexpr locationKind = cmSourceFileLocationKind::Known;
            cmSourceFile* sf = makefile->GetSource(fullPath, locationKind);
            if (sf != nullptr) {
              // Check if we know about this header already
              if (this->AutogenTarget.Headers.find(sf) !=
                  this->AutogenTarget.Headers.end()) {
                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 = makefile->CreateSource(fullPath, false, locationKind);
            }

            if (sf != nullptr) {
              auto eMuf = makeMUFile(sf, fullPath, true);
              // Ony process moc/uic when the parent is processed as well
              if (!muf.MocIt) {
                eMuf->MocIt = false;
              }
              if (!muf.UicIt) {
                eMuf->UicIt = false;
              }
              extraHeaders.emplace_back(std::move(eMuf));
            }
          }
        }
      }
    }
    // Move generated files to main headers list
    for (auto& eMuf : extraHeaders) {
      addMUFile(std::move(eMuf), true);
    }
  }

  // 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 (cmSourceFile* sf : makefile->GetSourceFiles()) {
      // sf->GetExtension() is only valid after sf->GetFullPath() ...
      // 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->GetFullPath(&pathError);
      if (!pathError.empty() || fullPath.empty()) {
        continue;
      }
      std::string const& ext = sf->GetExtension();

      auto const fileFormat = cmSystemTools::GetFileFormat(ext);
      if (fileFormat == cmSystemTools::HEADER_FILE_FORMAT) {
        if (this->AutogenTarget.Headers.find(sf) ==
            this->AutogenTarget.Headers.end()) {
          auto muf = makeMUFile(sf, fullPath, false);
          if (muf->SkipMoc || muf->SkipUic) {
            this->AutogenTarget.Headers.emplace(sf, std::move(muf));
          }
        }
      } else if (fileFormat == cmSystemTools::CXX_FILE_FORMAT) {
        if (this->AutogenTarget.Sources.find(sf) ==
            this->AutogenTarget.Sources.end()) {
          auto muf = makeMUFile(sf, fullPath, false);
          if (muf->SkipMoc || muf->SkipUic) {
            this->AutogenTarget.Sources.emplace(sf, std::move(muf));
          }
        }
      } else if (this->Uic.Enabled && (ext == kw.ui)) {
        // .ui file
        std::string realPath = cmSystemTools::GetRealPath(fullPath);
        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.FileFiles.push_back(std::move(realPath));
            std::vector<std::string> optsVec;
            cmSystemTools::ExpandListArgument(uicOpts, optsVec);
            this->Uic.FileOptions.push_back(std::move(optsVec));
          }
        } else {
          // Register skipped .ui file
          this->Uic.SkipUi.insert(std::move(realPath));
        }
      }
    }
  }

  // Process GENERATED sources and headers
  if (this->MocOrUicEnabled() && !this->AutogenTarget.FilesGenerated.empty()) {
    if (this->CMP0071Accept) {
      // Let the autogen target depend on the GENERATED files
      for (MUFile* muf : this->AutogenTarget.FilesGenerated) {
        this->AutogenTarget.DependFiles.insert(muf->RealPath);
      }
    } else if (this->CMP0071Warn) {
      std::string msg;
      msg += cmPolicies::GetPolicyWarning(cmPolicies::CMP0071);
      msg += '\n';
      std::string property;
      if (this->Moc.Enabled && this->Uic.Enabled) {
        property = kw.SKIP_AUTOGEN;
      } else if (this->Moc.Enabled) {
        property = kw.SKIP_AUTOMOC;
      } else if (this->Uic.Enabled) {
        property = kw.SKIP_AUTOUIC;
      }
      msg += "For compatibility, CMake is excluding the GENERATED source "
             "file(s):\n";
      for (MUFile* muf : this->AutogenTarget.FilesGenerated) {
        msg += "  ";
        msg += Quoted(muf->RealPath);
        msg += '\n';
      }
      msg += "from processing by ";
      msg += cmQtAutoGen::Tools(this->Moc.Enabled, this->Uic.Enabled, false);
      msg += ". 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 ";
      msg += property;
      msg += ":\n  set_property(SOURCE file.h PROPERTY ";
      msg += property;
      msg += " ON)\n";
      makefile->IssueMessage(MessageType::AUTHOR_WARNING, msg);
    }
  }

  // Process qrc files
  if (!this->Rcc.Qrcs.empty()) {
    const bool modernQt = (this->QtVersion.Major >= 5);
    // Target rcc options
    std::vector<std::string> optionsTarget;
    cmSystemTools::ExpandListArgument(
      this->Target->GetSafeProperty(kw.AUTORCC_OPTIONS), optionsTarget);

    // 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
    {
      cmFilePathChecksum const fpathCheckSum(makefile);
      for (Qrc& qrc : this->Rcc.Qrcs) {
        qrc.PathChecksum = fpathCheckSum.getPart(qrc.QrcFile);
        // RCC output file name
        {
          std::string rccFile = this->Dir.Build + "/";
          rccFile += qrc.PathChecksum;
          rccFile += "/qrc_";
          rccFile += qrc.QrcName;
          rccFile += ".cpp";
          qrc.RccFile = std::move(rccFile);
        }
        {
          std::string base = this->Dir.Info;
          base += "/RCC";
          base += qrc.QrcName;
          if (!qrc.Unique) {
            base += qrc.PathChecksum;
          }

          qrc.LockFile = base;
          qrc.LockFile += ".lock";

          qrc.InfoFile = base;
          qrc.InfoFile += "Info.cmake";

          qrc.SettingsFile = base;
          qrc.SettingsFile += "Settings.txt";

          if (this->MultiConfig) {
            for (std::string const& cfg : this->ConfigsList) {
              qrc.ConfigSettingsFile[cfg] =
                AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg);
            }
          }
        }
      }
    }
    // 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 += "_";
          name += qrc.PathChecksum;
        }
        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;
        RccLister const lister(this->Rcc.Executable, this->Rcc.ListOptions);
        if (!lister.list(qrc.QrcFile, qrc.Resources, error)) {
          cmSystemTools::Error(error);
          return false;
        }
      }
    }
  }

  return true;
}

bool cmQtAutoGenInitializer::InitAutogenTarget()
{
  cmMakefile* makefile = this->Target->Target->GetMakefile();
  cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
  cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator();

  // Register info file as generated by CMake
  makefile->AddCMakeOutputFile(this->AutogenTarget.InfoFile);

  // Files provided by the autogen target
  std::vector<std::string> autogenProvides;
  if (this->Moc.Enabled) {
    this->AddGeneratedSource(this->Moc.MocsCompilation, this->Moc, true);
    autogenProvides.push_back(this->Moc.MocsCompilation);
  }

  // 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 = "Automatic ";
    autogenComment += tools;
    autogenComment += " for target ";
    autogenComment += this->Target->GetName();
  }

  // Compose command lines
  cmCustomCommandLines commandLines;
  {
    cmCustomCommandLine currentLine;
    currentLine.push_back(cmSystemTools::GetCMakeCommand());
    currentLine.push_back("-E");
    currentLine.push_back("cmake_autogen");
    currentLine.push_back(this->AutogenTarget.InfoFile);
    currentLine.push_back("$<CONFIGURATION>");
    commandLines.push_back(std::move(currentLine));
  }

  // Use PRE_BUILD on demand
  bool usePRE_BUILD = false;
  if (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 (AutogenTarget.GlobalTarget) {
      usePRE_BUILD = false;
    }
  }
  // Create the autogen target/command
  if (usePRE_BUILD) {
    // Add additional autogen target dependencies to origin target
    for (cmTarget* depTarget : this->AutogenTarget.DependTargets) {
      this->Target->Target->AddUtility(depTarget->GetName(), makefile);
    }

    // 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!
    const std::vector<std::string> no_output;
    const std::vector<std::string> no_deps;
    cmCustomCommand cc(makefile, no_output, autogenProvides, no_deps,
                       commandLines, autogenComment.c_str(),
                       this->Dir.Work.c_str());
    cc.SetEscapeOldStyle(false);
    cc.SetEscapeAllowMakeVars(true);
    this->Target->Target->AddPreBuildCommand(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->Target->GetLinkImplementationLibraries(config);
        if (libs != nullptr) {
          for (cmLinkItem const& item : libs->Libraries) {
            cmGeneratorTarget const* libTarget = item.Target;
            if ((libTarget != nullptr) &&
                !StaticLibraryCycle(this->Target, 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);
        }
      }
    }

    // Create autogen target
    cmTarget* autogenTarget = makefile->AddUtilityCommand(
      this->AutogenTarget.Name, cmMakefile::TargetOrigin::Generator, true,
      this->Dir.Work.c_str(), /*byproducts=*/autogenProvides,
      std::vector<std::string>(this->AutogenTarget.DependFiles.begin(),
                               this->AutogenTarget.DependFiles.end()),
      commandLines, false, autogenComment.c_str());
    // Create autogen generator target
    localGen->AddGeneratorTarget(
      new cmGeneratorTarget(autogenTarget, localGen));

    // Forward origin utilities to autogen target
    if (this->AutogenTarget.DependOrigin) {
      for (BT<std::string> const& depName : this->Target->GetUtilities()) {
        autogenTarget->AddUtility(depName.Value, makefile);
      }
    }
    // Add additional autogen target dependencies to autogen target
    for (cmTarget* depTarget : this->AutogenTarget.DependTargets) {
      autogenTarget->AddUtility(depTarget->GetName(), makefile);
    }

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

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

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

  return true;
}

bool cmQtAutoGenInitializer::InitRccTargets()
{
  cmMakefile* makefile = this->Target->Target->GetMakefile();
  cmLocalGenerator* localGen = this->Target->GetLocalGenerator();

  for (Qrc const& qrc : this->Rcc.Qrcs) {
    // Register info file as generated by CMake
    makefile->AddCMakeOutputFile(qrc.InfoFile);
    // Register file at target
    this->AddGeneratedSource(qrc.RccFile, this->Rcc);

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

    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;
    if (this->MultiConfig) {
      // Build for all configurations
      for (std::string const& config : this->ConfigsList) {
        cmCustomCommandLine currentLine;
        currentLine.push_back(cmSystemTools::GetCMakeCommand());
        currentLine.push_back("-E");
        currentLine.push_back("cmake_autorcc");
        currentLine.push_back(qrc.InfoFile);
        currentLine.push_back(config);
        commandLines.push_back(std::move(currentLine));
      }
    } else {
      cmCustomCommandLine currentLine;
      currentLine.push_back(cmSystemTools::GetCMakeCommand());
      currentLine.push_back("-E");
      currentLine.push_back("cmake_autorcc");
      currentLine.push_back(qrc.InfoFile);
      currentLine.push_back("$<CONFIG>");
      commandLines.push_back(std::move(currentLine));
    }
    std::string ccComment = "Automatic RCC for ";
    ccComment += FileProjectRelativePath(makefile, qrc.QrcFile);

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

        cmTarget* autoRccTarget = makefile->AddUtilityCommand(
          ccName, cmMakefile::TargetOrigin::Generator, true,
          this->Dir.Work.c_str(), ccOutput, ccDepends, commandLines, false,
          ccComment.c_str());

        // Create autogen generator target
        localGen->AddGeneratorTarget(
          new cmGeneratorTarget(autoRccTarget, localGen));

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

      // Add autogen target to the global autogen target dependencies
      if (this->Rcc.GlobalTarget) {
        this->GlobalInitializer->AddToGlobalAutoRcc(localGen, ccName);
      }
    } else {
      // Create custom rcc command
      {
        std::vector<std::string> ccByproducts;

        // Add the resource files to the dependencies
        for (std::string const& fileName : qrc.Resources) {
          // Add resource file to the custom command dependencies
          ccDepends.push_back(fileName);
        }
        if (!this->Rcc.ExecutableTargetName.empty()) {
          ccDepends.push_back(this->Rcc.ExecutableTargetName);
        }
        makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends,
                                           /*main_dependency*/ std::string(),
                                           commandLines, ccComment.c_str(),
                                           this->Dir.Work.c_str());
      }
      // Reconfigure when .qrc file changes
      makefile->AddCMakeDependFile(qrc.QrcFile);
    }
  }

  return true;
}

bool cmQtAutoGenInitializer::SetupCustomTargets()
{
  // Create info directory on demand
  if (!cmSystemTools::MakeDirectory(this->Dir.Info)) {
    std::string emsg = ("AutoGen: Could not create directory: ");
    emsg += Quoted(this->Dir.Info);
    cmSystemTools::Error(emsg);
    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()
{
  InfoWriter ofs(this->AutogenTarget.InfoFile);
  if (ofs) {
    // Utility lambdas
    cmMakefile* makefile = this->Target->Target->GetMakefile();
    auto MfDef = [makefile](const char* key) {
      return makefile->GetSafeDefinition(key);
    };

    // Write common settings
    ofs.Write("# Meta\n");
    ofs.Write("AM_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");
    ofs.Write("AM_PARALLEL", this->AutogenTarget.Parallel);
    ofs.Write("AM_VERBOSITY", this->Verbosity);

    ofs.Write("# Directories\n");
    ofs.Write("AM_CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));
    ofs.Write("AM_CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));
    ofs.Write("AM_CMAKE_CURRENT_SOURCE_DIR",
              MfDef("CMAKE_CURRENT_SOURCE_DIR"));
    ofs.Write("AM_CMAKE_CURRENT_BINARY_DIR",
              MfDef("CMAKE_CURRENT_BINARY_DIR"));
    ofs.Write("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE",
              MfDef("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE"));
    ofs.Write("AM_BUILD_DIR", this->Dir.Build);
    ofs.Write("AM_INCLUDE_DIR", this->Dir.Include);
    ofs.WriteConfig("AM_INCLUDE_DIR", this->Dir.ConfigInclude);

    // Use sorted sets
    std::set<std::string> headers;
    std::set<std::string> sources;
    std::set<std::string> moc_headers;
    std::set<std::string> moc_sources;
    std::set<std::string> moc_skip;
    std::set<std::string> uic_headers;
    std::set<std::string> uic_sources;
    std::set<std::string> uic_skip;
    // Filter headers
    for (auto const& pair : this->AutogenTarget.Headers) {
      MUFile const& muf = *pair.second;
      if (muf.Generated && !this->CMP0071Accept) {
        continue;
      }
      if (muf.SkipMoc) {
        moc_skip.insert(muf.RealPath);
      }
      if (muf.SkipUic) {
        uic_skip.insert(muf.RealPath);
      }
      if (muf.MocIt && muf.UicIt) {
        headers.insert(muf.RealPath);
      } else if (muf.MocIt) {
        moc_headers.insert(muf.RealPath);
      } else if (muf.UicIt) {
        uic_headers.insert(muf.RealPath);
      }
    }
    // Filter sources
    for (auto const& pair : this->AutogenTarget.Sources) {
      MUFile const& muf = *pair.second;
      if (muf.Generated && !this->CMP0071Accept) {
        continue;
      }
      if (muf.SkipMoc) {
        moc_skip.insert(muf.RealPath);
      }
      if (muf.SkipUic) {
        uic_skip.insert(muf.RealPath);
      }
      if (muf.MocIt && muf.UicIt) {
        sources.insert(muf.RealPath);
      } else if (muf.MocIt) {
        moc_sources.insert(muf.RealPath);
      } else if (muf.UicIt) {
        uic_sources.insert(muf.RealPath);
      }
    }

    ofs.Write("# Qt\n");
    ofs.WriteUInt("AM_QT_VERSION_MAJOR", this->QtVersion.Major);
    ofs.Write("AM_QT_MOC_EXECUTABLE", this->Moc.Executable);
    ofs.Write("AM_QT_UIC_EXECUTABLE", this->Uic.Executable);

    ofs.Write("# Files\n");
    ofs.Write("AM_SETTINGS_FILE", this->AutogenTarget.SettingsFile);
    ofs.WriteConfig("AM_SETTINGS_FILE",
                    this->AutogenTarget.ConfigSettingsFile);
    ofs.WriteStrings("AM_HEADERS", headers);
    ofs.WriteStrings("AM_SOURCES", sources);

    // Write moc settings
    if (this->Moc.Enabled) {
      ofs.Write("# MOC settings\n");
      ofs.WriteStrings("AM_MOC_HEADERS", moc_headers);
      ofs.WriteStrings("AM_MOC_SOURCES", moc_sources);
      ofs.WriteStrings("AM_MOC_SKIP", moc_skip);
      ofs.WriteStrings("AM_MOC_DEFINITIONS", this->Moc.Defines);
      ofs.WriteConfigStrings("AM_MOC_DEFINITIONS", this->Moc.ConfigDefines);
      ofs.WriteStrings("AM_MOC_INCLUDES", this->Moc.Includes);
      ofs.WriteConfigStrings("AM_MOC_INCLUDES", this->Moc.ConfigIncludes);
      ofs.Write("AM_MOC_OPTIONS",
                this->Target->GetSafeProperty("AUTOMOC_MOC_OPTIONS"));
      ofs.Write("AM_MOC_RELAXED_MODE", MfDef("CMAKE_AUTOMOC_RELAXED_MODE"));
      ofs.Write("AM_MOC_MACRO_NAMES",
                this->Target->GetSafeProperty("AUTOMOC_MACRO_NAMES"));
      ofs.Write("AM_MOC_DEPEND_FILTERS",
                this->Target->GetSafeProperty("AUTOMOC_DEPEND_FILTERS"));
      ofs.Write("AM_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());

      ofs.Write("# UIC settings\n");
      ofs.WriteStrings("AM_UIC_HEADERS", uic_headers);
      ofs.WriteStrings("AM_UIC_SOURCES", uic_sources);
      ofs.WriteStrings("AM_UIC_SKIP", uic_skip);
      ofs.WriteStrings("AM_UIC_TARGET_OPTIONS", this->Uic.Options);
      ofs.WriteConfigStrings("AM_UIC_TARGET_OPTIONS", this->Uic.ConfigOptions);
      ofs.WriteStrings("AM_UIC_OPTIONS_FILES", this->Uic.FileFiles);
      ofs.WriteNestedLists("AM_UIC_OPTIONS_OPTIONS", this->Uic.FileOptions);
      ofs.WriteStrings("AM_UIC_SEARCH_PATHS", this->Uic.SearchPaths);
    }
  } else {
    std::string err = "AutoGen: Could not write file ";
    err += this->AutogenTarget.InfoFile;
    cmSystemTools::Error(err);
    return false;
  }

  return true;
}

bool cmQtAutoGenInitializer::SetupWriteRccInfo()
{
  for (Qrc const& qrc : this->Rcc.Qrcs) {
    InfoWriter ofs(qrc.InfoFile);
    if (ofs) {
      // Write
      ofs.Write("# Configurations\n");
      ofs.Write("ARCC_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");
      ofs.Write("ARCC_VERBOSITY", this->Verbosity);
      ofs.Write("# Settings file\n");
      ofs.Write("ARCC_SETTINGS_FILE", qrc.SettingsFile);
      ofs.WriteConfig("ARCC_SETTINGS_FILE", qrc.ConfigSettingsFile);

      ofs.Write("# Directories\n");
      ofs.Write("ARCC_BUILD_DIR", this->Dir.Build);
      ofs.Write("ARCC_INCLUDE_DIR", this->Dir.Include);
      ofs.WriteConfig("ARCC_INCLUDE_DIR", this->Dir.ConfigInclude);

      ofs.Write("# Rcc executable\n");
      ofs.Write("ARCC_RCC_EXECUTABLE", this->Rcc.Executable);
      ofs.WriteStrings("ARCC_RCC_LIST_OPTIONS", this->Rcc.ListOptions);

      ofs.Write("# Rcc job\n");
      ofs.Write("ARCC_LOCK_FILE", qrc.LockFile);
      ofs.Write("ARCC_SOURCE", qrc.QrcFile);
      ofs.Write("ARCC_OUTPUT_CHECKSUM", qrc.PathChecksum);
      ofs.Write("ARCC_OUTPUT_NAME",
                cmSystemTools::GetFilenameName(qrc.RccFile));
      ofs.WriteStrings("ARCC_OPTIONS", qrc.Options);
      ofs.WriteStrings("ARCC_INPUTS", qrc.Resources);
    } else {
      std::string err = "AutoRcc: Could not write file ";
      err += qrc.InfoFile;
      cmSystemTools::Error(err);
      return false;
    }
  }

  return true;
}

void cmQtAutoGenInitializer::RegisterGeneratedSource(
  std::string const& filename)
{
  cmMakefile* makefile = this->Target->Target->GetMakefile();
  cmSourceFile* gFile = makefile->GetOrCreateSource(filename, true);
  gFile->SetProperty("GENERATED", "1");
  gFile->SetProperty("SKIP_AUTOGEN", "1");
}

bool cmQtAutoGenInitializer::AddGeneratedSource(std::string const& filename,
                                                GenVarsT const& genVars,
                                                bool prepend)
{
  // Register source at makefile
  this->RegisterGeneratedSource(filename);
  // Add source file to target
  this->Target->AddSource(filename, prepend);
  // Add source file to source group
  return this->AddToSourceGroup(filename, genVars.GenNameUpper);
}

bool cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName,
                                              std::string const& genNameUpper)
{
  cmMakefile* makefile = this->Target->Target->GetMakefile();
  cmSourceGroup* sourceGroup = nullptr;
  // Acquire source group
  {
    std::string property;
    std::string groupName;
    {
      // Prefer generator specific source group name
      std::array<std::string, 2> props{ { genNameUpper + "_SOURCE_GROUP",
                                          "AUTOGEN_SOURCE_GROUP" } };
      for (std::string& prop : props) {
        const char* propName = makefile->GetState()->GetGlobalProperty(prop);
        if ((propName != nullptr) && (*propName != '\0')) {
          groupName = propName;
          property = std::move(prop);
          break;
        }
      }
    }
    // Generate a source group on demand
    if (!groupName.empty()) {
      sourceGroup = makefile->GetOrCreateSourceGroup(groupName);
      if (sourceGroup == nullptr) {
        std::string err;
        err += genNameUpper;
        err += " error in ";
        err += property;
        err += ": Could not find or create the source group ";
        err += cmQtAutoGen::Quoted(groupName);
        cmSystemTools::Error(err);
        return false;
      }
    }
  }
  if (sourceGroup != nullptr) {
    sourceGroup->AddGroupFile(fileName);
  }
  return true;
}

static unsigned int CharPtrToUInt(const char* const input)
{
  unsigned long tmp = 0;
  if (input != nullptr && cmSystemTools::StringToULong(input, &tmp)) {
    return static_cast<unsigned int>(tmp);
  }
  return 0;
}

static std::vector<cmQtAutoGen::IntegerVersion> GetKnownQtVersions(
  cmGeneratorTarget const* target)
{
  // Qt version variable prefixes
  static std::array<std::string, 3> const prefixes{ { "Qt6Core", "Qt5Core",
                                                      "QT" } };

  std::vector<cmQtAutoGen::IntegerVersion> result;
  result.reserve(prefixes.size() * 2);
  // Adds a version to the result (nullptr safe)
  auto addVersion = [&result](const char* major, const char* minor) {
    cmQtAutoGen::IntegerVersion ver(CharPtrToUInt(major),
                                    CharPtrToUInt(minor));
    if (ver.Major != 0) {
      result.emplace_back(ver);
    }
  };
  cmMakefile* makefile = target->Target->GetMakefile();

  // Read versions from variables
  for (const std::string& prefix : prefixes) {
    addVersion(makefile->GetDefinition(prefix + "_VERSION_MAJOR"),
               makefile->GetDefinition(prefix + "_VERSION_MINOR"));
  }

  // Read versions from directory properties
  for (const std::string& prefix : prefixes) {
    addVersion(makefile->GetProperty(prefix + "_VERSION_MAJOR"),
               makefile->GetProperty(prefix + "_VERSION_MINOR"));
  }

  return result;
}

std::pair<cmQtAutoGen::IntegerVersion, unsigned int>
cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target)
{
  std::pair<IntegerVersion, unsigned int> res(
    IntegerVersion(),
    CharPtrToUInt(target->GetLinkInterfaceDependentStringProperty(
      "QT_MAJOR_VERSION", "")));

  auto knownQtVersions = GetKnownQtVersions(target);
  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 it : knownQtVersions) {
        if (it.Major == res.second) {
          res.first = it;
          break;
        }
      }
    }
  }
  return res;
}

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

  // Custom executable
  {
    std::string const prop = genVars.GenNameUpper + "_EXECUTABLE";
    std::string const val = this->Target->Target->GetSafeProperty(prop);
    if (!val.empty()) {
      // Evaluate generator expression
      {
        cmListFileBacktrace lfbt =
          this->Target->Target->GetMakefile()->GetBacktrace();
        cmGeneratorExpression ge(lfbt);
        std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(val);
        genVars.Executable =
          cge->Evaluate(this->Target->GetLocalGenerator(), "");
      }
      if (genVars.Executable.empty() && !ignoreMissingTarget) {
        print_err(prop + " evaluates to an empty value");
        return false;
      }

      // Check if the provided executable already exists (it's possible for it
      // not to exist when building Qt itself).
      genVars.ExecutableExists = cmSystemTools::FileExists(genVars.Executable);
      return true;
    }
  }

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

    // Find target
    cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
    cmGeneratorTarget* target = localGen->FindGeneratorTargetToUse(targetName);
    if (target != nullptr) {
      genVars.ExecutableTargetName = targetName;
      genVars.ExecutableTarget = target;
      if (target->IsImported()) {
        genVars.Executable = target->ImportedGetLocation("");
      } else {
        genVars.Executable = target->GetLocation("");
      }
    } else {
      if (ignoreMissingTarget) {
        return true;
      }
      std::string err = "Could not find ";
      err += executable;
      err += " executable target ";
      err += targetName;
      print_err(err);
      return false;
    }
  }

  // Test executable
  {
    std::string err;
    if (!this->GlobalInitializer->GetExecutableTestOutput(
          executable, genVars.Executable, err, output)) {
      print_err(err);
      return false;
    }
    genVars.ExecutableExists = true;
  }

  return true;
}
