/* 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 "cmAlgorithms.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
#include "cmDuration.h"
#include "cmFilePathChecksum.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLinkItem.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmProcessOutput.h"
#include "cmSourceFile.h"
#include "cmSourceGroup.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmake.h"
#include "cmsys/FStream.hxx"
#include "cmsys/SystemInformation.hxx"

#include <algorithm>
#include <array>
#include <deque>
#include <map>
#include <set>
#include <sstream>
#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 bool AddToSourceGroup(cmMakefile* makefile, std::string const& fileName,
                             cmQtAutoGen::GeneratorT genType)
{
  cmSourceGroup* sourceGroup = nullptr;
  // Acquire source group
  {
    std::string property;
    std::string groupName;
    {
      std::array<std::string, 2> props;
      // Use generator specific group name
      switch (genType) {
        case cmQtAutoGen::GeneratorT::MOC:
          props[0] = "AUTOMOC_SOURCE_GROUP";
          break;
        case cmQtAutoGen::GeneratorT::RCC:
          props[0] = "AUTORCC_SOURCE_GROUP";
          break;
        default:
          props[0] = "AUTOGEN_SOURCE_GROUP";
          break;
      }
      props[1] = "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::ostringstream ost;
        ost << cmQtAutoGen::GeneratorNameUpper(genType);
        ost << ": " << property;
        ost << ": Could not find or create the source group ";
        ost << cmQtAutoGen::Quoted(groupName);
        cmSystemTools::Error(ost.str().c_str());
        return false;
      }
    }
  }
  if (sourceGroup != nullptr) {
    sourceGroup->AddGroupFile(fileName);
  }
  return true;
}

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::cmQtAutoGenInitializer(
  cmGeneratorTarget* target, bool mocEnabled, bool uicEnabled, bool rccEnabled,
  std::string const& qtVersionMajor)
  : Target(target)
  , MultiConfig(false)
  , QtVersionMajor(qtVersionMajor)
{
  Moc.Enabled = mocEnabled;
  Uic.Enabled = uicEnabled;
  Rcc.Enabled = rccEnabled;

  this->QtVersionMinor =
    cmQtAutoGenInitializer::GetQtMinorVersion(target, this->QtVersionMajor);
}

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

  // 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.c_str()) ? "1" : "0";
    }
  }

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

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

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

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

    // Autogen info dir
    this->DirInfo = cbd;
    this->DirInfo += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();
    this->DirInfo += '/';
    this->DirInfo += this->AutogenTargetName;
    this->DirInfo += ".dir";
    cmSystemTools::ConvertToUnixSlashes(this->DirInfo);

    // Autogen build dir
    this->DirBuild = this->Target->GetSafeProperty("AUTOGEN_BUILD_DIR");
    if (this->DirBuild.empty()) {
      this->DirBuild = cbd;
      this->DirBuild += '/';
      this->DirBuild += this->AutogenTargetName;
    }
    cmSystemTools::ConvertToUnixSlashes(this->DirBuild);
    // Remove build directories on cleanup
    AddCleanFile(makefile, this->DirBuild);

    // Working directory
    this->DirWork = cbd;
    cmSystemTools::ConvertToUnixSlashes(this->DirWork);

    // Include directory
    this->DirInclude = this->DirBuild;
    this->DirInclude += "/include";
    if (this->MultiConfig) {
      this->DirInclude += "_$<CONFIG>";
    }
    if (this->MultiConfig) {
      for (std::string const& cfg : this->ConfigsList) {
        std::string& dir = this->DirConfigInclude[cfg];
        dir = this->DirBuild;
        dir += "/include_";
        dir += cfg;
      }
    }
  }

  // Autogen info and settings files
  {
    this->AutogenInfoFile = this->DirInfo;
    this->AutogenInfoFile += "/AutogenInfo.cmake";

    this->AutogenSettingsFile = this->DirInfo;
    this->AutogenSettingsFile += "/AutogenOldSettings.txt";

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

  // Autogen target FOLDER property
  {
    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->AutogenFolder = folder;
    }
  }

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

    // Autogen target: Compute user defined dependencies
    {
      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->AutogenDependTargets.insert(depTarget);
          } else {
            this->AutogenDependFiles.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->Moc.Enabled || this->Uic.Enabled ||
      (this->Rcc.Enabled && this->MultiConfig)) {
    this->Target->AddIncludeDirectory(this->DirInclude, true);
  }

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

  // Create autogen target
  if ((this->Moc.Enabled || this->Uic.Enabled) && !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->DirBuild;
  this->Moc.MocsCompilation += "/mocs_compilation.cpp";

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

  // Moc includes
  {
    bool const appendImplicit = (this->QtVersionMajor == "5");
    auto GetIncludeDirs =
      [this, localGen, appendImplicit](std::string const& cfg) -> 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->GetIncludeDirectories(dirs, this->Target, "CXX", cfg, false,
                                      appendImplicit);
      return cmJoin(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::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::string {
      std::set<std::string> defines;
      localGen->AddCompileDefinitions(defines, this->Target, cfg, "CXX");
      return cmJoin(defines, ";");
    };

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

  // Moc executable
  if (!GetMocExecutable()) {
    return false;
  }

  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::string {
      std::vector<std::string> opts;
      this->Target->GetAutoUicOptions(opts, cfg);
      return cmJoin(opts, ";");
    };

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

    // Configuration specific settings
    if (this->MultiConfig) {
      for (std::string const& cfg : this->ConfigsList) {
        std::string options = UicGetOpts(cfg);
        if (options != this->Uic.Options) {
          this->Uic.ConfigOptions[cfg] = std::move(options);
        }
      }
    }
  }
  // .ui files skip and options
  {
    std::string const uiExt = "ui";
    std::string pathError;
    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 const& fPath = sf->GetFullPath(&pathError);
      if (!pathError.empty()) {
        pathError.clear();
        continue;
      }
      if (sf->GetExtension() == uiExt) {
        std::string const absFile = cmSystemTools::GetRealPath(fPath);
        // Check if the .ui file should be skipped
        if (sf->GetPropertyAsBool("SKIP_AUTOUIC") ||
            sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
          this->Uic.Skip.insert(absFile);
        }
        // Check if the .ui file has uic options
        std::string const uicOpts = sf->GetSafeProperty("AUTOUIC_OPTIONS");
        if (!uicOpts.empty()) {
          // Check if file isn't skipped
          if (this->Uic.Skip.count(absFile) == 0) {
            this->Uic.FileFiles.push_back(absFile);
            std::vector<std::string> optsVec;
            cmSystemTools::ExpandListArgument(uicOpts, optsVec);
            this->Uic.FileOptions.push_back(std::move(optsVec));
          }
        }
      }
    }
  }

  // Uic executable
  if (!GetUicExecutable()) {
    return false;
  }

  return true;
}

bool cmQtAutoGenInitializer::InitRcc()
{
  if (!GetRccExecutable()) {
    return false;
  }
  return true;
}

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

  // Scan through target files
  {
    std::string const qrcExt = "qrc";
    std::vector<cmSourceFile*> srcFiles;
    this->Target->GetConfigCommonSourceFiles(srcFiles);
    for (cmSourceFile* sf : srcFiles) {
      if (sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
        continue;
      }
      // sf->GetExtension() is only valid after sf->GetFullPath() ...
      std::string const& fPath = sf->GetFullPath();
      std::string const& ext = sf->GetExtension();
      // Register generated files that will be scanned by moc or uic
      if (this->Moc.Enabled || this->Uic.Enabled) {
        cmSystemTools::FileFormat const fileType =
          cmSystemTools::GetFileFormat(ext.c_str());
        if ((fileType == cmSystemTools::CXX_FILE_FORMAT) ||
            (fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
          std::string const absPath = cmSystemTools::GetRealPath(fPath);
          if ((this->Moc.Enabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) ||
              (this->Uic.Enabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) {
            // Register source
            const bool generated = sf->GetPropertyAsBool("GENERATED");
            if (fileType == cmSystemTools::HEADER_FILE_FORMAT) {
              if (generated) {
                this->MocUic.HeadersGenerated.push_back(absPath);
              } else {
                this->MocUic.Headers.push_back(absPath);
              }
            } else {
              if (generated) {
                this->MocUic.SourcesGenerated.push_back(absPath);
              } else {
                this->MocUic.Sources.push_back(absPath);
              }
            }
          }
        }
      }
      // Register rcc enabled files
      if (this->Rcc.Enabled && (ext == qrcExt) &&
          !sf->GetPropertyAsBool("SKIP_AUTORCC")) {
        // Register qrc file
        {
          Qrc qrc;
          qrc.QrcFile = cmSystemTools::GetRealPath(fPath);
          qrc.QrcName =
            cmSystemTools::GetFilenameWithoutLastExtension(qrc.QrcFile);
          qrc.Generated = sf->GetPropertyAsBool("GENERATED");
          // RCC options
          {
            std::string const opts = sf->GetSafeProperty("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();

  if (this->Moc.Enabled || this->Uic.Enabled) {
    // Read skip files from makefile sources
    {
      std::string pathError;
      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 const& fPath = sf->GetFullPath(&pathError);
        if (!pathError.empty()) {
          pathError.clear();
          continue;
        }
        cmSystemTools::FileFormat const fileType =
          cmSystemTools::GetFileFormat(sf->GetExtension().c_str());
        if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) &&
            !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
          continue;
        }
        const bool skipAll = sf->GetPropertyAsBool("SKIP_AUTOGEN");
        const bool mocSkip = this->Moc.Enabled &&
          (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC"));
        const bool uicSkip = this->Uic.Enabled &&
          (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC"));
        if (mocSkip || uicSkip) {
          std::string const absFile = cmSystemTools::GetRealPath(fPath);
          if (mocSkip) {
            this->Moc.Skip.insert(absFile);
          }
          if (uicSkip) {
            this->Uic.Skip.insert(absFile);
          }
        }
      }
    }

    // Process GENERATED sources and headers
    if (!this->MocUic.SourcesGenerated.empty() ||
        !this->MocUic.HeadersGenerated.empty()) {
      // Check status of policy CMP0071
      bool policyAccept = false;
      bool policyWarn = false;
      cmPolicies::PolicyStatus const CMP0071_status =
        makefile->GetPolicyStatus(cmPolicies::CMP0071);
      switch (CMP0071_status) {
        case cmPolicies::WARN:
          policyWarn = 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
          policyAccept = true;
          break;
      }

      if (policyAccept) {
        // Accept GENERATED sources
        for (std::string const& absFile : this->MocUic.HeadersGenerated) {
          this->MocUic.Headers.push_back(absFile);
          this->AutogenDependFiles.insert(absFile);
        }
        for (std::string const& absFile : this->MocUic.SourcesGenerated) {
          this->MocUic.Sources.push_back(absFile);
          this->AutogenDependFiles.insert(absFile);
        }
      } else {
        if (policyWarn) {
          std::string msg;
          msg += cmPolicies::GetPolicyWarning(cmPolicies::CMP0071);
          msg += "\n";
          std::string tools;
          std::string property;
          if (this->Moc.Enabled && this->Uic.Enabled) {
            tools = "AUTOMOC and AUTOUIC";
            property = "SKIP_AUTOGEN";
          } else if (this->Moc.Enabled) {
            tools = "AUTOMOC";
            property = "SKIP_AUTOMOC";
          } else if (this->Uic.Enabled) {
            tools = "AUTOUIC";
            property = "SKIP_AUTOUIC";
          }
          msg += "For compatibility, CMake is excluding the GENERATED source "
                 "file(s):\n";
          for (const std::string& absFile : this->MocUic.HeadersGenerated) {
            msg.append("  ").append(Quoted(absFile)).append("\n");
          }
          for (const std::string& absFile : this->MocUic.SourcesGenerated) {
            msg.append("  ").append(Quoted(absFile)).append("\n");
          }
          msg += "from processing by ";
          msg += tools;
          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(cmake::AUTHOR_WARNING, msg);
        }
      }
    }
    // Sort headers and sources
    if (this->Moc.Enabled || this->Uic.Enabled) {
      std::sort(this->MocUic.Headers.begin(), this->MocUic.Headers.end());
      std::sort(this->MocUic.Sources.begin(), this->MocUic.Sources.end());
    }
  }

  // Process qrc files
  if (!this->Rcc.Qrcs.empty()) {
    const bool QtV5 = (this->QtVersionMajor == "5");
    // Target rcc options
    std::vector<std::string> optionsTarget;
    cmSystemTools::ExpandListArgument(
      this->Target->GetSafeProperty("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->DirBuild + "/";
          rccFile += qrc.PathChecksum;
          rccFile += "/qrc_";
          rccFile += qrc.QrcName;
          rccFile += ".cpp";
          qrc.RccFile = std::move(rccFile);
        }
        {
          std::string base = this->DirInfo;
          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, QtV5);
      }
      // Merge file option
      RccMergeOptions(opts, qrc.Options, QtV5);
      qrc.Options = std::move(opts);
    }
    // RCC resources
    for (Qrc& qrc : this->Rcc.Qrcs) {
      if (!qrc.Generated) {
        std::string error;
        if (!RccListInputs(qrc.QrcFile, qrc.Resources, error)) {
          cmSystemTools::Error(error.c_str());
          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->AutogenInfoFile);

  // Files provided by the autogen target
  std::vector<std::string> autogenProvides;
  if (this->Moc.Enabled) {
    this->AddGeneratedSource(this->Moc.MocsCompilation, GeneratorT::MOC);
    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->AutogenInfoFile);
    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->AutogenDependFiles.empty()) {
      usePRE_BUILD = false;
    }
  }
  // Create the autogen target/command
  if (usePRE_BUILD) {
    // Add additional autogen target dependencies to origin target
    for (cmTarget* depTarget : this->AutogenDependTargets) {
      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->DirWork.c_str());
    cc.SetEscapeOldStyle(false);
    cc.SetEscapeAllowMakeVars(true);
    this->Target->Target->AddPreBuildCommand(cc);
  } else {

    // Add link library target dependencies to the autogen target
    // dependencies
    {
      // 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->AutogenDependTargets.insert(item.first->Target);
        }
      }
    }

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

    // Forward origin utilities to autogen target
    for (std::string const& depName : this->Target->Target->GetUtilities()) {
      autogenTarget->AddUtility(depName, makefile);
    }
    // Add additional autogen target dependencies to autogen target
    for (cmTarget* depTarget : this->AutogenDependTargets) {
      autogenTarget->AddUtility(depTarget->GetName(), makefile);
    }

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

    // Add autogen target to the origin target dependencies
    this->Target->Target->AddUtility(this->AutogenTargetName, makefile);
  }

  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, GeneratorT::RCC);

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

    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) {
      // Create custom rcc target
      std::string ccName;
      {
        ccName = this->Target->GetName();
        ccName += "_arcc_";
        ccName += qrc.QrcName;
        if (!qrc.Unique) {
          ccName += "_";
          ccName += qrc.PathChecksum;
        }
        std::vector<std::string> ccDepends;
        // Add the .qrc and info file to the custom target dependencies
        ccDepends.push_back(qrc.QrcFile);
        ccDepends.push_back(qrc.InfoFile);

        cmTarget* autoRccTarget = makefile->AddUtilityCommand(
          ccName, cmMakefile::TargetOrigin::Generator, true,
          this->DirWork.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->AutogenFolder.empty()) {
          autoRccTarget->SetProperty("FOLDER", this->AutogenFolder.c_str());
        }
      }
      // Add autogen target to the origin target dependencies
      this->Target->Target->AddUtility(ccName, makefile);
    } else {
      // Create custom rcc command
      {
        std::vector<std::string> ccByproducts;
        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);

        // 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);
        }
        makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends,
                                           /*main_dependency*/ std::string(),
                                           commandLines, ccComment.c_str(),
                                           this->DirWork.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->DirInfo)) {
    std::string emsg = ("AutoGen: Could not create directory: ");
    emsg += Quoted(this->DirInfo);
    cmSystemTools::Error(emsg.c_str());
    return false;
  }

  // Generate autogen target info file
  if (this->Moc.Enabled || this->Uic.Enabled) {
    // Write autogen target info files
    if (!this->SetupWriteAutogenInfo()) {
      return false;
    }
  }

  // Write AUTORCC info files
  if (this->Rcc.Enabled && !this->SetupWriteRccInfo()) {
    return false;
  }

  return true;
}

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

  cmGeneratedFileStream ofs;
  ofs.SetCopyIfDifferent(true);
  ofs.Open(this->AutogenInfoFile, false, true);
  if (ofs) {
    // Utility lambdas
    auto CWrite = [&ofs](const char* key, std::string const& value) {
      ofs << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value)
          << ")\n";
    };
    auto CWriteList = [&CWrite](const char* key,
                                std::vector<std::string> const& list) {
      CWrite(key, cmJoin(list, ";"));
    };
    auto CWriteNestedLists =
      [&CWrite](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 += cmJoin(list, ";");
          blist += "}";
          seplist.push_back(std::move(blist));
        }
        CWrite(key, cmJoin(seplist, cmQtAutoGen::ListSep));
      };
    auto CWriteSet = [&CWrite](const char* key,
                               std::set<std::string> const& list) {
      CWrite(key, cmJoin(list, ";"));
    };
    auto CWriteMap = [&ofs](const char* key,
                            std::map<std::string, std::string> const& map) {
      for (auto const& item : map) {
        ofs << "set(" << key << "_" << item.first << " "
            << cmOutputConverter::EscapeForCMake(item.second) << ")\n";
      }
    };
    auto MfDef = [makefile](const char* key) {
      return std::string(makefile->GetSafeDefinition(key));
    };

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

    ofs << "# Directories\n";
    CWrite("AM_CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));
    CWrite("AM_CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));
    CWrite("AM_CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR"));
    CWrite("AM_CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR"));
    CWrite("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE",
           MfDef("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE"));
    CWrite("AM_BUILD_DIR", this->DirBuild);
    CWrite("AM_INCLUDE_DIR", this->DirInclude);
    CWriteMap("AM_INCLUDE_DIR", this->DirConfigInclude);

    ofs << "# Files\n";
    CWriteList("AM_SOURCES", this->MocUic.Sources);
    CWriteList("AM_HEADERS", this->MocUic.Headers);
    CWrite("AM_SETTINGS_FILE", this->AutogenSettingsFile);
    CWriteMap("AM_SETTINGS_FILE", this->AutogenConfigSettingsFile);

    ofs << "# Qt\n";
    CWrite("AM_QT_VERSION_MAJOR", this->QtVersionMajor);
    CWrite("AM_QT_MOC_EXECUTABLE", this->Moc.Executable);
    CWrite("AM_QT_UIC_EXECUTABLE", this->Uic.Executable);

    if (this->Moc.Enabled) {
      ofs << "# MOC settings\n";
      CWriteSet("AM_MOC_SKIP", this->Moc.Skip);
      CWrite("AM_MOC_DEFINITIONS", this->Moc.Defines);
      CWriteMap("AM_MOC_DEFINITIONS", this->Moc.ConfigDefines);
      CWrite("AM_MOC_INCLUDES", this->Moc.Includes);
      CWriteMap("AM_MOC_INCLUDES", this->Moc.ConfigIncludes);
      CWrite("AM_MOC_OPTIONS",
             this->Target->GetSafeProperty("AUTOMOC_MOC_OPTIONS"));
      CWrite("AM_MOC_RELAXED_MODE", MfDef("CMAKE_AUTOMOC_RELAXED_MODE"));
      CWrite("AM_MOC_MACRO_NAMES",
             this->Target->GetSafeProperty("AUTOMOC_MACRO_NAMES"));
      CWrite("AM_MOC_DEPEND_FILTERS",
             this->Target->GetSafeProperty("AUTOMOC_DEPEND_FILTERS"));
      CWrite("AM_MOC_PREDEFS_CMD", this->Moc.PredefsCmd);
    }

    if (this->Uic.Enabled) {
      ofs << "# UIC settings\n";
      CWriteSet("AM_UIC_SKIP", this->Uic.Skip);
      CWrite("AM_UIC_TARGET_OPTIONS", this->Uic.Options);
      CWriteMap("AM_UIC_TARGET_OPTIONS", this->Uic.ConfigOptions);
      CWriteList("AM_UIC_OPTIONS_FILES", this->Uic.FileFiles);
      CWriteNestedLists("AM_UIC_OPTIONS_OPTIONS", this->Uic.FileOptions);
      CWriteList("AM_UIC_SEARCH_PATHS", this->Uic.SearchPaths);
    }
  } else {
    std::string err = "AutoGen: Could not write file ";
    err += this->AutogenInfoFile;
    cmSystemTools::Error(err.c_str());
    return false;
  }

  return true;
}

bool cmQtAutoGenInitializer::SetupWriteRccInfo()
{
  for (Qrc const& qrc : this->Rcc.Qrcs) {
    cmGeneratedFileStream ofs;
    ofs.SetCopyIfDifferent(true);
    ofs.Open(qrc.InfoFile, false, true);
    if (ofs) {
      // Utility lambdas
      auto CWrite = [&ofs](const char* key, std::string const& value) {
        ofs << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value)
            << ")\n";
      };
      auto CWriteMap = [&ofs](const char* key,
                              std::map<std::string, std::string> const& map) {
        for (auto const& item : map) {
          ofs << "set(" << key << "_" << item.first << " "
              << cmOutputConverter::EscapeForCMake(item.second) << ")\n";
        }
      };

      // Write
      ofs << "# Configurations\n";
      CWrite("ARCC_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");
      CWrite("ARCC_VERBOSITY", this->Verbosity);
      ofs << "# Settings file\n";
      CWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile);
      CWriteMap("ARCC_SETTINGS_FILE", qrc.ConfigSettingsFile);

      ofs << "# Directories\n";
      CWrite("ARCC_BUILD_DIR", this->DirBuild);
      CWrite("ARCC_INCLUDE_DIR", this->DirInclude);
      CWriteMap("ARCC_INCLUDE_DIR", this->DirConfigInclude);

      ofs << "# Rcc executable\n";
      CWrite("ARCC_RCC_EXECUTABLE", this->Rcc.Executable);
      CWrite("ARCC_RCC_LIST_OPTIONS", cmJoin(this->Rcc.ListOptions, ";"));

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

  return true;
}

void cmQtAutoGenInitializer::AddGeneratedSource(std::string const& filename,
                                                GeneratorT genType)
{
  // Register source file in makefile
  cmMakefile* makefile = this->Target->Target->GetMakefile();
  {
    cmSourceFile* gFile = makefile->GetOrCreateSource(filename, true);
    gFile->SetProperty("GENERATED", "1");
    gFile->SetProperty("SKIP_AUTOGEN", "On");
  }

  // Add source file to source group
  AddToSourceGroup(makefile, filename, genType);

  // Add source file to target
  this->Target->AddSource(filename);
}

std::string cmQtAutoGenInitializer::GetQtMajorVersion(
  cmGeneratorTarget const* target)
{
  cmMakefile* makefile = target->Target->GetMakefile();
  std::string qtMajor = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
  if (qtMajor.empty()) {
    qtMajor = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
  }
  const char* targetQtVersion =
    target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "");
  if (targetQtVersion != nullptr) {
    qtMajor = targetQtVersion;
  }
  return qtMajor;
}

std::string cmQtAutoGenInitializer::GetQtMinorVersion(
  cmGeneratorTarget const* target, std::string const& qtVersionMajor)
{
  cmMakefile* makefile = target->Target->GetMakefile();
  std::string qtMinor;
  if (qtVersionMajor == "5") {
    qtMinor = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR");
  }
  if (qtMinor.empty()) {
    qtMinor = makefile->GetSafeDefinition("QT_VERSION_MINOR");
  }

  const char* targetQtVersion =
    target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", "");
  if (targetQtVersion != nullptr) {
    qtMinor = targetQtVersion;
  }
  return qtMinor;
}

bool cmQtAutoGenInitializer::QtVersionGreaterOrEqual(
  unsigned long requestMajor, unsigned long requestMinor) const
{
  unsigned long majorUL(0);
  unsigned long minorUL(0);
  if (cmSystemTools::StringToULong(this->QtVersionMajor.c_str(), &majorUL) &&
      cmSystemTools::StringToULong(this->QtVersionMinor.c_str(), &minorUL)) {
    return (majorUL > requestMajor) ||
      (majorUL == requestMajor && minorUL >= requestMinor);
  }
  return false;
}

bool cmQtAutoGenInitializer::GetMocExecutable()
{
  std::string err;

  // Find moc executable
  {
    std::string targetName;
    if (this->QtVersionMajor == "5") {
      targetName = "Qt5::moc";
    } else if (QtVersionMajor == "4") {
      targetName = "Qt4::moc";
    } else {
      err = "The AUTOMOC feature supports only Qt 4 and Qt 5";
    }
    if (!targetName.empty()) {
      cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse(targetName);
      if (tgt != nullptr) {
        this->Moc.Executable = tgt->ImportedGetLocation("");
      } else {
        err = "Could not find target " + targetName;
      }
    }
  }

  // Test moc command
  if (err.empty()) {
    if (cmSystemTools::FileExists(this->Moc.Executable, true)) {
      std::vector<std::string> command;
      command.push_back(this->Moc.Executable);
      command.push_back("-h");
      std::string stdOut;
      std::string stdErr;
      int retVal = 0;
      bool result = cmSystemTools::RunSingleCommand(
        command, &stdOut, &stdErr, &retVal, nullptr,
        cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);
      if (!result) {
        err = "The moc test command failed: ";
        err += QuotedCommand(command);
      }
    } else {
      err = "The moc executable ";
      err += Quoted(this->Moc.Executable);
      err += " does not exist";
    }
  }

  // Print error
  if (!err.empty()) {
    std::string msg = "AutoMoc (";
    msg += this->Target->GetName();
    msg += "): ";
    msg += err;
    cmSystemTools::Error(msg.c_str());
    return false;
  }

  return true;
}

bool cmQtAutoGenInitializer::GetUicExecutable()
{
  std::string err;

  // Find uic executable
  {
    std::string targetName;
    if (this->QtVersionMajor == "5") {
      targetName = "Qt5::uic";
    } else if (QtVersionMajor == "4") {
      targetName = "Qt4::uic";
    } else {
      err = "The AUTOUIC feature supports only Qt 4 and Qt 5";
    }
    if (!targetName.empty()) {
      cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse(targetName);
      if (tgt != nullptr) {
        this->Uic.Executable = tgt->ImportedGetLocation("");
      } else {
        if (this->QtVersionMajor == "5") {
          // Project does not use Qt5Widgets, but has AUTOUIC ON anyway
        } else {
          err = "Could not find target " + targetName;
        }
      }
    }
  }

  // Test uic command
  if (err.empty()) {
    if (cmSystemTools::FileExists(this->Uic.Executable, true)) {
      std::vector<std::string> command;
      command.push_back(this->Uic.Executable);
      command.push_back("-h");
      std::string stdOut;
      std::string stdErr;
      int retVal = 0;
      bool result = cmSystemTools::RunSingleCommand(
        command, &stdOut, &stdErr, &retVal, nullptr,
        cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);
      if (!result) {
        err = "The uic test command failed: ";
        err += QuotedCommand(command);
      }
    } else {
      err = "The uic executable ";
      err += Quoted(this->Uic.Executable);
      err += " does not exist";
    }
  }

  // Print error
  if (!err.empty()) {
    std::string msg = "AutoUic (";
    msg += this->Target->GetName();
    msg += "): ";
    msg += err;
    cmSystemTools::Error(msg.c_str());
    return false;
  }

  return true;
}

bool cmQtAutoGenInitializer::GetRccExecutable()
{
  std::string err;

  // Find rcc executable
  {
    std::string targetName;
    if (this->QtVersionMajor == "5") {
      targetName = "Qt5::rcc";
    } else if (QtVersionMajor == "4") {
      targetName = "Qt4::rcc";
    } else {
      err = "The AUTORCC feature supports only Qt 4 and Qt 5";
    }
    if (!targetName.empty()) {
      cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse(targetName);
      if (tgt != nullptr) {
        this->Rcc.Executable = tgt->ImportedGetLocation("");
      } else {
        err = "Could not find target " + targetName;
      }
    }
  }

  // Test rcc command
  if (err.empty()) {
    if (cmSystemTools::FileExists(this->Rcc.Executable, true)) {
      std::vector<std::string> command;
      command.push_back(this->Rcc.Executable);
      command.push_back("-h");
      std::string stdOut;
      std::string stdErr;
      int retVal = 0;
      bool result = cmSystemTools::RunSingleCommand(
        command, &stdOut, &stdErr, &retVal, nullptr,
        cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);
      if (result) {
        // Detect if rcc supports (-)-list
        if (this->QtVersionMajor == "5") {
          if (stdOut.find("--list") != std::string::npos) {
            this->Rcc.ListOptions.push_back("--list");
          } else {
            this->Rcc.ListOptions.push_back("-list");
          }
        }
      } else {
        err = "The rcc test command failed: ";
        err += QuotedCommand(command);
      }
    } else {
      err = "The rcc executable ";
      err += Quoted(this->Rcc.Executable);
      err += " does not exist";
    }
  }

  // Print error
  if (!err.empty()) {
    std::string msg = "AutoRcc (";
    msg += this->Target->GetName();
    msg += "): ";
    msg += err;
    cmSystemTools::Error(msg.c_str());
    return false;
  }

  return true;
}

/// @brief Reads the resource files list from from a .qrc file
/// @arg fileName Must be the absolute path of the .qrc file
/// @return True if the rcc file was successfully read
bool cmQtAutoGenInitializer::RccListInputs(std::string const& fileName,
                                           std::vector<std::string>& files,
                                           std::string& error)
{
  if (!cmSystemTools::FileExists(fileName)) {
    error = "rcc resource file does not exist:\n  ";
    error += Quoted(fileName);
    error += "\n";
    return false;
  }
  if (!this->Rcc.ListOptions.empty()) {
    // Use rcc for file listing
    if (this->Rcc.Executable.empty()) {
      error = "rcc executable not available";
      return false;
    }

    // Run rcc list command in the directory of the qrc file with the
    // pathless
    // qrc file name argument. This way rcc prints relative paths.
    // This avoids issues on Windows when the qrc file is in a path that
    // contains non-ASCII characters.
    std::string const fileDir = cmSystemTools::GetFilenamePath(fileName);
    std::string const fileNameName = cmSystemTools::GetFilenameName(fileName);

    bool result = false;
    int retVal = 0;
    std::string rccStdOut;
    std::string rccStdErr;
    {
      std::vector<std::string> cmd;
      cmd.push_back(this->Rcc.Executable);
      cmd.insert(cmd.end(), this->Rcc.ListOptions.begin(),
                 this->Rcc.ListOptions.end());
      cmd.push_back(fileNameName);
      result = cmSystemTools::RunSingleCommand(
        cmd, &rccStdOut, &rccStdErr, &retVal, fileDir.c_str(),
        cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);
    }
    if (!result || retVal) {
      error = "rcc list process failed for:\n  ";
      error += Quoted(fileName);
      error += "\n";
      error += rccStdOut;
      error += "\n";
      error += rccStdErr;
      error += "\n";
      return false;
    }
    if (!RccListParseOutput(rccStdOut, rccStdErr, files, error)) {
      return false;
    }
  } else {
    // We can't use rcc for the file listing.
    // Read the qrc file content into string and parse it.
    {
      std::string qrcContents;
      {
        cmsys::ifstream ifs(fileName.c_str());
        if (ifs) {
          std::ostringstream osst;
          osst << ifs.rdbuf();
          qrcContents = osst.str();
        } else {
          error = "rcc file not readable:\n  ";
          error += Quoted(fileName);
          error += "\n";
          return false;
        }
      }
      // Parse string content
      RccListParseContent(qrcContents, files);
    }
  }

  // Convert relative paths to absolute paths
  RccListConvertFullPath(cmSystemTools::GetFilenamePath(fileName), files);
  return true;
}
