/* 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 <memory>
#include <set>
#include <sstream>
#include <utility>

#include "cmAlgorithms.h"
#include "cmCryptoHash.h"
#include "cmGeneratedFileStream.h"
#include "cmMakefile.h"
#include "cmQtAutoGen.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 const& 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),
                            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;
}
