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

#include <algorithm>
#include <atomic>
#include <cstddef>
#include <map>
#include <mutex>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#include <cm/memory>
#include <cm/string_view>
#include <cmext/algorithm>

#include "cmsys/FStream.hxx"
#include "cmsys/RegularExpression.hxx"

#include "cm_jsoncpp_value.h"

#include "cmCryptoHash.h"
#include "cmFileTime.h"
#include "cmGccDepfileReader.h"
#include "cmGccDepfileReaderTypes.h"
#include "cmGeneratedFileStream.h"
#include "cmQtAutoGen.h"
#include "cmQtAutoGenerator.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmWorkerPool.h"

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

namespace {

constexpr std::size_t MocUnderscoreLength = 4; // Length of "moc_"
constexpr std::size_t UiUnderscoreLength = 3;  // Length of "ui_"

/** \class cmQtAutoMocUicT
 * \brief AUTOMOC and AUTOUIC generator
 */
class cmQtAutoMocUicT : public cmQtAutoGenerator
{
public:
  cmQtAutoMocUicT();
  ~cmQtAutoMocUicT() override;

  cmQtAutoMocUicT(cmQtAutoMocUicT const&) = delete;
  cmQtAutoMocUicT& operator=(cmQtAutoMocUicT const&) = delete;

public:
  // -- Types

  /** Include string with sub parts.  */
  struct IncludeKeyT
  {
    IncludeKeyT(std::string const& key, std::size_t basePrefixLength);

    std::string Key;  // Full include string
    std::string Dir;  // Include directory
    std::string Base; // Base part of the include file name
  };

  /** Search key plus regular expression pair.  */
  struct KeyExpT
  {
    KeyExpT(std::string key, std::string const& exp)
      : Key(std::move(key))
      , Exp(exp)
    {
    }

    std::string Key;
    cmsys::RegularExpression Exp;
  };

  /** Source file parsing cache.  */
  class ParseCacheT
  {
  public:
    // -- Types

    /** Entry of the file parsing cache.  */
    struct FileT
    {
      void Clear();

      struct MocT
      {
        std::string Macro;
        struct IncludeT
        {
          std::vector<IncludeKeyT> Underscore;
          std::vector<IncludeKeyT> Dot;
        } Include;
        std::vector<std::string> Depends;
      } Moc;

      struct UicT
      {
        std::vector<IncludeKeyT> Include;
        std::vector<std::string> Depends;
      } Uic;
    };
    using FileHandleT = std::shared_ptr<FileT>;
    using GetOrInsertT = std::pair<FileHandleT, bool>;

  public:
    ParseCacheT();
    ~ParseCacheT();

    bool ReadFromFile(std::string const& fileName);
    bool WriteToFile(std::string const& fileName);

    //! Always returns a valid handle
    GetOrInsertT GetOrInsert(std::string const& fileName);

  private:
    std::unordered_map<std::string, FileHandleT> Map_;
  };

  /** Source file data.  */
  class SourceFileT
  {
  public:
    SourceFileT(std::string fileName)
      : FileName(std::move(fileName))
    {
    }

  public:
    std::string FileName;
    cmFileTime FileTime;
    ParseCacheT::FileHandleT ParseData;
    std::string BuildPath;
    bool IsHeader = false;
    bool Moc = false;
    bool Uic = false;
  };
  using SourceFileHandleT = std::shared_ptr<SourceFileT>;
  using SourceFileMapT = std::map<std::string, SourceFileHandleT>;

  /** Meta compiler file mapping information.  */
  struct MappingT
  {
    SourceFileHandleT SourceFile;
    std::string OutputFile;
    std::string IncludeString;
    std::vector<SourceFileHandleT> IncluderFiles;
  };
  using MappingHandleT = std::shared_ptr<MappingT>;
  using MappingMapT = std::map<std::string, MappingHandleT>;

  /** Common settings.  */
  class BaseSettingsT
  {
  public:
    // -- Constructors
    BaseSettingsT();
    ~BaseSettingsT();

    BaseSettingsT(BaseSettingsT const&) = delete;
    BaseSettingsT& operator=(BaseSettingsT const&) = delete;

    // -- Attributes
    // - Config
    bool MultiConfig = false;
    IntegerVersion QtVersion = { 4, 0 };
    unsigned int ThreadCount = 0;
    // - Directories
    std::string AutogenBuildDir;
    std::string AutogenIncludeDir;
    // - Files
    std::string CMakeExecutable;
    cmFileTime CMakeExecutableTime;
    std::string ParseCacheFile;
    std::string DepFile;
    std::string DepFileRuleName;
    std::vector<std::string> HeaderExtensions;
  };

  /** Shared common variables.  */
  class BaseEvalT
  {
  public:
    // -- Parse Cache
    bool ParseCacheChanged = false;
    cmFileTime ParseCacheTime;
    ParseCacheT ParseCache;

    // -- Sources
    SourceFileMapT Headers;
    SourceFileMapT Sources;
  };

  /** Moc settings.  */
  class MocSettingsT
  {
  public:
    // -- Constructors
    MocSettingsT();
    ~MocSettingsT();

    MocSettingsT(MocSettingsT const&) = delete;
    MocSettingsT& operator=(MocSettingsT const&) = delete;

    // -- Const methods
    bool skipped(std::string const& fileName) const;
    std::string MacrosString() const;

    // -- Attributes
    bool Enabled = false;
    bool SettingsChanged = false;
    bool RelaxedMode = false;
    bool PathPrefix = false;
    bool CanOutputDependencies = false;
    cmFileTime ExecutableTime;
    std::string Executable;
    std::string CompFileAbs;
    std::string PredefsFileAbs;
    std::unordered_set<std::string> SkipList;
    std::vector<std::string> IncludePaths;
    std::vector<std::string> Definitions;
    std::vector<std::string> OptionsIncludes;
    std::vector<std::string> OptionsDefinitions;
    std::vector<std::string> OptionsExtra;
    std::vector<std::string> PredefsCmd;
    std::vector<KeyExpT> DependFilters;
    std::vector<KeyExpT> MacroFilters;
    cmsys::RegularExpression RegExpInclude;
  };

  /** Moc shared variables.  */
  class MocEvalT
  {
  public:
    // -- predefines file
    cmFileTime PredefsTime;
    // -- Mappings
    MappingMapT HeaderMappings;
    MappingMapT SourceMappings;
    MappingMapT Includes;
    // -- Discovered files
    SourceFileMapT HeadersDiscovered;
    // -- Output directories
    std::unordered_set<std::string> OutputDirs;
    // -- Mocs compilation
    bool CompUpdated = false;
    std::vector<std::string> CompFiles;
  };

  /** Uic settings.  */
  class UicSettingsT
  {
  public:
    struct UiFile
    {
      std::vector<std::string> Options;
    };

  public:
    UicSettingsT();
    ~UicSettingsT();

    UicSettingsT(UicSettingsT const&) = delete;
    UicSettingsT& operator=(UicSettingsT const&) = delete;

    // -- Const methods
    bool skipped(std::string const& fileName) const;

    // -- Attributes
    bool Enabled = false;
    bool SettingsChanged = false;
    cmFileTime ExecutableTime;
    std::string Executable;
    std::unordered_set<std::string> SkipList;
    std::vector<std::string> Options;
    std::unordered_map<std::string, UiFile> UiFiles;
    std::vector<std::string> SearchPaths;
    cmsys::RegularExpression RegExpInclude;
  };

  /** Uic shared variables.  */
  class UicEvalT
  {
  public:
    // -- Discovered files
    SourceFileMapT UiFiles;
    // -- Mappings
    MappingMapT Includes;
    // -- Output directories
    std::unordered_set<std::string> OutputDirs;
  };

  /** Abstract job class for concurrent job processing.  */
  class JobT : public cmWorkerPool::JobT
  {
  protected:
    /** Protected default constructor.  */
    JobT(bool fence = false)
      : cmWorkerPool::JobT(fence)
    {
    }

    //! Get the generator. Only valid during Process() call!
    cmQtAutoMocUicT* Gen() const
    {
      return static_cast<cmQtAutoMocUicT*>(UserData());
    };

    // -- Accessors. Only valid during Process() call!
    Logger const& Log() const { return Gen()->Log(); }
    BaseSettingsT const& BaseConst() const { return Gen()->BaseConst(); }
    BaseEvalT& BaseEval() const { return Gen()->BaseEval(); }
    MocSettingsT const& MocConst() const { return Gen()->MocConst(); }
    MocEvalT& MocEval() const { return Gen()->MocEval(); }
    UicSettingsT const& UicConst() const { return Gen()->UicConst(); }
    UicEvalT& UicEval() const { return Gen()->UicEval(); }

    // -- Logging
    std::string MessagePath(cm::string_view path) const
    {
      return Gen()->MessagePath(path);
    }
    // - Error logging with automatic abort
    void LogError(GenT genType, cm::string_view message) const;
    void LogCommandError(GenT genType, cm::string_view message,
                         std::vector<std::string> const& command,
                         std::string const& output) const;

    /** @brief Run an external process. Use only during Process() call!  */
    bool RunProcess(GenT genType, cmWorkerPool::ProcessResultT& result,
                    std::vector<std::string> const& command,
                    std::string* infoMessage = nullptr);
  };

  /** Fence job utility class.  */
  class JobFenceT : public JobT
  {
  public:
    JobFenceT()
      : JobT(true)
    {
    }
    void Process() override{};
  };

  /** Generate moc_predefs.h.  */
  class JobMocPredefsT : public JobFenceT
  {
    void Process() override;
    bool Update(std::string* reason) const;
  };

  /** File parse job base class.  */
  class JobParseT : public JobT
  {
  public:
    JobParseT(SourceFileHandleT fileHandle)
      : FileHandle(std::move(fileHandle))
    {
    }

  protected:
    bool ReadFile();
    void CreateKeys(std::vector<IncludeKeyT>& container,
                    std::set<std::string> const& source,
                    std::size_t basePrefixLength);
    void MocMacro();
    void MocDependecies();
    void MocIncludes();
    void UicIncludes();

  protected:
    SourceFileHandleT FileHandle;
    std::string Content;
  };

  /** Header file parse job.  */
  class JobParseHeaderT : public JobParseT
  {
  public:
    using JobParseT::JobParseT;
    void Process() override;
  };

  /** Source file parse job.  */
  class JobParseSourceT : public JobParseT
  {
  public:
    using JobParseT::JobParseT;
    void Process() override;
  };

  /** Evaluate cached file parse data - moc.  */
  class JobEvalCacheT : public JobT
  {
  protected:
    std::string MessageSearchLocations() const;
    std::vector<std::string> SearchLocations;
  };

  /** Evaluate cached file parse data - moc.  */
  class JobEvalCacheMocT : public JobEvalCacheT
  {
    void Process() override;
    bool EvalHeader(SourceFileHandleT source);
    bool EvalSource(SourceFileHandleT const& source);
    bool FindIncludedHeader(SourceFileHandleT& headerHandle,
                            cm::string_view includerDir,
                            cm::string_view includeBase);
    bool RegisterIncluded(std::string const& includeString,
                          SourceFileHandleT includerFileHandle,
                          SourceFileHandleT sourceFileHandle) const;
    void RegisterMapping(MappingHandleT mappingHandle) const;
    std::string MessageHeader(cm::string_view headerBase) const;
  };

  /** Evaluate cached file parse data - uic.  */
  class JobEvalCacheUicT : public JobEvalCacheT
  {
    void Process() override;
    bool EvalFile(SourceFileHandleT const& sourceFileHandle);
    bool FindIncludedUi(cm::string_view sourceDirPrefix,
                        cm::string_view includePrefix);
    bool RegisterMapping(std::string const& includeString,
                         SourceFileHandleT includerFileHandle);

    std::string UiName;
    SourceFileHandleT UiFileHandle;
  };

  /** Evaluate cached file parse data - finish  */
  class JobEvalCacheFinishT : public JobFenceT
  {
    void Process() override;
  };

  /** Dependency probing base job.  */
  class JobProbeDepsT : public JobT
  {
  };

  /** Probes file dependencies and generates moc compile jobs.  */
  class JobProbeDepsMocT : public JobProbeDepsT
  {
    void Process() override;
    bool Generate(MappingHandleT const& mapping, bool compFile) const;
    bool Probe(MappingT const& mapping, std::string* reason) const;
    std::pair<std::string, cmFileTime> FindDependency(
      std::string const& sourceDir, std::string const& includeString) const;
  };

  /** Probes file dependencies and generates uic compile jobs.  */
  class JobProbeDepsUicT : public JobProbeDepsT
  {
    void Process() override;
    bool Probe(MappingT const& mapping, std::string* reason) const;
  };

  /** Dependency probing finish job.  */
  class JobProbeDepsFinishT : public JobFenceT
  {
    void Process() override;
  };

  /** Meta compiler base job.  */
  class JobCompileT : public JobT
  {
  public:
    JobCompileT(MappingHandleT uicMapping, std::unique_ptr<std::string> reason)
      : Mapping(std::move(uicMapping))
      , Reason(std::move(reason))
    {
    }

  protected:
    MappingHandleT Mapping;
    std::unique_ptr<std::string> Reason;
  };

  /** moc compiles a file.  */
  class JobCompileMocT : public JobCompileT
  {
  public:
    JobCompileMocT(MappingHandleT uicMapping,
                   std::unique_ptr<std::string> reason,
                   ParseCacheT::FileHandleT cacheEntry)
      : JobCompileT(std::move(uicMapping), std::move(reason))
      , CacheEntry(std::move(cacheEntry))
    {
    }
    void Process() override;

  protected:
    ParseCacheT::FileHandleT CacheEntry;
  };

  /** uic compiles a file.  */
  class JobCompileUicT : public JobCompileT
  {
  public:
    using JobCompileT::JobCompileT;
    void Process() override;
  };

  /** Generate mocs_compilation.cpp.  */
  class JobMocsCompilationT : public JobFenceT
  {
  private:
    void Process() override;
  };

  class JobDepFilesMergeT : public JobFenceT
  {
  private:
    void Process() override;
  };

  /** @brief The last job.  */
  class JobFinishT : public JobFenceT
  {
  private:
    void Process() override;
  };

  // -- Const settings interface
  BaseSettingsT const& BaseConst() const { return this->BaseConst_; }
  BaseEvalT& BaseEval() { return this->BaseEval_; }
  MocSettingsT const& MocConst() const { return this->MocConst_; }
  MocEvalT& MocEval() { return this->MocEval_; }
  UicSettingsT const& UicConst() const { return this->UicConst_; }
  UicEvalT& UicEval() { return this->UicEval_; }

  // -- Parallel job processing interface
  cmWorkerPool& WorkerPool() { return WorkerPool_; }
  void AbortError() { Abort(true); }
  void AbortSuccess() { Abort(false); }

  // -- Utility
  std::string AbsoluteBuildPath(cm::string_view relativePath) const;
  std::string AbsoluteIncludePath(cm::string_view relativePath) const;
  template <class JOBTYPE>
  void CreateParseJobs(SourceFileMapT const& sourceMap);
  std::string CollapseFullPathTS(std::string const& path) const;

private:
  // -- Abstract processing interface
  bool InitFromInfo(InfoT const& info) override;
  void InitJobs();
  bool Process() override;
  // -- Settings file
  void SettingsFileRead();
  bool SettingsFileWrite();
  // -- Parse cache
  void ParseCacheRead();
  bool ParseCacheWrite();
  // -- Thread processing
  void Abort(bool error);
  // -- Generation
  bool CreateDirectories();
  // -- Support for depfiles
  static std::vector<std::string> dependenciesFromDepFile(
    const char* filePath);

private:
  // -- Settings
  BaseSettingsT BaseConst_;
  BaseEvalT BaseEval_;
  MocSettingsT MocConst_;
  MocEvalT MocEval_;
  UicSettingsT UicConst_;
  UicEvalT UicEval_;
  // -- Settings file
  std::string SettingsFile_;
  std::string SettingsStringMoc_;
  std::string SettingsStringUic_;
  // -- Worker thread pool
  std::atomic<bool> JobError_ = ATOMIC_VAR_INIT(false);
  cmWorkerPool WorkerPool_;
  // -- Concurrent processing
  mutable std::mutex CMakeLibMutex_;
};

cmQtAutoMocUicT::IncludeKeyT::IncludeKeyT(std::string const& key,
                                          std::size_t basePrefixLength)
  : Key(key)
  , Dir(SubDirPrefix(key))
  , Base(cmSystemTools::GetFilenameWithoutLastExtension(key))
{
  if (basePrefixLength != 0) {
    Base = Base.substr(basePrefixLength);
  }
}

void cmQtAutoMocUicT::ParseCacheT::FileT::Clear()
{
  Moc.Macro.clear();
  Moc.Include.Underscore.clear();
  Moc.Include.Dot.clear();
  Moc.Depends.clear();

  Uic.Include.clear();
  Uic.Depends.clear();
}

cmQtAutoMocUicT::ParseCacheT::GetOrInsertT
cmQtAutoMocUicT::ParseCacheT::GetOrInsert(std::string const& fileName)
{
  // Find existing entry
  {
    auto it = Map_.find(fileName);
    if (it != Map_.end()) {
      return GetOrInsertT{ it->second, false };
    }
  }

  // Insert new entry
  return GetOrInsertT{
    Map_.emplace(fileName, std::make_shared<FileT>()).first->second, true
  };
}

cmQtAutoMocUicT::ParseCacheT::ParseCacheT() = default;
cmQtAutoMocUicT::ParseCacheT::~ParseCacheT() = default;

bool cmQtAutoMocUicT::ParseCacheT::ReadFromFile(std::string const& fileName)
{
  cmsys::ifstream fin(fileName.c_str());
  if (!fin) {
    return false;
  }
  FileHandleT fileHandle;

  std::string line;
  while (std::getline(fin, line)) {
    // Check if this an empty or a comment line
    if (line.empty() || line.front() == '#') {
      continue;
    }
    // Drop carriage return character at the end
    if (line.back() == '\r') {
      line.pop_back();
      if (line.empty()) {
        continue;
      }
    }
    // Check if this a file name line
    if (line.front() != ' ') {
      fileHandle = GetOrInsert(line).first;
      continue;
    }

    // Bad line or bad file handle
    if (!fileHandle || (line.size() < 6)) {
      continue;
    }

    constexpr std::size_t offset = 5;
    if (cmHasLiteralPrefix(line, " mmc:")) {
      fileHandle->Moc.Macro = line.substr(offset);
      continue;
    }
    if (cmHasLiteralPrefix(line, " miu:")) {
      fileHandle->Moc.Include.Underscore.emplace_back(line.substr(offset),
                                                      MocUnderscoreLength);
      continue;
    }
    if (cmHasLiteralPrefix(line, " mid:")) {
      fileHandle->Moc.Include.Dot.emplace_back(line.substr(offset), 0);
      continue;
    }
    if (cmHasLiteralPrefix(line, " mdp:")) {
      fileHandle->Moc.Depends.emplace_back(line.substr(offset));
      continue;
    }
    if (cmHasLiteralPrefix(line, " uic:")) {
      fileHandle->Uic.Include.emplace_back(line.substr(offset),
                                           UiUnderscoreLength);
      continue;
    }
    if (cmHasLiteralPrefix(line, " udp:")) {
      fileHandle->Uic.Depends.emplace_back(line.substr(offset));
      continue;
    }
  }
  return true;
}

bool cmQtAutoMocUicT::ParseCacheT::WriteToFile(std::string const& fileName)
{
  cmGeneratedFileStream ofs(fileName);
  if (!ofs) {
    return false;
  }
  ofs << "# Generated by CMake. Changes will be overwritten.\n";
  for (auto const& pair : Map_) {
    ofs << pair.first << '\n';
    FileT const& file = *pair.second;
    if (!file.Moc.Macro.empty()) {
      ofs << " mmc:" << file.Moc.Macro << '\n';
    }
    for (IncludeKeyT const& item : file.Moc.Include.Underscore) {
      ofs << " miu:" << item.Key << '\n';
    }
    for (IncludeKeyT const& item : file.Moc.Include.Dot) {
      ofs << " mid:" << item.Key << '\n';
    }
    for (std::string const& item : file.Moc.Depends) {
      ofs << " mdp:" << item << '\n';
    }
    for (IncludeKeyT const& item : file.Uic.Include) {
      ofs << " uic:" << item.Key << '\n';
    }
    for (std::string const& item : file.Uic.Depends) {
      ofs << " udp:" << item << '\n';
    }
  }
  return ofs.Close();
}

cmQtAutoMocUicT::BaseSettingsT::BaseSettingsT() = default;
cmQtAutoMocUicT::BaseSettingsT::~BaseSettingsT() = default;

cmQtAutoMocUicT::MocSettingsT::MocSettingsT()
{
  RegExpInclude.compile(
    "(^|\n)[ \t]*#[ \t]*include[ \t]+"
    "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
}

cmQtAutoMocUicT::MocSettingsT::~MocSettingsT() = default;

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

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

cmQtAutoMocUicT::UicSettingsT::UicSettingsT()
{
  RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+"
                        "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
}

cmQtAutoMocUicT::UicSettingsT::~UicSettingsT() = default;

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

void cmQtAutoMocUicT::JobT::LogError(GenT genType,
                                     cm::string_view message) const
{
  Gen()->AbortError();
  Gen()->Log().Error(genType, message);
}

void cmQtAutoMocUicT::JobT::LogCommandError(
  GenT genType, cm::string_view message,
  std::vector<std::string> const& command, std::string const& output) const
{
  Gen()->AbortError();
  Gen()->Log().ErrorCommand(genType, message, command, output);
}

bool cmQtAutoMocUicT::JobT::RunProcess(GenT genType,
                                       cmWorkerPool::ProcessResultT& result,
                                       std::vector<std::string> const& command,
                                       std::string* infoMessage)
{
  // Log command
  if (Log().Verbose()) {
    cm::string_view info;
    if (infoMessage != nullptr) {
      info = *infoMessage;
    }
    Log().Info(genType,
               cmStrCat(info,
                        info.empty() || cmHasSuffix(info, '\n') ? "" : "\n",
                        QuotedCommand(command), '\n'));
  }
  // Run command
  return cmWorkerPool::JobT::RunProcess(result, command,
                                        BaseConst().AutogenBuildDir);
}

void cmQtAutoMocUicT::JobMocPredefsT::Process()
{
  // (Re)generate moc_predefs.h on demand
  std::unique_ptr<std::string> reason;
  if (Log().Verbose()) {
    reason = cm::make_unique<std::string>();
  }
  if (!Update(reason.get())) {
    return;
  }
  std::string const& predefsFileAbs = MocConst().PredefsFileAbs;
  {
    cmWorkerPool::ProcessResultT result;
    {
      // Compose command
      std::vector<std::string> cmd = MocConst().PredefsCmd;
      // Add definitions
      cm::append(cmd, MocConst().OptionsDefinitions);
      // Add includes
      cm::append(cmd, MocConst().OptionsIncludes);
      // Execute command
      if (!RunProcess(GenT::MOC, result, cmd, reason.get())) {
        LogCommandError(GenT::MOC,
                        cmStrCat("The content generation command for ",
                                 MessagePath(predefsFileAbs), " failed.\n",
                                 result.ErrorMessage),
                        cmd, result.StdOut);
        return;
      }
    }

    // (Re)write predefs file only on demand
    if (cmQtAutoGenerator::FileDiffers(predefsFileAbs, result.StdOut)) {
      if (!cmQtAutoGenerator::FileWrite(predefsFileAbs, result.StdOut)) {
        LogError(
          GenT::MOC,
          cmStrCat("Writing ", MessagePath(predefsFileAbs), " failed."));
        return;
      }
    } else {
      // Touch to update the time stamp
      if (Log().Verbose()) {
        Log().Info(GenT::MOC, "Touching " + MessagePath(predefsFileAbs));
      }
      if (!cmSystemTools::Touch(predefsFileAbs, false)) {
        LogError(
          GenT::MOC,
          cmStrCat("Touching ", MessagePath(predefsFileAbs), " failed."));
        return;
      }
    }
  }

  // Read file time afterwards
  if (!MocEval().PredefsTime.Load(predefsFileAbs)) {
    LogError(GenT::MOC,
             cmStrCat("Reading the file time of ", MessagePath(predefsFileAbs),
                      " failed."));
    return;
  }
}

bool cmQtAutoMocUicT::JobMocPredefsT::Update(std::string* reason) const
{
  // Test if the file exists
  if (!MocEval().PredefsTime.Load(MocConst().PredefsFileAbs)) {
    if (reason != nullptr) {
      *reason = cmStrCat("Generating ", MessagePath(MocConst().PredefsFileAbs),
                         ", because it doesn't exist.");
    }
    return true;
  }

  // Test if the settings changed
  if (MocConst().SettingsChanged) {
    if (reason != nullptr) {
      *reason = cmStrCat("Generating ", MessagePath(MocConst().PredefsFileAbs),
                         ", because the moc settings changed.");
    }
    return true;
  }

  // Test if the executable is newer
  {
    std::string const& exec = MocConst().PredefsCmd.at(0);
    cmFileTime execTime;
    if (execTime.Load(exec)) {
      if (MocEval().PredefsTime.Older(execTime)) {
        if (reason != nullptr) {
          *reason =
            cmStrCat("Generating ", MessagePath(MocConst().PredefsFileAbs),
                     " because it is older than ", MessagePath(exec), '.');
        }
        return true;
      }
    }
  }

  return false;
}

bool cmQtAutoMocUicT::JobParseT::ReadFile()
{
  // Clear old parse information
  FileHandle->ParseData->Clear();
  std::string const& fileName = FileHandle->FileName;
  // Write info
  if (Log().Verbose()) {
    Log().Info(GenT::GEN, cmStrCat("Parsing ", MessagePath(fileName)));
  }
  // Read file content
  {
    std::string error;
    if (!cmQtAutoGenerator::FileRead(Content, fileName, &error)) {
      LogError(
        GenT::GEN,
        cmStrCat("Could not read ", MessagePath(fileName), ".\n", error));
      return false;
    }
  }
  // Warn if empty
  if (Content.empty()) {
    Log().Warning(GenT::GEN, cmStrCat(MessagePath(fileName), " is empty."));
    return false;
  }
  return true;
}

void cmQtAutoMocUicT::JobParseT::CreateKeys(
  std::vector<IncludeKeyT>& container, std::set<std::string> const& source,
  std::size_t basePrefixLength)
{
  if (source.empty()) {
    return;
  }
  container.reserve(source.size());
  for (std::string const& src : source) {
    container.emplace_back(src, basePrefixLength);
  }
}

void cmQtAutoMocUicT::JobParseT::MocMacro()
{
  for (KeyExpT const& filter : MocConst().MacroFilters) {
    // Run a simple find string check
    if (Content.find(filter.Key) == std::string::npos) {
      continue;
    }
    // Run the expensive regular expression check loop
    cmsys::RegularExpressionMatch match;
    if (filter.Exp.find(Content.c_str(), match)) {
      // Keep detected macro name
      FileHandle->ParseData->Moc.Macro = filter.Key;
      return;
    }
  }
}

void cmQtAutoMocUicT::JobParseT::MocDependecies()
{
  if (MocConst().DependFilters.empty() || MocConst().CanOutputDependencies) {
    return;
  }

  // Find dependency strings
  std::set<std::string> parseDepends;
  for (KeyExpT const& filter : MocConst().DependFilters) {
    // Run a simple find string check
    if (Content.find(filter.Key) == std::string::npos) {
      continue;
    }
    // Run the expensive regular expression check loop
    const char* contentChars = Content.c_str();
    cmsys::RegularExpressionMatch match;
    while (filter.Exp.find(contentChars, match)) {
      {
        std::string dep = match.match(1);
        if (!dep.empty()) {
          parseDepends.emplace(std::move(dep));
        }
      }
      contentChars += match.end();
    }
  }

  // Store dependency strings
  {
    auto& Depends = FileHandle->ParseData->Moc.Depends;
    Depends.reserve(parseDepends.size());
    for (std::string const& item : parseDepends) {
      Depends.emplace_back(item);
      // Replace end of line characters in filenames
      std::string& path = Depends.back();
      std::replace(path.begin(), path.end(), '\n', ' ');
      std::replace(path.begin(), path.end(), '\r', ' ');
    }
  }
}

void cmQtAutoMocUicT::JobParseT::MocIncludes()
{
  if (Content.find("moc") == std::string::npos) {
    return;
  }

  std::set<std::string> underscore;
  std::set<std::string> dot;
  {
    const char* contentChars = Content.c_str();
    cmsys::RegularExpression const& regExp = MocConst().RegExpInclude;
    cmsys::RegularExpressionMatch match;
    while (regExp.find(contentChars, match)) {
      std::string incString = match.match(2);
      std::string const incBase =
        cmSystemTools::GetFilenameWithoutLastExtension(incString);
      if (cmHasLiteralPrefix(incBase, "moc_")) {
        // moc_<BASE>.cpp
        // Remove the moc_ part from the base name
        underscore.emplace(std::move(incString));
      } else {
        // <BASE>.moc
        dot.emplace(std::move(incString));
      }
      // Forward content pointer
      contentChars += match.end();
    }
  }
  auto& Include = FileHandle->ParseData->Moc.Include;
  CreateKeys(Include.Underscore, underscore, MocUnderscoreLength);
  CreateKeys(Include.Dot, dot, 0);
}

void cmQtAutoMocUicT::JobParseT::UicIncludes()
{
  if (Content.find("ui_") == std::string::npos) {
    return;
  }

  std::set<std::string> includes;
  {
    const char* contentChars = Content.c_str();
    cmsys::RegularExpression const& regExp = UicConst().RegExpInclude;
    cmsys::RegularExpressionMatch match;
    while (regExp.find(contentChars, match)) {
      includes.emplace(match.match(2));
      // Forward content pointer
      contentChars += match.end();
    }
  }
  CreateKeys(FileHandle->ParseData->Uic.Include, includes, UiUnderscoreLength);
}

void cmQtAutoMocUicT::JobParseHeaderT::Process()
{
  if (!ReadFile()) {
    return;
  }
  // Moc parsing
  if (FileHandle->Moc) {
    MocMacro();
    MocDependecies();
  }
  // Uic parsing
  if (FileHandle->Uic) {
    UicIncludes();
  }
}

void cmQtAutoMocUicT::JobParseSourceT::Process()
{
  if (!ReadFile()) {
    return;
  }
  // Moc parsing
  if (FileHandle->Moc) {
    MocMacro();
    MocDependecies();
    MocIncludes();
  }
  // Uic parsing
  if (FileHandle->Uic) {
    UicIncludes();
  }
}

std::string cmQtAutoMocUicT::JobEvalCacheT::MessageSearchLocations() const
{
  std::string res;
  res.reserve(512);
  for (std::string const& path : SearchLocations) {
    res += "  ";
    res += MessagePath(path);
    res += '\n';
  }
  return res;
}

void cmQtAutoMocUicT::JobEvalCacheMocT::Process()
{
  // Evaluate headers
  for (auto const& pair : BaseEval().Headers) {
    if (!EvalHeader(pair.second)) {
      return;
    }
  }
  // Evaluate sources
  for (auto const& pair : BaseEval().Sources) {
    if (!EvalSource(pair.second)) {
      return;
    }
  }
}

bool cmQtAutoMocUicT::JobEvalCacheMocT::EvalHeader(SourceFileHandleT source)
{
  SourceFileT const& sourceFile = *source;
  auto const& parseData = sourceFile.ParseData->Moc;
  if (!source->Moc) {
    return true;
  }

  if (!parseData.Macro.empty()) {
    // Create a new mapping
    MappingHandleT handle = std::make_shared<MappingT>();
    handle->SourceFile = std::move(source);

    // Absolute build path
    if (BaseConst().MultiConfig) {
      handle->OutputFile = Gen()->AbsoluteIncludePath(sourceFile.BuildPath);
    } else {
      handle->OutputFile = Gen()->AbsoluteBuildPath(sourceFile.BuildPath);
    }

    // Register mapping in headers map
    RegisterMapping(handle);
  }

  return true;
}

bool cmQtAutoMocUicT::JobEvalCacheMocT::EvalSource(
  SourceFileHandleT const& source)
{
  SourceFileT const& sourceFile = *source;
  auto const& parseData = sourceFile.ParseData->Moc;
  if (!sourceFile.Moc ||
      (parseData.Macro.empty() && parseData.Include.Underscore.empty() &&
       parseData.Include.Dot.empty())) {
    return true;
  }

  std::string const sourceDirPrefix = SubDirPrefix(sourceFile.FileName);
  std::string const sourceBase =
    cmSystemTools::GetFilenameWithoutLastExtension(sourceFile.FileName);

  // For relaxed mode check if the own "moc_" or ".moc" file is included
  bool const relaxedMode = MocConst().RelaxedMode;
  bool sourceIncludesMocUnderscore = false;
  bool sourceIncludesDotMoc = false;
  // Check if the sources own "moc_" or ".moc" file is included
  if (relaxedMode) {
    for (IncludeKeyT const& incKey : parseData.Include.Underscore) {
      if (incKey.Base == sourceBase) {
        sourceIncludesMocUnderscore = true;
        break;
      }
    }
  }
  for (IncludeKeyT const& incKey : parseData.Include.Dot) {
    if (incKey.Base == sourceBase) {
      sourceIncludesDotMoc = true;
      break;
    }
  }

  // Check if this source needs to be moc processed but doesn't.
  if (!sourceIncludesDotMoc && !parseData.Macro.empty() &&
      !(relaxedMode && sourceIncludesMocUnderscore)) {
    LogError(GenT::MOC,
             cmStrCat(MessagePath(sourceFile.FileName), "\ncontains a ",
                      Quoted(parseData.Macro), " macro, but does not include ",
                      MessagePath(sourceBase + ".moc"),
                      "!\nConsider to\n  - add #include \"", sourceBase,
                      ".moc\"\n  - enable SKIP_AUTOMOC for this file"));
    return false;
  }

  // Evaluate "moc_" includes
  for (IncludeKeyT const& incKey : parseData.Include.Underscore) {
    SourceFileHandleT headerHandle;
    {
      std::string const headerBase = cmStrCat(incKey.Dir, incKey.Base);
      if (!FindIncludedHeader(headerHandle, sourceDirPrefix, headerBase)) {
        LogError(GenT::MOC,
                 cmStrCat(MessagePath(sourceFile.FileName),
                          "\nincludes the moc file ", MessagePath(incKey.Key),
                          ",\nbut a header ", MessageHeader(headerBase),
                          "\ncould not be found "
                          "in the following directories\n",
                          MessageSearchLocations()));
        return false;
      }
    }
    // The include might be handled differently in relaxed mode
    if (relaxedMode && !sourceIncludesDotMoc && !parseData.Macro.empty() &&
        (incKey.Base == sourceBase)) {
      // The <BASE>.cpp file includes a Qt macro but does not include the
      // <BASE>.moc file. In this case, the moc_<BASE>.cpp should probably
      // be generated from <BASE>.cpp instead of <BASE>.h, because otherwise
      // it won't build. But warn, since this is not how it is supposed to be
      // used. This is for KDE4 compatibility.

      // Issue a warning
      Log().Warning(
        GenT::MOC,
        cmStrCat(MessagePath(sourceFile.FileName), "\ncontains a ",
                 Quoted(parseData.Macro), " macro, but does not include ",
                 MessagePath(sourceBase + ".moc"), ".\nInstead it includes ",
                 MessagePath(incKey.Key), ".\nRunning moc on the source\n  ",
                 MessagePath(sourceFile.FileName), "!\nBetter include ",
                 MessagePath(sourceBase + ".moc"),
                 " for compatibility with regular mode.\n",
                 "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"));

      // Create mapping
      if (!RegisterIncluded(incKey.Key, source, source)) {
        return false;
      }
      continue;
    }

    // Check if header is skipped
    if (MocConst().skipped(headerHandle->FileName)) {
      continue;
    }
    // Create mapping
    if (!RegisterIncluded(incKey.Key, source, std::move(headerHandle))) {
      return false;
    }
  }

  // Evaluate ".moc" includes
  if (relaxedMode) {
    // Relaxed mode
    for (IncludeKeyT const& incKey : parseData.Include.Dot) {
      // Check if this is the sources own .moc file
      bool const ownMoc = (incKey.Base == sourceBase);
      if (ownMoc && !parseData.Macro.empty()) {
        // Create mapping for the regular use case
        if (!RegisterIncluded(incKey.Key, source, source)) {
          return false;
        }
        continue;
      }
      // Try to find a header instead but issue a warning.
      // This is for KDE4 compatibility.
      SourceFileHandleT headerHandle;
      {
        std::string const headerBase = cmStrCat(incKey.Dir, incKey.Base);
        if (!FindIncludedHeader(headerHandle, sourceDirPrefix, headerBase)) {
          LogError(
            GenT::MOC,
            cmStrCat(
              MessagePath(sourceFile.FileName), "\nincludes the moc file ",
              MessagePath(incKey.Key),
              ",\nwhich seems to be the moc file from a different source "
              "file.\nCMAKE_AUTOMOC_RELAXED_MODE:\nAlso a matching header ",
              MessageHeader(headerBase),
              "\ncould not be found in the following directories\n",
              MessageSearchLocations()));
          return false;
        }
      }
      // Check if header is skipped
      if (MocConst().skipped(headerHandle->FileName)) {
        continue;
      }
      // Issue a warning
      if (ownMoc && parseData.Macro.empty()) {
        Log().Warning(
          GenT::MOC,
          cmStrCat(MessagePath(sourceFile.FileName),
                   "\nincludes the moc file ", MessagePath(incKey.Key),
                   ", but does not contain a\n", MocConst().MacrosString(),
                   " macro.\nRunning moc on the header\n  ",
                   MessagePath(headerHandle->FileName), "!\nBetter include ",
                   MessagePath("moc_" + incKey.Base + ".cpp"),
                   " for a compatibility with regular mode.\n",
                   "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"));
      } else {
        Log().Warning(
          GenT::MOC,
          cmStrCat(MessagePath(sourceFile.FileName),
                   "\nincludes the moc file ", MessagePath(incKey.Key),
                   " instead of ", MessagePath("moc_" + incKey.Base + ".cpp"),
                   ".\nRunning moc on the header\n  ",
                   MessagePath(headerHandle->FileName), "!\nBetter include ",
                   MessagePath("moc_" + incKey.Base + ".cpp"),
                   " for compatibility with regular mode.\n",
                   "This is a CMAKE_AUTOMOC_RELAXED_MODE warning.\n"));
      }
      // Create mapping
      if (!RegisterIncluded(incKey.Key, source, std::move(headerHandle))) {
        return false;
      }
    }
  } else {
    // Strict mode
    for (IncludeKeyT const& incKey : parseData.Include.Dot) {
      // Check if this is the sources own .moc file
      bool const ownMoc = (incKey.Base == sourceBase);
      if (!ownMoc) {
        // Don't allow <BASE>.moc include other than own in regular mode
        LogError(GenT::MOC,
                 cmStrCat(MessagePath(sourceFile.FileName),
                          "\nincludes the moc file ", MessagePath(incKey.Key),
                          ",\nwhich seems to be the moc file from a different "
                          "source file.\nThis is not supported.  Include ",
                          MessagePath(sourceBase + ".moc"),
                          " to run moc on this source file."));
        return false;
      }
      // Accept but issue a warning if moc isn't required
      if (parseData.Macro.empty()) {
        Log().Warning(GenT::MOC,
                      cmStrCat(MessagePath(sourceFile.FileName),
                               "\nincludes the moc file ",
                               MessagePath(incKey.Key),
                               ", but does not contain a ",
                               MocConst().MacrosString(), " macro."));
      }
      // Create mapping
      if (!RegisterIncluded(incKey.Key, source, source)) {
        return false;
      }
    }
  }

  return true;
}

bool cmQtAutoMocUicT::JobEvalCacheMocT::FindIncludedHeader(
  SourceFileHandleT& headerHandle, cm::string_view includerDir,
  cm::string_view includeBase)
{
  // Clear search locations
  SearchLocations.clear();

  auto findHeader = [this,
                     &headerHandle](std::string const& basePath) -> bool {
    bool found = false;
    for (std::string const& ext : this->BaseConst().HeaderExtensions) {
      std::string const testPath =
        this->Gen()->CollapseFullPathTS(cmStrCat(basePath, '.', ext));
      cmFileTime fileTime;
      if (!fileTime.Load(testPath)) {
        // File not found
        continue;
      }

      // Return a known file if it exists already
      {
        auto it = BaseEval().Headers.find(testPath);
        if (it != BaseEval().Headers.end()) {
          headerHandle = it->second;
          found = true;
          break;
        }
      }

      // Created and return discovered file entry
      {
        SourceFileHandleT& handle = MocEval().HeadersDiscovered[testPath];
        if (!handle) {
          handle = std::make_shared<SourceFileT>(testPath);
          handle->FileTime = fileTime;
          handle->IsHeader = true;
          handle->Moc = true;
        }
        headerHandle = handle;
        found = true;
        break;
      }
    }
    if (!found) {
      this->SearchLocations.emplace_back(cmQtAutoGen::ParentDir(basePath));
    }
    return found;
  };

  // Search in vicinity of the source
  if (findHeader(cmStrCat(includerDir, includeBase))) {
    return true;
  }
  // Search in include directories
  for (std::string const& path : MocConst().IncludePaths) {
    if (findHeader(cmStrCat(path, '/', includeBase))) {
      return true;
    }
  }
  // Return without success
  return false;
}

bool cmQtAutoMocUicT::JobEvalCacheMocT::RegisterIncluded(
  std::string const& includeString, SourceFileHandleT includerFileHandle,
  SourceFileHandleT sourceFileHandle) const
{
  // Check if this file is already included
  MappingHandleT& handle = MocEval().Includes[includeString];
  if (handle) {
    // Check if the output file would be generated from different source files
    if (handle->SourceFile != sourceFileHandle) {
      std::string files =
        cmStrCat("  ", MessagePath(includerFileHandle->FileName), '\n');
      for (auto const& item : handle->IncluderFiles) {
        files += cmStrCat("  ", MessagePath(item->FileName), '\n');
      }
      LogError(
        GenT::MOC,
        cmStrCat("The source files\n", files,
                 "contain the same include string ",
                 MessagePath(includeString),
                 ", but\nthe moc file would be generated from different "
                 "source files\n  ",
                 MessagePath(sourceFileHandle->FileName), " and\n  ",
                 MessagePath(handle->SourceFile->FileName),
                 ".\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"));
      return false;
    }

    // The same mapping already exists. Just add to the includers list.
    handle->IncluderFiles.emplace_back(std::move(includerFileHandle));
    return true;
  }

  // Create a new mapping
  handle = std::make_shared<MappingT>();
  handle->IncludeString = includeString;
  handle->IncluderFiles.emplace_back(std::move(includerFileHandle));
  handle->SourceFile = std::move(sourceFileHandle);
  handle->OutputFile = Gen()->AbsoluteIncludePath(includeString);

  // Register mapping in sources/headers map
  RegisterMapping(handle);
  return true;
}

void cmQtAutoMocUicT::JobEvalCacheMocT::RegisterMapping(
  MappingHandleT mappingHandle) const
{
  auto& regMap = mappingHandle->SourceFile->IsHeader
    ? MocEval().HeaderMappings
    : MocEval().SourceMappings;
  // Check if source file already gets mapped
  auto& regHandle = regMap[mappingHandle->SourceFile->FileName];
  if (!regHandle) {
    // Yet unknown mapping
    regHandle = std::move(mappingHandle);
  } else {
    // Mappings with include string override those without
    if (!mappingHandle->IncludeString.empty()) {
      regHandle = std::move(mappingHandle);
    }
  }
}

std::string cmQtAutoMocUicT::JobEvalCacheMocT::MessageHeader(
  cm::string_view headerBase) const
{
  return MessagePath(cmStrCat(
    headerBase, ".{", cmJoin(this->BaseConst().HeaderExtensions, ","), '}'));
}

void cmQtAutoMocUicT::JobEvalCacheUicT::Process()
{
  // Prepare buffers
  SearchLocations.reserve((UicConst().SearchPaths.size() + 1) * 2);

  // Evaluate headers
  for (auto const& pair : BaseEval().Headers) {
    if (!EvalFile(pair.second)) {
      return;
    }
  }
  // Evaluate sources
  for (auto const& pair : BaseEval().Sources) {
    if (!EvalFile(pair.second)) {
      return;
    }
  }
}

bool cmQtAutoMocUicT::JobEvalCacheUicT::EvalFile(
  SourceFileHandleT const& sourceFileHandle)
{
  SourceFileT const& sourceFile = *sourceFileHandle;
  auto const& Include = sourceFile.ParseData->Uic.Include;
  if (!sourceFile.Uic || Include.empty()) {
    return true;
  }

  std::string const sourceDirPrefix = SubDirPrefix(sourceFile.FileName);
  for (IncludeKeyT const& incKey : Include) {
    // Find .ui file
    UiName = cmStrCat(incKey.Base, ".ui");
    if (!FindIncludedUi(sourceDirPrefix, incKey.Dir)) {
      LogError(GenT::UIC,
               cmStrCat(MessagePath(sourceFile.FileName),
                        "\nincludes the uic file ", MessagePath(incKey.Key),
                        ",\nbut the user interface file ", MessagePath(UiName),
                        "\ncould not be found in the following directories\n",
                        MessageSearchLocations()));
      return false;
    }
    // Check if the file is skipped
    if (UicConst().skipped(UiFileHandle->FileName)) {
      continue;
    }
    // Register mapping
    if (!RegisterMapping(incKey.Key, sourceFileHandle)) {
      return false;
    }
  }

  return true;
}

bool cmQtAutoMocUicT::JobEvalCacheUicT::FindIncludedUi(
  cm::string_view sourceDirPrefix, cm::string_view includePrefix)
{
  // Clear locations buffer
  SearchLocations.clear();

  auto findUi = [this](std::string const& testPath) -> bool {
    std::string const fullPath = this->Gen()->CollapseFullPathTS(testPath);
    cmFileTime fileTime;
    if (!fileTime.Load(fullPath)) {
      this->SearchLocations.emplace_back(cmQtAutoGen::ParentDir(fullPath));
      return false;
    }
    // .ui file found in files system!
    // Get or create .ui file handle
    SourceFileHandleT& handle = this->UicEval().UiFiles[fullPath];
    if (!handle) {
      // The file wasn't registered, yet
      handle = std::make_shared<SourceFileT>(fullPath);
      handle->FileTime = fileTime;
    }
    this->UiFileHandle = handle;
    return true;
  };

  // Vicinity of the source
  if (findUi(cmStrCat(sourceDirPrefix, UiName))) {
    return true;
  }
  if (!includePrefix.empty()) {
    if (findUi(cmStrCat(sourceDirPrefix, includePrefix, UiName))) {
      return true;
    }
  }
  // Additional AUTOUIC search paths
  auto const& searchPaths = UicConst().SearchPaths;
  if (!searchPaths.empty()) {
    for (std::string const& sPath : searchPaths) {
      if (findUi(cmStrCat(sPath, '/', UiName))) {
        return true;
      }
    }
    if (!includePrefix.empty()) {
      for (std::string const& sPath : searchPaths) {
        if (findUi(cmStrCat(sPath, '/', includePrefix, UiName))) {
          return true;
        }
      }
    }
  }

  return false;
}

bool cmQtAutoMocUicT::JobEvalCacheUicT::RegisterMapping(
  std::string const& includeString, SourceFileHandleT includerFileHandle)
{
  auto& Includes = Gen()->UicEval().Includes;
  auto it = Includes.find(includeString);
  if (it != Includes.end()) {
    MappingHandleT const& handle = it->second;
    if (handle->SourceFile != UiFileHandle) {
      // The output file already gets generated - from a different .ui file!
      std::string files =
        cmStrCat("  ", MessagePath(includerFileHandle->FileName), '\n');
      for (auto const& item : handle->IncluderFiles) {
        files += cmStrCat("  ", MessagePath(item->FileName), '\n');
      }
      LogError(
        GenT::UIC,
        cmStrCat(
          "The source files\n", files, "contain the same include string ",
          Quoted(includeString),
          ", but\nthe uic file would be generated from different "
          "user interface files\n  ",
          MessagePath(UiFileHandle->FileName), " and\n  ",
          MessagePath(handle->SourceFile->FileName),
          ".\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"));
      return false;
    }
    // Add includer file to existing mapping
    handle->IncluderFiles.emplace_back(std::move(includerFileHandle));
  } else {
    // New mapping handle
    MappingHandleT handle = std::make_shared<MappingT>();
    handle->IncludeString = includeString;
    handle->IncluderFiles.emplace_back(std::move(includerFileHandle));
    handle->SourceFile = UiFileHandle;
    handle->OutputFile = Gen()->AbsoluteIncludePath(includeString);
    // Register mapping
    Includes.emplace(includeString, std::move(handle));
  }
  return true;
}

void cmQtAutoMocUicT::JobEvalCacheFinishT::Process()
{
  // Add discovered header parse jobs
  Gen()->CreateParseJobs<JobParseHeaderT>(MocEval().HeadersDiscovered);

  // Add dependency probing jobs
  {
    // Add fence job to ensure all parsing has finished
    Gen()->WorkerPool().EmplaceJob<JobFenceT>();
    if (MocConst().Enabled) {
      Gen()->WorkerPool().EmplaceJob<JobProbeDepsMocT>();
    }
    if (UicConst().Enabled) {
      Gen()->WorkerPool().EmplaceJob<JobProbeDepsUicT>();
    }
    // Add probe finish job
    Gen()->WorkerPool().EmplaceJob<JobProbeDepsFinishT>();
  }
}

void cmQtAutoMocUicT::JobProbeDepsMocT::Process()
{
  // Create moc header jobs
  for (auto const& pair : MocEval().HeaderMappings) {
    // Register if this mapping is a candidate for mocs_compilation.cpp
    bool const compFile = pair.second->IncludeString.empty();
    if (compFile) {
      MocEval().CompFiles.emplace_back(pair.second->SourceFile->BuildPath);
    }
    if (!Generate(pair.second, compFile)) {
      return;
    }
  }

  // Create moc source jobs
  for (auto const& pair : MocEval().SourceMappings) {
    if (!Generate(pair.second, false)) {
      return;
    }
  }
}

bool cmQtAutoMocUicT::JobProbeDepsMocT::Generate(MappingHandleT const& mapping,
                                                 bool compFile) const
{
  std::unique_ptr<std::string> reason;
  if (Log().Verbose()) {
    reason = cm::make_unique<std::string>();
  }
  if (Probe(*mapping, reason.get())) {
    // Register the parent directory for creation
    MocEval().OutputDirs.emplace(cmQtAutoGen::ParentDir(mapping->OutputFile));
    // Fetch the cache entry for the source file
    std::string const& sourceFile = mapping->SourceFile->FileName;
    ParseCacheT::GetOrInsertT cacheEntry =
      BaseEval().ParseCache.GetOrInsert(sourceFile);
    // Add moc job
    Gen()->WorkerPool().EmplaceJob<JobCompileMocT>(
      mapping, std::move(reason), std::move(cacheEntry.first));
    // Check if a moc job for a mocs_compilation.cpp entry was generated
    if (compFile) {
      MocEval().CompUpdated = true;
    }
  }
  return true;
}

bool cmQtAutoMocUicT::JobProbeDepsMocT::Probe(MappingT const& mapping,
                                              std::string* reason) const
{
  std::string const& sourceFile = mapping.SourceFile->FileName;
  std::string const& outputFile = mapping.OutputFile;

  // Test if the output file exists
  cmFileTime outputFileTime;
  if (!outputFileTime.Load(outputFile)) {
    if (reason != nullptr) {
      *reason =
        cmStrCat("Generating ", MessagePath(outputFile),
                 ", because it doesn't exist, from ", MessagePath(sourceFile));
    }
    return true;
  }

  // Test if any setting changed
  if (MocConst().SettingsChanged) {
    if (reason != nullptr) {
      *reason = cmStrCat("Generating ", MessagePath(outputFile),
                         ", because the uic settings changed, from ",
                         MessagePath(sourceFile));
    }
    return true;
  }

  // Test if the source file is newer
  if (outputFileTime.Older(mapping.SourceFile->FileTime)) {
    if (reason != nullptr) {
      *reason = cmStrCat("Generating ", MessagePath(outputFile),
                         ", because it's older than its source file, from ",
                         MessagePath(sourceFile));
    }
    return true;
  }

  // Test if the moc_predefs file is newer
  if (!MocConst().PredefsFileAbs.empty()) {
    if (outputFileTime.Older(MocEval().PredefsTime)) {
      if (reason != nullptr) {
        *reason = cmStrCat("Generating ", MessagePath(outputFile),
                           ", because it's older than ",
                           MessagePath(MocConst().PredefsFileAbs), ", from ",
                           MessagePath(sourceFile));
      }
      return true;
    }
  }

  // Test if the moc executable is newer
  if (outputFileTime.Older(MocConst().ExecutableTime)) {
    if (reason != nullptr) {
      *reason = cmStrCat("Generating ", MessagePath(outputFile),
                         ", because it's older than the moc executable, from ",
                         MessagePath(sourceFile));
    }
    return true;
  }

  // Test if a dependency file is newer
  {
    // Check dependency timestamps
    std::string const sourceDir = SubDirPrefix(sourceFile);
    for (std::string const& dep : mapping.SourceFile->ParseData->Moc.Depends) {
      // Find dependency file
      auto const depMatch = FindDependency(sourceDir, dep);
      if (depMatch.first.empty()) {
        Log().Warning(GenT::MOC,
                      cmStrCat(MessagePath(sourceFile), " depends on ",
                               MessagePath(dep),
                               " but the file does not exist."));
        continue;
      }
      // Test if dependency file is older
      if (outputFileTime.Older(depMatch.second)) {
        if (reason != nullptr) {
          *reason = cmStrCat("Generating ", MessagePath(outputFile),
                             ", because it's older than its dependency file ",
                             MessagePath(depMatch.first), ", from ",
                             MessagePath(sourceFile));
        }
        return true;
      }
    }
  }

  return false;
}

std::pair<std::string, cmFileTime>
cmQtAutoMocUicT::JobProbeDepsMocT::FindDependency(
  std::string const& sourceDir, std::string const& includeString) const
{
  using ResPair = std::pair<std::string, cmFileTime>;
  // moc's dependency file contains absolute paths
  if (MocConst().CanOutputDependencies) {
    ResPair res{ includeString, {} };
    if (res.second.Load(res.first)) {
      return res;
    }
    return {};
  }
  // Search in vicinity of the source
  {
    ResPair res{ sourceDir + includeString, {} };
    if (res.second.Load(res.first)) {
      return res;
    }
  }
  // Search in include directories
  for (std::string const& includePath : MocConst().IncludePaths) {
    ResPair res{ cmStrCat(includePath, '/', includeString), {} };
    if (res.second.Load(res.first)) {
      return res;
    }
  }
  // Return empty
  return ResPair();
}

void cmQtAutoMocUicT::JobProbeDepsUicT::Process()
{
  for (auto const& pair : Gen()->UicEval().Includes) {
    MappingHandleT const& mapping = pair.second;
    std::unique_ptr<std::string> reason;
    if (Log().Verbose()) {
      reason = cm::make_unique<std::string>();
    }
    if (!Probe(*mapping, reason.get())) {
      continue;
    }

    // Register the parent directory for creation
    UicEval().OutputDirs.emplace(cmQtAutoGen::ParentDir(mapping->OutputFile));
    // Add uic job
    Gen()->WorkerPool().EmplaceJob<JobCompileUicT>(mapping, std::move(reason));
  }
}

bool cmQtAutoMocUicT::JobProbeDepsUicT::Probe(MappingT const& mapping,
                                              std::string* reason) const
{
  std::string const& sourceFile = mapping.SourceFile->FileName;
  std::string const& outputFile = mapping.OutputFile;

  // Test if the build file exists
  cmFileTime outputFileTime;
  if (!outputFileTime.Load(outputFile)) {
    if (reason != nullptr) {
      *reason =
        cmStrCat("Generating ", MessagePath(outputFile),
                 ", because it doesn't exist, from ", MessagePath(sourceFile));
    }
    return true;
  }

  // Test if the uic settings changed
  if (UicConst().SettingsChanged) {
    if (reason != nullptr) {
      *reason = cmStrCat("Generating ", MessagePath(outputFile),
                         ", because the uic settings changed, from ",
                         MessagePath(sourceFile));
    }
    return true;
  }

  // Test if the source file is newer
  if (outputFileTime.Older(mapping.SourceFile->FileTime)) {
    if (reason != nullptr) {
      *reason = cmStrCat("Generating ", MessagePath(outputFile),
                         " because it's older than the source file ",
                         MessagePath(sourceFile));
    }
    return true;
  }

  // Test if the uic executable is newer
  if (outputFileTime.Older(UicConst().ExecutableTime)) {
    if (reason != nullptr) {
      *reason = cmStrCat("Generating ", MessagePath(outputFile),
                         ", because it's older than the uic executable, from ",
                         MessagePath(sourceFile));
    }
    return true;
  }

  return false;
}

void cmQtAutoMocUicT::JobProbeDepsFinishT::Process()
{
  // Create output directories
  {
    using StringSet = std::unordered_set<std::string>;
    auto createDirs = [this](GenT genType, StringSet const& dirSet) {
      for (std::string const& dirName : dirSet) {
        if (!cmSystemTools::MakeDirectory(dirName)) {
          this->LogError(
            genType,
            cmStrCat("Creating directory ", MessagePath(dirName), " failed."));
          return;
        }
      }
    };
    if (MocConst().Enabled && UicConst().Enabled) {
      StringSet outputDirs = MocEval().OutputDirs;
      outputDirs.insert(UicEval().OutputDirs.begin(),
                        UicEval().OutputDirs.end());
      createDirs(GenT::GEN, outputDirs);
    } else if (MocConst().Enabled) {
      createDirs(GenT::MOC, MocEval().OutputDirs);
    } else if (UicConst().Enabled) {
      createDirs(GenT::UIC, UicEval().OutputDirs);
    }
  }

  if (MocConst().Enabled) {
    // Add mocs compilations job
    Gen()->WorkerPool().EmplaceJob<JobMocsCompilationT>();
  }

  if (!BaseConst().DepFile.empty()) {
    // Add job to merge dep files
    Gen()->WorkerPool().EmplaceJob<JobDepFilesMergeT>();
  }

  // Add finish job
  Gen()->WorkerPool().EmplaceJob<JobFinishT>();
}

void cmQtAutoMocUicT::JobCompileMocT::Process()
{
  std::string const& sourceFile = Mapping->SourceFile->FileName;
  std::string const& outputFile = Mapping->OutputFile;

  // Compose moc command
  std::vector<std::string> cmd;
  {
    // Reserve large enough
    cmd.reserve(MocConst().OptionsDefinitions.size() +
                MocConst().OptionsIncludes.size() +
                MocConst().OptionsExtra.size() + 16);
    cmd.push_back(MocConst().Executable);
    // Add definitions
    cm::append(cmd, MocConst().OptionsDefinitions);
    // Add includes
    cm::append(cmd, MocConst().OptionsIncludes);
    // Add predefs include
    if (!MocConst().PredefsFileAbs.empty()) {
      cmd.emplace_back("--include");
      cmd.push_back(MocConst().PredefsFileAbs);
    }
    // Add path prefix on demand
    if (MocConst().PathPrefix && Mapping->SourceFile->IsHeader) {
      for (std::string const& dir : MocConst().IncludePaths) {
        cm::string_view prefix = sourceFile;
        if (cmHasPrefix(prefix, dir)) {
          prefix.remove_prefix(dir.size());
          if (cmHasPrefix(prefix, '/')) {
            prefix.remove_prefix(1);
            auto slashPos = prefix.rfind('/');
            if (slashPos != cm::string_view::npos) {
              cmd.emplace_back("-p");
              cmd.emplace_back(prefix.substr(0, slashPos));
            } else {
              cmd.emplace_back("-p");
              cmd.emplace_back("./");
            }
            break;
          }
        }
      }
    }
    // Add extra options
    cm::append(cmd, MocConst().OptionsExtra);
    if (MocConst().CanOutputDependencies) {
      cmd.emplace_back("--output-dep-file");
    }
    // Add output file
    cmd.emplace_back("-o");
    cmd.push_back(outputFile);
    // Add source file
    cmd.push_back(sourceFile);
  }

  // Execute moc command
  cmWorkerPool::ProcessResultT result;
  if (!RunProcess(GenT::MOC, result, cmd, Reason.get())) {
    // Moc command failed
    std::string includers;
    if (!Mapping->IncluderFiles.empty()) {
      includers = "included by\n";
      for (auto const& item : Mapping->IncluderFiles) {
        includers += cmStrCat("  ", MessagePath(item->FileName), '\n');
      }
    }
    LogCommandError(GenT::MOC,
                    cmStrCat("The moc process failed to compile\n  ",
                             MessagePath(sourceFile), "\ninto\n  ",
                             MessagePath(outputFile), '\n', includers,
                             result.ErrorMessage),
                    cmd, result.StdOut);
    return;
  }

  // Moc command success. Print moc output.
  if (!result.StdOut.empty()) {
    Log().Info(GenT::MOC, result.StdOut);
  }

  // Extract dependencies from the dep file moc generated for us
  if (MocConst().CanOutputDependencies) {
    const std::string depfile = outputFile + ".d";
    if (Log().Verbose()) {
      Log().Info(GenT::MOC,
                 "Reading dependencies from " + MessagePath(depfile));
    }
    if (!cmSystemTools::FileExists(depfile)) {
      Log().Warning(GenT::MOC,
                    "Dependency file " + MessagePath(depfile) +
                      " does not exist.");
      return;
    }
    CacheEntry->Moc.Depends = dependenciesFromDepFile(depfile.c_str());
  }
}

void cmQtAutoMocUicT::JobCompileUicT::Process()
{
  std::string const& sourceFile = Mapping->SourceFile->FileName;
  std::string const& outputFile = Mapping->OutputFile;

  // Compose uic command
  std::vector<std::string> cmd;
  cmd.push_back(UicConst().Executable);
  {
    std::vector<std::string> allOpts = UicConst().Options;
    auto optionIt = UicConst().UiFiles.find(sourceFile);
    if (optionIt != UicConst().UiFiles.end()) {
      UicMergeOptions(allOpts, optionIt->second.Options,
                      (BaseConst().QtVersion.Major == 5));
    }
    cm::append(cmd, allOpts);
  }
  cmd.emplace_back("-o");
  cmd.emplace_back(outputFile);
  cmd.emplace_back(sourceFile);

  cmWorkerPool::ProcessResultT result;
  if (RunProcess(GenT::UIC, result, cmd, Reason.get())) {
    // Uic command success
    // Print uic output
    if (!result.StdOut.empty()) {
      Log().Info(GenT::UIC, result.StdOut);
    }
  } else {
    // Uic command failed
    std::string includers;
    for (auto const& item : Mapping->IncluderFiles) {
      includers += cmStrCat("  ", MessagePath(item->FileName), '\n');
    }
    LogCommandError(GenT::UIC,
                    cmStrCat("The uic process failed to compile\n  ",
                             MessagePath(sourceFile), "\ninto\n  ",
                             MessagePath(outputFile), "\nincluded by\n",
                             includers, result.ErrorMessage),
                    cmd, result.StdOut);
  }
}

void cmQtAutoMocUicT::JobMocsCompilationT::Process()
{
  // Compose mocs compilation file content
  std::string content =
    "// This file is autogenerated. Changes will be overwritten.\n";

  if (MocEval().CompFiles.empty()) {
    // Placeholder content
    content += "// No files found that require moc or the moc files are "
               "included\n"
               "enum some_compilers { need_more_than_nothing };\n";
  } else {
    // Valid content
    const bool mc = BaseConst().MultiConfig;
    cm::string_view const wrapFront = mc ? "#include <" : "#include \"";
    cm::string_view const wrapBack = mc ? ">\n" : "\"\n";
    content += cmWrap(wrapFront, MocEval().CompFiles, wrapBack, "");
  }

  std::string const& compAbs = MocConst().CompFileAbs;
  if (cmQtAutoGenerator::FileDiffers(compAbs, content)) {
    // Actually write mocs compilation file
    if (Log().Verbose()) {
      Log().Info(GenT::MOC,
                 "Generating MOC compilation " + MessagePath(compAbs));
    }
    if (!FileWrite(compAbs, content)) {
      LogError(GenT::MOC,
               cmStrCat("Writing MOC compilation ", MessagePath(compAbs),
                        " failed."));
    }
  } else if (MocEval().CompUpdated) {
    // Only touch mocs compilation file
    if (Log().Verbose()) {
      Log().Info(GenT::MOC,
                 "Touching MOC compilation " + MessagePath(compAbs));
    }
    if (!cmSystemTools::Touch(compAbs, false)) {
      LogError(GenT::MOC,
               cmStrCat("Touching MOC compilation ", MessagePath(compAbs),
                        " failed."));
    }
  }
}

/*
 * Escapes paths for Ninja depfiles.
 * This is a re-implementation of what moc does when writing depfiles.
 */
std::string escapeDependencyPath(cm::string_view path)
{
  std::string escapedPath;
  escapedPath.reserve(path.size());
  const size_t s = path.size();
  int backslashCount = 0;
  for (size_t i = 0; i < s; ++i) {
    if (path[i] == '\\') {
      ++backslashCount;
    } else {
      if (path[i] == '$') {
        escapedPath.push_back('$');
      } else if (path[i] == '#') {
        escapedPath.push_back('\\');
      } else if (path[i] == ' ') {
        // Double the amount of written backslashes,
        // and add one more to escape the space.
        while (backslashCount-- >= 0) {
          escapedPath.push_back('\\');
        }
      }
      backslashCount = 0;
    }
    escapedPath.push_back(path[i]);
  }
  return escapedPath;
}

void cmQtAutoMocUicT::JobDepFilesMergeT::Process()
{
  if (Log().Verbose()) {
    Log().Info(GenT::MOC, "Merging MOC dependencies");
  }
  auto processDepFile =
    [](const std::string& mocOutputFile) -> std::vector<std::string> {
    std::string f = mocOutputFile + ".d";
    if (!cmSystemTools::FileExists(f)) {
      return {};
    }
    return dependenciesFromDepFile(f.c_str());
  };

  std::vector<std::string> dependencies;
  ParseCacheT& parseCache = BaseEval().ParseCache;
  auto processMappingEntry = [&](const MappingMapT::value_type& m) {
    auto cacheEntry = parseCache.GetOrInsert(m.first);
    if (cacheEntry.first->Moc.Depends.empty()) {
      cacheEntry.first->Moc.Depends = processDepFile(m.second->OutputFile);
    }
    dependencies.insert(dependencies.end(),
                        cacheEntry.first->Moc.Depends.begin(),
                        cacheEntry.first->Moc.Depends.end());
  };

  std::for_each(MocEval().HeaderMappings.begin(),
                MocEval().HeaderMappings.end(), processMappingEntry);
  std::for_each(MocEval().SourceMappings.begin(),
                MocEval().SourceMappings.end(), processMappingEntry);

  // Remove duplicates to make the depfile smaller
  std::sort(dependencies.begin(), dependencies.end());
  dependencies.erase(std::unique(dependencies.begin(), dependencies.end()),
                     dependencies.end());

  // Add form files
  for (const auto& uif : UicEval().UiFiles) {
    dependencies.push_back(uif.first);
  }

  // Write the file
  cmsys::ofstream ofs;
  ofs.open(BaseConst().DepFile.c_str(),
           (std::ios::out | std::ios::binary | std::ios::trunc));
  if (!ofs) {
    LogError(GenT::GEN,
             cmStrCat("Cannot open ", MessagePath(BaseConst().DepFile),
                      " for writing."));
    return;
  }
  ofs << BaseConst().DepFileRuleName << ": \\\n";
  for (const std::string& file : dependencies) {
    ofs << '\t' << escapeDependencyPath(file) << " \\\n";
    if (!ofs.good()) {
      LogError(GenT::GEN,
               cmStrCat("Writing depfile", MessagePath(BaseConst().DepFile),
                        " failed."));
      return;
    }
  }

  // Add the CMake executable to re-new cache data if necessary.
  // Also, this is the last entry, so don't add a backslash.
  ofs << '\t' << escapeDependencyPath(BaseConst().CMakeExecutable) << '\n';
}

void cmQtAutoMocUicT::JobFinishT::Process()
{
  Gen()->AbortSuccess();
}

cmQtAutoMocUicT::cmQtAutoMocUicT()
  : cmQtAutoGenerator(GenT::GEN)
{
}
cmQtAutoMocUicT::~cmQtAutoMocUicT() = default;

bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
{
  // -- Required settings
  if (!info.GetBool("MULTI_CONFIG", BaseConst_.MultiConfig, true) ||
      !info.GetUInt("QT_VERSION_MAJOR", BaseConst_.QtVersion.Major, true) ||
      !info.GetUInt("QT_VERSION_MINOR", BaseConst_.QtVersion.Minor, true) ||
      !info.GetUInt("PARALLEL", BaseConst_.ThreadCount, false) ||
      !info.GetString("BUILD_DIR", BaseConst_.AutogenBuildDir, true) ||
      !info.GetStringConfig("INCLUDE_DIR", BaseConst_.AutogenIncludeDir,
                            true) ||
      !info.GetString("CMAKE_EXECUTABLE", BaseConst_.CMakeExecutable, true) ||
      !info.GetStringConfig("PARSE_CACHE_FILE", BaseConst_.ParseCacheFile,
                            true) ||
      !info.GetString("DEP_FILE", BaseConst_.DepFile, false) ||
      !info.GetString("DEP_FILE_RULE_NAME", BaseConst_.DepFileRuleName,
                      false) ||
      !info.GetStringConfig("SETTINGS_FILE", SettingsFile_, true) ||
      !info.GetArray("HEADER_EXTENSIONS", BaseConst_.HeaderExtensions, true) ||
      !info.GetString("QT_MOC_EXECUTABLE", MocConst_.Executable, false) ||
      !info.GetString("QT_UIC_EXECUTABLE", UicConst_.Executable, false)) {
    return false;
  }

  // -- Checks
  if (!BaseConst_.CMakeExecutableTime.Load(BaseConst_.CMakeExecutable)) {
    return info.LogError(cmStrCat("The CMake executable ",
                                  MessagePath(BaseConst_.CMakeExecutable),
                                  " does not exist."));
  }

  // -- Evaluate values
  BaseConst_.ThreadCount = std::min(BaseConst_.ThreadCount, ParallelMax);
  WorkerPool_.SetThreadCount(BaseConst_.ThreadCount);

  // -- Moc
  if (!MocConst_.Executable.empty()) {
    // -- Moc is enabled
    MocConst_.Enabled = true;

    // -- Temporary buffers
    struct
    {
      std::vector<std::string> MacroNames;
      std::vector<std::string> DependFilters;
    } tmp;

    // -- Required settings
    if (!info.GetBool("MOC_RELAXED_MODE", MocConst_.RelaxedMode, false) ||
        !info.GetBool("MOC_PATH_PREFIX", MocConst_.PathPrefix, true) ||
        !info.GetArray("MOC_SKIP", MocConst_.SkipList, false) ||
        !info.GetArrayConfig("MOC_DEFINITIONS", MocConst_.Definitions,
                             false) ||
        !info.GetArrayConfig("MOC_INCLUDES", MocConst_.IncludePaths, false) ||
        !info.GetArray("MOC_OPTIONS", MocConst_.OptionsExtra, false) ||
        !info.GetStringConfig("MOC_COMPILATION_FILE", MocConst_.CompFileAbs,
                              true) ||
        !info.GetArray("MOC_PREDEFS_CMD", MocConst_.PredefsCmd, false) ||
        !info.GetStringConfig("MOC_PREDEFS_FILE", MocConst_.PredefsFileAbs,
                              !MocConst_.PredefsCmd.empty()) ||
        !info.GetArray("MOC_MACRO_NAMES", tmp.MacroNames, true) ||
        !info.GetArray("MOC_DEPEND_FILTERS", tmp.DependFilters, false)) {
      return false;
    }

    // -- Evaluate settings
    for (std::string const& item : tmp.MacroNames) {
      MocConst_.MacroFilters.emplace_back(
        item, ("[\n][ \t]*{?[ \t]*" + item).append("[^a-zA-Z0-9_]"));
    }
    // Can moc output dependencies or do we need to setup dependency filters?
    if (BaseConst_.QtVersion >= IntegerVersion(5, 15)) {
      MocConst_.CanOutputDependencies = true;
    } else {
      Json::Value const& val = info.GetValue("MOC_DEPEND_FILTERS");
      if (!val.isArray()) {
        return info.LogError("MOC_DEPEND_FILTERS JSON value is not an array.");
      }
      Json::ArrayIndex const arraySize = val.size();
      for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
        // Test entry closure
        auto testEntry = [&info, ii](bool test, cm::string_view msg) -> bool {
          if (!test) {
            info.LogError(
              cmStrCat("MOC_DEPEND_FILTERS filter ", ii, ": ", msg));
          }
          return !test;
        };

        Json::Value const& pairVal = val[ii];

        if (testEntry(pairVal.isArray(), "JSON value is not an array.") ||
            testEntry(pairVal.size() == 2, "JSON array size invalid.")) {
          return false;
        }

        Json::Value const& keyVal = pairVal[0u];
        Json::Value const& expVal = pairVal[1u];
        if (testEntry(keyVal.isString(),
                      "JSON value for keyword is not a string.") ||
            testEntry(expVal.isString(),
                      "JSON value for regular expression is not a string.")) {
          return false;
        }

        std::string const key = keyVal.asString();
        std::string const exp = expVal.asString();
        if (testEntry(!key.empty(), "Keyword is empty.") ||
            testEntry(!exp.empty(), "Regular expression is empty.")) {
          return false;
        }

        this->MocConst_.DependFilters.emplace_back(key, exp);
        if (testEntry(
              this->MocConst_.DependFilters.back().Exp.is_valid(),
              cmStrCat("Regular expression compilation failed.\nKeyword: ",
                       Quoted(key), "\nExpression: ", Quoted(exp)))) {
          return false;
        }
      }
    }
    // Check if moc executable exists (by reading the file time)
    if (!MocConst_.ExecutableTime.Load(MocConst_.Executable)) {
      return info.LogError(cmStrCat("The moc executable ",
                                    MessagePath(MocConst_.Executable),
                                    " does not exist."));
    }
  }

  // -- Uic
  if (!UicConst_.Executable.empty()) {
    // Uic is enabled
    UicConst_.Enabled = true;

    // -- Required settings
    if (!info.GetArray("UIC_SKIP", UicConst_.SkipList, false) ||
        !info.GetArray("UIC_SEARCH_PATHS", UicConst_.SearchPaths, false) ||
        !info.GetArrayConfig("UIC_OPTIONS", UicConst_.Options, false)) {
      return false;
    }
    // .ui files
    {
      Json::Value const& val = info.GetValue("UIC_UI_FILES");
      if (!val.isArray()) {
        return info.LogError("UIC_UI_FILES JSON value is not an array.");
      }
      Json::ArrayIndex const arraySize = val.size();
      for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
        // Test entry closure
        auto testEntry = [&info, ii](bool test, cm::string_view msg) -> bool {
          if (!test) {
            info.LogError(cmStrCat("UIC_UI_FILES entry ", ii, ": ", msg));
          }
          return !test;
        };

        Json::Value const& entry = val[ii];
        if (testEntry(entry.isArray(), "JSON value is not an array.") ||
            testEntry(entry.size() == 2, "JSON array size invalid.")) {
          return false;
        }

        Json::Value const& entryName = entry[0u];
        Json::Value const& entryOptions = entry[1u];
        if (testEntry(entryName.isString(),
                      "JSON value for name is not a string.") ||
            testEntry(entryOptions.isArray(),
                      "JSON value for options is not an array.")) {
          return false;
        }

        auto& uiFile = UicConst_.UiFiles[entryName.asString()];
        InfoT::GetJsonArray(uiFile.Options, entryOptions);
      }
    }

    // -- Evaluate settings
    // Check if uic executable exists (by reading the file time)
    if (!UicConst_.ExecutableTime.Load(UicConst_.Executable)) {
      return info.LogError(cmStrCat("The uic executable ",
                                    MessagePath(UicConst_.Executable),
                                    " does not exist."));
    }
  }

  // -- Headers
  {
    Json::Value const& val = info.GetValue("HEADERS");
    if (!val.isArray()) {
      return info.LogError("HEADERS JSON value is not an array.");
    }
    Json::ArrayIndex const arraySize = val.size();
    for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
      // Test entry closure
      auto testEntry = [&info, ii](bool test, cm::string_view msg) -> bool {
        if (!test) {
          info.LogError(cmStrCat("HEADERS entry ", ii, ": ", msg));
        }
        return !test;
      };

      Json::Value const& entry = val[ii];
      if (testEntry(entry.isArray(), "JSON value is not an array.") ||
          testEntry(entry.size() == 3, "JSON array size invalid.")) {
        return false;
      }

      Json::Value const& entryName = entry[0u];
      Json::Value const& entryFlags = entry[1u];
      Json::Value const& entryBuild = entry[2u];
      if (testEntry(entryName.isString(),
                    "JSON value for name is not a string.") ||
          testEntry(entryFlags.isString(),
                    "JSON value for flags is not a string.") ||
          testEntry(entryBuild.isString(),
                    "JSON value for build path is not a string.")) {
        return false;
      }

      std::string name = entryName.asString();
      std::string flags = entryFlags.asString();
      std::string build = entryBuild.asString();
      if (testEntry(flags.size() == 2, "Invalid flags string size")) {
        return false;
      }

      cmFileTime fileTime;
      if (!fileTime.Load(name)) {
        return info.LogError(cmStrCat(
          "The header file ", this->MessagePath(name), " does not exist."));
      }

      SourceFileHandleT sourceHandle = std::make_shared<SourceFileT>(name);
      sourceHandle->FileTime = fileTime;
      sourceHandle->IsHeader = true;
      sourceHandle->Moc = (flags[0] == 'M');
      sourceHandle->Uic = (flags[1] == 'U');
      if (sourceHandle->Moc && MocConst().Enabled) {
        if (build.empty()) {
          return info.LogError(
            cmStrCat("Header file ", ii, " build path is empty"));
        }
        sourceHandle->BuildPath = std::move(build);
      }
      BaseEval().Headers.emplace(std::move(name), std::move(sourceHandle));
    }
  }

  // -- Sources
  {
    Json::Value const& val = info.GetValue("SOURCES");
    if (!val.isArray()) {
      return info.LogError("SOURCES JSON value is not an array.");
    }
    Json::ArrayIndex const arraySize = val.size();
    for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
      // Test entry closure
      auto testEntry = [&info, ii](bool test, cm::string_view msg) -> bool {
        if (!test) {
          info.LogError(cmStrCat("SOURCES entry ", ii, ": ", msg));
        }
        return !test;
      };

      Json::Value const& entry = val[ii];
      if (testEntry(entry.isArray(), "JSON value is not an array.") ||
          testEntry(entry.size() == 2, "JSON array size invalid.")) {
        return false;
      }

      Json::Value const& entryName = entry[0u];
      Json::Value const& entryFlags = entry[1u];
      if (testEntry(entryName.isString(),
                    "JSON value for name is not a string.") ||
          testEntry(entryFlags.isString(),
                    "JSON value for flags is not a string.")) {
        return false;
      }

      std::string name = entryName.asString();
      std::string flags = entryFlags.asString();
      if (testEntry(flags.size() == 2, "Invalid flags string size")) {
        return false;
      }

      cmFileTime fileTime;
      if (!fileTime.Load(name)) {
        return info.LogError(cmStrCat(
          "The source file ", this->MessagePath(name), " does not exist."));
      }

      SourceFileHandleT sourceHandle = std::make_shared<SourceFileT>(name);
      sourceHandle->FileTime = fileTime;
      sourceHandle->IsHeader = false;
      sourceHandle->Moc = (flags[0] == 'M');
      sourceHandle->Uic = (flags[1] == 'U');
      BaseEval().Sources.emplace(std::move(name), std::move(sourceHandle));
    }
  }

  // -- Init derived information
  // Moc variables
  if (MocConst().Enabled) {
    // Compose moc includes list
    {
      // Compute framework paths
      std::set<std::string> frameworkPaths;
      for (std::string const& path : MocConst().IncludePaths) {
        // Extract framework path
        if (cmHasLiteralSuffix(path, ".framework/Headers")) {
          // Go up twice to get to the framework root
          std::vector<std::string> pathComponents;
          cmSystemTools::SplitPath(path, pathComponents);
          frameworkPaths.emplace(cmSystemTools::JoinPath(
            pathComponents.begin(), pathComponents.end() - 2));
        }
      }
      // Reserve options
      MocConst_.OptionsIncludes.reserve(MocConst().IncludePaths.size() +
                                        frameworkPaths.size() * 2);
      // Append includes
      for (std::string const& path : MocConst().IncludePaths) {
        MocConst_.OptionsIncludes.emplace_back("-I" + path);
      }
      // Append framework includes
      for (std::string const& path : frameworkPaths) {
        MocConst_.OptionsIncludes.emplace_back("-F");
        MocConst_.OptionsIncludes.push_back(path);
      }
    }

    // Compose moc definitions list
    {
      MocConst_.OptionsDefinitions.reserve(MocConst().Definitions.size());
      for (std::string const& def : MocConst().Definitions) {
        MocConst_.OptionsDefinitions.emplace_back("-D" + def);
      }
    }
  }

  return true;
}

template <class JOBTYPE>
void cmQtAutoMocUicT::CreateParseJobs(SourceFileMapT const& sourceMap)
{
  cmFileTime const parseCacheTime = BaseEval().ParseCacheTime;
  ParseCacheT& parseCache = BaseEval().ParseCache;
  for (auto& src : sourceMap) {
    // Get or create the file parse data reference
    ParseCacheT::GetOrInsertT cacheEntry = parseCache.GetOrInsert(src.first);
    src.second->ParseData = std::move(cacheEntry.first);
    // Create a parse job if the cache file was missing or is older
    if (cacheEntry.second || src.second->FileTime.Newer(parseCacheTime)) {
      BaseEval().ParseCacheChanged = true;
      WorkerPool().EmplaceJob<JOBTYPE>(src.second);
    }
  }
}

/** Concurrently callable implementation of cmSystemTools::CollapseFullPath */
std::string cmQtAutoMocUicT::CollapseFullPathTS(std::string const& path) const
{
  std::lock_guard<std::mutex> guard(CMakeLibMutex_);
  return cmSystemTools::CollapseFullPath(path, ProjectDirs().CurrentSource);
}

void cmQtAutoMocUicT::InitJobs()
{
  // Add moc_predefs.h job
  if (MocConst().Enabled && !MocConst().PredefsCmd.empty()) {
    WorkerPool().EmplaceJob<JobMocPredefsT>();
  }

  // Add header parse jobs
  CreateParseJobs<JobParseHeaderT>(BaseEval().Headers);
  // Add source parse jobs
  CreateParseJobs<JobParseSourceT>(BaseEval().Sources);

  // Add parse cache evaluations jobs
  {
    // Add a fence job to ensure all parsing has finished
    WorkerPool().EmplaceJob<JobFenceT>();
    if (MocConst().Enabled) {
      WorkerPool().EmplaceJob<JobEvalCacheMocT>();
    }
    if (UicConst().Enabled) {
      WorkerPool().EmplaceJob<JobEvalCacheUicT>();
    }
    // Add evaluate job
    WorkerPool().EmplaceJob<JobEvalCacheFinishT>();
  }
}

bool cmQtAutoMocUicT::Process()
{
  SettingsFileRead();
  ParseCacheRead();
  if (!CreateDirectories()) {
    return false;
  }
  InitJobs();
  if (!WorkerPool_.Process(this)) {
    return false;
  }
  if (JobError_) {
    return false;
  }
  if (!ParseCacheWrite()) {
    return false;
  }
  if (!SettingsFileWrite()) {
    return false;
  }
  return true;
}

void cmQtAutoMocUicT::SettingsFileRead()
{
  // Compose current settings strings
  {
    cmCryptoHash cryptoHash(cmCryptoHash::AlgoSHA256);
    auto cha = [&cryptoHash](cm::string_view value) {
      cryptoHash.Append(value);
      cryptoHash.Append(";");
    };

    if (MocConst_.Enabled) {
      cryptoHash.Initialize();
      cha(MocConst().Executable);
      for (auto const& item : MocConst().OptionsDefinitions) {
        cha(item);
      }
      for (auto const& item : MocConst().OptionsIncludes) {
        cha(item);
      }
      for (auto const& item : MocConst().OptionsExtra) {
        cha(item);
      }
      for (auto const& item : MocConst().PredefsCmd) {
        cha(item);
      }
      for (auto const& filter : MocConst().DependFilters) {
        cha(filter.Key);
      }
      for (auto const& filter : MocConst().MacroFilters) {
        cha(filter.Key);
      }
      SettingsStringMoc_ = cryptoHash.FinalizeHex();
    }

    if (UicConst().Enabled) {
      cryptoHash.Initialize();
      cha(UicConst().Executable);
      std::for_each(UicConst().Options.begin(), UicConst().Options.end(), cha);
      for (const auto& item : UicConst().UiFiles) {
        cha(item.first);
        auto const& opts = item.second.Options;
        std::for_each(opts.begin(), opts.end(), cha);
      }
      SettingsStringUic_ = cryptoHash.FinalizeHex();
    }
  }

  // Read old settings and compare
  {
    std::string content;
    if (cmQtAutoGenerator::FileRead(content, SettingsFile_)) {
      if (MocConst().Enabled) {
        if (SettingsStringMoc_ != SettingsFind(content, "moc")) {
          MocConst_.SettingsChanged = true;
        }
      }
      if (UicConst().Enabled) {
        if (SettingsStringUic_ != SettingsFind(content, "uic")) {
          UicConst_.SettingsChanged = true;
        }
      }
      // In case any setting changed remove the old settings file.
      // This triggers a full rebuild on the next run if the current
      // build is aborted before writing the current settings in the end.
      if (MocConst().SettingsChanged || UicConst().SettingsChanged) {
        cmSystemTools::RemoveFile(SettingsFile_);
      }
    } else {
      // Settings file read failed
      if (MocConst().Enabled) {
        MocConst_.SettingsChanged = true;
      }
      if (UicConst().Enabled) {
        UicConst_.SettingsChanged = true;
      }
    }
  }
}

bool cmQtAutoMocUicT::SettingsFileWrite()
{
  // Only write if any setting changed
  if (MocConst().SettingsChanged || UicConst().SettingsChanged) {
    if (Log().Verbose()) {
      Log().Info(
        GenT::GEN,
        cmStrCat("Writing the settings file ", MessagePath(SettingsFile_)));
    }
    // Compose settings file content
    std::string content;
    {
      auto SettingAppend = [&content](cm::string_view key,
                                      cm::string_view value) {
        if (!value.empty()) {
          content += cmStrCat(key, ':', value, '\n');
        }
      };
      SettingAppend("moc", SettingsStringMoc_);
      SettingAppend("uic", SettingsStringUic_);
    }
    // Write settings file
    std::string error;
    if (!cmQtAutoGenerator::FileWrite(SettingsFile_, content, &error)) {
      Log().Error(GenT::GEN,
                  cmStrCat("Writing the settings file ",
                           MessagePath(SettingsFile_), " failed.\n", error));
      // Remove old settings file to trigger a full rebuild on the next run
      cmSystemTools::RemoveFile(SettingsFile_);
      return false;
    }
  }
  return true;
}

void cmQtAutoMocUicT::ParseCacheRead()
{
  cm::string_view reason;
  // Don't read the cache if it is invalid
  if (!BaseEval().ParseCacheTime.Load(BaseConst().ParseCacheFile)) {
    reason = "Refreshing parse cache because it doesn't exist.";
  } else if (MocConst().SettingsChanged || UicConst().SettingsChanged) {
    reason = "Refreshing parse cache because the settings changed.";
  } else if (BaseEval().ParseCacheTime.Older(
               BaseConst().CMakeExecutableTime)) {
    reason =
      "Refreshing parse cache because it is older than the CMake executable.";
  }

  if (!reason.empty()) {
    // Don't read but refresh the complete parse cache
    if (Log().Verbose()) {
      Log().Info(GenT::GEN, reason);
    }
    BaseEval().ParseCacheChanged = true;
  } else {
    // Read parse cache
    BaseEval().ParseCache.ReadFromFile(BaseConst().ParseCacheFile);
  }
}

bool cmQtAutoMocUicT::ParseCacheWrite()
{
  if (BaseEval().ParseCacheChanged) {
    if (Log().Verbose()) {
      Log().Info(GenT::GEN,
                 cmStrCat("Writing the parse cache file ",
                          MessagePath(BaseConst().ParseCacheFile)));
    }
    if (!BaseEval().ParseCache.WriteToFile(BaseConst().ParseCacheFile)) {
      Log().Error(GenT::GEN,
                  cmStrCat("Writing the parse cache file ",
                           MessagePath(BaseConst().ParseCacheFile),
                           " failed."));
      return false;
    }
  }
  return true;
}

bool cmQtAutoMocUicT::CreateDirectories()
{
  // Create AUTOGEN include directory
  if (!cmSystemTools::MakeDirectory(BaseConst().AutogenIncludeDir)) {
    Log().Error(GenT::GEN,
                cmStrCat("Creating the AUTOGEN include directory ",
                         MessagePath(BaseConst().AutogenIncludeDir),
                         " failed."));
    return false;
  }
  return true;
}

std::vector<std::string> cmQtAutoMocUicT::dependenciesFromDepFile(
  const char* filePath)
{
  cmGccDepfileContent content = cmReadGccDepfile(filePath);
  if (content.empty()) {
    return {};
  }

  // Moc outputs a depfile with exactly one rule.
  // Discard the rule and return the dependencies.
  return content.front().paths;
}

void cmQtAutoMocUicT::Abort(bool error)
{
  if (error) {
    JobError_.store(true);
  }
  WorkerPool_.Abort();
}

std::string cmQtAutoMocUicT::AbsoluteBuildPath(
  cm::string_view relativePath) const
{
  return cmStrCat(BaseConst().AutogenBuildDir, '/', relativePath);
}

std::string cmQtAutoMocUicT::AbsoluteIncludePath(
  cm::string_view relativePath) const
{
  return cmStrCat(BaseConst().AutogenIncludeDir, '/', relativePath);
}

} // End of unnamed namespace

bool cmQtAutoMocUic(cm::string_view infoFile, cm::string_view config)
{
  return cmQtAutoMocUicT().Run(infoFile, config);
}
