/* 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 <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->CollapseFullPath(relativePath, AutogenBuildDir);
}

/**
 * @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(GenT::GEN, FileName, "The source file is empty");
      }
    } else {
      wrk.LogFileError(GenT::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(GenT::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(GenT::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(GenT::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(GenT::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(GenT::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(GenT::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(GenT::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(GenT::MOC, FileName, emsg);
      }
      return false;
    }
  }

  // Convert pre jobs to actual jobs
  for (JobPre& jobPre : jobs) {
    JobHandleT jobHandle = cm::make_unique<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 = cm::make_unique<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 = cm::make_unique<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(GenT::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(GenT::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(GenT::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(GenT::MOC, result, cmd)) {
        std::string emsg = "The content generation command for ";
        emsg += Quoted(wrk.Moc().PredefsFileRel);
        emsg += " failed.\n";
        emsg += result.ErrorMessage;
        wrk.LogCommandError(GenT::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)) {
        std::string error;
        if (wrk.FileSys().FileWrite(wrk.Moc().PredefsFileAbs, result.StdOut,
                                    &error)) {
          // Success
        } else {
          std::string emsg = "Writing ";
          emsg += Quoted(wrk.Moc().PredefsFileRel);
          emsg += " failed. ";
          emsg += error;
          wrk.LogFileError(GenT::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(GenT::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(GenT::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(GenT::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(GenT::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(GenT::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(GenT::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(GenT::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(GenT::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(GenT::MOC, reason);
          }
          return true;
        }
        if (!error.empty()) {
          wrk.LogError(GenT::MOC, error);
          return false;
        }
      } else {
        std::string message = "Could not find dependency file ";
        message += Quoted(depFileRel);
        wrk.LogFileWarning(GenT::MOC, SourceFile, message);
      }
    }
  }

  return false;
}

void cmQtAutoGeneratorMocUic::JobMocT::GenerateMoc(WorkerT& wrk)
{
  // Make sure the parent directory exists
  if (!wrk.FileSys().MakeParentDirectory(BuildFile)) {
    wrk.LogFileError(GenT::MOC, BuildFile,
                     "Could not create parent directory.");
    return;
  }
  {
    // 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(GenT::MOC, result, cmd)) {
      // Moc command success
      // Print moc output
      if (!result.StdOut.empty()) {
        wrk.LogInfo(GenT::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(GenT::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(GenT::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(GenT::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(GenT::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(GenT::UIC, reason);
      }
      return true;
    }
  }

  return false;
}

void cmQtAutoGeneratorMocUic::JobUicT::GenerateUic(WorkerT& wrk)
{
  // Make sure the parent directory exists
  if (!wrk.FileSys().MakeParentDirectory(BuildFile)) {
    wrk.LogFileError(GenT::UIC, BuildFile,
                     "Could not create parent directory.");
    return;
  }
  {
    // 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(GenT::UIC, result, cmd)) {
      // Uic command success
      // Print uic output
      if (!result.StdOut.empty()) {
        wrk.LogInfo(GenT::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(GenT::UIC, emsg, cmd, result.StdOut);
      }
      wrk.FileSys().FileRemove(BuildFile);
    }
  }
}

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(
  GenT genType, std::string const& message) const
{
  Log().Info(genType, message);
}

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

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

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

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

void cmQtAutoGeneratorMocUic::WorkerT::LogCommandError(
  GenT 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(
  GenT 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(); });
    }
  }

  if (!wrk.Process_->IsStarted()) {
    wrk.UVProcessFinished();
  }
}

void cmQtAutoGeneratorMocUic::WorkerT::UVProcessFinished()
{
  {
    std::lock_guard<std::mutex> lock(ProcessMutex_);
    if (Process_ && (Process_->IsFinished() || !Process_->IsStarted())) {
      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 loop
  uv_disable_stdio_inheritance();
#ifdef CMAKE_UV_SIGNAL_HACK
  UVHackRAII_ = cm::make_unique<cmUVSignalHackRAII>();
#endif
  UVLoop_ = cm::make_unique<uv_loop_t>();
  uv_loop_init(UVLoop());

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

cmQtAutoGeneratorMocUic::~cmQtAutoGeneratorMocUic()
{
  // Close libuv loop
  uv_loop_close(UVLoop());
}

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(GenT::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(GenT::GEN, InfoFile(), "Autogen build directory missing");
    return false;
  }
  // include directory
  Base_.AutogenIncludeDir = InfoGetConfig("AM_INCLUDE_DIR");
  if (Base_.AutogenIncludeDir.empty()) {
    Log().ErrorFile(GenT::GEN, InfoFile(),
                    "Autogen include directory missing");
    return false;
  }

  // - Files
  SettingsFile_ = InfoGetConfig("AM_SETTINGS_FILE");
  if (SettingsFile_.empty()) {
    Log().ErrorFile(GenT::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) {
    for (std::string& sfl : InfoGetList("AM_MOC_SKIP")) {
      Moc_.SkipList.insert(std::move(sfl));
    }
    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(
            GenT::MOC, InfoFile(),
            "AUTOMOC_DEPEND_FILTERS list size is not a multiple of 2");
          return false;
        }
      }
      if (!error.empty()) {
        Log().ErrorFile(GenT::MOC, InfoFile(), error);
        return false;
      }
    }
    Moc_.PredefsCmd = InfoGetList("AM_MOC_PREDEFS_CMD");
    // Install moc predefs job
    if (!Moc().PredefsCmd.empty()) {
      JobQueues_.MocPredefs.emplace_back(cm::make_unique<JobMocPredefsT>());
    }
  }

  // - Uic
  Uic_.Executable = InfoGet("AM_QT_UIC_EXECUTABLE");
  Uic_.Enabled = !Uic().Executable.empty();
  if (Uic().Enabled) {
    for (std::string& sfl : InfoGetList("AM_UIC_SKIP")) {
      Uic_.SkipList.insert(std::move(sfl));
    }
    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(GenT::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;
      }
    }
  }

  // - Headers and sources
  {
    auto addHeader = [this](std::string&& hdr, bool moc, bool uic) {
      this->JobQueues_.Headers.emplace_back(
        cm::make_unique<JobParseT>(std::move(hdr), moc, uic, true));
    };
    auto addSource = [this](std::string&& src, bool moc, bool uic) {
      this->JobQueues_.Sources.emplace_back(
        cm::make_unique<JobParseT>(std::move(src), moc, uic, false));
    };

    // Add headers
    for (std::string& hdr : InfoGetList("AM_HEADERS")) {
      addHeader(std::move(hdr), true, true);
    }
    if (Moc().Enabled) {
      for (std::string& hdr : InfoGetList("AM_MOC_HEADERS")) {
        addHeader(std::move(hdr), true, false);
      }
    }
    if (Uic().Enabled) {
      for (std::string& hdr : InfoGetList("AM_UIC_HEADERS")) {
        addHeader(std::move(hdr), false, true);
      }
    }

    // Add sources
    for (std::string& src : InfoGetList("AM_SOURCES")) {
      addSource(std::move(src), true, true);
    }
    if (Moc().Enabled) {
      for (std::string& src : InfoGetList("AM_MOC_SOURCES")) {
        addSource(std::move(src), true, false);
      }
    }
    if (Uic().Enabled) {
      for (std::string& src : InfoGetList("AM_UIC_SOURCES")) {
        addSource(std::move(src), false, true);
      }
    }
  }

  // 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(GenT::GEN, "Writing settings file " + Quoted(SettingsFile_));
    }
    // Compose settings file content
    std::string content;
    {
      auto SettingAppend = [&content](const char* key,
                                      std::string const& value) {
        if (!value.empty()) {
          content += key;
          content += ':';
          content += value;
          content += '\n';
        }
      };
      SettingAppend("moc", SettingsStringMoc_);
      SettingAppend("uic", SettingsStringUic_);
    }
    // Write settings file
    std::string error;
    if (!FileSys().FileWrite(SettingsFile_, content, &error)) {
      Log().ErrorFile(GenT::GEN, SettingsFile_,
                      "Settings file writing failed. " + error);
      // Remove old settings file to trigger a full rebuild on the next run
      FileSys().FileRemove(SettingsFile_);
      RegisterJobError();
    }
  }
}

void cmQtAutoGeneratorMocUic::CreateDirectories()
{
  // Create AUTOGEN include directory
  if (!FileSys().MakeDirectory(Base().AutogenIncludeDir)) {
    Log().ErrorFile(GenT::GEN, Base().AutogenIncludeDir,
                    "Could not create directory.");
    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();
  }
  {
    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(GenT::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(GenT::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(GenT::MOC, "Generating MOC compilation " + compAbs);
        }
        std::string error;
        if (!FileSys().FileWrite(compAbs, content, &error)) {
          Log().ErrorFile(GenT::MOC, compAbs,
                          "mocs compilation file writing failed. " + error);
          RegisterJobError();
          return;
        }
      } else if (MocAutoFileUpdated_) {
        // Only touch mocs compilation file
        if (Log().Verbose()) {
          Log().Info(GenT::MOC, "Touching mocs compilation " + compAbs);
        }
        FileSys().Touch(compAbs);
      }
    }
    // Write mocs compilation wrapper file
    if (Base().MultiConfig) {
    }
  }
}
