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