/* 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 "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmSourceFile.h"
#include "cmSourceGroup.h"
#include "cmState.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cm_sys_stat.h"
#include "cmake.h"
#include "cmsys/FStream.hxx"

#include <algorithm>
#include <array>
#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)));
}

inline static bool AutogenMultiConfig(cmGlobalGenerator* globalGen)
{
  return globalGen->IsMultiConfig();
}

static std::string GetAutogenTargetName(cmGeneratorTarget const* target)
{
  std::string autogenTargetName = target->GetName();
  autogenTargetName += "_autogen";
  return autogenTargetName;
}

static std::string GetAutogenTargetFilesDir(cmGeneratorTarget const* target)
{
  cmMakefile* makefile = target->Target->GetMakefile();
  std::string targetDir = makefile->GetCurrentBinaryDirectory();
  targetDir += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();
  targetDir += "/";
  targetDir += GetAutogenTargetName(target);
  targetDir += ".dir";
  return targetDir;
}

static std::string GetAutogenTargetBuildDir(cmGeneratorTarget const* target)
{
  std::string targetDir = GetSafeProperty(target, "AUTOGEN_BUILD_DIR");
  if (targetDir.empty()) {
    cmMakefile* makefile = target->Target->GetMakefile();
    targetDir = makefile->GetCurrentBinaryDirectory();
    targetDir += "/";
    targetDir += GetAutogenTargetName(target);
  }
  return targetDir;
}

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, const std::string& 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;
}

static bool QtVersionGreaterOrEqual(const std::string& major,
                                    const std::string& minor,
                                    unsigned long requestMajor,
                                    unsigned long requestMinor)
{
  unsigned long majorUL(0);
  unsigned long minorUL(0);
  if (cmSystemTools::StringToULong(major.c_str(), &majorUL) &&
      cmSystemTools::StringToULong(minor.c_str(), &minorUL)) {
    return (majorUL > requestMajor) ||
      (majorUL == requestMajor && minorUL >= requestMinor);
  }
  return false;
}

static std::vector<std::string> GetConfigurations(
  cmMakefile* makefile, std::string* config = nullptr)
{
  std::vector<std::string> configs;
  {
    std::string cfg = makefile->GetConfigurations(configs);
    if (config != nullptr) {
      *config = cfg;
    }
  }
  // Add empty configuration on demand
  if (configs.empty()) {
    configs.push_back("");
  }
  return configs;
}

static std::vector<std::string> GetConfigurationSuffixes(cmMakefile* makefile)
{
  std::vector<std::string> suffixes;
  if (AutogenMultiConfig(makefile->GetGlobalGenerator())) {
    makefile->GetConfigurations(suffixes);
    for (std::string& suffix : suffixes) {
      suffix.insert(0, "_");
    }
  }
  if (suffixes.empty()) {
    suffixes.push_back("");
  }
  return suffixes;
}

static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
                                 const std::string& 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, const std::string& fileName,
                             cmQtAutoGen::GeneratorType 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, const std::string& fileName)
{
  makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", fileName.c_str(),
                           false);
}

static void AddGeneratedSource(cmGeneratorTarget* target,
                               const std::string& filename,
                               cmQtAutoGen::GeneratorType genType)
{
  cmMakefile* makefile = target->Target->GetMakefile();
  {
    cmSourceFile* gFile = makefile->GetOrCreateSource(filename, true);
    gFile->SetProperty("GENERATED", "1");
    gFile->SetProperty("SKIP_AUTOGEN", "On");
  }
  target->AddSource(filename);

  AddToSourceGroup(makefile, filename, genType);
}

struct cmQtAutoGenSetup
{
  std::set<std::string> MocSkip;
  std::set<std::string> UicSkip;

  std::map<std::string, std::string> ConfigMocIncludes;
  std::map<std::string, std::string> ConfigMocDefines;
  std::map<std::string, std::string> ConfigUicOptions;
};

static void SetupAcquireSkipFiles(cmQtAutoGenDigest const& digest,
                                  cmQtAutoGenSetup& setup)
{
  // Read skip files from makefile sources
  {
    const std::vector<cmSourceFile*>& allSources =
      digest.Target->Makefile->GetSourceFiles();
    for (cmSourceFile* sf : allSources) {
      // sf->GetExtension() is only valid after sf->GetFullPath() ...
      const std::string& fPath = sf->GetFullPath();
      const cmSystemTools::FileFormat 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 = digest.MocEnabled &&
        (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC"));
      const bool uicSkip = digest.UicEnabled &&
        (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC"));
      if (mocSkip || uicSkip) {
        const std::string absFile = cmSystemTools::GetRealPath(fPath);
        if (mocSkip) {
          setup.MocSkip.insert(absFile);
        }
        if (uicSkip) {
          setup.UicSkip.insert(absFile);
        }
      }
    }
  }
}

static void SetupAutoTargetMoc(const cmQtAutoGenDigest& digest,
                               std::string const& config,
                               std::vector<std::string> const& configs,
                               cmQtAutoGenSetup& setup)
{
  cmGeneratorTarget const* target = digest.Target;
  cmLocalGenerator* localGen = target->GetLocalGenerator();
  cmMakefile* makefile = target->Target->GetMakefile();

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

  if (QtVersionGreaterOrEqual(digest.QtVersionMajor, digest.QtVersionMinor, 5,
                              8)) {
    AddDefinitionEscaped(
      makefile, "_moc_predefs_cmd",
      makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"));
  }
  // Moc includes and compile definitions
  {
    auto GetCompileDefinitionsAndDirectories = [target, localGen](
      const std::string& cfg, std::string& incs, std::string& defs) {
      {
        std::vector<std::string> includeDirs;
        // Get the include dirs for this target, without stripping the implicit
        // include dirs off, see
        // https://gitlab.kitware.com/cmake/cmake/issues/13667
        localGen->GetIncludeDirectories(includeDirs, target, "CXX", cfg,
                                        false);
        incs = cmJoin(includeDirs, ";");
      }
      {
        std::set<std::string> defines;
        localGen->AddCompileDefinitions(defines, target, cfg, "CXX");
        defs += cmJoin(defines, ";");
      }
    };

    // Default settings
    std::string incs;
    std::string compileDefs;
    GetCompileDefinitionsAndDirectories(config, incs, compileDefs);
    AddDefinitionEscaped(makefile, "_moc_incs", incs);
    AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs);

    // Configuration specific settings
    for (std::string const& cfg : configs) {
      std::string configIncs;
      std::string configCompileDefs;
      GetCompileDefinitionsAndDirectories(cfg, configIncs, configCompileDefs);
      if (configIncs != incs) {
        setup.ConfigMocIncludes[cfg] = configIncs;
      }
      if (configCompileDefs != compileDefs) {
        setup.ConfigMocDefines[cfg] = configCompileDefs;
      }
    }
  }

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

    if (digest.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 (digest.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 += " (" + target->GetName() + ")";
      cmSystemTools::Error(err.c_str());
    }
  }
}

static void SetupAutoTargetUic(const cmQtAutoGenDigest& digest,
                               std::string const& config,
                               std::vector<std::string> const& configs,
                               cmQtAutoGenSetup& setup)
{
  cmGeneratorTarget const* target = digest.Target;
  cmMakefile* makefile = target->Target->GetMakefile();

  AddDefinitionEscaped(makefile, "_uic_skip", setup.UicSkip);

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

    // Default settings
    const std::string uicOpts = UicGetOpts(config);
    AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts);

    // Configuration specific settings
    for (std::string const& cfg : configs) {
      const std::string configUicOpts = UicGetOpts(cfg);
      if (configUicOpts != uicOpts) {
        setup.ConfigUicOptions[cfg] = configUicOpts;
      }
    }
  }
  // Uic files options
  {
    std::vector<std::string> uiFileFiles;
    std::vector<std::vector<std::string>> uiFileOptions;
    {
      const std::string uiExt = "ui";
      const std::vector<cmSourceFile*>& srcFiles = makefile->GetSourceFiles();
      for (cmSourceFile* sf : srcFiles) {
        // sf->GetExtension() is only valid after sf->GetFullPath() ...
        const std::string& fPath = sf->GetFullPath();
        if (sf->GetExtension() == uiExt) {
          // Check if the files has uic options
          const std::string uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS");
          if (!uicOpts.empty()) {
            const std::string absFile = cmSystemTools::GetRealPath(fPath);
            // Check if file isn't skipped
            if (setup.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);
  }

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

    cmLocalGenerator* localGen = target->GetLocalGenerator();
    if (digest.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 (digest.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 += " (" + target->GetName() + ")";
      cmSystemTools::Error(err.c_str());
    }
  }
}

static std::string RccGetExecutable(cmGeneratorTarget const* target,
                                    const std::string& qtMajorVersion)
{
  std::string rccExec;
  std::string err;

  cmLocalGenerator* localGen = target->GetLocalGenerator();
  if (qtMajorVersion == "5") {
    cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::rcc");
    if (tgt != nullptr) {
      rccExec = SafeString(tgt->ImportedGetLocation(""));
    } else {
      err = "AUTORCC: Qt5::rcc target not found";
    }
  } else if (qtMajorVersion == "4") {
    cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::rcc");
    if (tgt != nullptr) {
      rccExec = 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 += " (" + target->GetName() + ")";
    cmSystemTools::Error(err.c_str());
  }
  return rccExec;
}

static void SetupAutoTargetRcc(const cmQtAutoGenDigest& digest)
{
  std::vector<std::string> rccFiles;
  std::vector<std::string> rccBuilds;
  std::vector<std::vector<std::string>> rccOptions;
  std::vector<std::vector<std::string>> rccInputs;

  for (cmQtAutoGenDigestQrc const& qrcDigest : digest.Qrcs) {
    rccFiles.push_back(qrcDigest.QrcFile);
    rccBuilds.push_back(qrcDigest.RccFile);
    rccOptions.push_back(qrcDigest.Options);
    rccInputs.push_back(qrcDigest.Resources);
  }

  cmMakefile* makefile = digest.Target->Target->GetMakefile();
  AddDefinitionEscaped(makefile, "_qt_rcc_executable",
                       RccGetExecutable(digest.Target, digest.QtVersionMajor));
  AddDefinitionEscaped(makefile, "_rcc_files", rccFiles);
  AddDefinitionEscaped(makefile, "_rcc_builds", rccBuilds);
  AddDefinitionEscaped(makefile, "_rcc_options", rccOptions);
  AddDefinitionEscaped(makefile, "_rcc_inputs", rccInputs);
}

void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
  cmQtAutoGenDigest& digest)
{
  cmGeneratorTarget* target = digest.Target;
  cmMakefile* makefile = target->Target->GetMakefile();
  cmLocalGenerator* localGen = target->GetLocalGenerator();
  cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator();

  // Create a custom target for running generators at buildtime
  const bool multiConfig = AutogenMultiConfig(globalGen);
  const std::string autogenTargetName = GetAutogenTargetName(target);
  const std::string autogenBuildDir = GetAutogenTargetBuildDir(target);
  const std::string workingDirectory =
    cmSystemTools::CollapseFullPath("", makefile->GetCurrentBinaryDirectory());
  const std::vector<std::string> suffixes = GetConfigurationSuffixes(makefile);
  std::set<std::string> autogenDependFiles;
  std::set<std::string> autogenDependTargets;
  std::vector<std::string> autogenProvides;

  // Remove build directories on cleanup
  AddCleanFile(makefile, autogenBuildDir);

  // Remove old settings on cleanup
  {
    std::string base = GetAutogenTargetFilesDir(target);
    base += "/AutogenOldSettings";
    for (std::string const& suffix : suffixes) {
      AddCleanFile(makefile, (base + suffix).append(".cmake"));
    }
  }

  // Compose command lines
  cmCustomCommandLines commandLines;
  {
    cmCustomCommandLine currentLine;
    currentLine.push_back(cmSystemTools::GetCMakeCommand());
    currentLine.push_back("-E");
    currentLine.push_back("cmake_autogen");
    currentLine.push_back(GetAutogenTargetFilesDir(target));
    currentLine.push_back("$<CONFIGURATION>");
    commandLines.push_back(currentLine);
  }

  // Compose target comment
  std::string autogenComment;
  {
    std::vector<std::string> toolNames;
    if (digest.MocEnabled) {
      toolNames.push_back("MOC");
    }
    if (digest.UicEnabled) {
      toolNames.push_back("UIC");
    }
    if (digest.RccEnabled) {
      toolNames.push_back("RCC");
    }

    std::string tools = toolNames[0];
    toolNames.erase(toolNames.begin());
    while (toolNames.size() > 1) {
      tools += ", " + toolNames[0];
      toolNames.erase(toolNames.begin());
    }
    if (toolNames.size() == 1) {
      tools += " and " + toolNames[0];
    }
    autogenComment = "Automatic " + tools + " for target " + target->GetName();
  }

  // Add moc compilation to generated files list
  if (digest.MocEnabled) {
    const std::string mocsComp = autogenBuildDir + "/mocs_compilation.cpp";
    AddGeneratedSource(target, mocsComp, cmQtAutoGen::MOC);
    autogenProvides.push_back(mocsComp);
  }

  // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES
  if (digest.MocEnabled || digest.UicEnabled) {
    std::string includeDir = autogenBuildDir + "/include";
    if (multiConfig) {
      includeDir += "_$<CONFIG>";
    }
    target->AddIncludeDirectory(includeDir, true);
  }

  // Extract relevant source files
  std::vector<std::string> generatedSources;
  std::vector<std::string> generatedHeaders;
  {
    const std::string qrcExt = "qrc";
    std::vector<cmSourceFile*> srcFiles;
    target->GetConfigCommonSourceFiles(srcFiles);
    for (cmSourceFile* sf : srcFiles) {
      if (sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
        continue;
      }
      // sf->GetExtension() is only valid after sf->GetFullPath() ...
      const std::string& fPath = sf->GetFullPath();
      const std::string& ext = sf->GetExtension();
      // Register generated files that will be scanned by moc or uic
      if (digest.MocEnabled || digest.UicEnabled) {
        const cmSystemTools::FileFormat fileType =
          cmSystemTools::GetFileFormat(ext.c_str());
        if ((fileType == cmSystemTools::CXX_FILE_FORMAT) ||
            (fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
          const std::string absPath = cmSystemTools::GetRealPath(fPath);
          if ((digest.MocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) ||
              (digest.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 {
                digest.Headers.push_back(absPath);
              }
            } else {
              if (generated) {
                generatedSources.push_back(absPath);
              } else {
                digest.Sources.push_back(absPath);
              }
            }
          }
        }
      }
      // Register rcc enabled files
      if (digest.RccEnabled && (ext == qrcExt) &&
          !sf->GetPropertyAsBool("SKIP_AUTORCC")) {
        // Register qrc file
        {
          cmQtAutoGenDigestQrc qrcDigest;
          qrcDigest.QrcFile = cmSystemTools::GetRealPath(fPath);
          qrcDigest.QrcName =
            cmSystemTools::GetFilenameWithoutLastExtension(qrcDigest.QrcFile);
          qrcDigest.Generated = sf->GetPropertyAsBool("GENERATED");
          // RCC options
          {
            const std::string opts = GetSafeProperty(sf, "AUTORCC_OPTIONS");
            if (!opts.empty()) {
              cmSystemTools::ExpandListArgument(opts, qrcDigest.Options);
            }
          }
          digest.Qrcs.push_back(std::move(qrcDigest));
        }
      }
    }
    // 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.
    target->ClearSourcesCache();
  }

  // Process GENERATED sources and headers
  if (!generatedSources.empty() || !generatedHeaders.empty()) {
    // Check status of policy CMP0071
    bool policyAccept = false;
    bool policyWarn = false;
    const cmPolicies::PolicyStatus CMP0071_status =
      target->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) {
        digest.Headers.push_back(absFile);
        autogenDependFiles.insert(absFile);
      }
      for (std::string const& absFile : generatedSources) {
        digest.Sources.push_back(absFile);
        autogenDependFiles.insert(absFile);
      }
    } else {
      if (policyWarn) {
        std::string msg;
        msg += cmPolicies::GetPolicyWarning(cmPolicies::CMP0071);
        msg += "\n";
        std::string tools;
        if (digest.MocEnabled) {
          tools += "AUTOMOC";
        }
        if (digest.UicEnabled) {
          if (!tools.empty()) {
            tools += ",";
          }
          tools += "AUTOUIC";
        }
        if (!generatedHeaders.empty()) {
          msg.append(tools).append(": Ignoring GENERATED header file(s):\n");
          for (const std::string& absFile : generatedHeaders) {
            msg.append("  ").append(cmQtAutoGen::Quoted(absFile)).append("\n");
          }
        }
        if (!generatedSources.empty()) {
          msg.append(tools).append(": Ignoring GENERATED source file(s):\n");
          for (const std::string& absFile : generatedSources) {
            msg.append("  ").append(cmQtAutoGen::Quoted(absFile)).append("\n");
          }
        }
        makefile->IssueMessage(cmake::AUTHOR_WARNING, msg);
      }
    }
  }
  // Sort headers and sources
  std::sort(digest.Headers.begin(), digest.Headers.end());
  std::sort(digest.Sources.begin(), digest.Sources.end());

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

    // Check if file name is unique
    for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
      qrcDigest.Unique = true;
      for (cmQtAutoGenDigestQrc const& qrcDig2 : digest.Qrcs) {
        if ((&qrcDigest != &qrcDig2) &&
            (qrcDigest.QrcName == qrcDig2.QrcName)) {
          qrcDigest.Unique = false;
          break;
        }
      }
    }
    // Path checksum
    {
      const cmFilePathChecksum fpathCheckSum(makefile);
      for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
        qrcDigest.PathChecksum = fpathCheckSum.getPart(qrcDigest.QrcFile);
        // RCC output file name
        std::string rccFile = autogenBuildDir + "/";
        rccFile += qrcDigest.PathChecksum;
        rccFile += "/qrc_";
        rccFile += qrcDigest.QrcName;
        rccFile += ".cpp";
        qrcDigest.RccFile = std::move(rccFile);
      }
    }
    // RCC options
    for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
      // Target options
      std::vector<std::string> opts = optionsTarget;
      // Merge computed "-name XYZ" option
      {
        std::string name = qrcDigest.QrcName;
        // Replace '-' with '_'. The former is not valid for symbol names.
        std::replace(name.begin(), name.end(), '-', '_');
        if (!qrcDigest.Unique) {
          name += "_";
          name += qrcDigest.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, qrcDigest.Options, QtV5);
      qrcDigest.Options = std::move(opts);
    }
    for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
      // Register file at target
      AddGeneratedSource(target, qrcDigest.RccFile, cmQtAutoGen::RCC);
      autogenProvides.push_back(qrcDigest.RccFile);
      // Dependencies
      if (qrcDigest.Generated) {
        // Add the GENERATED .qrc file to the dependencies
        autogenDependFiles.insert(qrcDigest.QrcFile);
      } else {
        // Add the resource files to the dependencies
        {
          std::string error;
          if (cmQtAutoGen::RccListInputs(digest.QtVersionMajor, rcc,
                                         qrcDigest.QrcFile,
                                         qrcDigest.Resources, &error)) {
            for (std::string const& fileName : qrcDigest.Resources) {
              autogenDependFiles.insert(fileName);
            }
          } else {
            cmSystemTools::Error(error.c_str());
          }
        }
        // Run cmake again when .qrc file changes
        makefile->AddCMakeDependFile(qrcDigest.QrcFile);
      }
    }
  }

  // Add user defined autogen target dependencies
  {
    const std::string deps = GetSafeProperty(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->GetName());
        } else {
          autogenDependFiles.insert(depName);
        }
      }
    }
  }

  // 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 (const std::string& depTarget : autogenDependTargets) {
      target->Target->AddUtility(depTarget, 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(),
                       workingDirectory.c_str());
    cc.SetEscapeOldStyle(false);
    cc.SetEscapeAllowMakeVars(true);
    target->Target->AddPreBuildCommand(cc);
  } else {

    // Add utility target dependencies to the autogen target dependencies
    for (const std::string& depTarget : target->Target->GetUtilities()) {
      autogenDependTargets.insert(depTarget);
    }
    // Add link library target dependencies to the autogen target dependencies
    for (const auto& item : target->Target->GetOriginalLinkLibraries()) {
      if (makefile->FindTargetToUse(item.first) != nullptr) {
        autogenDependTargets.insert(item.first);
      }
    }

    // Convert file dependencies std::set to std::vector
    const std::vector<std::string> autogenDepends(autogenDependFiles.begin(),
                                                  autogenDependFiles.end());
    // Create autogen target
    cmTarget* autogenTarget = makefile->AddUtilityCommand(
      autogenTargetName, true, workingDirectory.c_str(),
      /*byproducts=*/autogenProvides, autogenDepends, commandLines, false,
      autogenComment.c_str());
    // Create autogen generator target
    localGen->AddGeneratorTarget(
      new cmGeneratorTarget(autogenTarget, localGen));

    // Add additional autogen target dependencies to autogen target
    for (const std::string& depTarget : autogenDependTargets) {
      autogenTarget->AddUtility(depTarget, makefile);
    }

    // Set FOLDER property in autogen target
    {
      const char* autogenFolder =
        makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER");
      if (autogenFolder == nullptr) {
        autogenFolder =
          makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER");
      }
      // Inherit FOLDER property from target (#13688)
      if (autogenFolder == nullptr) {
        autogenFolder = SafeString(target->Target->GetProperty("FOLDER"));
      }
      if ((autogenFolder != nullptr) && (*autogenFolder != '\0')) {
        autogenTarget->SetProperty("FOLDER", autogenFolder);
      }
    }

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

void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
  const cmQtAutoGenDigest& digest)
{
  cmGeneratorTarget const* target = digest.Target;
  cmMakefile* makefile = target->Target->GetMakefile();

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

  // Get configurations
  std::string config;
  const std::vector<std::string> configs(GetConfigurations(makefile, &config));

  // Configuration suffixes
  std::map<std::string, std::string> configSuffix;
  if (AutogenMultiConfig(target->GetGlobalGenerator())) {
    for (std::string const& cfg : configs) {
      configSuffix[cfg] = "_" + cfg;
    }
  }

  // Configurations settings buffers
  cmQtAutoGenSetup setup;

  // Basic setup
  AddDefinitionEscaped(makefile, "_build_dir",
                       GetAutogenTargetBuildDir(target));
  AddDefinitionEscaped(makefile, "_qt_version_major", digest.QtVersionMajor);
  AddDefinitionEscaped(makefile, "_qt_version_minor", digest.QtVersionMinor);
  AddDefinitionEscaped(makefile, "_sources", digest.Sources);
  AddDefinitionEscaped(makefile, "_headers", digest.Headers);
  {
    if (digest.MocEnabled || digest.UicEnabled) {
      SetupAcquireSkipFiles(digest, setup);
      if (digest.MocEnabled) {
        SetupAutoTargetMoc(digest, config, configs, setup);
      }
      if (digest.UicEnabled) {
        SetupAutoTargetUic(digest, config, configs, setup);
      }
    }
    if (digest.RccEnabled) {
      SetupAutoTargetRcc(digest);
    }
  }

  // Generate info file
  std::string infoFile = GetAutogenTargetFilesDir(target);
  infoFile += "/AutogenInfo.cmake";
  {
    std::string inf = cmSystemTools::GetCMakeRoot();
    inf += "/Modules/AutogenInfo.cmake.in";
    makefile->ConfigureFile(inf.c_str(), infoFile.c_str(), false, true, false);
  }

  // Append custom definitions to info file on demand
  if (!configSuffix.empty() || !setup.ConfigMocDefines.empty() ||
      !setup.ConfigMocIncludes.empty() || !setup.ConfigUicOptions.empty()) {

    // Ensure we have write permission in case .in was read-only.
    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(infoFile, perm);
    if (!(perm & mode_write)) {
      cmSystemTools::SetPermissions(infoFile, perm | mode_write);
    }

    // Open and write file
    cmsys::ofstream ofs(infoFile.c_str(), std::ios::app);
    if (ofs) {
      auto OfsWriteMap = [&ofs](
        const char* key, const std::map<std::string, std::string>& map) {
        for (auto const& item : map) {
          ofs << "set(" << key << "_" << item.first << " "
              << cmOutputConverter::EscapeForCMake(item.second) << ")\n";
        }
      };
      ofs << "# Configuration specific options\n";
      OfsWriteMap("AM_CONFIG_SUFFIX", configSuffix);
      OfsWriteMap("AM_MOC_DEFINITIONS", setup.ConfigMocDefines);
      OfsWriteMap("AM_MOC_INCLUDES", setup.ConfigMocIncludes);
      OfsWriteMap("AM_UIC_TARGET_OPTIONS", setup.ConfigUicOptions);
    } else {
      // File open error
      std::string error = "Internal CMake error when trying to open file: ";
      error += cmQtAutoGen::Quoted(infoFile);
      error += " for writing.";
      cmSystemTools::Error(error.c_str());
    }
  }
}
