/* 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)));
}

static cmQtAutoGen::MultiConfig AutogenMultiConfig(
  cmGlobalGenerator* globalGen)
{
  if (!globalGen->IsMultiConfig()) {
    return 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;
  //}

  return cmQtAutoGen::WRAP;
}

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, 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;
}

static bool QtVersionGreaterOrEqual(std::string const& major,
                                    std::string const& 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 void GetConfigs(cmMakefile* makefile, std::string& configDefault,
                       std::vector<std::string>& configsList)
{
  configDefault = makefile->GetConfigurations(configsList);
  if (configsList.empty()) {
    configsList.push_back("");
  }
}

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::vector<std::string> AddGeneratedSource(
  cmGeneratorTarget* target, std::string const& filename,
  cmQtAutoGen::MultiConfig multiConfig,
  const std::vector<std::string>& configsList, cmQtAutoGen::Generator genType)
{
  std::vector<std::string> genFiles;
  // Register source file in makefile and source group
  if (multiConfig != cmQtAutoGen::FULL) {
    genFiles.push_back(filename);
  } else {
    for (std::string const& cfg : configsList) {
      genFiles.push_back(
        cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg));
    }
  }
  {
    cmMakefile* makefile = 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 (multiConfig != cmQtAutoGen::FULL) {
    target->AddSource(filename);
  } else {
    for (std::string const& cfg : configsList) {
      std::string src = "$<$<CONFIG:";
      src += cfg;
      src += ">:";
      src += cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg);
      src += ">";
      target->AddSource(src);
    }
  }

  return genFiles;
}

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() ...
      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 = digest.MocEnabled &&
        (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC"));
      const bool uicSkip = digest.UicEnabled &&
        (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC"));
      if (mocSkip || uicSkip) {
        std::string const absFile = cmSystemTools::GetRealPath(fPath);
        if (mocSkip) {
          setup.MocSkip.insert(absFile);
        }
        if (uicSkip) {
          setup.UicSkip.insert(absFile);
        }
      }
    }
  }
}

static void SetupAutoTargetMoc(cmQtAutoGenDigest const& digest,
                               std::string const& configDefault,
                               std::vector<std::string> const& configsList,
                               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"));

  // Compiler predefines
  if (target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES")) {
    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 GetIncludeDirs = [target,
                           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, target, "CXX", cfg, false);
      return cmJoin(includeDirs, ";");
    };
    auto GetCompileDefinitions =
      [target, localGen](std::string const& cfg) -> std::string {
      std::set<std::string> defines;
      localGen->AddCompileDefinitions(defines, target, cfg, "CXX");
      return cmJoin(defines, ";");
    };

    // Default configuration settings
    std::string const includeDirs = GetIncludeDirs(configDefault);
    std::string const compileDefs = GetCompileDefinitions(configDefault);
    // Other configuration settings
    for (std::string const& cfg : configsList) {
      {
        std::string const configIncludeDirs = GetIncludeDirs(cfg);
        if (configIncludeDirs != includeDirs) {
          setup.ConfigMocIncludes[cfg] = configIncludeDirs;
        }
      }
      {
        std::string const configCompileDefs = GetCompileDefinitions(cfg);
        if (configCompileDefs != compileDefs) {
          setup.ConfigMocDefines[cfg] = configCompileDefs;
        }
      }
    }
    AddDefinitionEscaped(makefile, "_moc_include_dirs", includeDirs);
    AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs);
  }

  // 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(cmQtAutoGenDigest const& 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;
    {
      std::string const usp = GetSafeProperty(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 = [target](std::string const& cfg) -> std::string {
      std::vector<std::string> opts;
      target->GetAutoUicOptions(opts, cfg);
      return cmJoin(opts, ";");
    };

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

    // Configuration specific settings
    for (std::string const& cfg : configs) {
      std::string const 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;
    {
      std::string const uiExt = "ui";
      const std::vector<cmSourceFile*>& srcFiles = makefile->GetSourceFiles();
      for (cmSourceFile* sf : srcFiles) {
        // sf->GetExtension() is only valid after sf->GetFullPath() ...
        std::string const& fPath = sf->GetFullPath();
        if (sf->GetExtension() == uiExt) {
          // Check if the files has uic options
          std::string const uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS");
          if (!uicOpts.empty()) {
            std::string const 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,
                                    std::string const& 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(cmQtAutoGenDigest const& 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();

  std::string const autogenTargetName = GetAutogenTargetName(target);
  std::string const autogenInfoDir = GetAutogenTargetFilesDir(target);
  std::string const autogenBuildDir = GetAutogenTargetBuildDir(target);
  std::string const workingDirectory =
    cmSystemTools::CollapseFullPath("", makefile->GetCurrentBinaryDirectory());

  cmQtAutoGen::MultiConfig const multiConfig = AutogenMultiConfig(globalGen);
  std::string configDefault;
  std::vector<std::string> configsList;
  GetConfigs(makefile, configDefault, configsList);

  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 = autogenInfoDir + "/AutogenOldSettings";
    if (multiConfig == cmQtAutoGen::SINGLE) {
      AddCleanFile(makefile, base.append(".cmake"));
    } else {
      for (std::string const& cfg : configsList) {
        std::string filename = base;
        filename += "_";
        filename += cfg;
        filename += ".cmake";
        AddCleanFile(makefile, filename);
      }
    }
  }

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

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

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

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

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

  // Extract relevant source files
  std::vector<std::string> generatedSources;
  std::vector<std::string> generatedHeaders;
  {
    std::string const 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() ...
      std::string const& fPath = sf->GetFullPath();
      std::string const& ext = sf->GetExtension();
      // Register generated files that will be scanned by moc or uic
      if (digest.MocEnabled || digest.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 ((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
          {
            std::string const 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;
    cmPolicies::PolicyStatus const 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;
        std::string property;
        if (digest.MocEnabled && digest.UicEnabled) {
          tools = "AUTOMOC and AUTOUIC";
          property = "SKIP_AUTOGEN";
        } else if (digest.MocEnabled) {
          tools = "AUTOMOC";
          property = "SKIP_AUTOMOC";
        } else if (digest.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);
      }
    }
  }
  // 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");
    std::string const 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
    {
      cmFilePathChecksum const 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
      {
        auto files = AddGeneratedSource(target, qrcDigest.RccFile, multiConfig,
                                        configsList, cmQtAutoGen::RCC);
        for (std::string& file : files) {
          autogenProvides.push_back(std::move(file));
        }
      }
      // 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
  {
    std::string const 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 (std::string const& 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 (std::string const& 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 (std::string const& 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(
  cmQtAutoGenDigest const& digest)
{
  cmGeneratorTarget const* target = digest.Target;
  cmMakefile* makefile = target->Target->GetMakefile();
  cmQtAutoGen::MultiConfig const multiConfig =
    AutogenMultiConfig(target->GetGlobalGenerator());

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

  // Configurations
  std::string configDefault;
  std::vector<std::string> configsList;
  std::map<std::string, std::string> configSuffixes;
  {
    configDefault = makefile->GetConfigurations(configsList);
    if (configsList.empty()) {
      configsList.push_back("");
    }
  }
  for (std::string const& cfg : configsList) {
    configSuffixes[cfg] = "_" + cfg;
  }

  // Configurations settings buffers
  cmQtAutoGenSetup setup;

  // Basic setup
  AddDefinitionEscaped(makefile, "_multi_config",
                       cmQtAutoGen::MultiConfigName(multiConfig));
  AddDefinitionEscaped(makefile, "_build_dir",
                       GetAutogenTargetBuildDir(target));
  AddDefinitionEscaped(makefile, "_sources", digest.Sources);
  AddDefinitionEscaped(makefile, "_headers", digest.Headers);
  AddDefinitionEscaped(makefile, "_qt_version_major", digest.QtVersionMajor);
  AddDefinitionEscaped(makefile, "_qt_version_minor", digest.QtVersionMinor);
  {
    if (digest.MocEnabled || digest.UicEnabled) {
      SetupAcquireSkipFiles(digest, setup);
      if (digest.MocEnabled) {
        SetupAutoTargetMoc(digest, configDefault, configsList, setup);
      }
      if (digest.UicEnabled) {
        SetupAutoTargetUic(digest, configDefault, configsList, setup);
      }
    }
    if (digest.RccEnabled) {
      SetupAutoTargetRcc(digest);
    }
  }

  // Generate info file
  {
    std::string const infoDir = GetAutogenTargetFilesDir(target);
    if (!cmSystemTools::MakeDirectory(infoDir)) {
      std::string emsg = ("Could not create directory: ");
      emsg += cmQtAutoGen::Quoted(infoDir);
      cmSystemTools::Error(emsg.c_str());
    }
    std::string const infoFile = infoDir + "/AutogenInfo.cmake";
    {
      std::string infoFileIn = cmSystemTools::GetCMakeRoot();
      infoFileIn += "/Modules/AutogenInfo.cmake.in";
      makefile->ConfigureFile(infoFileIn.c_str(), infoFile.c_str(), false,
                              true, false);
    }

    // Append custom definitions to info file
    // --------------------------------------

    // 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, 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", 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());
    }
  }
}
