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

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

#include "cmAlgorithms.h"
#include "cmCryptoHash.h"
#include "cmMakefile.h"
#include "cmQtAutoGen.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 dependencies 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 dependencies 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 {
    // Relative build path
    std::string relPath = wrk.FileSys().GetFilePathChecksum(SourceFile);
    relPath += "/moc_";
    relPath += wrk.FileSys().GetFilenameWithoutLastExtension(SourceFile);

    // Register relative file path with duplication check
    relPath = wrk.Gen().ParallelMocAutoRegister(relPath);

    // Absolute build path
    if (wrk.Base().MultiConfig) {
      BuildFile = wrk.Base().AutogenIncludeDir;
      BuildFile += '/';
      BuildFile += relPath;
    } else {
      BuildFile = wrk.Base().AbsoluteBuildPath(relPath);
    }
  }

  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.emplace_back("--include");
      cmd.push_back(wrk.Moc().PredefsFileAbs);
    }
    cmd.emplace_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.emplace_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, [&wrk] { wrk.UVProcessFinished(); });
    }
  }
}

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())
{
  // 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() = default;

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

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

  // -- Meta
  Log().RaiseVerbosity(InfoGet("AM_VERBOSITY"));
  Base_.MultiConfig = InfoGetBool("AM_MULTI_CONFIG");
  {
    unsigned long num = Base_.NumThreads;
    if (cmSystemTools::StringToULong(InfoGet("AM_PARALLEL").c_str(), &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
  Base_.AutogenIncludeDir = InfoGetConfig("AM_INCLUDE_DIR");
  if (Base_.AutogenIncludeDir.empty()) {
    Log().ErrorFile(GeneratorT::GEN, InfoFile(),
                    "Autogen include directory missing");
    return false;
  }

  // - 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").c_str(),
                                     &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");
    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.emplace_back();
            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 mismatch (" << 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.emplace_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 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 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());
}

std::string cmQtAutoGeneratorMocUic::ParallelMocAutoRegister(
  std::string const& baseName)
{
  std::string res;
  {
    std::lock_guard<std::mutex> mocLock(JobsMutex_);
    res = baseName;
    res += ".cpp";
    if (MocAutoFiles_.find(res) == MocAutoFiles_.end()) {
      MocAutoFiles_.emplace(res);
    } else {
      // Append number suffix to the file name
      for (unsigned int ii = 2; ii != 1024; ++ii) {
        res = baseName;
        res += '_';
        res += std::to_string(ii);
        res += ".cpp";
        if (MocAutoFiles_.find(res) == MocAutoFiles_.end()) {
          MocAutoFiles_.emplace(res);
          break;
        }
      }
    }
  }
  return res;
}

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) {
    }
  }
}
