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

#include <algorithm>
#include <array>
#include <functional>
#include <list>
#include <memory>
#include <sstream>
#include <utility>

#include "cmAlgorithms.h"
#include "cmCryptoHash.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
#include "cmake.h"

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

// -- Class methods

std::string cmQtAutoGeneratorMocUic::BaseSettingsT::AbsoluteBuildPath(
  std::string const& relativePath) const
{
  return FileSys->CollapseCombinedPath(AutogenBuildDir, relativePath);
}

/**
 * @brief Tries to find the header file to the given file base path by
 * appending different header extensions
 * @return True on success
 */
bool cmQtAutoGeneratorMocUic::BaseSettingsT::FindHeader(
  std::string& header, std::string const& testBasePath) const
{
  for (std::string const& ext : HeaderExtensions) {
    std::string testFilePath(testBasePath);
    testFilePath.push_back('.');
    testFilePath += ext;
    if (FileSys->FileExists(testFilePath)) {
      header = testFilePath;
      return true;
    }
  }
  return false;
}

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

/**
 * @brief Returns the first relevant Qt macro name found in the given C++ code
 * @return The name of the Qt macro or an empty string
 */
std::string cmQtAutoGeneratorMocUic::MocSettingsT::FindMacro(
  std::string const& content) const
{
  for (KeyExpT const& filter : MacroFilters) {
    // Run a simple find string operation before the expensive
    // regular expression check
    if (content.find(filter.Key) != std::string::npos) {
      cmsys::RegularExpressionMatch match;
      if (filter.Exp.find(content.c_str(), match)) {
        // Return macro name on demand
        return filter.Key;
      }
    }
  }
  return std::string();
}

std::string cmQtAutoGeneratorMocUic::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;
}

std::string cmQtAutoGeneratorMocUic::MocSettingsT::FindIncludedFile(
  std::string const& sourcePath, std::string const& includeString) const
{
  // Search in vicinity of the source
  {
    std::string testPath = sourcePath;
    testPath += includeString;
    if (FileSys->FileExists(testPath)) {
      return FileSys->GetRealPath(testPath);
    }
  }
  // Search in include directories
  for (std::string const& path : IncludePaths) {
    std::string fullPath = path;
    fullPath.push_back('/');
    fullPath += includeString;
    if (FileSys->FileExists(fullPath)) {
      return FileSys->GetRealPath(fullPath);
    }
  }
  // Return empty string
  return std::string();
}

void cmQtAutoGeneratorMocUic::MocSettingsT::FindDependencies(
  std::string const& content, std::set<std::string>& depends) const
{
  if (!DependFilters.empty() && !content.empty()) {
    for (KeyExpT const& filter : DependFilters) {
      // Run a simple find string check
      if (content.find(filter.Key) != std::string::npos) {
        // 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()) {
              depends.emplace(std::move(dep));
            }
          }
          contentChars += match.end();
        }
      }
    }
  }
}

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

void cmQtAutoGeneratorMocUic::JobParseT::Process(WorkerT& wrk)
{
  if (AutoMoc && Header) {
    // Don't parse header for moc if the file is included by a source already
    if (wrk.Gen().ParallelMocIncluded(FileName)) {
      AutoMoc = false;
    }
  }

  if (AutoMoc || AutoUic) {
    std::string error;
    MetaT meta;
    if (wrk.FileSys().FileRead(meta.Content, FileName, &error)) {
      if (!meta.Content.empty()) {
        meta.FileDir = wrk.FileSys().SubDirPrefix(FileName);
        meta.FileBase =
          wrk.FileSys().GetFilenameWithoutLastExtension(FileName);

        bool success = true;
        if (AutoMoc) {
          if (Header) {
            success = ParseMocHeader(wrk, meta);
          } else {
            success = ParseMocSource(wrk, meta);
          }
        }
        if (AutoUic && success) {
          ParseUic(wrk, meta);
        }
      } else {
        wrk.LogFileWarning(GeneratorT::GEN, FileName,
                           "The source file is empty");
      }
    } else {
      wrk.LogFileError(GeneratorT::GEN, FileName,
                       "Could not read the file: " + error);
    }
  }
}

bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk,
                                                        MetaT const& meta)
{
  struct JobPre
  {
    bool self;       // source file is self
    bool underscore; // "moc_" style include
    std::string SourceFile;
    std::string IncludeString;
  };

  struct MocInclude
  {
    std::string Inc;  // full include string
    std::string Dir;  // include string directory
    std::string Base; // include string file base
  };

  // Check if this source file contains a relevant macro
  std::string const ownMacro = wrk.Moc().FindMacro(meta.Content);

  // Extract moc includes from file
  std::deque<MocInclude> mocIncsUsc;
  std::deque<MocInclude> mocIncsDot;
  {
    if (meta.Content.find("moc") != std::string::npos) {
      const char* contentChars = meta.Content.c_str();
      cmsys::RegularExpressionMatch match;
      while (wrk.Moc().RegExpInclude.find(contentChars, match)) {
        std::string incString = match.match(2);
        std::string incDir(wrk.FileSys().SubDirPrefix(incString));
        std::string incBase =
          wrk.FileSys().GetFilenameWithoutLastExtension(incString);
        if (cmHasLiteralPrefix(incBase, "moc_")) {
          // moc_<BASE>.cxx
          // Remove the moc_ part from the base name
          mocIncsUsc.emplace_back(MocInclude{
            std::move(incString), std::move(incDir), incBase.substr(4) });
        } else {
          // <BASE>.moc
          mocIncsDot.emplace_back(MocInclude{
            std::move(incString), std::move(incDir), std::move(incBase) });
        }
        // Forward content pointer
        contentChars += match.end();
      }
    }
  }

  // Check if there is anything to do
  if (ownMacro.empty() && mocIncsUsc.empty() && mocIncsDot.empty()) {
    return true;
  }

  bool ownDotMocIncluded = false;
  bool ownMocUscIncluded = false;
  std::deque<JobPre> jobs;

  // Process moc_<BASE>.cxx includes
  for (const MocInclude& mocInc : mocIncsUsc) {
    std::string const header =
      MocFindIncludedHeader(wrk, meta.FileDir, mocInc.Dir + mocInc.Base);
    if (!header.empty()) {
      // Check if header is skipped
      if (wrk.Moc().skipped(header)) {
        continue;
      }
      // Register moc job
      const bool ownMoc = (mocInc.Base == meta.FileBase);
      jobs.emplace_back(JobPre{ ownMoc, true, header, mocInc.Inc });
      // Store meta information for relaxed mode
      if (ownMoc) {
        ownMocUscIncluded = true;
      }
    } else {
      {
        std::string emsg = "The file includes the moc file ";
        emsg += Quoted(mocInc.Inc);
        emsg += ", but the header ";
        emsg += Quoted(MocStringHeaders(wrk, mocInc.Base));
        emsg += " could not be found.";
        wrk.LogFileError(GeneratorT::MOC, FileName, emsg);
      }
      return false;
    }
  }

  // Process <BASE>.moc includes
  for (const MocInclude& mocInc : mocIncsDot) {
    const bool ownMoc = (mocInc.Base == meta.FileBase);
    if (wrk.Moc().RelaxedMode) {
      // Relaxed mode
      if (!ownMacro.empty() && ownMoc) {
        // Add self
        jobs.emplace_back(JobPre{ ownMoc, false, FileName, mocInc.Inc });
        ownDotMocIncluded = true;
      } else {
        // In relaxed mode try to find a header instead but issue a warning.
        // This is for KDE4 compatibility
        std::string const header =
          MocFindIncludedHeader(wrk, meta.FileDir, mocInc.Dir + mocInc.Base);
        if (!header.empty()) {
          // Check if header is skipped
          if (wrk.Moc().skipped(header)) {
            continue;
          }
          // Register moc job
          jobs.emplace_back(JobPre{ ownMoc, false, header, mocInc.Inc });
          if (ownMacro.empty()) {
            if (ownMoc) {
              std::string emsg = "The file includes the moc file ";
              emsg += Quoted(mocInc.Inc);
              emsg += ", but does not contain a ";
              emsg += wrk.Moc().MacrosString();
              emsg += " macro.\nRunning moc on\n  ";
              emsg += Quoted(header);
              emsg += "!\nBetter include ";
              emsg += Quoted("moc_" + mocInc.Base + ".cpp");
              emsg += " for a compatibility with strict mode.\n"
                      "(CMAKE_AUTOMOC_RELAXED_MODE warning)\n";
              wrk.LogFileWarning(GeneratorT::MOC, FileName, emsg);
            } else {
              std::string emsg = "The file includes the moc file ";
              emsg += Quoted(mocInc.Inc);
              emsg += " instead of ";
              emsg += Quoted("moc_" + mocInc.Base + ".cpp");
              emsg += ".\nRunning moc on\n  ";
              emsg += Quoted(header);
              emsg += "!\nBetter include ";
              emsg += Quoted("moc_" + mocInc.Base + ".cpp");
              emsg += " for compatibility with strict mode.\n"
                      "(CMAKE_AUTOMOC_RELAXED_MODE warning)\n";
              wrk.LogFileWarning(GeneratorT::MOC, FileName, emsg);
            }
          }
        } else {
          {
            std::string emsg = "The file includes the moc file ";
            emsg += Quoted(mocInc.Inc);
            emsg += ", which seems to be the moc file from a different "
                    "source file.\nCMAKE_AUTOMOC_RELAXED_MODE: Also a "
                    "matching header ";
            emsg += Quoted(MocStringHeaders(wrk, mocInc.Base));
            emsg += " could not be found.";
            wrk.LogFileError(GeneratorT::MOC, FileName, emsg);
          }
          return false;
        }
      }
    } else {
      // Strict mode
      if (ownMoc) {
        // Include self
        jobs.emplace_back(JobPre{ ownMoc, false, FileName, mocInc.Inc });
        ownDotMocIncluded = true;
        // Accept but issue a warning if moc isn't required
        if (ownMacro.empty()) {
          std::string emsg = "The file includes the moc file ";
          emsg += Quoted(mocInc.Inc);
          emsg += ", but does not contain a ";
          emsg += wrk.Moc().MacrosString();
          emsg += " macro.";
          wrk.LogFileWarning(GeneratorT::MOC, FileName, emsg);
        }
      } else {
        // Don't allow <BASE>.moc include other than self in strict mode
        {
          std::string emsg = "The file includes the moc file ";
          emsg += Quoted(mocInc.Inc);
          emsg += ", which seems to be the moc file from a different "
                  "source file.\nThis is not supported. Include ";
          emsg += Quoted(meta.FileBase + ".moc");
          emsg += " to run moc on this source file.";
          wrk.LogFileError(GeneratorT::MOC, FileName, emsg);
        }
        return false;
      }
    }
  }

  if (!ownMacro.empty() && !ownDotMocIncluded) {
    // In this case, check whether the scanned file itself contains a
    // Q_OBJECT.
    // If this is the case, the moc_foo.cpp should probably be generated from
    // foo.cpp instead of foo.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.
    if (wrk.Moc().RelaxedMode && ownMocUscIncluded) {
      JobPre uscJobPre;
      // Remove underscore job request
      {
        auto itC = jobs.begin();
        auto itE = jobs.end();
        for (; itC != itE; ++itC) {
          JobPre& job(*itC);
          if (job.self && job.underscore) {
            uscJobPre = std::move(job);
            jobs.erase(itC);
            break;
          }
        }
      }
      // Issue a warning
      {
        std::string emsg = "The file contains a ";
        emsg += ownMacro;
        emsg += " macro, but does not include ";
        emsg += Quoted(meta.FileBase + ".moc");
        emsg += ". Instead it includes ";
        emsg += Quoted(uscJobPre.IncludeString);
        emsg += ".\nRunning moc on\n  ";
        emsg += Quoted(FileName);
        emsg += "!\nBetter include ";
        emsg += Quoted(meta.FileBase + ".moc");
        emsg += " for compatibility with strict mode.\n"
                "(CMAKE_AUTOMOC_RELAXED_MODE warning)";
        wrk.LogFileWarning(GeneratorT::MOC, FileName, emsg);
      }
      // Add own source job
      jobs.emplace_back(
        JobPre{ true, false, FileName, uscJobPre.IncludeString });
    } else {
      // Otherwise always error out since it will not compile.
      {
        std::string emsg = "The file contains a ";
        emsg += ownMacro;
        emsg += " macro, but does not include ";
        emsg += Quoted(meta.FileBase + ".moc");
        emsg += "!\nConsider to\n - add #include \"";
        emsg += meta.FileBase;
        emsg += ".moc\"\n - enable SKIP_AUTOMOC for this file";
        wrk.LogFileError(GeneratorT::MOC, FileName, emsg);
      }
      return false;
    }
  }

  // Convert pre jobs to actual jobs
  for (JobPre& jobPre : jobs) {
    JobHandleT jobHandle(new JobMocT(std::move(jobPre.SourceFile), FileName,
                                     std::move(jobPre.IncludeString)));
    if (jobPre.self) {
      // Read depdendencies from this source
      static_cast<JobMocT&>(*jobHandle).FindDependencies(wrk, meta.Content);
    }
    if (!wrk.Gen().ParallelJobPushMoc(jobHandle)) {
      return false;
    }
  }
  return true;
}

bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocHeader(WorkerT& wrk,
                                                        MetaT const& meta)
{
  bool success = true;
  std::string const macroName = wrk.Moc().FindMacro(meta.Content);
  if (!macroName.empty()) {
    JobHandleT jobHandle(
      new JobMocT(std::string(FileName), std::string(), std::string()));
    // Read depdendencies from this source
    static_cast<JobMocT&>(*jobHandle).FindDependencies(wrk, meta.Content);
    success = wrk.Gen().ParallelJobPushMoc(jobHandle);
  }
  return success;
}

std::string cmQtAutoGeneratorMocUic::JobParseT::MocStringHeaders(
  WorkerT& wrk, std::string const& fileBase) const
{
  std::string res = fileBase;
  res += ".{";
  res += cmJoin(wrk.Base().HeaderExtensions, ",");
  res += "}";
  return res;
}

std::string cmQtAutoGeneratorMocUic::JobParseT::MocFindIncludedHeader(
  WorkerT& wrk, std::string const& includerDir, std::string const& includeBase)
{
  std::string header;
  // Search in vicinity of the source
  if (!wrk.Base().FindHeader(header, includerDir + includeBase)) {
    // Search in include directories
    for (std::string const& path : wrk.Moc().IncludePaths) {
      std::string fullPath = path;
      fullPath.push_back('/');
      fullPath += includeBase;
      if (wrk.Base().FindHeader(header, fullPath)) {
        break;
      }
    }
  }
  // Sanitize
  if (!header.empty()) {
    header = wrk.FileSys().GetRealPath(header);
  }
  return header;
}

bool cmQtAutoGeneratorMocUic::JobParseT::ParseUic(WorkerT& wrk,
                                                  MetaT const& meta)
{
  bool success = true;
  if (meta.Content.find("ui_") != std::string::npos) {
    const char* contentChars = meta.Content.c_str();
    cmsys::RegularExpressionMatch match;
    while (wrk.Uic().RegExpInclude.find(contentChars, match)) {
      if (!ParseUicInclude(wrk, meta, match.match(2))) {
        success = false;
        break;
      }
      contentChars += match.end();
    }
  }
  return success;
}

bool cmQtAutoGeneratorMocUic::JobParseT::ParseUicInclude(
  WorkerT& wrk, MetaT const& meta, std::string&& includeString)
{
  bool success = false;
  std::string uiInputFile = UicFindIncludedFile(wrk, meta, includeString);
  if (!uiInputFile.empty()) {
    if (!wrk.Uic().skipped(uiInputFile)) {
      JobHandleT jobHandle(new JobUicT(std::move(uiInputFile), FileName,
                                       std::move(includeString)));
      success = wrk.Gen().ParallelJobPushUic(jobHandle);
    } else {
      // A skipped file is successful
      success = true;
    }
  }
  return success;
}

std::string cmQtAutoGeneratorMocUic::JobParseT::UicFindIncludedFile(
  WorkerT& wrk, MetaT const& meta, std::string const& includeString)
{
  std::string res;
  std::string searchFile =
    wrk.FileSys().GetFilenameWithoutLastExtension(includeString).substr(3);
  searchFile += ".ui";
  // Collect search paths list
  std::deque<std::string> testFiles;
  {
    std::string const searchPath = wrk.FileSys().SubDirPrefix(includeString);

    std::string searchFileFull;
    if (!searchPath.empty()) {
      searchFileFull = searchPath;
      searchFileFull += searchFile;
    }
    // Vicinity of the source
    {
      std::string const sourcePath = meta.FileDir;
      testFiles.push_back(sourcePath + searchFile);
      if (!searchPath.empty()) {
        testFiles.push_back(sourcePath + searchFileFull);
      }
    }
    // AUTOUIC search paths
    if (!wrk.Uic().SearchPaths.empty()) {
      for (std::string const& sPath : wrk.Uic().SearchPaths) {
        testFiles.push_back((sPath + "/").append(searchFile));
      }
      if (!searchPath.empty()) {
        for (std::string const& sPath : wrk.Uic().SearchPaths) {
          testFiles.push_back((sPath + "/").append(searchFileFull));
        }
      }
    }
  }

  // Search for the .ui file!
  for (std::string const& testFile : testFiles) {
    if (wrk.FileSys().FileExists(testFile)) {
      res = wrk.FileSys().GetRealPath(testFile);
      break;
    }
  }

  // Log error
  if (res.empty()) {
    std::string emsg = "Could not find ";
    emsg += Quoted(searchFile);
    emsg += " in\n";
    for (std::string const& testFile : testFiles) {
      emsg += "  ";
      emsg += Quoted(testFile);
      emsg += "\n";
    }
    wrk.LogFileError(GeneratorT::UIC, FileName, emsg);
  }

  return res;
}

void cmQtAutoGeneratorMocUic::JobMocPredefsT::Process(WorkerT& wrk)
{
  // (Re)generate moc_predefs.h on demand
  bool generate(false);
  bool fileExists(wrk.FileSys().FileExists(wrk.Moc().PredefsFileAbs));
  if (!fileExists) {
    if (wrk.Log().Verbose()) {
      std::string reason = "Generating ";
      reason += Quoted(wrk.Moc().PredefsFileRel);
      reason += " because it doesn't exist";
      wrk.LogInfo(GeneratorT::MOC, reason);
    }
    generate = true;
  } else if (wrk.Moc().SettingsChanged) {
    if (wrk.Log().Verbose()) {
      std::string reason = "Generating ";
      reason += Quoted(wrk.Moc().PredefsFileRel);
      reason += " because the settings changed.";
      wrk.LogInfo(GeneratorT::MOC, reason);
    }
    generate = true;
  }
  if (generate) {
    ProcessResultT result;
    {
      // Compose command
      std::vector<std::string> cmd = wrk.Moc().PredefsCmd;
      // Add includes
      cmd.insert(cmd.end(), wrk.Moc().Includes.begin(),
                 wrk.Moc().Includes.end());
      // Add definitions
      for (std::string const& def : wrk.Moc().Definitions) {
        cmd.push_back("-D" + def);
      }
      // Execute command
      if (!wrk.RunProcess(GeneratorT::MOC, result, cmd)) {
        std::string emsg = "The content generation command for ";
        emsg += Quoted(wrk.Moc().PredefsFileRel);
        emsg += " failed.\n";
        emsg += result.ErrorMessage;
        wrk.LogCommandError(GeneratorT::MOC, emsg, cmd, result.StdOut);
      }
    }

    // (Re)write predefs file only on demand
    if (!result.error()) {
      if (!fileExists ||
          wrk.FileSys().FileDiffers(wrk.Moc().PredefsFileAbs, result.StdOut)) {
        if (wrk.FileSys().FileWrite(GeneratorT::MOC, wrk.Moc().PredefsFileAbs,
                                    result.StdOut)) {
          // Success
        } else {
          std::string emsg = "Writing ";
          emsg += Quoted(wrk.Moc().PredefsFileRel);
          emsg += " failed.";
          wrk.LogFileError(GeneratorT::MOC, wrk.Moc().PredefsFileAbs, emsg);
        }
      } else {
        // Touch to update the time stamp
        if (wrk.Log().Verbose()) {
          std::string msg = "Touching ";
          msg += Quoted(wrk.Moc().PredefsFileRel);
          msg += ".";
          wrk.LogInfo(GeneratorT::MOC, msg);
        }
        wrk.FileSys().Touch(wrk.Moc().PredefsFileAbs);
      }
    }
  }
}

void cmQtAutoGeneratorMocUic::JobMocT::FindDependencies(
  WorkerT& wrk, std::string const& content)
{
  wrk.Moc().FindDependencies(content, Depends);
  DependsValid = true;
}

void cmQtAutoGeneratorMocUic::JobMocT::Process(WorkerT& wrk)
{
  // Compute build file name
  if (!IncludeString.empty()) {
    BuildFile = wrk.Base().AutogenIncludeDir;
    BuildFile += '/';
    BuildFile += IncludeString;
  } else {
    std::string rel = wrk.FileSys().GetFilePathChecksum(SourceFile);
    rel += "/moc_";
    rel += wrk.FileSys().GetFilenameWithoutLastExtension(SourceFile);
    rel += ".cpp";
    // Register relative file path
    wrk.Gen().ParallelMocAutoRegister(rel);
    // Absolute build path
    if (wrk.Base().MultiConfig) {
      BuildFile = wrk.Base().AutogenIncludeDir;
      BuildFile += '/';
      BuildFile += rel;
    } else {
      BuildFile = wrk.Base().AbsoluteBuildPath(rel);
    }
  }

  if (UpdateRequired(wrk)) {
    GenerateMoc(wrk);
  }
}

bool cmQtAutoGeneratorMocUic::JobMocT::UpdateRequired(WorkerT& wrk)
{
  bool const verbose = wrk.Gen().Log().Verbose();

  // Test if the build file exists
  if (!wrk.FileSys().FileExists(BuildFile)) {
    if (verbose) {
      std::string reason = "Generating ";
      reason += Quoted(BuildFile);
      reason += " from its source file ";
      reason += Quoted(SourceFile);
      reason += " because it doesn't exist";
      wrk.LogInfo(GeneratorT::MOC, reason);
    }
    return true;
  }

  // Test if any setting changed
  if (wrk.Moc().SettingsChanged) {
    if (verbose) {
      std::string reason = "Generating ";
      reason += Quoted(BuildFile);
      reason += " from ";
      reason += Quoted(SourceFile);
      reason += " because the MOC settings changed";
      wrk.LogInfo(GeneratorT::MOC, reason);
    }
    return true;
  }

  // Test if the moc_predefs file is newer
  if (!wrk.Moc().PredefsFileAbs.empty()) {
    bool isOlder = false;
    {
      std::string error;
      isOlder = wrk.FileSys().FileIsOlderThan(
        BuildFile, wrk.Moc().PredefsFileAbs, &error);
      if (!isOlder && !error.empty()) {
        wrk.LogError(GeneratorT::MOC, error);
        return false;
      }
    }
    if (isOlder) {
      if (verbose) {
        std::string reason = "Generating ";
        reason += Quoted(BuildFile);
        reason += " because it's older than: ";
        reason += Quoted(wrk.Moc().PredefsFileAbs);
        wrk.LogInfo(GeneratorT::MOC, reason);
      }
      return true;
    }
  }

  // Test if the source file is newer
  {
    bool isOlder = false;
    {
      std::string error;
      isOlder = wrk.FileSys().FileIsOlderThan(BuildFile, SourceFile, &error);
      if (!isOlder && !error.empty()) {
        wrk.LogError(GeneratorT::MOC, error);
        return false;
      }
    }
    if (isOlder) {
      if (verbose) {
        std::string reason = "Generating ";
        reason += Quoted(BuildFile);
        reason += " because it's older than its source file ";
        reason += Quoted(SourceFile);
        wrk.LogInfo(GeneratorT::MOC, reason);
      }
      return true;
    }
  }

  // Test if a dependency file is newer
  {
    // Read dependencies on demand
    if (!DependsValid) {
      std::string content;
      {
        std::string error;
        if (!wrk.FileSys().FileRead(content, SourceFile, &error)) {
          std::string emsg = "Could not read file\n  ";
          emsg += Quoted(SourceFile);
          emsg += "\nrequired by moc include ";
          emsg += Quoted(IncludeString);
          emsg += " in\n  ";
          emsg += Quoted(IncluderFile);
          emsg += ".\n";
          emsg += error;
          wrk.LogError(GeneratorT::MOC, emsg);
          return false;
        }
      }
      FindDependencies(wrk, content);
    }
    // Check dependency timestamps
    std::string error;
    std::string sourceDir = wrk.FileSys().SubDirPrefix(SourceFile);
    for (std::string const& depFileRel : Depends) {
      std::string depFileAbs =
        wrk.Moc().FindIncludedFile(sourceDir, depFileRel);
      if (!depFileAbs.empty()) {
        if (wrk.FileSys().FileIsOlderThan(BuildFile, depFileAbs, &error)) {
          if (verbose) {
            std::string reason = "Generating ";
            reason += Quoted(BuildFile);
            reason += " from ";
            reason += Quoted(SourceFile);
            reason += " because it is older than it's dependency file ";
            reason += Quoted(depFileAbs);
            wrk.LogInfo(GeneratorT::MOC, reason);
          }
          return true;
        }
        if (!error.empty()) {
          wrk.LogError(GeneratorT::MOC, error);
          return false;
        }
      } else {
        std::string message = "Could not find dependency file ";
        message += Quoted(depFileRel);
        wrk.LogFileWarning(GeneratorT::MOC, SourceFile, message);
      }
    }
  }

  return false;
}

void cmQtAutoGeneratorMocUic::JobMocT::GenerateMoc(WorkerT& wrk)
{
  // Make sure the parent directory exists
  if (wrk.FileSys().MakeParentDirectory(GeneratorT::MOC, BuildFile)) {
    // Compose moc command
    std::vector<std::string> cmd;
    cmd.push_back(wrk.Moc().Executable);
    // Add options
    cmd.insert(cmd.end(), wrk.Moc().AllOptions.begin(),
               wrk.Moc().AllOptions.end());
    // Add predefs include
    if (!wrk.Moc().PredefsFileAbs.empty()) {
      cmd.push_back("--include");
      cmd.push_back(wrk.Moc().PredefsFileAbs);
    }
    cmd.push_back("-o");
    cmd.push_back(BuildFile);
    cmd.push_back(SourceFile);

    // Execute moc command
    ProcessResultT result;
    if (wrk.RunProcess(GeneratorT::MOC, result, cmd)) {
      // Moc command success
      // Print moc output
      if (!result.StdOut.empty()) {
        wrk.LogInfo(GeneratorT::MOC, result.StdOut);
      }
      // Notify the generator that a not included file changed (on demand)
      if (IncludeString.empty()) {
        wrk.Gen().ParallelMocAutoUpdated();
      }
    } else {
      // Moc command failed
      {
        std::string emsg = "The moc process failed to compile\n  ";
        emsg += Quoted(SourceFile);
        emsg += "\ninto\n  ";
        emsg += Quoted(BuildFile);
        emsg += ".\n";
        emsg += result.ErrorMessage;
        wrk.LogCommandError(GeneratorT::MOC, emsg, cmd, result.StdOut);
      }
      wrk.FileSys().FileRemove(BuildFile);
    }
  }
}

void cmQtAutoGeneratorMocUic::JobUicT::Process(WorkerT& wrk)
{
  // Compute build file name
  BuildFile = wrk.Base().AutogenIncludeDir;
  BuildFile += '/';
  BuildFile += IncludeString;

  if (UpdateRequired(wrk)) {
    GenerateUic(wrk);
  }
}

bool cmQtAutoGeneratorMocUic::JobUicT::UpdateRequired(WorkerT& wrk)
{
  bool const verbose = wrk.Gen().Log().Verbose();

  // Test if the build file exists
  if (!wrk.FileSys().FileExists(BuildFile)) {
    if (verbose) {
      std::string reason = "Generating ";
      reason += Quoted(BuildFile);
      reason += " from its source file ";
      reason += Quoted(SourceFile);
      reason += " because it doesn't exist";
      wrk.LogInfo(GeneratorT::UIC, reason);
    }
    return true;
  }

  // Test if the uic settings changed
  if (wrk.Uic().SettingsChanged) {
    if (verbose) {
      std::string reason = "Generating ";
      reason += Quoted(BuildFile);
      reason += " from ";
      reason += Quoted(SourceFile);
      reason += " because the UIC settings changed";
      wrk.LogInfo(GeneratorT::UIC, reason);
    }
    return true;
  }

  // Test if the source file is newer
  {
    bool isOlder = false;
    {
      std::string error;
      isOlder = wrk.FileSys().FileIsOlderThan(BuildFile, SourceFile, &error);
      if (!isOlder && !error.empty()) {
        wrk.LogError(GeneratorT::UIC, error);
        return false;
      }
    }
    if (isOlder) {
      if (verbose) {
        std::string reason = "Generating ";
        reason += Quoted(BuildFile);
        reason += " because it's older than its source file ";
        reason += Quoted(SourceFile);
        wrk.LogInfo(GeneratorT::UIC, reason);
      }
      return true;
    }
  }

  return false;
}

void cmQtAutoGeneratorMocUic::JobUicT::GenerateUic(WorkerT& wrk)
{
  // Make sure the parent directory exists
  if (wrk.FileSys().MakeParentDirectory(GeneratorT::UIC, BuildFile)) {
    // Compose uic command
    std::vector<std::string> cmd;
    cmd.push_back(wrk.Uic().Executable);
    {
      std::vector<std::string> allOpts = wrk.Uic().TargetOptions;
      auto optionIt = wrk.Uic().Options.find(SourceFile);
      if (optionIt != wrk.Uic().Options.end()) {
        UicMergeOptions(allOpts, optionIt->second,
                        (wrk.Base().QtVersionMajor == 5));
      }
      cmd.insert(cmd.end(), allOpts.begin(), allOpts.end());
    }
    cmd.push_back("-o");
    cmd.push_back(BuildFile);
    cmd.push_back(SourceFile);

    ProcessResultT result;
    if (wrk.RunProcess(GeneratorT::UIC, result, cmd)) {
      // Uic command success
      // Print uic output
      if (!result.StdOut.empty()) {
        wrk.LogInfo(GeneratorT::UIC, result.StdOut);
      }
    } else {
      // Uic command failed
      {
        std::string emsg = "The uic process failed to compile\n  ";
        emsg += Quoted(SourceFile);
        emsg += "\ninto\n  ";
        emsg += Quoted(BuildFile);
        emsg += "\nincluded by\n  ";
        emsg += Quoted(IncluderFile);
        emsg += ".\n";
        emsg += result.ErrorMessage;
        wrk.LogCommandError(GeneratorT::UIC, emsg, cmd, result.StdOut);
      }
      wrk.FileSys().FileRemove(BuildFile);
    }
  }
}

void cmQtAutoGeneratorMocUic::JobDeleterT::operator()(JobT* job)
{
  delete job;
}

cmQtAutoGeneratorMocUic::WorkerT::WorkerT(cmQtAutoGeneratorMocUic* gen,
                                          uv_loop_t* uvLoop)
  : Gen_(gen)
{
  // Initialize uv asynchronous callback for process starting
  ProcessRequest_.init(*uvLoop, &WorkerT::UVProcessStart, this);
  // Start thread
  Thread_ = std::thread(&WorkerT::Loop, this);
}

cmQtAutoGeneratorMocUic::WorkerT::~WorkerT()
{
  // Join thread
  if (Thread_.joinable()) {
    Thread_.join();
  }
}

void cmQtAutoGeneratorMocUic::WorkerT::LogInfo(
  GeneratorT genType, std::string const& message) const
{
  return Log().Info(genType, message);
}

void cmQtAutoGeneratorMocUic::WorkerT::LogWarning(
  GeneratorT genType, std::string const& message) const
{
  return Log().Warning(genType, message);
}

void cmQtAutoGeneratorMocUic::WorkerT::LogFileWarning(
  GeneratorT genType, std::string const& filename,
  std::string const& message) const
{
  return Log().WarningFile(genType, filename, message);
}

void cmQtAutoGeneratorMocUic::WorkerT::LogError(
  GeneratorT genType, std::string const& message) const
{
  Gen().ParallelRegisterJobError();
  Log().Error(genType, message);
}

void cmQtAutoGeneratorMocUic::WorkerT::LogFileError(
  GeneratorT genType, std::string const& filename,
  std::string const& message) const
{
  Gen().ParallelRegisterJobError();
  Log().ErrorFile(genType, filename, message);
}

void cmQtAutoGeneratorMocUic::WorkerT::LogCommandError(
  GeneratorT genType, std::string const& message,
  std::vector<std::string> const& command, std::string const& output) const
{
  Gen().ParallelRegisterJobError();
  Log().ErrorCommand(genType, message, command, output);
}

bool cmQtAutoGeneratorMocUic::WorkerT::RunProcess(
  GeneratorT genType, ProcessResultT& result,
  std::vector<std::string> const& command)
{
  if (command.empty()) {
    return false;
  }

  // Create process instance
  {
    std::lock_guard<std::mutex> lock(ProcessMutex_);
    Process_ = cm::make_unique<ReadOnlyProcessT>();
    Process_->setup(&result, true, command, Gen().Base().AutogenBuildDir);
  }

  // Send asynchronous process start request to libuv loop
  ProcessRequest_.send();

  // Log command
  if (this->Log().Verbose()) {
    std::string msg = "Running command:\n";
    msg += QuotedCommand(command);
    msg += '\n';
    this->LogInfo(genType, msg);
  }

  // Wait until the process has been finished and destroyed
  {
    std::unique_lock<std::mutex> ulock(ProcessMutex_);
    while (Process_) {
      ProcessCondition_.wait(ulock);
    }
  }
  return !result.error();
}

void cmQtAutoGeneratorMocUic::WorkerT::Loop()
{
  while (true) {
    Gen().WorkerSwapJob(JobHandle_);
    if (JobHandle_) {
      JobHandle_->Process(*this);
    } else {
      break;
    }
  }
}

void cmQtAutoGeneratorMocUic::WorkerT::UVProcessStart(uv_async_t* handle)
{
  auto& wrk = *reinterpret_cast<WorkerT*>(handle->data);
  {
    std::lock_guard<std::mutex> lock(wrk.ProcessMutex_);
    if (wrk.Process_ && !wrk.Process_->IsStarted()) {
      wrk.Process_->start(handle->loop,
                          std::bind(&WorkerT::UVProcessFinished, &wrk));
    }
  }
}

void cmQtAutoGeneratorMocUic::WorkerT::UVProcessFinished()
{
  {
    std::lock_guard<std::mutex> lock(ProcessMutex_);
    if (Process_ && Process_->IsFinished()) {
      Process_.reset();
    }
  }
  // Notify idling thread
  ProcessCondition_.notify_one();
}

cmQtAutoGeneratorMocUic::cmQtAutoGeneratorMocUic()
  : Base_(&FileSys())
  , Moc_(&FileSys())
  , Stage_(StageT::SETTINGS_READ)
  , JobsRemain_(0)
  , JobError_(false)
  , JobThreadsAbort_(false)
  , MocAutoFileUpdated_(false)
{
  // Precompile regular expressions
  Moc_.RegExpInclude.compile(
    "(^|\n)[ \t]*#[ \t]*include[ \t]+"
    "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
  Uic_.RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+"
                             "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");

  // Initialize libuv asynchronous iteration request
  UVRequest().init(*UVLoop(), &cmQtAutoGeneratorMocUic::UVPollStage, this);
}

cmQtAutoGeneratorMocUic::~cmQtAutoGeneratorMocUic()
{
}

bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile)
{
  // -- Meta
  Base_.HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions();

  // 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) {
      valueConf = 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;
  };

  // -- Read info file
  if (!makefile->ReadListFile(InfoFile().c_str())) {
    Log().ErrorFile(GeneratorT::GEN, InfoFile(), "File processing failed");
    return false;
  }

  // -- Meta
  Base_.MultiConfig = InfoGetBool("AM_MULTI_CONFIG");
  {
    unsigned long num = Base_.NumThreads;
    if (cmSystemTools::StringToULong(InfoGet("AM_PARALLEL"), &num)) {
      num = std::max<unsigned long>(num, 1);
      num = std::min<unsigned long>(num, ParallelMax);
      Base_.NumThreads = static_cast<unsigned int>(num);
    }
  }

  // - Files and directories
  Base_.ProjectSourceDir = InfoGet("AM_CMAKE_SOURCE_DIR");
  Base_.ProjectBinaryDir = InfoGet("AM_CMAKE_BINARY_DIR");
  Base_.CurrentSourceDir = InfoGet("AM_CMAKE_CURRENT_SOURCE_DIR");
  Base_.CurrentBinaryDir = InfoGet("AM_CMAKE_CURRENT_BINARY_DIR");
  Base_.IncludeProjectDirsBefore =
    InfoGetBool("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE");
  Base_.AutogenBuildDir = InfoGet("AM_BUILD_DIR");
  if (Base_.AutogenBuildDir.empty()) {
    Log().ErrorFile(GeneratorT::GEN, InfoFile(),
                    "Autogen build directory missing");
    return false;
  }
  // include directory
  {
    std::string dirRel = InfoGetConfig("AM_INCLUDE_DIR");
    if (dirRel.empty()) {
      Log().ErrorFile(GeneratorT::GEN, InfoFile(),
                      "Autogen include directory missing");
      return false;
    }
    Base_.AutogenIncludeDir = Base_.AbsoluteBuildPath(dirRel);
  }

  // - Files
  SettingsFile_ = InfoGetConfig("AM_SETTINGS_FILE");
  if (SettingsFile_.empty()) {
    Log().ErrorFile(GeneratorT::GEN, InfoFile(), "Settings file name missing");
    return false;
  }

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

  // - Moc
  Moc_.Executable = InfoGet("AM_QT_MOC_EXECUTABLE");
  Moc_.Enabled = !Moc().Executable.empty();
  if (Moc().Enabled) {
    {
      auto lst = InfoGetList("AM_MOC_SKIP");
      Moc_.SkipList.insert(lst.begin(), lst.end());
    }
    Moc_.Definitions = InfoGetConfigList("AM_MOC_DEFINITIONS");
#ifdef _WIN32
    {
      std::string win32("WIN32");
      auto itB = Moc().Definitions.cbegin();
      auto itE = Moc().Definitions.cend();
      if (std::find(itB, itE, win32) == itE) {
        Moc_.Definitions.emplace_back(std::move(win32));
      }
    }
#endif
    Moc_.IncludePaths = InfoGetConfigList("AM_MOC_INCLUDES");
    Moc_.Options = InfoGetList("AM_MOC_OPTIONS");
    Moc_.RelaxedMode = InfoGetBool("AM_MOC_RELAXED_MODE");
    for (std::string const& item : InfoGetList("AM_MOC_MACRO_NAMES")) {
      Moc_.MacroFilters.emplace_back(
        item, ("[\n][ \t]*{?[ \t]*" + item).append("[^a-zA-Z0-9_]"));
    }
    {
      auto pushFilter = [this](std::string const& key, std::string const& exp,
                               std::string& error) {
        if (!key.empty()) {
          if (!exp.empty()) {
            Moc_.DependFilters.push_back(KeyExpT());
            KeyExpT& filter(Moc_.DependFilters.back());
            if (filter.Exp.compile(exp)) {
              filter.Key = key;
            } else {
              error = "Regular expression compiling failed";
            }
          } else {
            error = "Regular expression is empty";
          }
        } else {
          error = "Key is empty";
        }
        if (!error.empty()) {
          error = ("AUTOMOC_DEPEND_FILTERS: " + error);
          error += "\n";
          error += "  Key: ";
          error += Quoted(key);
          error += "\n";
          error += "  Exp: ";
          error += Quoted(exp);
          error += "\n";
        }
      };

      std::string error;
      // Insert default filter for Q_PLUGIN_METADATA
      if (Base().QtVersionMajor != 4) {
        pushFilter("Q_PLUGIN_METADATA", "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\("
                                        "[^\\)]*FILE[ \t]*\"([^\"]+)\"",
                   error);
      }
      // Insert user defined dependency filters
      {
        std::vector<std::string> flts = InfoGetList("AM_MOC_DEPEND_FILTERS");
        if ((flts.size() % 2) == 0) {
          for (std::vector<std::string>::iterator itC = flts.begin(),
                                                  itE = flts.end();
               itC != itE; itC += 2) {
            pushFilter(*itC, *(itC + 1), error);
            if (!error.empty()) {
              break;
            }
          }
        } else {
          Log().ErrorFile(
            GeneratorT::MOC, InfoFile(),
            "AUTOMOC_DEPEND_FILTERS list size is not a multiple of 2");
          return false;
        }
      }
      if (!error.empty()) {
        Log().ErrorFile(GeneratorT::MOC, InfoFile(), error);
        return false;
      }
    }
    Moc_.PredefsCmd = InfoGetList("AM_MOC_PREDEFS_CMD");
    // Install moc predefs job
    if (!Moc().PredefsCmd.empty()) {
      JobQueues_.MocPredefs.emplace_back(new JobMocPredefsT());
    }
  }

  // - Uic
  Uic_.Executable = InfoGet("AM_QT_UIC_EXECUTABLE");
  Uic_.Enabled = !Uic().Executable.empty();
  if (Uic().Enabled) {
    {
      auto lst = InfoGetList("AM_UIC_SKIP");
      Uic_.SkipList.insert(lst.begin(), lst.end());
    }
    Uic_.SearchPaths = InfoGetList("AM_UIC_SEARCH_PATHS");
    Uic_.TargetOptions = InfoGetConfigList("AM_UIC_TARGET_OPTIONS");
    {
      auto sources = InfoGetList("AM_UIC_OPTIONS_FILES");
      auto options = InfoGetLists("AM_UIC_OPTIONS_OPTIONS");
      // Compare list sizes
      if (sources.size() != options.size()) {
        std::ostringstream ost;
        ost << "files/options lists sizes missmatch (" << sources.size() << "/"
            << options.size() << ")";
        Log().ErrorFile(GeneratorT::UIC, InfoFile(), ost.str());
        return false;
      }
      auto fitEnd = sources.cend();
      auto fit = sources.begin();
      auto oit = options.begin();
      while (fit != fitEnd) {
        Uic_.Options[*fit] = std::move(*oit);
        ++fit;
        ++oit;
      }
    }
  }

  // Initialize source file jobs
  {
    std::hash<std::string> stringHash;
    std::set<std::size_t> uniqueHeaders;

    // Add header jobs
    for (std::string& hdr : InfoGetList("AM_HEADERS")) {
      const bool moc = !Moc().skipped(hdr);
      const bool uic = !Uic().skipped(hdr);
      if ((moc || uic) && uniqueHeaders.emplace(stringHash(hdr)).second) {
        JobQueues_.Headers.emplace_back(
          new JobParseT(std::move(hdr), moc, uic, true));
      }
    }
    // Add source jobs
    {
      std::vector<std::string> sources = InfoGetList("AM_SOURCES");
      // Add header(s) for the source file
      for (std::string& src : sources) {
        const bool srcMoc = !Moc().skipped(src);
        const bool srcUic = !Uic().skipped(src);
        if (!srcMoc && !srcUic) {
          continue;
        }
        // Search for the default header file and a private header
        {
          std::array<std::string, 2> bases;
          bases[0] = FileSys().SubDirPrefix(src);
          bases[0] += FileSys().GetFilenameWithoutLastExtension(src);
          bases[1] = bases[0];
          bases[1] += "_p";
          for (std::string const& headerBase : bases) {
            std::string header;
            if (Base().FindHeader(header, headerBase)) {
              const bool moc = srcMoc && !Moc().skipped(header);
              const bool uic = srcUic && !Uic().skipped(header);
              if ((moc || uic) &&
                  uniqueHeaders.emplace(stringHash(header)).second) {
                JobQueues_.Headers.emplace_back(
                  new JobParseT(std::move(header), moc, uic, true));
              }
            }
          }
        }
        // Add source job
        JobQueues_.Sources.emplace_back(
          new JobParseT(std::move(src), srcMoc, srcUic));
      }
    }
  }

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

  // Init file path checksum generator
  FileSys().setupFilePathChecksum(
    Base().CurrentSourceDir, Base().CurrentBinaryDir, Base().ProjectSourceDir,
    Base().ProjectBinaryDir);

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

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

    // Sort include directories on demand
    if (Base().IncludeProjectDirsBefore) {
      // Move strings to temporary list
      std::list<std::string> includes;
      includes.insert(includes.end(), Moc().IncludePaths.begin(),
                      Moc().IncludePaths.end());
      Moc_.IncludePaths.clear();
      Moc_.IncludePaths.reserve(includes.size());
      // Append project directories only
      {
        std::array<std::string const*, 2> const movePaths = {
          { &Base().ProjectBinaryDir, &Base().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())) {
              Moc_.IncludePaths.push_back(path);
              it = includes.erase(it);
            } else {
              ++it;
            }
          }
        }
      }
      // Append remaining directories
      Moc_.IncludePaths.insert(Moc_.IncludePaths.end(), includes.begin(),
                               includes.end());
    }
    // Compose moc includes list
    {
      std::set<std::string> frameworkPaths;
      for (std::string const& path : Moc().IncludePaths) {
        Moc_.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;
          FileSys().SplitPath(path, pathComponents);
          std::string frameworkPath = FileSys().JoinPath(
            pathComponents.begin(), pathComponents.end() - 2);
          frameworkPaths.insert(frameworkPath);
        }
      }
      // Append framework includes
      for (std::string const& path : frameworkPaths) {
        Moc_.Includes.push_back("-F");
        Moc_.Includes.push_back(path);
      }
    }
    // Setup single list with all options
    {
      // Add includes
      Moc_.AllOptions.insert(Moc_.AllOptions.end(), Moc().Includes.begin(),
                             Moc().Includes.end());
      // Add definitions
      for (std::string const& def : Moc().Definitions) {
        Moc_.AllOptions.push_back("-D" + def);
      }
      // Add options
      Moc_.AllOptions.insert(Moc_.AllOptions.end(), Moc().Options.begin(),
                             Moc().Options.end());
    }
  }

  return true;
}

bool cmQtAutoGeneratorMocUic::Process()
{
  // Run libuv event loop
  UVRequest().send();
  if (uv_run(UVLoop(), UV_RUN_DEFAULT) == 0) {
    if (JobError_) {
      return false;
    }
  } else {
    return false;
  }
  return true;
}

void cmQtAutoGeneratorMocUic::UVPollStage(uv_async_t* handle)
{
  reinterpret_cast<cmQtAutoGeneratorMocUic*>(handle->data)->PollStage();
}

void cmQtAutoGeneratorMocUic::PollStage()
{
  switch (Stage_) {
    case StageT::SETTINGS_READ:
      SettingsFileRead();
      SetStage(StageT::CREATE_DIRECTORIES);
      break;
    case StageT::CREATE_DIRECTORIES:
      CreateDirectories();
      SetStage(StageT::PARSE_SOURCES);
      break;
    case StageT::PARSE_SOURCES:
      if (ThreadsStartJobs(JobQueues_.Sources)) {
        SetStage(StageT::PARSE_HEADERS);
      }
      break;
    case StageT::PARSE_HEADERS:
      if (ThreadsStartJobs(JobQueues_.Headers)) {
        SetStage(StageT::MOC_PREDEFS);
      }
      break;
    case StageT::MOC_PREDEFS:
      if (ThreadsStartJobs(JobQueues_.MocPredefs)) {
        SetStage(StageT::MOC_PROCESS);
      }
      break;
    case StageT::MOC_PROCESS:
      if (ThreadsStartJobs(JobQueues_.Moc)) {
        SetStage(StageT::MOCS_COMPILATION);
      }
      break;
    case StageT::MOCS_COMPILATION:
      if (ThreadsJobsDone()) {
        MocGenerateCompilation();
        SetStage(StageT::UIC_PROCESS);
      }
      break;
    case StageT::UIC_PROCESS:
      if (ThreadsStartJobs(JobQueues_.Uic)) {
        SetStage(StageT::SETTINGS_WRITE);
      }
      break;
    case StageT::SETTINGS_WRITE:
      SettingsFileWrite();
      SetStage(StageT::FINISH);
      break;
    case StageT::FINISH:
      if (ThreadsJobsDone()) {
        // Clear all libuv handles
        ThreadsStop();
        UVRequest().reset();
        // Set highest END stage manually
        Stage_ = StageT::END;
      }
      break;
    case StageT::END:
      break;
  }
}

void cmQtAutoGeneratorMocUic::SetStage(StageT stage)
{
  if (JobError_) {
    stage = StageT::FINISH;
  }
  // Only allow to increase the stage
  if (Stage_ < stage) {
    Stage_ = stage;
    UVRequest().send();
  }
}

void cmQtAutoGeneratorMocUic::SettingsFileRead()
{
  // Compose current settings strings
  {
    cmCryptoHash crypt(cmCryptoHash::AlgoSHA256);
    std::string const sep(" ~~~ ");
    if (Moc_.Enabled) {
      std::string str;
      str += Moc().Executable;
      str += sep;
      str += cmJoin(Moc().AllOptions, ";");
      str += sep;
      str += Base().IncludeProjectDirsBefore ? "TRUE" : "FALSE";
      str += sep;
      str += cmJoin(Moc().PredefsCmd, ";");
      str += sep;
      SettingsStringMoc_ = crypt.HashString(str);
    }
    if (Uic().Enabled) {
      std::string str;
      str += Uic().Executable;
      str += sep;
      str += cmJoin(Uic().TargetOptions, ";");
      for (const auto& item : Uic().Options) {
        str += sep;
        str += item.first;
        str += sep;
        str += cmJoin(item.second, ";");
      }
      str += sep;
      SettingsStringUic_ = crypt.HashString(str);
    }
  }

  // Read old settings and compare
  {
    std::string content;
    if (FileSys().FileRead(content, SettingsFile_)) {
      if (Moc().Enabled) {
        if (SettingsStringMoc_ != SettingsFind(content, "moc")) {
          Moc_.SettingsChanged = true;
        }
      }
      if (Uic().Enabled) {
        if (SettingsStringUic_ != SettingsFind(content, "uic")) {
          Uic_.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 (Moc().SettingsChanged || Uic().SettingsChanged) {
        FileSys().FileRemove(SettingsFile_);
      }
    } else {
      // Settings file read failed
      if (Moc().Enabled) {
        Moc_.SettingsChanged = true;
      }
      if (Uic().Enabled) {
        Uic_.SettingsChanged = true;
      }
    }
  }
}

void cmQtAutoGeneratorMocUic::SettingsFileWrite()
{
  std::lock_guard<std::mutex> jobsLock(JobsMutex_);
  // Only write if any setting changed
  if (!JobError_ && (Moc().SettingsChanged || Uic().SettingsChanged)) {
    if (Log().Verbose()) {
      Log().Info(GeneratorT::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
    if (!FileSys().FileWrite(GeneratorT::GEN, SettingsFile_, content)) {
      Log().ErrorFile(GeneratorT::GEN, SettingsFile_,
                      "Settings file writing failed");
      // Remove old settings file to trigger a full rebuild on the next run
      FileSys().FileRemove(SettingsFile_);
      RegisterJobError();
    }
  }
}

void cmQtAutoGeneratorMocUic::CreateDirectories()
{
  // Create AUTOGEN include directory
  if (!FileSys().MakeDirectory(GeneratorT::GEN, Base().AutogenIncludeDir)) {
    RegisterJobError();
  }
}

bool cmQtAutoGeneratorMocUic::ThreadsStartJobs(JobQueueT& queue)
{
  bool done = false;
  std::size_t queueSize = queue.size();

  // Change the active queue
  {
    std::lock_guard<std::mutex> jobsLock(JobsMutex_);
    // Check if there are still unfinished jobs from the previous queue
    if (JobsRemain_ == 0) {
      if (!JobThreadsAbort_) {
        JobQueue_.swap(queue);
        JobsRemain_ = queueSize;
      } else {
        // Abort requested
        queue.clear();
        queueSize = 0;
      }
      done = true;
    }
  }

  if (done && (queueSize != 0)) {
    // Start new threads on demand
    if (Workers_.empty()) {
      Workers_.resize(Base().NumThreads);
      for (auto& item : Workers_) {
        item = cm::make_unique<WorkerT>(this, UVLoop());
      }
    } else {
      // Notify threads
      if (queueSize == 1) {
        JobsConditionRead_.notify_one();
      } else {
        JobsConditionRead_.notify_all();
      }
    }
  }

  return done;
}

void cmQtAutoGeneratorMocUic::ThreadsStop()
{
  if (!Workers_.empty()) {
    // Clear all jobs
    {
      std::lock_guard<std::mutex> jobsLock(JobsMutex_);
      JobThreadsAbort_ = true;
      JobsRemain_ -= JobQueue_.size();
      JobQueue_.clear();

      JobQueues_.Sources.clear();
      JobQueues_.Headers.clear();
      JobQueues_.MocPredefs.clear();
      JobQueues_.Moc.clear();
      JobQueues_.Uic.clear();
    }
    // Wake threads
    JobsConditionRead_.notify_all();
    // Join and clear threads
    Workers_.clear();
  }
}

bool cmQtAutoGeneratorMocUic::ThreadsJobsDone()
{
  std::lock_guard<std::mutex> jobsLock(JobsMutex_);
  return (JobsRemain_ == 0);
}

void cmQtAutoGeneratorMocUic::WorkerSwapJob(JobHandleT& jobHandle)
{
  bool const jobProcessed(jobHandle);
  if (jobProcessed) {
    jobHandle.reset(nullptr);
  }
  {
    std::unique_lock<std::mutex> jobsLock(JobsMutex_);
    // Reduce the remaining job count and notify the libuv loop
    // when all jobs are done
    if (jobProcessed) {
      --JobsRemain_;
      if (JobsRemain_ == 0) {
        UVRequest().send();
      }
    }
    // Wait for new jobs
    while (!JobThreadsAbort_ && JobQueue_.empty()) {
      JobsConditionRead_.wait(jobsLock);
    }
    // Try to pick up a new job handle
    if (!JobThreadsAbort_ && !JobQueue_.empty()) {
      jobHandle = std::move(JobQueue_.front());
      JobQueue_.pop_front();
    }
  }
}

void cmQtAutoGeneratorMocUic::ParallelRegisterJobError()
{
  std::lock_guard<std::mutex> jobsLock(JobsMutex_);
  RegisterJobError();
}

// Private method that requires cmQtAutoGeneratorMocUic::JobsMutex_ to be
// locked
void cmQtAutoGeneratorMocUic::RegisterJobError()
{
  JobError_ = true;
  if (!JobThreadsAbort_) {
    JobThreadsAbort_ = true;
    // Clear remaining jobs
    if (JobsRemain_ != 0) {
      JobsRemain_ -= JobQueue_.size();
      JobQueue_.clear();
    }
  }
}

bool cmQtAutoGeneratorMocUic::ParallelJobPushMoc(JobHandleT& jobHandle)
{
  std::lock_guard<std::mutex> jobsLock(JobsMutex_);
  if (!JobThreadsAbort_) {
    bool pushJobHandle = true;
    // Do additional tests if this is an included moc job
    const JobMocT& mocJob(static_cast<JobMocT&>(*jobHandle));
    if (!mocJob.IncludeString.empty()) {
      // Register included moc file and look for collisions
      MocIncludedFiles_.emplace(mocJob.SourceFile);
      if (!MocIncludedStrings_.emplace(mocJob.IncludeString).second) {
        // Another source file includes the same moc file!
        for (const JobHandleT& otherHandle : JobQueues_.Moc) {
          const JobMocT& otherJob(static_cast<JobMocT&>(*otherHandle));
          if (otherJob.IncludeString == mocJob.IncludeString) {
            // Check if the same moc file would be generated from different
            // source files which is an error.
            if (otherJob.SourceFile != mocJob.SourceFile) {
              // Include string collision
              std::string error = "The two source files\n  ";
              error += Quoted(mocJob.IncluderFile);
              error += " and\n  ";
              error += Quoted(otherJob.IncluderFile);
              error += "\ncontain the the same moc include string ";
              error += Quoted(mocJob.IncludeString);
              error += "\nbut the moc file would be generated from different "
                       "source files\n  ";
              error += Quoted(mocJob.SourceFile);
              error += " and\n  ";
              error += Quoted(otherJob.SourceFile);
              error += ".\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";
              Log().Error(GeneratorT::MOC, error);
              RegisterJobError();
            }
            // Do not push this job in since the included moc file already
            // gets generated by an other job.
            pushJobHandle = false;
            break;
          }
        }
      }
    }
    // Push job on demand
    if (pushJobHandle) {
      JobQueues_.Moc.emplace_back(std::move(jobHandle));
    }
  }
  return !JobError_;
}

bool cmQtAutoGeneratorMocUic::ParallelJobPushUic(JobHandleT& jobHandle)
{
  std::lock_guard<std::mutex> jobsLock(JobsMutex_);
  if (!JobThreadsAbort_) {
    bool pushJobHandle = true;
    // Look for include collisions.
    const JobUicT& uicJob(static_cast<JobUicT&>(*jobHandle));
    for (const JobHandleT& otherHandle : JobQueues_.Uic) {
      const JobUicT& otherJob(static_cast<JobUicT&>(*otherHandle));
      if (otherJob.IncludeString == uicJob.IncludeString) {
        // Check if the same uic file would be generated from different
        // source files which would be an error.
        if (otherJob.SourceFile != uicJob.SourceFile) {
          // Include string collision
          std::string error = "The two source files\n  ";
          error += Quoted(uicJob.IncluderFile);
          error += " and\n  ";
          error += Quoted(otherJob.IncluderFile);
          error += "\ncontain the the same uic include string ";
          error += Quoted(uicJob.IncludeString);
          error += "\nbut the uic file would be generated from different "
                   "source files\n  ";
          error += Quoted(uicJob.SourceFile);
          error += " and\n  ";
          error += Quoted(otherJob.SourceFile);
          error +=
            ".\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";
          Log().Error(GeneratorT::UIC, error);
          RegisterJobError();
        }
        // Do not push this job in since the uic file already
        // gets generated by an other job.
        pushJobHandle = false;
        break;
      }
    }
    if (pushJobHandle) {
      JobQueues_.Uic.emplace_back(std::move(jobHandle));
    }
  }
  return !JobError_;
}

bool cmQtAutoGeneratorMocUic::ParallelMocIncluded(
  std::string const& sourceFile)
{
  std::lock_guard<std::mutex> mocLock(JobsMutex_);
  return (MocIncludedFiles_.find(sourceFile) != MocIncludedFiles_.end());
}

void cmQtAutoGeneratorMocUic::ParallelMocAutoRegister(
  std::string const& mocFile)
{
  std::lock_guard<std::mutex> mocLock(JobsMutex_);
  MocAutoFiles_.emplace(mocFile);
}

void cmQtAutoGeneratorMocUic::ParallelMocAutoUpdated()
{
  std::lock_guard<std::mutex> mocLock(JobsMutex_);
  MocAutoFileUpdated_ = true;
}

void cmQtAutoGeneratorMocUic::MocGenerateCompilation()
{
  std::lock_guard<std::mutex> mocLock(JobsMutex_);
  if (!JobError_ && Moc().Enabled) {
    // Write mocs compilation build file
    {
      // Compose mocs compilation file content
      std::string content =
        "// This file is autogenerated. Changes will be overwritten.\n";
      if (MocAutoFiles_.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 sbeg = Base().MultiConfig ? '<' : '"';
        char const send = Base().MultiConfig ? '>' : '"';
        for (std::string const& mocfile : MocAutoFiles_) {
          content += "#include ";
          content += sbeg;
          content += mocfile;
          content += send;
          content += '\n';
        }
      }

      std::string const& compAbs = Moc().CompFileAbs;
      if (FileSys().FileDiffers(compAbs, content)) {
        // Actually write mocs compilation file
        if (Log().Verbose()) {
          Log().Info(GeneratorT::MOC, "Generating MOC compilation " + compAbs);
        }
        if (!FileSys().FileWrite(GeneratorT::MOC, compAbs, content)) {
          Log().ErrorFile(GeneratorT::MOC, compAbs,
                          "mocs compilation file writing failed");
          RegisterJobError();
          return;
        }
      } else if (MocAutoFileUpdated_) {
        // Only touch mocs compilation file
        if (Log().Verbose()) {
          Log().Info(GeneratorT::MOC, "Touching mocs compilation " + compAbs);
        }
        FileSys().Touch(compAbs);
      }
    }
    // Write mocs compilation wrapper file
    if (Base().MultiConfig) {
    }
  }
}
