/* 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 (cmSystemTools::StringStartsWith(path, ppath->c_str())) {
              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;
}
