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

#include "cmAlgorithms.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
#include "cmFilePathChecksum.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 "cm_sys_stat.h"
#include "cmake.h"
#include "cmsys/FStream.hxx"

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

inline static const char* SafeString(const char* value)
{
  return (value != nullptr) ? value : "";
}

inline static std::string GetSafeProperty(cmGeneratorTarget const* target,
                                          const char* key)
{
  return std::string(SafeString(target->GetProperty(key)));
}

inline static std::string GetSafeProperty(cmSourceFile const* sf,
                                          const char* key)
{
  return std::string(SafeString(sf->GetProperty(key)));
}

static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
                                 std::string const& value)
{
  makefile->AddDefinition(key,
                          cmOutputConverter::EscapeForCMake(value).c_str());
}

static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
                                 const std::vector<std::string>& values)
{
  makefile->AddDefinition(
    key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str());
}

static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
                                 const std::set<std::string>& values)
{
  makefile->AddDefinition(
    key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str());
}

static void AddDefinitionEscaped(
  cmMakefile* makefile, const char* key,
  const std::vector<std::vector<std::string>>& 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));
  }
  makefile->AddDefinition(key, cmOutputConverter::EscapeForCMake(
                                 cmJoin(seplist, cmQtAutoGen::listSep))
                                 .c_str());
}

static bool AddToSourceGroup(cmMakefile* makefile, std::string const& fileName,
                             cmQtAutoGen::Generator 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::MOC:
          props[0] = "AUTOMOC_SOURCE_GROUP";
          break;
        case cmQtAutoGen::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.c_str());
    std::string pBinary = cmSystemTools::RelativePath(
      makefile->GetCurrentBinaryDirectory(), fileName.c_str());
    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;
}

cmQtAutoGeneratorInitializer::cmQtAutoGeneratorInitializer(
  cmGeneratorTarget* target, bool mocEnabled, bool uicEnabled, bool rccEnabled,
  std::string const& qtVersionMajor)
  : Target(target)
  , MocEnabled(mocEnabled)
  , UicEnabled(uicEnabled)
  , RccEnabled(rccEnabled)
  , QtVersionMajor(qtVersionMajor)
  , MultiConfig(cmQtAutoGen::WRAP)
{
  this->QtVersionMinor = cmQtAutoGeneratorInitializer::GetQtMinorVersion(
    target, this->QtVersionMajor);
}

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

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

  // Multi configuration
  {
    if (!globalGen->IsMultiConfig()) {
      this->MultiConfig = cmQtAutoGen::SINGLE;
    }

    // FIXME: Xcode does not support per-config sources, yet.
    //        (EXCLUDED_SOURCE_FILE_NAMES)
    // if (globalGen->GetName().find("Xcode") != std::string::npos) {
    //  return cmQtAutoGen::FULL;
    //}

    // FIXME: Visual Studio does not support per-config sources, yet.
    //        (EXCLUDED_SOURCE_FILE_NAMES)
    // if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
    //  return cmQtAutoGen::FULL;
    //}
  }

  // 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 = GetSafeProperty(this->Target, "AUTOGEN_BUILD_DIR");
    if (this->DirBuild.empty()) {
      this->DirBuild = cbd;
      this->DirBuild += "/";
      this->DirBuild += this->AutogenTargetName;
    }
    cmSystemTools::ConvertToUnixSlashes(this->DirBuild);

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

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

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

  // 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 = SafeString(this->Target->Target->GetProperty("FOLDER"));
    }
    if (folder != nullptr) {
      this->AutogenFolder = folder;
    }
  }

  std::set<std::string> autogenDependFiles;
  std::set<cmTarget*> autogenDependTargets;
  std::vector<std::string> autogenProvides;

  // Remove build directories on cleanup
  AddCleanFile(makefile, this->DirBuild);
  // Remove old settings on cleanup
  {
    std::string base = this->DirInfo;
    base += "/AutogenOldSettings";
    if (this->MultiConfig == cmQtAutoGen::SINGLE) {
      AddCleanFile(makefile, base.append(".cmake"));
    } else {
      for (std::string const& cfg : this->ConfigsList) {
        std::string filename = base;
        filename += "_";
        filename += cfg;
        filename += ".cmake";
        AddCleanFile(makefile, filename);
      }
    }
  }

  // Add moc compilation to generated files list
  if (this->MocEnabled) {
    std::string const mocsComp = this->DirBuild + "/mocs_compilation.cpp";
    auto files = this->AddGeneratedSource(mocsComp, cmQtAutoGen::MOC);
    for (std::string& file : files) {
      autogenProvides.push_back(std::move(file));
    }
  }

  // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES
  if (this->MocEnabled || this->UicEnabled) {
    std::string includeDir = this->DirBuild + "/include";
    if (this->MultiConfig != cmQtAutoGen::SINGLE) {
      includeDir += "_$<CONFIG>";
    }
    this->Target->AddIncludeDirectory(includeDir, true);
  }

  // Acquire rcc executable and features
  if (this->RccEnabled) {
    {
      std::string err;
      if (this->QtVersionMajor == "5") {
        cmGeneratorTarget* tgt =
          localGen->FindGeneratorTargetToUse("Qt5::rcc");
        if (tgt != nullptr) {
          this->RccExecutable = SafeString(tgt->ImportedGetLocation(""));
        } else {
          err = "AUTORCC: Qt5::rcc target not found";
        }
      } else if (QtVersionMajor == "4") {
        cmGeneratorTarget* tgt =
          localGen->FindGeneratorTargetToUse("Qt4::rcc");
        if (tgt != nullptr) {
          this->RccExecutable = SafeString(tgt->ImportedGetLocation(""));
        } else {
          err = "AUTORCC: Qt4::rcc target not found";
        }
      } else {
        err = "The AUTORCC feature supports only Qt 4 and Qt 5";
      }
      if (!err.empty()) {
        err += " (";
        err += this->Target->GetName();
        err += ")";
        cmSystemTools::Error(err.c_str());
      }
    }
    // Detect if rcc supports (-)-list
    if (!this->RccExecutable.empty() && (this->QtVersionMajor == "5")) {
      std::vector<std::string> command;
      command.push_back(this->RccExecutable);
      command.push_back("--help");
      std::string rccStdOut;
      std::string rccStdErr;
      int retVal = 0;
      bool result = cmSystemTools::RunSingleCommand(
        command, &rccStdOut, &rccStdErr, &retVal, nullptr,
        cmSystemTools::OUTPUT_NONE, 0.0, cmProcessOutput::Auto);
      if (result && retVal == 0 &&
          rccStdOut.find("--list") != std::string::npos) {
        this->RccListOptions.push_back("--list");
      } else {
        this->RccListOptions.push_back("-list");
      }
    }
  }

  // Extract relevant source files
  std::vector<std::string> generatedSources;
  std::vector<std::string> generatedHeaders;
  {
    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->MocEnabled || this->UicEnabled) {
        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->MocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) ||
              (this->UicEnabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) {
            // Register source
            const bool generated = sf->GetPropertyAsBool("GENERATED");
            if (fileType == cmSystemTools::HEADER_FILE_FORMAT) {
              if (generated) {
                generatedHeaders.push_back(absPath);
              } else {
                this->Headers.push_back(absPath);
              }
            } else {
              if (generated) {
                generatedSources.push_back(absPath);
              } else {
                this->Sources.push_back(absPath);
              }
            }
          }
        }
      }
      // Register rcc enabled files
      if (this->RccEnabled && (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 = GetSafeProperty(sf, "AUTORCC_OPTIONS");
            if (!opts.empty()) {
              cmSystemTools::ExpandListArgument(opts, qrc.Options);
            }
          }
          this->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();
  }
  // Read skip files from makefile sources
  if (this->MocEnabled || this->UicEnabled) {
    const std::vector<cmSourceFile*>& allSources = makefile->GetSourceFiles();
    for (cmSourceFile* sf : allSources) {
      // sf->GetExtension() is only valid after sf->GetFullPath() ...
      std::string const& fPath = sf->GetFullPath();
      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->MocEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC"));
      const bool uicSkip =
        this->UicEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC"));
      if (mocSkip || uicSkip) {
        std::string const absFile = cmSystemTools::GetRealPath(fPath);
        if (mocSkip) {
          this->MocSkip.insert(absFile);
        }
        if (uicSkip) {
          this->UicSkip.insert(absFile);
        }
      }
    }
  }

  // Process GENERATED sources and headers
  if (!generatedSources.empty() || !generatedHeaders.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 : generatedHeaders) {
        this->Headers.push_back(absFile);
        autogenDependFiles.insert(absFile);
      }
      for (std::string const& absFile : generatedSources) {
        this->Sources.push_back(absFile);
        autogenDependFiles.insert(absFile);
      }
    } else {
      if (policyWarn) {
        std::string msg;
        msg += cmPolicies::GetPolicyWarning(cmPolicies::CMP0071);
        msg += "\n";
        std::string tools;
        std::string property;
        if (this->MocEnabled && this->UicEnabled) {
          tools = "AUTOMOC and AUTOUIC";
          property = "SKIP_AUTOGEN";
        } else if (this->MocEnabled) {
          tools = "AUTOMOC";
          property = "SKIP_AUTOMOC";
        } else if (this->UicEnabled) {
          tools = "AUTOUIC";
          property = "SKIP_AUTOUIC";
        }
        msg += "For compatibility, CMake is excluding the GENERATED source "
               "file(s):\n";
        for (const std::string& absFile : generatedHeaders) {
          msg.append("  ").append(cmQtAutoGen::Quoted(absFile)).append("\n");
        }
        for (const std::string& absFile : generatedSources) {
          msg.append("  ").append(cmQtAutoGen::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);
      }
    }
    // Clear lists
    generatedSources.clear();
    generatedHeaders.clear();
  }
  // Sort headers and sources
  if (this->MocEnabled || this->UicEnabled) {
    std::sort(this->Headers.begin(), this->Headers.end());
    std::sort(this->Sources.begin(), this->Sources.end());
  }

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

    // Check if file name is unique
    for (Qrc& qrc : this->Qrcs) {
      qrc.Unique = true;
      for (Qrc const& qrc2 : this->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->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.InfoFile = base;
          qrc.InfoFile += "Info.cmake";
          qrc.SettingsFile = base;
          qrc.SettingsFile += "Settings.cmake";
        }
      }
    }
    // RCC options
    for (Qrc& qrc : this->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));
        cmQtAutoGen::RccMergeOptions(opts, nameOpts, QtV5);
      }
      // Merge file option
      cmQtAutoGen::RccMergeOptions(opts, qrc.Options, QtV5);
      qrc.Options = std::move(opts);
    }
    for (Qrc& qrc : this->Qrcs) {
      // Register file at target
      std::vector<std::string> const ccOutput =
        this->AddGeneratedSource(qrc.RccFile, cmQtAutoGen::RCC);

      cmCustomCommandLines commandLines;
      {
        cmCustomCommandLine currentLine;
        currentLine.push_back(cmSystemTools::GetCMakeCommand());
        currentLine.push_back("-E");
        currentLine.push_back("cmake_autorcc");
        currentLine.push_back(qrc.InfoFile);
        currentLine.push_back("$<CONFIGURATION>");
        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 file to the custom target dependencies
          ccDepends.push_back(qrc.QrcFile);

          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 file to the custom command dependencies
          ccDepends.push_back(qrc.QrcFile);

          // Add the resource files to the dependencies
          {
            std::string error;
            if (cmQtAutoGen::RccListInputs(this->RccExecutable,
                                           this->RccListOptions, qrc.QrcFile,
                                           qrc.Resources, &error)) {
              for (std::string const& fileName : qrc.Resources) {
                // Add resource file to the custom command dependencies
                ccDepends.push_back(fileName);
              }
            } else {
              cmSystemTools::Error(error.c_str());
            }
          }
          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);
      }
    }
  }

  // Create _autogen target
  if (this->MocEnabled || this->UicEnabled) {
    // Add user defined autogen target dependencies
    {
      std::string const deps =
        GetSafeProperty(this->Target, "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) {
            autogenDependTargets.insert(depTarget);
          } else {
            autogenDependFiles.insert(depName);
          }
        }
      }
    }

    // Compose target comment
    std::string autogenComment;
    {
      std::string tools;
      if (this->MocEnabled) {
        tools += "MOC";
      }
      if (this->UicEnabled) {
        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 (!autogenDependFiles.empty()) {
        usePRE_BUILD = false;
      }
    }
    // Create the autogen target/command
    if (usePRE_BUILD) {
      // Add additional autogen target dependencies to origin target
      for (cmTarget* depTarget : 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()) {
            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>(autogenDependFiles.begin(),
                                 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 : 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);
    }
  }
}

void cmQtAutoGeneratorInitializer::SetupCustomTargets()
{
  cmMakefile* makefile = this->Target->Target->GetMakefile();

  // forget the variables added here afterwards again:
  cmMakefile::ScopePushPop varScope(makefile);
  static_cast<void>(varScope);

  // Configuration suffixes
  std::map<std::string, std::string> configSuffixes;
  for (std::string const& cfg : this->ConfigsList) {
    std::string& suffix = configSuffixes[cfg];
    suffix = "_";
    suffix += cfg;
  }

  // Basic setup
  AddDefinitionEscaped(makefile, "_multi_config",
                       cmQtAutoGen::MultiConfigName(this->MultiConfig));
  AddDefinitionEscaped(makefile, "_build_dir", this->DirBuild);

  if (this->MocEnabled || this->UicEnabled) {
    AddDefinitionEscaped(makefile, "_qt_version_major", this->QtVersionMajor);
    AddDefinitionEscaped(makefile, "_settings_file",
                         this->AutogenSettingsFile);
    AddDefinitionEscaped(makefile, "_sources", this->Sources);
    AddDefinitionEscaped(makefile, "_headers", this->Headers);

    if (this->MocEnabled) {
      this->SetupCustomTargetsMoc();
    }
    if (this->UicEnabled) {
      this->SetupCustomTargetsUic();
    }
  }
  if (this->RccEnabled) {
    AddDefinitionEscaped(makefile, "_qt_rcc_executable", this->RccExecutable);
    AddDefinitionEscaped(makefile, "_qt_rcc_list_options",
                         this->RccListOptions);
  }

  // Create info directory on demand
  if (!cmSystemTools::MakeDirectory(this->DirInfo)) {
    std::string emsg = ("Could not create directory: ");
    emsg += cmQtAutoGen::Quoted(this->DirInfo);
    cmSystemTools::Error(emsg.c_str());
  }

  auto ReOpenInfoFile = [](cmsys::ofstream& ofs,
                           std::string const& fileName) -> bool {
    // Ensure we have write permission
    mode_t perm = 0;
#if defined(_WIN32) && !defined(__CYGWIN__)
    mode_t mode_write = S_IWRITE;
#else
    mode_t mode_write = S_IWUSR;
#endif
    cmSystemTools::GetPermissions(fileName, perm);
    if (!(perm & mode_write)) {
      cmSystemTools::SetPermissions(fileName, perm | mode_write);
    }

    ofs.open(fileName.c_str(), std::ios::app);
    if (!ofs) {
      // File open error
      std::string error = "Internal CMake error when trying to open file: ";
      error += cmQtAutoGen::Quoted(fileName);
      error += " for writing.";
      cmSystemTools::Error(error.c_str());
    }
    return static_cast<bool>(ofs);
  };

  // Generate autogen target info file
  if (this->MocEnabled || this->UicEnabled) {
    {
      std::string infoFileIn = cmSystemTools::GetCMakeRoot();
      infoFileIn += "/Modules/AutogenInfo.cmake.in";
      makefile->ConfigureFile(
        infoFileIn.c_str(), this->AutogenInfoFile.c_str(), false, true, false);
    }

    // Append custom definitions to info file
    // --------------------------------------
    cmsys::ofstream ofs;
    if (ReOpenInfoFile(ofs, this->AutogenInfoFile)) {
      auto OfsWriteMap = [&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";
        }
      };
      ofs << "# Configurations options\n";
      OfsWriteMap("AM_CONFIG_SUFFIX", configSuffixes);
      OfsWriteMap("AM_MOC_DEFINITIONS", this->ConfigMocDefines);
      OfsWriteMap("AM_MOC_INCLUDES", this->ConfigMocIncludes);
      OfsWriteMap("AM_UIC_TARGET_OPTIONS", this->ConfigUicOptions);
      // Settings files (only require for multi configuration generators)
      if (this->MultiConfig != cmQtAutoGen::SINGLE) {
        std::map<std::string, std::string> settingsFiles;
        for (std::string const& cfg : this->ConfigsList) {
          settingsFiles[cfg] = cmQtAutoGen::AppendFilenameSuffix(
            this->AutogenSettingsFile, "_" + cfg);
        }
        OfsWriteMap("AM_SETTINGS_FILE", settingsFiles);
      }
    }
  }

  // Generate auto RCC info files
  if (this->RccEnabled) {
    std::string infoFileIn = cmSystemTools::GetCMakeRoot();
    infoFileIn += "/Modules/AutoRccInfo.cmake.in";
    for (Qrc const& qrc : this->Qrcs) {
      // Configure info file
      makefile->ConfigureFile(infoFileIn.c_str(), qrc.InfoFile.c_str(), false,
                              true, false);

      // Append custom definitions to info file
      // --------------------------------------
      cmsys::ofstream ofs;
      if (ReOpenInfoFile(ofs, qrc.InfoFile)) {
        {
          ofs << "# Job\n";
          auto OfsWrite = [&ofs](const char* key, std::string const& value) {
            ofs << "set(" << key << " "
                << cmOutputConverter::EscapeForCMake(value) << ")\n";

          };
          OfsWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile);
          OfsWrite("ARCC_SOURCE", qrc.QrcFile);
          OfsWrite("ARCC_OUTPUT", qrc.RccFile);
          OfsWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";"));
          OfsWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";"));
        }
        {
          ofs << "# Configurations options\n";
          auto OfsWriteMap = [&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";
            }
          };
          OfsWriteMap("ARCC_CONFIG_SUFFIX", configSuffixes);

          // Settings files (only require for multi configuration generators)
          if (this->MultiConfig != cmQtAutoGen::SINGLE) {
            std::map<std::string, std::string> settingsFiles;
            for (std::string const& cfg : this->ConfigsList) {
              settingsFiles[cfg] =
                cmQtAutoGen::AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg);
            }
            OfsWriteMap("ARCC_SETTINGS_FILE", settingsFiles);
          }
        }
      } else {
        break;
      }
    }
  }
}

void cmQtAutoGeneratorInitializer::SetupCustomTargetsMoc()
{
  cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
  cmMakefile* makefile = this->Target->Target->GetMakefile();

  AddDefinitionEscaped(makefile, "_moc_skip", this->MocSkip);
  AddDefinitionEscaped(makefile, "_moc_options",
                       GetSafeProperty(this->Target, "AUTOMOC_MOC_OPTIONS"));
  AddDefinitionEscaped(makefile, "_moc_relaxed_mode",
                       makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE"
                                                                    : "FALSE");
  AddDefinitionEscaped(makefile, "_moc_macro_names",
                       GetSafeProperty(this->Target, "AUTOMOC_MACRO_NAMES"));
  AddDefinitionEscaped(
    makefile, "_moc_depend_filters",
    GetSafeProperty(this->Target, "AUTOMOC_DEPEND_FILTERS"));

  // Compiler predefines
  if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") &&
      this->QtVersionGreaterOrEqual(5, 8)) {
    AddDefinitionEscaped(
      makefile, "_moc_predefs_cmd",
      makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"));
  }
  // Moc includes and compile definitions
  {
    auto GetIncludeDirs = [this,
                           localGen](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> includeDirs;
      localGen->GetIncludeDirectories(includeDirs, this->Target, "CXX", cfg,
                                      false);
      return cmJoin(includeDirs, ";");
    };
    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 settings
    std::string const includeDirs = GetIncludeDirs(this->ConfigDefault);
    std::string const compileDefs = GetCompileDefinitions(this->ConfigDefault);
    // Other configuration settings
    for (std::string const& cfg : this->ConfigsList) {
      {
        std::string const configIncludeDirs = GetIncludeDirs(cfg);
        if (configIncludeDirs != includeDirs) {
          this->ConfigMocIncludes[cfg] = configIncludeDirs;
        }
      }
      {
        std::string const configCompileDefs = GetCompileDefinitions(cfg);
        if (configCompileDefs != compileDefs) {
          this->ConfigMocDefines[cfg] = configCompileDefs;
        }
      }
    }
    AddDefinitionEscaped(makefile, "_moc_include_dirs", includeDirs);
    AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs);
  }

  // Moc executable
  {
    std::string mocExec;
    std::string err;

    if (this->QtVersionMajor == "5") {
      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::moc");
      if (tgt != nullptr) {
        mocExec = SafeString(tgt->ImportedGetLocation(""));
      } else {
        err = "AUTOMOC: Qt5::moc target not found";
      }
    } else if (this->QtVersionMajor == "4") {
      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::moc");
      if (tgt != nullptr) {
        mocExec = SafeString(tgt->ImportedGetLocation(""));
      } else {
        err = "AUTOMOC: Qt4::moc target not found";
      }
    } else {
      err = "The AUTOMOC feature supports only Qt 4 and Qt 5";
    }

    if (err.empty()) {
      AddDefinitionEscaped(makefile, "_qt_moc_executable", mocExec);
    } else {
      err += " (";
      err += this->Target->GetName();
      err += ")";
      cmSystemTools::Error(err.c_str());
    }
  }
}

void cmQtAutoGeneratorInitializer::SetupCustomTargetsUic()
{
  cmMakefile* makefile = this->Target->Target->GetMakefile();

  // Uic search paths
  {
    std::vector<std::string> uicSearchPaths;
    {
      std::string const usp =
        GetSafeProperty(this->Target, "AUTOUIC_SEARCH_PATHS");
      if (!usp.empty()) {
        cmSystemTools::ExpandListArgument(usp, uicSearchPaths);
        std::string const srcDir = makefile->GetCurrentSourceDirectory();
        for (std::string& path : uicSearchPaths) {
          path = cmSystemTools::CollapseFullPath(path, srcDir);
        }
      }
    }
    AddDefinitionEscaped(makefile, "_uic_search_paths", uicSearchPaths);
  }
  // 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
    std::string const uicOpts = UicGetOpts(this->ConfigDefault);
    AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts);

    // Configuration specific settings
    for (std::string const& cfg : this->ConfigsList) {
      std::string const configUicOpts = UicGetOpts(cfg);
      if (configUicOpts != uicOpts) {
        this->ConfigUicOptions[cfg] = configUicOpts;
      }
    }
  }
  // .ui files skip and options
  {
    std::vector<std::string> uiFileFiles;
    std::vector<std::vector<std::string>> uiFileOptions;
    {
      std::string const uiExt = "ui";
      for (cmSourceFile* sf : makefile->GetSourceFiles()) {
        // sf->GetExtension() is only valid after sf->GetFullPath() ...
        std::string const& fPath = sf->GetFullPath();
        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->UicSkip.insert(absFile);
          }
          // Check if the .ui file has uic options
          std::string const uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS");
          if (!uicOpts.empty()) {
            // Check if file isn't skipped
            if (this->UicSkip.count(absFile) == 0) {
              uiFileFiles.push_back(absFile);
              std::vector<std::string> optsVec;
              cmSystemTools::ExpandListArgument(uicOpts, optsVec);
              uiFileOptions.push_back(std::move(optsVec));
            }
          }
        }
      }
    }
    AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles);
    AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions);
  }

  AddDefinitionEscaped(makefile, "_uic_skip", this->UicSkip);

  // Uic executable
  {
    std::string err;
    std::string uicExec;

    cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
    if (this->QtVersionMajor == "5") {
      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::uic");
      if (tgt != nullptr) {
        uicExec = SafeString(tgt->ImportedGetLocation(""));
      } else {
        // Project does not use Qt5Widgets, but has AUTOUIC ON anyway
      }
    } else if (this->QtVersionMajor == "4") {
      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::uic");
      if (tgt != nullptr) {
        uicExec = SafeString(tgt->ImportedGetLocation(""));
      } else {
        err = "AUTOUIC: Qt4::uic target not found";
      }
    } else {
      err = "The AUTOUIC feature supports only Qt 4 and Qt 5";
    }

    if (err.empty()) {
      AddDefinitionEscaped(makefile, "_qt_uic_executable", uicExec);
    } else {
      err += " (";
      err += this->Target->GetName();
      err += ")";
      cmSystemTools::Error(err.c_str());
    }
  }
}

std::vector<std::string> cmQtAutoGeneratorInitializer::AddGeneratedSource(
  std::string const& filename, cmQtAutoGen::Generator genType)
{
  std::vector<std::string> genFiles;
  // Register source file in makefile and source group
  if (this->MultiConfig != cmQtAutoGen::FULL) {
    genFiles.push_back(filename);
  } else {
    for (std::string const& cfg : this->ConfigsList) {
      genFiles.push_back(
        cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg));
    }
  }
  {
    cmMakefile* makefile = this->Target->Target->GetMakefile();
    for (std::string const& genFile : genFiles) {
      {
        cmSourceFile* gFile = makefile->GetOrCreateSource(genFile, true);
        gFile->SetProperty("GENERATED", "1");
        gFile->SetProperty("SKIP_AUTOGEN", "On");
      }
      AddToSourceGroup(makefile, genFile, genType);
    }
  }

  // Add source file to target
  if (this->MultiConfig != cmQtAutoGen::FULL) {
    this->Target->AddSource(filename);
  } else {
    for (std::string const& cfg : this->ConfigsList) {
      std::string src = "$<$<CONFIG:";
      src += cfg;
      src += ">:";
      src += cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg);
      src += ">";
      this->Target->AddSource(src);
    }
  }

  return genFiles;
}

std::string cmQtAutoGeneratorInitializer::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 cmQtAutoGeneratorInitializer::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 cmQtAutoGeneratorInitializer::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;
}
