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

#include <algorithm>
#include <array>
#include <list>
#include <set>
#include <sstream>
#include <utility>

#include "cm_memory.hxx"

#include "cmAlgorithms.h"
#include "cmCryptoHash.h"
#include "cmGeneratedFileStream.h"
#include "cmMakefile.h"
#include "cmQtAutoGen.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmake.h"
#include "cmsys/FStream.hxx"

#if defined(__APPLE__)
#  include <unistd.h>
#endif

static constexpr std::size_t MocUnderscoreLength = 4; // Length of "moc_"
static constexpr std::size_t UiUnderscoreLength = 3;  // Length of "ui_"

cmQtAutoMocUic::IncludeKeyT::IncludeKeyT(std::string const& key,
                                         std::size_t basePrefixLength)
  : Key(key)
  , Dir(SubDirPrefix(key))
  , Base(cmSystemTools::GetFilenameWithoutLastExtension(key))
{
  if (basePrefixLength != 0) {
    Base = Base.substr(basePrefixLength);
  }
}

void cmQtAutoMocUic::ParseCacheT::FileT::Clear()
{
  Moc.Macro.clear();
  Moc.Include.Underscore.clear();
  Moc.Include.Dot.clear();
  Moc.Depends.clear();

  Uic.Include.clear();
  Uic.Depends.clear();
}

cmQtAutoMocUic::ParseCacheT::FileHandleT cmQtAutoMocUic::ParseCacheT::Get(
  std::string const& fileName) const
{
  auto it = Map_.find(fileName);
  if (it != Map_.end()) {
    return it->second;
  }
  return FileHandleT();
}

cmQtAutoMocUic::ParseCacheT::GetOrInsertT
cmQtAutoMocUic::ParseCacheT::GetOrInsert(std::string const& fileName)
{
  // Find existing entry
  {
    auto it = Map_.find(fileName);
    if (it != Map_.end()) {
      return GetOrInsertT{ it->second, false };
    }
  }

  // Insert new entry
  return GetOrInsertT{
    Map_.emplace(fileName, std::make_shared<FileT>()).first->second, true
  };
}

cmQtAutoMocUic::ParseCacheT::ParseCacheT() = default;
cmQtAutoMocUic::ParseCacheT::~ParseCacheT() = default;

void cmQtAutoMocUic::ParseCacheT::Clear()
{
  Map_.clear();
}

bool cmQtAutoMocUic::ParseCacheT::ReadFromFile(std::string const& fileName)
{
  cmsys::ifstream fin(fileName.c_str());
  if (!fin) {
    return false;
  }
  FileHandleT fileHandle;

  std::string line;
  while (std::getline(fin, line)) {
    // Check if this an empty or a comment line
    if (line.empty() || line.front() == '#') {
      continue;
    }
    // Drop carriage return character at the end
    if (line.back() == '\r') {
      line.pop_back();
      if (line.empty()) {
        continue;
      }
    }
    // Check if this a file name line
    if (line.front() != ' ') {
      fileHandle = GetOrInsert(line).first;
      continue;
    }

    // Bad line or bad file handle
    if (!fileHandle || (line.size() < 6)) {
      continue;
    }

    constexpr std::size_t offset = 5;
    if (cmHasLiteralPrefix(line, " mmc:")) {
      fileHandle->Moc.Macro = line.substr(offset);
      continue;
    }
    if (cmHasLiteralPrefix(line, " miu:")) {
      fileHandle->Moc.Include.Underscore.emplace_back(line.substr(offset),
                                                      MocUnderscoreLength);
      continue;
    }
    if (cmHasLiteralPrefix(line, " mid:")) {
      fileHandle->Moc.Include.Dot.emplace_back(line.substr(offset), 0);
      continue;
    }
    if (cmHasLiteralPrefix(line, " mdp:")) {
      fileHandle->Moc.Depends.emplace_back(line.substr(offset));
      continue;
    }
    if (cmHasLiteralPrefix(line, " uic:")) {
      fileHandle->Uic.Include.emplace_back(line.substr(offset),
                                           UiUnderscoreLength);
      continue;
    }
    if (cmHasLiteralPrefix(line, " udp:")) {
      fileHandle->Uic.Depends.emplace_back(line.substr(offset));
      continue;
    }
  }
  return true;
}

bool cmQtAutoMocUic::ParseCacheT::WriteToFile(std::string const& fileName)
{
  cmGeneratedFileStream ofs(fileName);
  if (!ofs) {
    return false;
  }
  ofs << "# Generated by CMake. Changes will be overwritten." << std::endl;
  for (auto const& pair : Map_) {
    ofs << pair.first << std::endl;
    FileT const& file = *pair.second;
    if (!file.Moc.Macro.empty()) {
      ofs << " mmc:" << file.Moc.Macro << std::endl;
    }
    for (IncludeKeyT const& item : file.Moc.Include.Underscore) {
      ofs << " miu:" << item.Key << std::endl;
    }
    for (IncludeKeyT const& item : file.Moc.Include.Dot) {
      ofs << " mid:" << item.Key << std::endl;
    }
    for (std::string const& item : file.Moc.Depends) {
      ofs << " mdp:" << item << std::endl;
    }
    for (IncludeKeyT const& item : file.Uic.Include) {
      ofs << " uic:" << item.Key << std::endl;
    }
    for (std::string const& item : file.Uic.Depends) {
      ofs << " udp:" << item << std::endl;
    }
  }
  return ofs.Close();
}

cmQtAutoMocUic::BaseSettingsT::BaseSettingsT() = default;
cmQtAutoMocUic::BaseSettingsT::~BaseSettingsT() = default;

cmQtAutoMocUic::MocSettingsT::MocSettingsT()
{
  RegExpInclude.compile(
    "(^|\n)[ \t]*#[ \t]*include[ \t]+"
    "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
}

cmQtAutoMocUic::MocSettingsT::~MocSettingsT() = default;

bool cmQtAutoMocUic::MocSettingsT::skipped(std::string const& fileName) const
{
  return (!Enabled || (SkipList.find(fileName) != SkipList.end()));
}

std::string cmQtAutoMocUic::MocSettingsT::MacrosString() const
{
  std::string res;
  const auto itB = MacroFilters.cbegin();
  const auto itE = MacroFilters.cend();
  const auto itL = itE - 1;
  auto itC = itB;
  for (; itC != itE; ++itC) {
    // Separator
    if (itC != itB) {
      if (itC != itL) {
        res += ", ";
      } else {
        res += " or ";
      }
    }
    // Key
    res += itC->Key;
  }
  return res;
}

cmQtAutoMocUic::UicSettingsT::UicSettingsT()
{
  RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+"
                        "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
}

cmQtAutoMocUic::UicSettingsT::~UicSettingsT() = default;

bool cmQtAutoMocUic::UicSettingsT::skipped(std::string const& fileName) const
{
  return (!Enabled || (SkipList.find(fileName) != SkipList.end()));
}

void cmQtAutoMocUic::JobT::LogError(GenT genType,
                                    std::string const& message) const
{
  Gen()->AbortError();
  Gen()->Log().Error(genType, message);
}

void cmQtAutoMocUic::JobT::LogFileError(GenT genType,
                                        std::string const& filename,
                                        std::string const& message) const
{
  Gen()->AbortError();
  Gen()->Log().ErrorFile(genType, filename, message);
}

void cmQtAutoMocUic::JobT::LogCommandError(
  GenT genType, std::string const& message,
  std::vector<std::string> const& command, std::string const& output) const
{
  Gen()->AbortError();
  Gen()->Log().ErrorCommand(genType, message, command, output);
}

bool cmQtAutoMocUic::JobT::RunProcess(GenT genType,
                                      cmWorkerPool::ProcessResultT& result,
                                      std::vector<std::string> const& command,
                                      std::string* infoMessage)
{
  // Log command
  if (Log().Verbose()) {
    std::string msg;
    if ((infoMessage != nullptr) && !infoMessage->empty()) {
      msg = *infoMessage;
      if (msg.back() != '\n') {
        msg += '\n';
      }
    }
    msg += QuotedCommand(command);
    msg += '\n';
    Log().Info(genType, msg);
  }
  return cmWorkerPool::JobT::RunProcess(result, command,
                                        BaseConst().AutogenBuildDir);
}

void cmQtAutoMocUic::JobMocPredefsT::Process()
{
  // (Re)generate moc_predefs.h on demand
  std::unique_ptr<std::string> reason;
  if (Log().Verbose()) {
    reason = cm::make_unique<std::string>();
  }
  if (!Update(reason.get())) {
    return;
  }
  std::string const& predefsFileRel = MocConst().PredefsFileRel;
  std::string const& predefsFileAbs = MocConst().PredefsFileAbs;
  {
    cmWorkerPool::ProcessResultT result;
    {
      // Compose command
      std::vector<std::string> cmd = MocConst().PredefsCmd;
      // Add includes
      cmAppend(cmd, MocConst().Includes);
      // Add definitions
      for (std::string const& def : MocConst().Definitions) {
        cmd.emplace_back("-D" + def);
      }
      // Execute command
      if (!RunProcess(GenT::MOC, result, cmd, reason.get())) {
        std::string msg = "The content generation command for ";
        msg += Quoted(predefsFileRel);
        msg += " failed.\n";
        msg += result.ErrorMessage;
        LogCommandError(GenT::MOC, msg, cmd, result.StdOut);
        return;
      }
    }

    // (Re)write predefs file only on demand
    if (cmQtAutoGenerator::FileDiffers(predefsFileAbs, result.StdOut)) {
      if (!cmQtAutoGenerator::FileWrite(predefsFileAbs, result.StdOut)) {
        std::string msg = "Writing ";
        msg += Quoted(predefsFileRel);
        msg += " failed.";
        LogFileError(GenT::MOC, predefsFileAbs, msg);
        return;
      }
    } else {
      // Touch to update the time stamp
      if (Log().Verbose()) {
        Log().Info(GenT::MOC, "Touching " + Quoted(predefsFileRel));
      }
      if (!cmSystemTools::Touch(predefsFileAbs, false)) {
        std::string msg = "Touching ";
        msg += Quoted(predefsFileAbs);
        msg += " failed.";
        LogFileError(GenT::MOC, predefsFileAbs, msg);
        return;
      }
    }
  }

  // Read file time afterwards
  if (!MocEval().PredefsTime.Load(predefsFileAbs)) {
    LogFileError(GenT::MOC, predefsFileAbs, "File time reading failed.");
    return;
  }
}

bool cmQtAutoMocUic::JobMocPredefsT::Update(std::string* reason) const
{
  // Test if the file exists
  if (!MocEval().PredefsTime.Load(MocConst().PredefsFileAbs)) {
    if (reason != nullptr) {
      *reason = "Generating ";
      *reason += Quoted(MocConst().PredefsFileRel);
      *reason += ", because it doesn't exist.";
    }
    return true;
  }

  // Test if the settings changed
  if (MocConst().SettingsChanged) {
    if (reason != nullptr) {
      *reason = "Generating ";
      *reason += Quoted(MocConst().PredefsFileRel);
      *reason += ", because the moc settings changed.";
    }
    return true;
  }

  // Test if the executable is newer
  {
    std::string const& exec = MocConst().PredefsCmd.at(0);
    cmFileTime execTime;
    if (execTime.Load(exec)) {
      if (MocEval().PredefsTime.Older(execTime)) {
        if (reason != nullptr) {
          *reason = "Generating ";
          *reason += Quoted(MocConst().PredefsFileRel);
          *reason += " because it is older than ";
          *reason += Quoted(exec);
          *reason += ".";
        }
        return true;
      }
    }
  }

  return false;
}

bool cmQtAutoMocUic::JobParseT::ReadFile()
{
  // Clear old parse information
  FileHandle->ParseData->Clear();
  std::string const& fileName = FileHandle->FileName;
  // Write info
  if (Log().Verbose()) {
    Log().Info(GenT::GEN, "Parsing " + Quoted(fileName));
  }
  // Read file content
  {
    std::string error;
    if (!cmQtAutoGenerator::FileRead(Content, fileName, &error)) {
      LogFileError(GenT::GEN, fileName, "Could not read the file: " + error);
      return false;
    }
  }
  // Warn if empty
  if (Content.empty()) {
    Log().WarningFile(GenT::GEN, fileName, "The file is empty.");
    return false;
  }
  return true;
}

void cmQtAutoMocUic::JobParseT::CreateKeys(std::vector<IncludeKeyT>& container,
                                           std::set<std::string> const& source,
                                           std::size_t basePrefixLength)
{
  if (source.empty()) {
    return;
  }
  container.reserve(source.size());
  for (std::string const& src : source) {
    container.emplace_back(src, basePrefixLength);
  }
}

void cmQtAutoMocUic::JobParseT::MocMacro()
{
  for (KeyExpT const& filter : MocConst().MacroFilters) {
    // Run a simple find string check
    if (Content.find(filter.Key) == std::string::npos) {
      continue;
    }
    // Run the expensive regular expression check loop
    cmsys::RegularExpressionMatch match;
    if (filter.Exp.find(Content.c_str(), match)) {
      // Keep detected macro name
      FileHandle->ParseData->Moc.Macro = filter.Key;
      return;
    }
  }
}

void cmQtAutoMocUic::JobParseT::MocDependecies()
{
  if (MocConst().DependFilters.empty()) {
    return;
  }

  // Find dependency strings
  std::set<std::string> parseDepends;
  for (KeyExpT const& filter : MocConst().DependFilters) {
    // Run a simple find string check
    if (Content.find(filter.Key) == std::string::npos) {
      continue;
    }
    // Run the expensive regular expression check loop
    const char* contentChars = Content.c_str();
    cmsys::RegularExpressionMatch match;
    while (filter.Exp.find(contentChars, match)) {
      {
        std::string dep = match.match(1);
        if (!dep.empty()) {
          parseDepends.emplace(std::move(dep));
        }
      }
      contentChars += match.end();
    }
  }

  // Store dependency strings
  {
    auto& Depends = FileHandle->ParseData->Moc.Depends;
    Depends.reserve(parseDepends.size());
    for (std::string const& item : parseDepends) {
      Depends.emplace_back(item);
      // Replace end of line characters in filenames
      std::string& path = Depends.back();
      std::replace(path.begin(), path.end(), '\n', ' ');
      std::replace(path.begin(), path.end(), '\r', ' ');
    }
  }
}

void cmQtAutoMocUic::JobParseT::MocIncludes()
{
  if (Content.find("moc") == std::string::npos) {
    return;
  }

  std::set<std::string> underscore;
  std::set<std::string> dot;
  {
    const char* contentChars = Content.c_str();
    cmsys::RegularExpression const& regExp = MocConst().RegExpInclude;
    cmsys::RegularExpressionMatch match;
    while (regExp.find(contentChars, match)) {
      std::string incString = match.match(2);
      std::string const incBase =
        cmSystemTools::GetFilenameWithoutLastExtension(incString);
      if (cmHasLiteralPrefix(incBase, "moc_")) {
        // moc_<BASE>.cpp
        // Remove the moc_ part from the base name
        underscore.emplace(std::move(incString));
      } else {
        // <BASE>.moc
        dot.emplace(std::move(incString));
      }
      // Forward content pointer
      contentChars += match.end();
    }
  }
  auto& Include = FileHandle->ParseData->Moc.Include;
  CreateKeys(Include.Underscore, underscore, MocUnderscoreLength);
  CreateKeys(Include.Dot, dot, 0);
}

void cmQtAutoMocUic::JobParseT::UicIncludes()
{
  if (Content.find("ui_") == std::string::npos) {
    return;
  }

  std::set<std::string> includes;
  {
    const char* contentChars = Content.c_str();
    cmsys::RegularExpression const& regExp = UicConst().RegExpInclude;
    cmsys::RegularExpressionMatch match;
    while (regExp.find(contentChars, match)) {
      includes.emplace(match.match(2));
      // Forward content pointer
      contentChars += match.end();
    }
  }
  CreateKeys(FileHandle->ParseData->Uic.Include, includes, UiUnderscoreLength);
}

void cmQtAutoMocUic::JobParseHeaderT::Process()
{
  if (!ReadFile()) {
    return;
  }
  // Moc parsing
  if (FileHandle->Moc) {
    MocMacro();
    MocDependecies();
  }
  // Uic parsing
  if (FileHandle->Uic) {
    UicIncludes();
  }
}

void cmQtAutoMocUic::JobParseSourceT::Process()
{
  if (!ReadFile()) {
    return;
  }
  // Moc parsing
  if (FileHandle->Moc) {
    MocMacro();
    MocDependecies();
    MocIncludes();
  }
  // Uic parsing
  if (FileHandle->Uic) {
    UicIncludes();
  }
}

void cmQtAutoMocUic::JobEvaluateT::Process()
{
  // Evaluate for moc
  if (MocConst().Enabled) {
    // Evaluate headers
    for (auto const& pair : BaseEval().Headers) {
      if (!MocEvalHeader(pair.second)) {
        return;
      }
    }
    // Evaluate sources
    for (auto const& pair : BaseEval().Sources) {
      if (!MocEvalSource(pair.second)) {
        return;
      }
    }
  }
  // Evaluate for uic
  if (UicConst().Enabled) {
    if (!UicEval(BaseEval().Headers) || !UicEval(BaseEval().Sources)) {
      return;
    }
  }

  // Add discovered header parse jobs
  Gen()->CreateParseJobs<JobParseHeaderT>(MocEval().HeadersDiscovered);
  // Add generate job after
  Gen()->WorkerPool().EmplaceJob<JobGenerateT>();
}

bool cmQtAutoMocUic::JobEvaluateT::MocEvalHeader(SourceFileHandleT source)
{
  SourceFileT const& sourceFile = *source;
  auto const& parseData = sourceFile.ParseData->Moc;
  if (!source->Moc) {
    return true;
  }

  if (!parseData.Macro.empty()) {
    // Create a new mapping
    MappingHandleT handle = std::make_shared<MappingT>();
    handle->SourceFile = std::move(source);

    // Absolute build path
    if (BaseConst().MultiConfig) {
      handle->OutputFile = Gen()->AbsoluteIncludePath(sourceFile.BuildPath);
    } else {
      handle->OutputFile = Gen()->AbsoluteBuildPath(sourceFile.BuildPath);
    }

    // Register mapping in headers map
    MocRegisterMapping(handle, true);
  }

  return true;
}

bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource(
  SourceFileHandleT const& source)
{
  SourceFileT const& sourceFile = *source;
  auto const& parseData = sourceFile.ParseData->Moc;
  if (!sourceFile.Moc ||
      (parseData.Macro.empty() && parseData.Include.Underscore.empty() &&
       parseData.Include.Dot.empty())) {
    return true;
  }

  std::string const sourceDir = SubDirPrefix(sourceFile.FileName);
  std::string const sourceBase =
    cmSystemTools::GetFilenameWithoutLastExtension(sourceFile.FileName);

  // For relaxed mode check if the own "moc_" or ".moc" file is included
  bool const relaxedMode = MocConst().RelaxedMode;
  bool sourceIncludesMocUnderscore = false;
  bool sourceIncludesDotMoc = false;
  // Check if the sources own "moc_" or ".moc" file is included
  if (relaxedMode) {
    for (IncludeKeyT const& incKey : parseData.Include.Underscore) {
      if (incKey.Base == sourceBase) {
        sourceIncludesMocUnderscore = true;
        break;
      }
    }
  }
  for (IncludeKeyT const& incKey : parseData.Include.Dot) {
    if (incKey.Base == sourceBase) {
      sourceIncludesDotMoc = true;
      break;
    }
  }

  // Check if this source needs to be moc processed but doesn't.
  if (!sourceIncludesDotMoc && !parseData.Macro.empty() &&
      !(relaxedMode && sourceIncludesMocUnderscore)) {
    {
      std::string emsg = "The file contains a ";
      emsg += Quoted(parseData.Macro);
      emsg += " macro, but does not include ";
      emsg += Quoted(sourceBase + ".moc");
      emsg += "!\nConsider to\n  - add #include \"";
      emsg += sourceBase;
      emsg += ".moc\"\n  - enable SKIP_AUTOMOC for this file";
      LogFileError(GenT::MOC, sourceFile.FileName, emsg);
    }
    return false;
  }

  // Evaluate "moc_" includes
  for (IncludeKeyT const& incKey : parseData.Include.Underscore) {
    std::string const headerBase = incKey.Dir + incKey.Base;
    SourceFileHandleT header = MocFindIncludedHeader(sourceDir, headerBase);
    if (!header) {
      {
        std::string msg = "The file includes the moc file ";
        msg += Quoted(incKey.Key);
        msg += ",\nbut the header could not be found "
               "in the following locations\n";
        msg += MocMessageTestHeaders(headerBase);
        LogFileError(GenT::MOC, sourceFile.FileName, msg);
      }
      return false;
    }
    // The include might be handled differently in relaxed mode
    if (relaxedMode && !sourceIncludesDotMoc && !parseData.Macro.empty() &&
        (incKey.Base == sourceBase)) {
      // The <BASE>.cpp file includes a Qt macro but does not include the
      // <BASE>.moc file. In this case, the moc_<BASE>.cpp should probably
      // be generated from <BASE>.cpp instead of <BASE>.h, because otherwise
      // it won't build. But warn, since this is not how it is supposed to be
      // used. This is for KDE4 compatibility.
      {
        // Issue a warning
        std::string msg = "The file contains a ";
        msg += Quoted(parseData.Macro);
        msg += " macro, but does not include ";
        msg += Quoted(sourceBase + ".moc");
        msg += ".\nInstead it includes ";
        msg += Quoted(incKey.Key);
        msg += ".\nRunning moc on the source\n  ";
        msg += Quoted(sourceFile.FileName);
        msg += "!\nBetter include ";
        msg += Quoted(sourceBase + ".moc");
        msg += " for compatibility with regular mode.\n";
        msg += "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n";
        Log().WarningFile(GenT::MOC, sourceFile.FileName, msg);
      }
      // Create mapping
      if (!MocRegisterIncluded(incKey.Key, source, source, false)) {
        return false;
      }
      continue;
    }

    // Check if header is skipped
    if (MocConst().skipped(header->FileName)) {
      continue;
    }
    // Create mapping
    if (!MocRegisterIncluded(incKey.Key, source, std::move(header), true)) {
      return false;
    }
  }

  // Evaluate ".moc" includes
  if (relaxedMode) {
    // Relaxed mode
    for (IncludeKeyT const& incKey : parseData.Include.Dot) {
      // Check if this is the sources own .moc file
      bool const ownMoc = (incKey.Base == sourceBase);
      if (ownMoc && !parseData.Macro.empty()) {
        // Create mapping for the regular use case
        if (!MocRegisterIncluded(incKey.Key, source, source, false)) {
          return false;
        }
        continue;
      }
      // Try to find a header instead but issue a warning.
      // This is for KDE4 compatibility.
      std::string const headerBase = incKey.Dir + incKey.Base;
      SourceFileHandleT header = MocFindIncludedHeader(sourceDir, headerBase);
      if (!header) {
        std::string msg = "The file includes the moc file ";
        msg += Quoted(incKey.Key);
        msg += ",\nwhich seems to be the moc file from a different source "
               "file.\nCMAKE_AUTOMOC_RELAXED_MODE: Also a matching header"
               "could not be found in the following locations\n";
        msg += MocMessageTestHeaders(headerBase);
        LogFileError(GenT::MOC, sourceFile.FileName, msg);
        return false;
      }
      // Check if header is skipped
      if (MocConst().skipped(header->FileName)) {
        continue;
      }
      // Issue a warning
      if (ownMoc && parseData.Macro.empty()) {
        std::string msg = "The file includes the moc file ";
        msg += Quoted(incKey.Key);
        msg += ", but does not contain a\n";
        msg += MocConst().MacrosString();
        msg += " macro.\nRunning moc on the header\n  ";
        msg += Quoted(header->FileName);
        msg += "!\nBetter include ";
        msg += Quoted("moc_" + incKey.Base + ".cpp");
        msg += " for a compatibility with regular mode.\n";
        msg += "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n";
        Log().WarningFile(GenT::MOC, sourceFile.FileName, msg);
      } else {
        std::string msg = "The file includes the moc file ";
        msg += Quoted(incKey.Key);
        msg += " instead of ";
        msg += Quoted("moc_" + incKey.Base + ".cpp");
        msg += ".\nRunning moc on the header\n  ";
        msg += Quoted(header->FileName);
        msg += "!\nBetter include ";
        msg += Quoted("moc_" + incKey.Base + ".cpp");
        msg += " for compatibility with regular mode.\n";
        msg += "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n";
        Log().WarningFile(GenT::MOC, sourceFile.FileName, msg);
      }
      // Create mapping
      if (!MocRegisterIncluded(incKey.Key, source, std::move(header), true)) {
        return false;
      }
    }
  } else {
    // Strict mode
    for (IncludeKeyT const& incKey : parseData.Include.Dot) {
      // Check if this is the sources own .moc file
      bool const ownMoc = (incKey.Base == sourceBase);
      if (!ownMoc) {
        // Don't allow <BASE>.moc include other than own in regular mode
        std::string msg = "The file includes the moc file ";
        msg += Quoted(incKey.Key);
        msg += ",\nwhich seems to be the moc file from a different "
               "source file.\nThis is not supported.  Include ";
        msg += Quoted(sourceBase + ".moc");
        msg += " to run moc on this source file.";
        LogFileError(GenT::MOC, sourceFile.FileName, msg);
        return false;
      }
      // Accept but issue a warning if moc isn't required
      if (parseData.Macro.empty()) {
        std::string msg = "The file includes the moc file ";
        msg += Quoted(incKey.Key);
        msg += ", but does not contain a ";
        msg += MocConst().MacrosString();
        msg += " macro.";
        Log().WarningFile(GenT::MOC, sourceFile.FileName, msg);
      }
      // Create mapping
      if (!MocRegisterIncluded(incKey.Key, source, source, false)) {
        return false;
      }
    }
  }

  return true;
}

cmQtAutoMocUic::SourceFileHandleT
cmQtAutoMocUic::JobEvaluateT::MocFindIncludedHeader(
  std::string const& includerDir, std::string const& includeBase) const
{
  // Search in vicinity of the source
  {
    SourceFileHandleT res = MocFindHeader(includerDir + includeBase);
    if (res) {
      return res;
    }
  }
  // Search in include directories
  for (std::string const& path : MocConst().IncludePaths) {
    std::string testPath = path;
    testPath += '/';
    testPath += includeBase;
    SourceFileHandleT res = MocFindHeader(testPath);
    if (res) {
      return res;
    }
  }
  // Return without success
  return SourceFileHandleT();
}

cmQtAutoMocUic::SourceFileHandleT cmQtAutoMocUic::JobEvaluateT::MocFindHeader(
  std::string const& basePath) const
{
  std::string testPath;
  testPath.reserve(basePath.size() + 8);
  for (std::string const& ext : BaseConst().HeaderExtensions) {
    testPath.clear();
    testPath += basePath;
    testPath += '.';
    testPath += ext;
    cmFileTime fileTime;
    if (fileTime.Load(testPath)) {
      // Compute real path of the file
      testPath = cmSystemTools::GetRealPath(testPath);
      // Return a known file if it exists already
      {
        auto it = BaseEval().Headers.find(testPath);
        if (it != BaseEval().Headers.end()) {
          return it->second;
        }
      }
      // Created and return discovered file entry
      SourceFileHandleT& res = MocEval().HeadersDiscovered[testPath];
      if (!res) {
        res = std::make_shared<SourceFileT>(testPath);
        res->FileTime = fileTime;
        res->Moc = true;
      }
      return res;
    }
  }
  // Return without success
  return SourceFileHandleT();
}

std::string cmQtAutoMocUic::JobEvaluateT::MocMessageTestHeaders(
  std::string const& fileBase) const
{
  std::ostringstream res;
  {
    std::string exts = ".{";
    exts += cmJoin(BaseConst().HeaderExtensions, ",");
    exts += '}';
    // Compose result string
    res << "  " << fileBase << exts << '\n';
    for (std::string const& path : MocConst().IncludePaths) {
      res << "  " << path << '/' << fileBase << exts << '\n';
    }
  }
  return res.str();
}

bool cmQtAutoMocUic::JobEvaluateT::MocRegisterIncluded(
  std::string const& includeString, SourceFileHandleT includerFileHandle,
  SourceFileHandleT sourceFileHandle, bool sourceIsHeader) const
{
  // Check if this file is already included
  MappingHandleT& handle = MocEval().Includes[includeString];
  if (handle) {
    // Check if the output file would be generated from different source files
    if (handle->SourceFile != sourceFileHandle) {
      std::string msg = "The source files\n  ";
      msg += Quoted(includerFileHandle->FileName);
      msg += '\n';
      for (auto const& item : handle->IncluderFiles) {
        msg += "  ";
        msg += Quoted(item->FileName);
        msg += '\n';
      }
      msg += "contain the same include string ";
      msg += Quoted(includeString);
      msg += ", but\nthe moc file would be generated from different "
             "source files\n  ";
      msg += Quoted(sourceFileHandle->FileName);
      msg += " and\n  ";
      msg += Quoted(handle->SourceFile->FileName);
      msg += ".\nConsider to\n"
             "  - not include the \"moc_<NAME>.cpp\" file\n"
             "  - add a directory prefix to a \"<NAME>.moc\" include "
             "(e.g \"sub/<NAME>.moc\")\n"
             "  - rename the source file(s)\n";
      LogError(GenT::MOC, msg);
      return false;
    }

    // The same mapping already exists. Just add to the includers list.
    handle->IncluderFiles.emplace_back(std::move(includerFileHandle));
    return true;
  }

  // Create a new mapping
  handle = std::make_shared<MappingT>();
  handle->IncludeString = includeString;
  handle->IncluderFiles.emplace_back(std::move(includerFileHandle));
  handle->SourceFile = std::move(sourceFileHandle);
  handle->OutputFile += Gen()->AbsoluteIncludePath(includeString);

  // Register mapping in sources/headers map
  MocRegisterMapping(handle, sourceIsHeader);
  return true;
}

void cmQtAutoMocUic::JobEvaluateT::MocRegisterMapping(
  MappingHandleT mappingHandle, bool sourceIsHeader) const
{
  auto& regMap =
    sourceIsHeader ? MocEval().HeaderMappings : MocEval().SourceMappings;
  // Check if source file already gets mapped
  auto& regHandle = regMap[mappingHandle->SourceFile->FileName];
  if (!regHandle) {
    // Yet unknown mapping
    regHandle = std::move(mappingHandle);
  } else {
    // Mappings with include string override those without
    if (!mappingHandle->IncludeString.empty()) {
      regHandle = std::move(mappingHandle);
    }
  }
}

bool cmQtAutoMocUic::JobEvaluateT::UicEval(SourceFileMapT const& fileMap)
{
  for (auto const& pair : fileMap) {
    if (!UicEvalFile(pair.second)) {
      return false;
    }
  }
  return true;
}

bool cmQtAutoMocUic::JobEvaluateT::UicEvalFile(
  SourceFileHandleT sourceFileHandle)
{
  SourceFileT const& sourceFile = *sourceFileHandle;
  auto const& Include = sourceFile.ParseData->Uic.Include;
  if (!sourceFile.Uic || Include.empty()) {
    return true;
  }

  std::string const sourceDir = SubDirPrefix(sourceFile.FileName);
  for (IncludeKeyT const& incKey : Include) {
    // Find .ui file name
    SourceFileHandleT uiFileHandle =
      UicFindIncludedUi(sourceFile.FileName, sourceDir, incKey);
    if (!uiFileHandle || UicConst().skipped(uiFileHandle->FileName)) {
      continue;
    }
    // Register mapping
    if (!UicRegisterMapping(incKey.Key, std::move(uiFileHandle),
                            std::move(sourceFileHandle))) {
      return false;
    }
  }

  return true;
}

bool cmQtAutoMocUic::JobEvaluateT::UicRegisterMapping(
  std::string const& includeString, SourceFileHandleT uiFileHandle,
  SourceFileHandleT includerFileHandle)
{
  auto& Includes = Gen()->UicEval().Includes;
  auto it = Includes.find(includeString);
  if (it != Includes.end()) {
    MappingHandleT const& handle = it->second;
    if (handle->SourceFile != uiFileHandle) {
      // The output file already gets generated - from a different .ui file!
      std::string msg = "The source files\n  ";
      msg += Quoted(includerFileHandle->FileName);
      msg += '\n';
      for (auto const& item : handle->IncluderFiles) {
        msg += "  ";
        msg += Quoted(item->FileName);
        msg += '\n';
      }
      msg += "contain the same include string ";
      msg += Quoted(includeString);
      msg += ", but\nthe uic file would be generated from different "
             "user interface files\n  ";
      msg += Quoted(uiFileHandle->FileName);
      msg += " and\n  ";
      msg += Quoted(handle->SourceFile->FileName);
      msg += ".\nConsider to\n"
             "  - add a directory prefix to a \"ui_<NAME>.h\" include "
             "(e.g \"sub/ui_<NAME>.h\")\n"
             "  - rename the <NAME>.ui file(s) and adjust the \"ui_<NAME>.h\" "
             "include(s)\n";
      LogError(GenT::UIC, msg);
      return false;
    }
    // Add includer file to existing mapping
    handle->IncluderFiles.emplace_back(std::move(includerFileHandle));
  } else {
    // New mapping handle
    MappingHandleT handle = std::make_shared<MappingT>();
    handle->IncludeString = includeString;
    handle->IncluderFiles.emplace_back(std::move(includerFileHandle));
    handle->SourceFile = std::move(uiFileHandle);
    handle->OutputFile += Gen()->AbsoluteIncludePath(includeString);
    // Register mapping
    Includes.emplace(includeString, std::move(handle));
  }
  return true;
}

cmQtAutoMocUic::SourceFileHandleT
cmQtAutoMocUic::JobEvaluateT::UicFindIncludedUi(
  std::string const& sourceFile, std::string const& sourceDir,
  IncludeKeyT const& incKey) const
{
  std::string searchFileName = incKey.Base;
  searchFileName += ".ui";
  // Collect search paths list
  std::vector<std::string> testFiles;
  {
    auto& searchPaths = UicConst().SearchPaths;
    testFiles.reserve((searchPaths.size() + 1) * 2);

    // Vicinity of the source
    testFiles.emplace_back(sourceDir + searchFileName);
    if (!incKey.Dir.empty()) {
      std::string path = sourceDir;
      path += incKey.Dir;
      path += searchFileName;
      testFiles.emplace_back(path);
    }
    // AUTOUIC search paths
    if (!searchPaths.empty()) {
      for (std::string const& sPath : searchPaths) {
        std::string path = sPath;
        path += '/';
        path += searchFileName;
        testFiles.emplace_back(std::move(path));
      }
      if (!incKey.Dir.empty()) {
        for (std::string const& sPath : searchPaths) {
          std::string path = sPath;
          path += '/';
          path += incKey.Dir;
          path += searchFileName;
          testFiles.emplace_back(std::move(path));
        }
      }
    }
  }

  // Search for the .ui file!
  for (std::string const& testFile : testFiles) {
    cmFileTime fileTime;
    if (fileTime.Load(testFile)) {
      // .ui file found in files system!
      std::string realPath = cmSystemTools::GetRealPath(testFile);
      // Get or create .ui file handle
      SourceFileHandleT& handle = Gen()->UicEval().UiFiles[realPath];
      if (!handle) {
        // The file wasn't registered, yet
        handle = std::make_shared<SourceFileT>(realPath);
        handle->FileTime = fileTime;
      }
      return handle;
    }
  }

  // Log error
  {
    std::string msg = "The file includes the uic file ";
    msg += Quoted(incKey.Key);
    msg += ",\nbut the user interface file ";
    msg += Quoted(searchFileName);
    msg += "\ncould not be found in the following locations\n";
    for (std::string const& testFile : testFiles) {
      msg += "  ";
      msg += Quoted(testFile);
      msg += '\n';
    }
    LogFileError(GenT::UIC, sourceFile, msg);
  }

  return SourceFileHandleT();
}

void cmQtAutoMocUic::JobGenerateT::Process()
{
  // Add moc compile jobs
  if (MocConst().Enabled) {
    for (auto const& pair : MocEval().HeaderMappings) {
      // Register if this mapping is a candidate for mocs_compilation.cpp
      bool const compFile = pair.second->IncludeString.empty();
      if (compFile) {
        MocEval().CompFiles.emplace_back(pair.second->SourceFile->BuildPath);
      }
      if (!MocGenerate(pair.second, compFile)) {
        return;
      }
    }
    for (auto const& pair : MocEval().SourceMappings) {
      if (!MocGenerate(pair.second, false)) {
        return;
      }
    }

    // Add mocs compilations job on demand
    Gen()->WorkerPool().EmplaceJob<JobMocsCompilationT>();
  }

  // Add uic compile jobs
  if (UicConst().Enabled) {
    for (auto const& pair : Gen()->UicEval().Includes) {
      if (!UicGenerate(pair.second)) {
        return;
      }
    }
  }

  // Add finish job
  Gen()->WorkerPool().EmplaceJob<JobFinishT>();
}

bool cmQtAutoMocUic::JobGenerateT::MocGenerate(MappingHandleT const& mapping,
                                               bool compFile) const
{
  std::unique_ptr<std::string> reason;
  if (Log().Verbose()) {
    reason = cm::make_unique<std::string>();
  }
  if (MocUpdate(*mapping, reason.get())) {
    // Create the parent directory
    if (!MakeParentDirectory(mapping->OutputFile)) {
      LogFileError(GenT::MOC, mapping->OutputFile,
                   "Could not create parent directory.");
      return false;
    }
    // Add moc job
    Gen()->WorkerPool().EmplaceJob<JobMocT>(mapping, std::move(reason));
    // Check if a moc job for a mocs_compilation.cpp entry was generated
    if (compFile) {
      MocEval().CompUpdated = true;
    }
  }
  return true;
}

bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping,
                                             std::string* reason) const
{
  std::string const& sourceFile = mapping.SourceFile->FileName;
  std::string const& outputFile = mapping.OutputFile;

  // Test if the output file exists
  cmFileTime outputFileTime;
  if (!outputFileTime.Load(outputFile)) {
    if (reason != nullptr) {
      *reason = "Generating ";
      *reason += Quoted(outputFile);
      *reason += ", because it doesn't exist, from ";
      *reason += Quoted(sourceFile);
    }
    return true;
  }

  // Test if any setting changed
  if (MocConst().SettingsChanged) {
    if (reason != nullptr) {
      *reason = "Generating ";
      *reason += Quoted(outputFile);
      *reason += ", because the uic settings changed, from ";
      *reason += Quoted(sourceFile);
    }
    return true;
  }

  // Test if the source file is newer
  if (outputFileTime.Older(mapping.SourceFile->FileTime)) {
    if (reason != nullptr) {
      *reason = "Generating ";
      *reason += Quoted(outputFile);
      *reason += ", because it's older than its source file, from ";
      *reason += Quoted(sourceFile);
    }
    return true;
  }

  // Test if the moc_predefs file is newer
  if (!MocConst().PredefsFileAbs.empty()) {
    if (outputFileTime.Older(MocEval().PredefsTime)) {
      if (reason != nullptr) {
        *reason = "Generating ";
        *reason += Quoted(outputFile);
        *reason += ", because it's older than ";
        *reason += Quoted(MocConst().PredefsFileAbs);
        *reason += ", from ";
        *reason += Quoted(sourceFile);
      }
      return true;
    }
  }

  // Test if the moc executable is newer
  if (outputFileTime.Older(MocConst().ExecutableTime)) {
    if (reason != nullptr) {
      *reason = "Generating ";
      *reason += Quoted(outputFile);
      *reason += ", because it's older than the moc executable, from ";
      *reason += Quoted(sourceFile);
    }
    return true;
  }

  // Test if a dependency file is newer
  {
    // Check dependency timestamps
    std::string const sourceDir = SubDirPrefix(sourceFile);
    for (std::string const& dep : mapping.SourceFile->ParseData->Moc.Depends) {
      // Find dependency file
      auto const depMatch = MocFindDependency(sourceDir, dep);
      if (depMatch.first.empty()) {
        Log().WarningFile(GenT::MOC, sourceFile,
                          "Could not find dependency file " + Quoted(dep));
        continue;
      }
      // Test if dependency file is older
      if (outputFileTime.Older(depMatch.second)) {
        if (reason != nullptr) {
          *reason = "Generating ";
          *reason += Quoted(outputFile);
          *reason += ", because it's older than its dependency file ";
          *reason += Quoted(depMatch.first);
          *reason += ", from ";
          *reason += Quoted(sourceFile);
        }
        return true;
      }
    }
  }

  return false;
}

std::pair<std::string, cmFileTime>
cmQtAutoMocUic::JobGenerateT::MocFindDependency(
  std::string const& sourceDir, std::string const& includeString) const
{
  typedef std::pair<std::string, cmFileTime> ResPair;
  // Search in vicinity of the source
  {
    ResPair res{ sourceDir + includeString, {} };
    if (res.second.Load(res.first)) {
      return res;
    }
  }
  // Search in include directories
  for (std::string const& includePath : MocConst().IncludePaths) {
    ResPair res{ includePath, {} };
    res.first += '/';
    res.first += includeString;
    if (res.second.Load(res.first)) {
      return res;
    }
  }
  // Return empty
  return ResPair();
}

bool cmQtAutoMocUic::JobGenerateT::UicGenerate(
  MappingHandleT const& mapping) const
{
  std::unique_ptr<std::string> reason;
  if (Log().Verbose()) {
    reason = cm::make_unique<std::string>();
  }
  if (UicUpdate(*mapping, reason.get())) {
    // Create the parent directory
    if (!MakeParentDirectory(mapping->OutputFile)) {
      LogFileError(GenT::UIC, mapping->OutputFile,
                   "Could not create parent directory.");
      return false;
    }
    // Add uic job
    Gen()->WorkerPool().EmplaceJob<JobUicT>(mapping, std::move(reason));
  }
  return true;
}

bool cmQtAutoMocUic::JobGenerateT::UicUpdate(MappingT const& mapping,
                                             std::string* reason) const
{
  std::string const& sourceFile = mapping.SourceFile->FileName;
  std::string const& outputFile = mapping.OutputFile;

  // Test if the build file exists
  cmFileTime outputFileTime;
  if (!outputFileTime.Load(outputFile)) {
    if (reason != nullptr) {
      *reason = "Generating ";
      *reason += Quoted(outputFile);
      *reason += ", because it doesn't exist, from ";
      *reason += Quoted(sourceFile);
    }
    return true;
  }

  // Test if the uic settings changed
  if (UicConst().SettingsChanged) {
    if (reason != nullptr) {
      *reason = "Generating ";
      *reason += Quoted(outputFile);
      *reason += ", because the uic settings changed, from ";
      *reason += Quoted(sourceFile);
    }
    return true;
  }

  // Test if the source file is newer
  if (outputFileTime.Older(mapping.SourceFile->FileTime)) {
    if (reason != nullptr) {
      *reason = "Generating ";
      *reason += Quoted(outputFile);
      *reason += " because it's older than the source file ";
      *reason += Quoted(sourceFile);
    }
    return true;
  }

  // Test if the uic executable is newer
  if (outputFileTime.Older(UicConst().ExecutableTime)) {
    if (reason != nullptr) {
      *reason = "Generating ";
      *reason += Quoted(outputFile);
      *reason += ", because it's older than the uic executable, from ";
      *reason += Quoted(sourceFile);
    }
    return true;
  }

  return false;
}

void cmQtAutoMocUic::JobMocT::Process()
{
  std::string const& sourceFile = Mapping->SourceFile->FileName;
  std::string const& outputFile = Mapping->OutputFile;

  // Compose moc command
  std::vector<std::string> cmd;
  cmd.push_back(MocConst().Executable);
  // Add options
  cmAppend(cmd, MocConst().AllOptions);
  // Add predefs include
  if (!MocConst().PredefsFileAbs.empty()) {
    cmd.emplace_back("--include");
    cmd.push_back(MocConst().PredefsFileAbs);
  }
  cmd.emplace_back("-o");
  cmd.push_back(outputFile);
  cmd.push_back(sourceFile);

  // Execute moc command
  cmWorkerPool::ProcessResultT result;
  if (RunProcess(GenT::MOC, result, cmd, Reason.get())) {
    // Moc command success. Print moc output.
    if (!result.StdOut.empty()) {
      Log().Info(GenT::MOC, result.StdOut);
    }
  } else {
    // Moc command failed
    std::string msg = "The moc process failed to compile\n  ";
    msg += Quoted(sourceFile);
    msg += "\ninto\n  ";
    msg += Quoted(outputFile);
    if (Mapping->IncluderFiles.empty()) {
      msg += ".\n";
    } else {
      msg += "\nincluded by\n";
      for (auto const& item : Mapping->IncluderFiles) {
        msg += "  ";
        msg += Quoted(item->FileName);
        msg += '\n';
      }
    }
    msg += result.ErrorMessage;
    LogCommandError(GenT::MOC, msg, cmd, result.StdOut);
  }
}

void cmQtAutoMocUic::JobUicT::Process()
{
  std::string const& sourceFile = Mapping->SourceFile->FileName;
  std::string const& outputFile = Mapping->OutputFile;

  // Compose uic command
  std::vector<std::string> cmd;
  cmd.push_back(UicConst().Executable);
  {
    std::vector<std::string> allOpts = UicConst().TargetOptions;
    auto optionIt = UicConst().Options.find(sourceFile);
    if (optionIt != UicConst().Options.end()) {
      UicMergeOptions(allOpts, optionIt->second,
                      (BaseConst().QtVersionMajor == 5));
    }
    cmAppend(cmd, allOpts);
  }
  cmd.emplace_back("-o");
  cmd.emplace_back(outputFile);
  cmd.emplace_back(sourceFile);

  cmWorkerPool::ProcessResultT result;
  if (RunProcess(GenT::UIC, result, cmd, Reason.get())) {
    // Uic command success
    // Print uic output
    if (!result.StdOut.empty()) {
      Log().Info(GenT::UIC, result.StdOut);
    }
  } else {
    // Uic command failed
    std::string msg = "The uic process failed to compile\n  ";
    msg += Quoted(sourceFile);
    msg += "\ninto\n  ";
    msg += Quoted(outputFile);
    msg += "\nincluded by\n";
    for (auto const& item : Mapping->IncluderFiles) {
      msg += "  ";
      msg += Quoted(item->FileName);
      msg += '\n';
    }
    msg += result.ErrorMessage;
    LogCommandError(GenT::UIC, msg, cmd, result.StdOut);
  }
}

void cmQtAutoMocUic::JobMocsCompilationT::Process()
{
  // Compose mocs compilation file content
  std::string content =
    "// This file is autogenerated. Changes will be overwritten.\n";

  if (MocEval().CompFiles.empty()) {
    // Placeholder content
    content += "// No files found that require moc or the moc files are "
               "included\n";
    content += "enum some_compilers { need_more_than_nothing };\n";
  } else {
    // Valid content
    char const clampB = BaseConst().MultiConfig ? '<' : '"';
    char const clampE = BaseConst().MultiConfig ? '>' : '"';
    for (std::string const& mocfile : MocEval().CompFiles) {
      content += "#include ";
      content += clampB;
      content += mocfile;
      content += clampE;
      content += '\n';
    }
  }

  std::string const& compAbs = MocConst().CompFileAbs;
  if (cmQtAutoGenerator::FileDiffers(compAbs, content)) {
    // Actually write mocs compilation file
    if (Log().Verbose()) {
      Log().Info(GenT::MOC, "Generating MOC compilation " + compAbs);
    }
    if (!FileWrite(compAbs, content)) {
      LogFileError(GenT::MOC, compAbs,
                   "mocs compilation file writing failed.");
    }
  } else if (MocEval().CompUpdated) {
    // Only touch mocs compilation file
    if (Log().Verbose()) {
      Log().Info(GenT::MOC, "Touching mocs compilation " + compAbs);
    }
    if (!cmSystemTools::Touch(compAbs, false)) {
      LogFileError(GenT::MOC, compAbs,
                   "mocs compilation file touching failed.");
    }
  }
}

void cmQtAutoMocUic::JobFinishT::Process()
{
  Gen()->AbortSuccess();
}

cmQtAutoMocUic::cmQtAutoMocUic() = default;
cmQtAutoMocUic::~cmQtAutoMocUic() = default;

bool cmQtAutoMocUic::Init(cmMakefile* makefile)
{
  // Utility lambdas
  auto InfoGet = [makefile](const char* key) {
    return makefile->GetSafeDefinition(key);
  };
  auto InfoGetBool = [makefile](const char* key) {
    return makefile->IsOn(key);
  };
  auto InfoGetList = [makefile](const char* key) -> std::vector<std::string> {
    std::vector<std::string> list;
    cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list);
    return list;
  };
  auto InfoGetLists =
    [makefile](const char* key) -> std::vector<std::vector<std::string>> {
    std::vector<std::vector<std::string>> lists;
    {
      std::string const value = makefile->GetSafeDefinition(key);
      std::string::size_type pos = 0;
      while (pos < value.size()) {
        std::string::size_type next = value.find(ListSep, pos);
        std::string::size_type length =
          (next != std::string::npos) ? next - pos : value.size() - pos;
        // Remove enclosing braces
        if (length >= 2) {
          std::string::const_iterator itBeg = value.begin() + (pos + 1);
          std::string::const_iterator itEnd = itBeg + (length - 2);
          {
            std::string subValue(itBeg, itEnd);
            std::vector<std::string> list;
            cmSystemTools::ExpandListArgument(subValue, list);
            lists.push_back(std::move(list));
          }
        }
        pos += length;
        pos += ListSep.size();
      }
    }
    return lists;
  };
  auto InfoGetConfig = [makefile, this](const char* key) -> std::string {
    const char* valueConf = nullptr;
    {
      std::string keyConf = key;
      keyConf += '_';
      keyConf += InfoConfig();
      valueConf = makefile->GetDefinition(keyConf);
    }
    if (valueConf == nullptr) {
      return makefile->GetSafeDefinition(key);
    }
    return std::string(valueConf);
  };
  auto InfoGetConfigList =
    [&InfoGetConfig](const char* key) -> std::vector<std::string> {
    std::vector<std::string> list;
    cmSystemTools::ExpandListArgument(InfoGetConfig(key), list);
    return list;
  };
  auto LogInfoError = [this](std::string const& msg) -> bool {
    std::ostringstream err;
    err << "In " << Quoted(this->InfoFile()) << ":\n" << msg;
    this->Log().Error(GenT::GEN, err.str());
    return false;
  };
  auto MatchSizes = [&LogInfoError](const char* keyA, const char* keyB,
                                    std::size_t sizeA,
                                    std::size_t sizeB) -> bool {
    if (sizeA == sizeB) {
      return true;
    }
    std::ostringstream err;
    err << "Lists sizes mismatch " << keyA << '(' << sizeA << ") " << keyB
        << '(' << sizeB << ')';
    return LogInfoError(err.str());
  };

  // -- Read info file
  if (!makefile->ReadListFile(InfoFile())) {
    return LogInfoError("File processing failed");
  }

  // -- Meta
  Logger_.RaiseVerbosity(InfoGet("AM_VERBOSITY"));
  BaseConst_.MultiConfig = InfoGetBool("AM_MULTI_CONFIG");
  {
    unsigned long num = 1;
    if (cmSystemTools::StringToULong(InfoGet("AM_PARALLEL").c_str(), &num)) {
      num = std::max<unsigned long>(num, 1);
      num = std::min<unsigned long>(num, ParallelMax);
    }
    WorkerPool_.SetThreadCount(static_cast<unsigned int>(num));
  }
  BaseConst_.HeaderExtensions =
    makefile->GetCMakeInstance()->GetHeaderExtensions();

  // - Files and directories
  BaseConst_.IncludeProjectDirsBefore =
    InfoGetBool("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE");
  BaseConst_.ProjectSourceDir = InfoGet("AM_CMAKE_SOURCE_DIR");
  BaseConst_.ProjectBinaryDir = InfoGet("AM_CMAKE_BINARY_DIR");
  BaseConst_.CurrentSourceDir = InfoGet("AM_CMAKE_CURRENT_SOURCE_DIR");
  BaseConst_.CurrentBinaryDir = InfoGet("AM_CMAKE_CURRENT_BINARY_DIR");
  BaseConst_.AutogenBuildDir = InfoGet("AM_BUILD_DIR");
  if (BaseConst_.AutogenBuildDir.empty()) {
    return LogInfoError("Autogen build directory missing.");
  }
  BaseConst_.AutogenIncludeDir = InfoGetConfig("AM_INCLUDE_DIR");
  if (BaseConst_.AutogenIncludeDir.empty()) {
    return LogInfoError("Autogen include directory missing.");
  }
  BaseConst_.CMakeExecutable = InfoGetConfig("AM_CMAKE_EXECUTABLE");
  if (BaseConst_.CMakeExecutable.empty()) {
    return LogInfoError("CMake executable file name missing.");
  }
  if (!BaseConst_.CMakeExecutableTime.Load(BaseConst_.CMakeExecutable)) {
    std::string error = "The CMake executable ";
    error += Quoted(BaseConst_.CMakeExecutable);
    error += " does not exist.";
    return LogInfoError(error);
  }
  BaseConst_.ParseCacheFile = InfoGetConfig("AM_PARSE_CACHE_FILE");
  if (BaseConst_.ParseCacheFile.empty()) {
    return LogInfoError("Parse cache file name missing.");
  }

  // - Settings file
  SettingsFile_ = InfoGetConfig("AM_SETTINGS_FILE");
  if (SettingsFile_.empty()) {
    return LogInfoError("Settings file name missing.");
  }

  // - Qt environment
  {
    unsigned long qtv = BaseConst_.QtVersionMajor;
    if (cmSystemTools::StringToULong(InfoGet("AM_QT_VERSION_MAJOR").c_str(),
                                     &qtv)) {
      BaseConst_.QtVersionMajor = static_cast<unsigned int>(qtv);
    }
  }

  // - Moc
  MocConst_.Executable = InfoGet("AM_QT_MOC_EXECUTABLE");
  if (!MocConst().Executable.empty()) {
    MocConst_.Enabled = true;
    // Load the executable file time
    if (!MocConst_.ExecutableTime.Load(MocConst_.Executable)) {
      std::string error = "The moc executable ";
      error += Quoted(MocConst_.Executable);
      error += " does not exist.";
      return LogInfoError(error);
    }
    for (std::string& sfl : InfoGetList("AM_MOC_SKIP")) {
      MocConst_.SkipList.insert(std::move(sfl));
    }
    MocConst_.Definitions = InfoGetConfigList("AM_MOC_DEFINITIONS");
    MocConst_.IncludePaths = InfoGetConfigList("AM_MOC_INCLUDES");
    MocConst_.Options = InfoGetList("AM_MOC_OPTIONS");
    MocConst_.RelaxedMode = InfoGetBool("AM_MOC_RELAXED_MODE");
    for (std::string const& item : InfoGetList("AM_MOC_MACRO_NAMES")) {
      MocConst_.MacroFilters.emplace_back(
        item, ("[\n][ \t]*{?[ \t]*" + item).append("[^a-zA-Z0-9_]"));
    }
    {
      auto addFilter = [this, &LogInfoError](std::string const& key,
                                             std::string const& exp) -> bool {
        auto filterErr = [&LogInfoError, &key, &exp](const char* err) -> bool {
          std::ostringstream ferr;
          ferr << "AUTOMOC_DEPEND_FILTERS: " << err << '\n';
          ferr << "  Key: " << Quoted(key) << '\n';
          ferr << "  Exp: " << Quoted(exp) << '\n';
          return LogInfoError(ferr.str());
        };
        if (key.empty()) {
          return filterErr("Key is empty");
        }
        if (exp.empty()) {
          return filterErr("Regular expression is empty");
        }
        this->MocConst_.DependFilters.emplace_back(key, exp);
        if (!this->MocConst_.DependFilters.back().Exp.is_valid()) {
          return filterErr("Regular expression compiling failed");
        }
        return true;
      };

      // Insert default filter for Q_PLUGIN_METADATA
      if (BaseConst().QtVersionMajor != 4) {
        if (!addFilter("Q_PLUGIN_METADATA",
                       "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\("
                       "[^\\)]*FILE[ \t]*\"([^\"]+)\"")) {
          return false;
        }
      }
      // Insert user defined dependency filters
      std::vector<std::string> flts = InfoGetList("AM_MOC_DEPEND_FILTERS");
      if ((flts.size() % 2) != 0) {
        return LogInfoError(
          "AUTOMOC_DEPEND_FILTERS list size is not a multiple of 2");
      }
      for (auto itC = flts.begin(), itE = flts.end(); itC != itE; itC += 2) {
        if (!addFilter(*itC, *(itC + 1))) {
          return false;
        }
      }
    }
    MocConst_.PredefsCmd = InfoGetList("AM_MOC_PREDEFS_CMD");
  }

  // - Uic
  UicConst_.Executable = InfoGet("AM_QT_UIC_EXECUTABLE");
  if (!UicConst().Executable.empty()) {
    UicConst_.Enabled = true;
    // Load the executable file time
    if (!UicConst_.ExecutableTime.Load(UicConst_.Executable)) {
      std::string error = "The uic executable ";
      error += Quoted(UicConst_.Executable);
      error += " does not exist.";
      return LogInfoError(error);
    }
    for (std::string& sfl : InfoGetList("AM_UIC_SKIP")) {
      UicConst_.SkipList.insert(std::move(sfl));
    }
    UicConst_.SearchPaths = InfoGetList("AM_UIC_SEARCH_PATHS");
    UicConst_.TargetOptions = InfoGetConfigList("AM_UIC_TARGET_OPTIONS");
    {
      const char* keyFiles = "AM_UIC_OPTIONS_FILES";
      const char* keyOpts = "AM_UIC_OPTIONS_OPTIONS";
      auto sources = InfoGetList(keyFiles);
      auto options = InfoGetLists(keyOpts);
      if (!MatchSizes(keyFiles, keyOpts, sources.size(), options.size())) {
        return false;
      }
      auto fitEnd = sources.cend();
      auto fit = sources.begin();
      auto oit = options.begin();
      while (fit != fitEnd) {
        UicConst_.Options[*fit] = std::move(*oit);
        ++fit;
        ++oit;
      }
    }
  }

  // - Headers and sources
  {
    auto makeSource =
      [&LogInfoError](std::string const& fileName,
                      std::string const& fileFlags) -> SourceFileHandleT {
      if (fileFlags.size() != 2) {
        LogInfoError("Invalid file flags string size");
        return SourceFileHandleT();
      }
      cmFileTime fileTime;
      if (!fileTime.Load(fileName)) {
        LogInfoError("The source file " + cmQtAutoGen::Quoted(fileName) +
                     " does not exist.");
        return SourceFileHandleT();
      }
      SourceFileHandleT sfh = std::make_shared<SourceFileT>(fileName);
      sfh->FileTime = fileTime;
      sfh->Moc = (fileFlags[0] == 'M');
      sfh->Uic = (fileFlags[1] == 'U');
      return sfh;
    };

    // Headers
    {
      // Get file lists
      const char *keyFiles = "AM_HEADERS", *keyFlags = "AM_HEADERS_FLAGS";
      std::vector<std::string> files = InfoGetList(keyFiles);
      std::vector<std::string> flags = InfoGetList(keyFlags);
      std::vector<std::string> builds;
      if (!MatchSizes(keyFiles, keyFlags, files.size(), flags.size())) {
        return false;
      }
      if (MocConst().Enabled) {
        const char* keyPaths = "AM_HEADERS_BUILD_PATHS";
        builds = InfoGetList(keyPaths);
        if (!MatchSizes(keyFiles, keyPaths, files.size(), builds.size())) {
          return false;
        }
      }
      // Process file lists
      for (std::size_t ii = 0; ii != files.size(); ++ii) {
        std::string& fileName(files[ii]);
        SourceFileHandleT sfh = makeSource(fileName, flags[ii]);
        if (!sfh) {
          return false;
        }
        if (MocConst().Enabled) {
          sfh->BuildPath = std::move(builds[ii]);
          if (sfh->BuildPath.empty()) {
            Log().ErrorFile(GenT::GEN, this->InfoFile(),
                            "Header file build path is empty");
            return false;
          }
        }
        BaseEval().Headers.emplace(std::move(fileName), std::move(sfh));
      }
    }

    // Sources
    {
      const char *keyFiles = "AM_SOURCES", *keyFlags = "AM_SOURCES_FLAGS";
      std::vector<std::string> files = InfoGetList(keyFiles);
      std::vector<std::string> flags = InfoGetList(keyFlags);
      if (!MatchSizes(keyFiles, keyFlags, files.size(), flags.size())) {
        return false;
      }
      // Process file lists
      for (std::size_t ii = 0; ii != files.size(); ++ii) {
        std::string& fileName(files[ii]);
        SourceFileHandleT sfh = makeSource(fileName, flags[ii]);
        if (!sfh) {
          return false;
        }
        BaseEval().Sources.emplace(std::move(fileName), std::move(sfh));
      }
    }
  }

  // Init derived information
  // ------------------------

  // Moc variables
  if (MocConst().Enabled) {
    // Mocs compilation file
    MocConst_.CompFileAbs = AbsoluteBuildPath("mocs_compilation.cpp");

    // Moc predefs file
    if (!MocConst_.PredefsCmd.empty()) {
      MocConst_.PredefsFileRel = "moc_predefs";
      if (BaseConst_.MultiConfig) {
        MocConst_.PredefsFileRel += '_';
        MocConst_.PredefsFileRel += InfoConfig();
      }
      MocConst_.PredefsFileRel += ".h";
      MocConst_.PredefsFileAbs = AbsoluteBuildPath(MocConst().PredefsFileRel);
    }

    // Sort include directories on demand
    if (BaseConst().IncludeProjectDirsBefore) {
      // Move strings to temporary list
      std::list<std::string> includes(MocConst().IncludePaths.begin(),
                                      MocConst().IncludePaths.end());
      MocConst_.IncludePaths.clear();
      MocConst_.IncludePaths.reserve(includes.size());
      // Append project directories only
      {
        std::array<std::string const*, 2> const movePaths = {
          { &BaseConst().ProjectBinaryDir, &BaseConst().ProjectSourceDir }
        };
        for (std::string const* ppath : movePaths) {
          std::list<std::string>::iterator it = includes.begin();
          while (it != includes.end()) {
            std::string const& path = *it;
            if (cmHasPrefix(path, *ppath)) {
              MocConst_.IncludePaths.push_back(path);
              it = includes.erase(it);
            } else {
              ++it;
            }
          }
        }
      }
      // Append remaining directories
      MocConst_.IncludePaths.insert(MocConst_.IncludePaths.end(),
                                    includes.begin(), includes.end());
    }
    // Compose moc includes list
    {
      std::set<std::string> frameworkPaths;
      for (std::string const& path : MocConst().IncludePaths) {
        MocConst_.Includes.push_back("-I" + path);
        // Extract framework path
        if (cmHasLiteralSuffix(path, ".framework/Headers")) {
          // Go up twice to get to the framework root
          std::vector<std::string> pathComponents;
          cmSystemTools::SplitPath(path, pathComponents);
          frameworkPaths.emplace(cmSystemTools::JoinPath(
            pathComponents.begin(), pathComponents.end() - 2));
        }
      }
      // Append framework includes
      for (std::string const& path : frameworkPaths) {
        MocConst_.Includes.emplace_back("-F");
        MocConst_.Includes.push_back(path);
      }
    }
    // Setup single list with all options
    {
      // Add includes
      MocConst_.AllOptions.insert(MocConst_.AllOptions.end(),
                                  MocConst().Includes.begin(),
                                  MocConst().Includes.end());
      // Add definitions
      for (std::string const& def : MocConst().Definitions) {
        MocConst_.AllOptions.push_back("-D" + def);
      }
      // Add options
      MocConst_.AllOptions.insert(MocConst_.AllOptions.end(),
                                  MocConst().Options.begin(),
                                  MocConst().Options.end());
    }
  }

  return true;
}

template <class JOBTYPE>
void cmQtAutoMocUic::CreateParseJobs(SourceFileMapT const& sourceMap)
{
  cmFileTime const parseCacheTime = BaseEval().ParseCacheTime;
  ParseCacheT& parseCache = BaseEval().ParseCache;
  for (auto& src : sourceMap) {
    // Get or create the file parse data reference
    ParseCacheT::GetOrInsertT cacheEntry = parseCache.GetOrInsert(src.first);
    src.second->ParseData = std::move(cacheEntry.first);
    // Create a parse job if the cache file was missing or is older
    if (cacheEntry.second || src.second->FileTime.Newer(parseCacheTime)) {
      BaseEval().ParseCacheChanged = true;
      WorkerPool().EmplaceJob<JOBTYPE>(src.second);
    }
  }
}

void cmQtAutoMocUic::InitJobs()
{
  // Add moc_predefs.h job
  if (MocConst().Enabled && !MocConst().PredefsCmd.empty()) {
    WorkerPool().EmplaceJob<JobMocPredefsT>();
  }
  // Add header parse jobs
  CreateParseJobs<JobParseHeaderT>(BaseEval().Headers);
  // Add source parse jobs
  CreateParseJobs<JobParseSourceT>(BaseEval().Sources);
  // Add evaluate job
  WorkerPool().EmplaceJob<JobEvaluateT>();
}

bool cmQtAutoMocUic::Process()
{
  SettingsFileRead();
  ParseCacheRead();
  if (!CreateDirectories()) {
    return false;
  }
  InitJobs();
  if (!WorkerPool_.Process(this)) {
    return false;
  }
  if (JobError_) {
    return false;
  }
  if (!ParseCacheWrite()) {
    return false;
  }
  if (!SettingsFileWrite()) {
    return false;
  }
  return true;
}

void cmQtAutoMocUic::SettingsFileRead()
{
  // Compose current settings strings
  {
    cmCryptoHash cryptoHash(cmCryptoHash::AlgoSHA256);
    std::string const sep(";");
    auto cha = [&cryptoHash, &sep](std::string const& value) {
      cryptoHash.Append(value);
      cryptoHash.Append(sep);
    };

    if (MocConst_.Enabled) {
      cryptoHash.Initialize();
      cha(MocConst().Executable);
      for (auto const& value : MocConst().AllOptions) {
        cha(value);
      }
      cha(BaseConst().IncludeProjectDirsBefore ? "TRUE" : "FALSE");
      for (auto const& value : MocConst().PredefsCmd) {
        cha(value);
      }
      for (auto const& filter : MocConst().DependFilters) {
        cha(filter.Key);
      }
      for (auto const& filter : MocConst().MacroFilters) {
        cha(filter.Key);
      }
      SettingsStringMoc_ = cryptoHash.FinalizeHex();
    }

    if (UicConst().Enabled) {
      cryptoHash.Initialize();
      cha(UicConst().Executable);
      for (auto const& value : UicConst().TargetOptions) {
        cha(value);
      }
      for (const auto& item : UicConst().Options) {
        cha(item.first);
        for (auto const& svalue : item.second) {
          cha(svalue);
        }
      }
      SettingsStringUic_ = cryptoHash.FinalizeHex();
    }
  }

  // Read old settings and compare
  {
    std::string content;
    if (cmQtAutoGenerator::FileRead(content, SettingsFile_)) {
      if (MocConst().Enabled) {
        if (SettingsStringMoc_ != SettingsFind(content, "moc")) {
          MocConst_.SettingsChanged = true;
        }
      }
      if (UicConst().Enabled) {
        if (SettingsStringUic_ != SettingsFind(content, "uic")) {
          UicConst_.SettingsChanged = true;
        }
      }
      // In case any setting changed remove the old settings file.
      // This triggers a full rebuild on the next run if the current
      // build is aborted before writing the current settings in the end.
      if (MocConst().SettingsChanged || UicConst().SettingsChanged) {
        cmSystemTools::RemoveFile(SettingsFile_);
      }
    } else {
      // Settings file read failed
      if (MocConst().Enabled) {
        MocConst_.SettingsChanged = true;
      }
      if (UicConst().Enabled) {
        UicConst_.SettingsChanged = true;
      }
    }
  }
}

bool cmQtAutoMocUic::SettingsFileWrite()
{
  // Only write if any setting changed
  if (MocConst().SettingsChanged || UicConst().SettingsChanged) {
    if (Log().Verbose()) {
      Log().Info(GenT::GEN, "Writing settings file " + Quoted(SettingsFile_));
    }
    // Compose settings file content
    std::string content;
    {
      auto SettingAppend = [&content](const char* key,
                                      std::string const& value) {
        if (!value.empty()) {
          content += key;
          content += ':';
          content += value;
          content += '\n';
        }
      };
      SettingAppend("moc", SettingsStringMoc_);
      SettingAppend("uic", SettingsStringUic_);
    }
    // Write settings file
    std::string error;
    if (!cmQtAutoGenerator::FileWrite(SettingsFile_, content, &error)) {
      Log().ErrorFile(GenT::GEN, SettingsFile_,
                      "Settings file writing failed. " + error);
      // Remove old settings file to trigger a full rebuild on the next run
      cmSystemTools::RemoveFile(SettingsFile_);
      return false;
    }
  }
  return true;
}

void cmQtAutoMocUic::ParseCacheRead()
{
  const char* reason = nullptr;
  // Don't read the cache if it is invalid
  if (!BaseEval().ParseCacheTime.Load(BaseConst().ParseCacheFile)) {
    reason = "Refreshing parse cache because it doesn't exist.";
  } else if (MocConst().SettingsChanged || UicConst().SettingsChanged) {
    reason = "Refreshing parse cache because the settings changed.";
  } else if (BaseEval().ParseCacheTime.Older(
               BaseConst().CMakeExecutableTime)) {
    reason =
      "Refreshing parse cache because it is older than the CMake executable.";
  }

  if (reason != nullptr) {
    // Don't read but refresh the complete parse cache
    if (Log().Verbose()) {
      Log().Info(GenT::GEN, reason);
    }
    BaseEval().ParseCacheChanged = true;
  } else {
    // Read parse cache
    BaseEval().ParseCache.ReadFromFile(BaseConst().ParseCacheFile);
  }
}

bool cmQtAutoMocUic::ParseCacheWrite()
{
  if (BaseEval().ParseCacheChanged) {
    if (Log().Verbose()) {
      Log().Info(GenT::GEN,
                 "Writing parse cache file " +
                   Quoted(BaseConst().ParseCacheFile));
    }
    if (!BaseEval().ParseCache.WriteToFile(BaseConst().ParseCacheFile)) {
      Log().ErrorFile(GenT::GEN, BaseConst().ParseCacheFile,
                      "Parse cache file writing failed.");
      return false;
    }
  }
  return true;
}

bool cmQtAutoMocUic::CreateDirectories()
{
  // Create AUTOGEN include directory
  if (!cmSystemTools::MakeDirectory(BaseConst().AutogenIncludeDir)) {
    Log().ErrorFile(GenT::GEN, BaseConst().AutogenIncludeDir,
                    "Could not create directory.");
    return false;
  }
  return true;
}

void cmQtAutoMocUic::Abort(bool error)
{
  if (error) {
    JobError_.store(true);
  }
  WorkerPool_.Abort();
}

std::string cmQtAutoMocUic::AbsoluteBuildPath(
  std::string const& relativePath) const
{
  std::string res(BaseConst().AutogenBuildDir);
  res += '/';
  res += relativePath;
  return res;
}

std::string cmQtAutoMocUic::AbsoluteIncludePath(
  std::string const& relativePath) const
{
  std::string res(BaseConst().AutogenIncludeDir);
  res += '/';
  res += relativePath;
  return res;
}
