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

#include "cmConfigure.h"
#include "cmsys/FStream.hxx"
#include "cmsys/Terminal.h"
#include <algorithm>
#include <assert.h>
#include <list>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <utility>

#include "cmAlgorithms.h"
#include "cmCryptoHash.h"
#include "cmFilePathChecksum.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmOutputConverter.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmSystemTools.h"
#include "cm_auto_ptr.hxx"
#include "cmake.h"

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

// -- Static variables

static const char* SettingsKeyMoc = "AM_MOC_SETTINGS_HASH";
static const char* SettingsKeyUic = "AM_UIC_SETTINGS_HASH";
static const char* SettingsKeyRcc = "AM_RCC_SETTINGS_HASH";

// -- Static functions

inline static std::string Quoted(const std::string& text)
{
  return cmQtAutoGeneratorCommon::Quoted(text);
}

static std::string QuotedCommand(const std::vector<std::string>& command)
{
  std::string res;
  for (std::vector<std::string>::const_iterator cit = command.begin();
       cit != command.end(); ++cit) {
    if (!res.empty()) {
      res.push_back(' ');
    }
    const std::string cesc = Quoted(*cit);
    if (cit->empty() || (cesc.size() > (cit->size() + 2)) ||
        (cesc.find(' ') != std::string::npos)) {
      res += cesc;
    } else {
      res += *cit;
    }
  }
  return res;
}

static void InfoGet(cmMakefile* makefile, const char* key, std::string& value)
{
  value = makefile->GetSafeDefinition(key);
}

static void InfoGet(cmMakefile* makefile, const char* key, bool& value)
{
  value = makefile->IsOn(key);
}

static void InfoGet(cmMakefile* makefile, const char* key,
                    std::vector<std::string>& list)
{
  cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list);
}

static void InfoGetConfig(cmMakefile* makefile, const char* key,
                          const std::string& config, std::string& value)
{
  const char* valueConf = CM_NULLPTR;
  {
    std::string keyConf = key;
    if (!config.empty()) {
      keyConf += "_";
      keyConf += config;
    }
    valueConf = makefile->GetDefinition(keyConf);
  }
  if (valueConf == CM_NULLPTR) {
    valueConf = makefile->GetSafeDefinition(key);
  }
  value = valueConf;
}

static void InfoGetConfig(cmMakefile* makefile, const char* key,
                          const std::string& config,
                          std::vector<std::string>& list)
{
  std::string value;
  InfoGetConfig(makefile, key, config, value);
  cmSystemTools::ExpandListArgument(value, list);
}

inline static bool SettingsMatch(cmMakefile* makefile, const char* key,
                                 const std::string& value)
{
  return (value == makefile->GetSafeDefinition(key));
}

static void SettingAppend(std::string& str, const char* key,
                          const std::string& value)
{
  if (!value.empty()) {
    str += "set(";
    str += key;
    str += " ";
    str += cmOutputConverter::EscapeForCMake(value);
    str += ")\n";
  }
}

static std::string SubDirPrefix(const std::string& fileName)
{
  std::string res(cmsys::SystemTools::GetFilenamePath(fileName));
  if (!res.empty()) {
    res += '/';
  }
  return res;
}

static bool FileNameIsUnique(const std::string& filePath,
                             const std::map<std::string, std::string>& fileMap)
{
  size_t count(0);
  const std::string fileName = cmsys::SystemTools::GetFilenameName(filePath);
  for (std::map<std::string, std::string>::const_iterator si = fileMap.begin();
       si != fileMap.end(); ++si) {
    if (cmsys::SystemTools::GetFilenameName(si->first) == fileName) {
      ++count;
      if (count > 1) {
        return false;
      }
    }
  }
  return true;
}

static bool ReadAll(std::string& content, const std::string& filename)
{
  bool success = false;
  {
    cmsys::ifstream ifs(filename.c_str());
    if (ifs) {
      std::ostringstream osst;
      osst << ifs.rdbuf();
      content = osst.str();
      success = true;
    }
  }
  return success;
}

/**
 * @brief Tests if buildFile doesn't exist or is older than sourceFile
 * @return True if buildFile doesn't exist or is older than sourceFile
 */
static bool FileAbsentOrOlder(const std::string& buildFile,
                              const std::string& sourceFile)
{
  int result = 0;
  bool success =
    cmsys::SystemTools::FileTimeCompare(buildFile, sourceFile, &result);
  return (!success || (result <= 0));
}

static bool ListContains(const std::vector<std::string>& list,
                         const std::string& entry)
{
  return (std::find(list.begin(), list.end(), entry) != list.end());
}

static std::string JoinOptionsList(const std::vector<std::string>& opts)
{
  return cmOutputConverter::EscapeForCMake(cmJoin(opts, ";"));
}

static std::string JoinOptionsMap(
  const std::map<std::string, std::string>& opts)
{
  std::string result;
  for (std::map<std::string, std::string>::const_iterator it = opts.begin();
       it != opts.end(); ++it) {
    if (it != opts.begin()) {
      result += cmQtAutoGeneratorCommon::listSep;
    }
    result += it->first;
    result += "===";
    result += it->second;
  }
  return result;
}

static std::string JoinExts(const std::vector<std::string>& lst)
{
  std::string result;
  if (!lst.empty()) {
    const std::string separator = ",";
    for (std::vector<std::string>::const_iterator it = lst.begin();
         it != lst.end(); ++it) {
      if (it != lst.begin()) {
        result += separator;
      }
      result += '.';
      result += *it;
    }
  }
  return result;
}

static void UicMergeOptions(std::vector<std::string>& opts,
                            const std::vector<std::string>& fileOpts,
                            bool isQt5)
{
  static const char* valueOptions[] = { "tr",      "translate",
                                        "postfix", "generator",
                                        "include", // Since Qt 5.3
                                        "g" };
  std::vector<std::string> extraOpts;
  for (std::vector<std::string>::const_iterator it = fileOpts.begin();
       it != fileOpts.end(); ++it) {
    std::vector<std::string>::iterator existingIt =
      std::find(opts.begin(), opts.end(), *it);
    if (existingIt != opts.end()) {
      const char* o = it->c_str();
      if (*o == '-') {
        ++o;
      }
      if (isQt5 && *o == '-') {
        ++o;
      }
      if (std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions),
                       cmStrCmp(*it)) != cmArrayEnd(valueOptions)) {
        assert(existingIt + 1 != opts.end());
        *(existingIt + 1) = *(it + 1);
        ++it;
      }
    } else {
      extraOpts.push_back(*it);
    }
  }
  opts.insert(opts.end(), extraOpts.begin(), extraOpts.end());
}

// -- Class methods

cmQtAutoGenerators::cmQtAutoGenerators()
  : Verbose(cmsys::SystemTools::HasEnv("VERBOSE"))
  , ColorOutput(true)
  , MocSettingsChanged(false)
  , MocPredefsChanged(false)
  , MocRunFailed(false)
  , UicSettingsChanged(false)
  , UicRunFailed(false)
  , RccSettingsChanged(false)
  , RccRunFailed(false)
{

  std::string colorEnv;
  cmsys::SystemTools::GetEnv("COLOR", colorEnv);
  if (!colorEnv.empty()) {
    if (cmSystemTools::IsOn(colorEnv.c_str())) {
      this->ColorOutput = true;
    } else {
      this->ColorOutput = false;
    }
  }

  // Moc macro filters
  this->MocMacroFilters[0].first = "Q_OBJECT";
  this->MocMacroFilters[0].second.compile("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]");
  this->MocMacroFilters[1].first = "Q_GADGET";
  this->MocMacroFilters[1].second.compile("[\n][ \t]*Q_GADGET[^a-zA-Z0-9_]");

  // Precompile regular expressions
  this->MocRegExpInclude.compile(
    "[\n][ \t]*#[ \t]*include[ \t]+"
    "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
  this->UicRegExpInclude.compile("[\n][ \t]*#[ \t]*include[ \t]+"
                                 "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
}

bool cmQtAutoGenerators::Run(const std::string& targetDirectory,
                             const std::string& config)
{
  cmake cm(cmake::RoleScript);
  cm.SetHomeOutputDirectory(targetDirectory);
  cm.SetHomeDirectory(targetDirectory);
  cm.GetCurrentSnapshot().SetDefaultDefinitions();
  cmGlobalGenerator gg(&cm);

  cmStateSnapshot snapshot = cm.GetCurrentSnapshot();
  snapshot.GetDirectory().SetCurrentBinary(targetDirectory);
  snapshot.GetDirectory().SetCurrentSource(targetDirectory);

  CM_AUTO_PTR<cmMakefile> mf(new cmMakefile(&gg, snapshot));
  gg.SetCurrentMakefile(mf.get());

  bool success = false;
  if (this->ReadAutogenInfoFile(mf.get(), targetDirectory, config)) {
    // Read old settings
    this->SettingsFileRead(mf.get());
    // Init and run
    this->Init(mf.get());
    if (this->RunAutogen()) {
      // Write current settings
      if (this->SettingsFileWrite()) {
        success = true;
      }
    }
  }
  return success;
}

bool cmQtAutoGenerators::MocDependFilterPush(const std::string& key,
                                             const std::string& regExp)
{
  bool success = false;
  if (!key.empty()) {
    if (!regExp.empty()) {
      MocDependFilter filter;
      filter.key = key;
      if (filter.regExp.compile(regExp)) {
        this->MocDependFilters.push_back(filter);
        success = true;
      } else {
        this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Compiling "
                       "regular expression failed.\nKey:  " +
                       Quoted(key) + "\nExp.: " + Quoted(regExp));
      }
    } else {
      this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Regular "
                     "expression is empty");
    }
  } else {
    this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Key is empty");
  }
  return success;
}

bool cmQtAutoGenerators::ReadAutogenInfoFile(
  cmMakefile* makefile, const std::string& targetDirectory,
  const std::string& config)
{
  std::string filename(cmSystemTools::CollapseFullPath(targetDirectory));
  cmSystemTools::ConvertToUnixSlashes(filename);
  filename += "/AutogenInfo.cmake";

  if (!makefile->ReadListFile(filename.c_str())) {
    this->LogError("AutoGen: Error processing file: " + filename);
    return false;
  }

  // - Old settings file
  {
    this->SettingsFile = cmSystemTools::CollapseFullPath(targetDirectory);
    cmSystemTools::ConvertToUnixSlashes(this->SettingsFile);
    this->SettingsFile += "/AutogenOldSettings";
    this->SettingsFile += this->ConfigSuffix;
    this->SettingsFile += ".cmake";
  }

  // -- Meta
  InfoGetConfig(makefile, "AM_CONFIG_SUFFIX", config, this->ConfigSuffix);

  // - Files and directories
  InfoGet(makefile, "AM_CMAKE_SOURCE_DIR", this->ProjectSourceDir);
  InfoGet(makefile, "AM_CMAKE_BINARY_DIR", this->ProjectBinaryDir);
  InfoGet(makefile, "AM_CMAKE_CURRENT_SOURCE_DIR", this->CurrentSourceDir);
  InfoGet(makefile, "AM_CMAKE_CURRENT_BINARY_DIR", this->CurrentBinaryDir);
  InfoGet(makefile, "AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE",
          this->IncludeProjectDirsBefore);
  InfoGet(makefile, "AM_BUILD_DIR", this->AutogenBuildDir);
  if (this->AutogenBuildDir.empty()) {
    this->LogError("AutoGen: Error: Missing autogen build directory ");
    return false;
  }
  InfoGet(makefile, "AM_SOURCES", this->Sources);
  InfoGet(makefile, "AM_HEADERS", this->Headers);

  // - Qt environment
  InfoGet(makefile, "AM_QT_VERSION_MAJOR", this->QtMajorVersion);
  if (this->QtMajorVersion.empty()) {
    InfoGet(makefile, "AM_Qt5Core_VERSION_MAJOR", this->QtMajorVersion);
  }
  InfoGet(makefile, "AM_QT_MOC_EXECUTABLE", this->MocExecutable);
  InfoGet(makefile, "AM_QT_UIC_EXECUTABLE", this->UicExecutable);
  InfoGet(makefile, "AM_QT_RCC_EXECUTABLE", this->RccExecutable);

  InfoGet(makefile, "AM_MOC_PREDEFS_CMD", this->MocPredefsCmd);
  // Check Qt version
  if ((this->QtMajorVersion != "4") && (this->QtMajorVersion != "5")) {
    this->LogError("AutoGen: Error: Unsupported Qt version: " +
                   Quoted(this->QtMajorVersion));
    return false;
  }

  // - Moc
  if (this->MocEnabled()) {
    InfoGet(makefile, "AM_MOC_SKIP", this->MocSkipList);
    InfoGetConfig(makefile, "AM_MOC_DEFINITIONS", config,
                  this->MocDefinitions);
#ifdef _WIN32
    {
      const std::string win32("WIN32");
      if (!ListContains(this->MocDefinitions, win32)) {
        this->MocDefinitions.push_back(win32);
      }
    }
#endif
    InfoGetConfig(makefile, "AM_MOC_INCLUDES", config, this->MocIncludePaths);
    InfoGet(makefile, "AM_MOC_OPTIONS", this->MocOptions);
    InfoGet(makefile, "AM_MOC_RELAXED_MODE", this->MocRelaxedMode);
    {
      std::vector<std::string> mocDependFilters;
      InfoGet(makefile, "AM_MOC_DEPEND_FILTERS", mocDependFilters);
      // Insert Q_PLUGIN_METADATA dependency filter
      if (this->QtMajorVersion != "4") {
        this->MocDependFilterPush("Q_PLUGIN_METADATA",
                                  "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\("
                                  "[^\\)]*FILE[ \t]*\"([^\"]+)\"");
      }
      // Insert user defined dependency filters
      if ((mocDependFilters.size() % 2) == 0) {
        for (std::vector<std::string>::const_iterator dit =
               mocDependFilters.begin();
             dit != mocDependFilters.end(); dit += 2) {
          if (!this->MocDependFilterPush(*dit, *(dit + 1))) {
            return false;
          }
        }
      } else {
        this->LogError(
          "AutoMoc: Error: AUTOMOC_DEPEND_FILTERS list size is not "
          "a multiple of 2 in:\n" +
          Quoted(filename));
        return false;
      }
    }
  }

  // - Uic
  if (this->UicEnabled()) {
    InfoGet(makefile, "AM_UIC_SKIP", this->UicSkipList);
    InfoGet(makefile, "AM_UIC_SEARCH_PATHS", this->UicSearchPaths);
    InfoGetConfig(makefile, "AM_UIC_TARGET_OPTIONS", config,
                  this->UicTargetOptions);
    {
      std::vector<std::string> uicFilesVec;
      std::vector<std::string> uicOptionsVec;
      InfoGet(makefile, "AM_UIC_OPTIONS_FILES", uicFilesVec);
      InfoGet(makefile, "AM_UIC_OPTIONS_OPTIONS", uicOptionsVec);
      // Compare list sizes
      if (uicFilesVec.size() == uicOptionsVec.size()) {
        for (std::vector<std::string>::iterator
               fileIt = uicFilesVec.begin(),
               optionIt = uicOptionsVec.begin();
             fileIt != uicFilesVec.end(); ++fileIt, ++optionIt) {
          cmSystemTools::ReplaceString(*optionIt,
                                       cmQtAutoGeneratorCommon::listSep, ";");
          this->UicOptions[*fileIt] = *optionIt;
        }
      } else {
        this->LogError(
          "AutoGen: Error: Uic files/options lists size missmatch in:\n" +
          Quoted(filename));
        return false;
      }
    }
  }

  // - Rcc
  if (this->RccEnabled()) {
    InfoGet(makefile, "AM_RCC_SOURCES", this->RccSources);
    // File options
    {
      std::vector<std::string> rccFilesVec;
      std::vector<std::string> rccOptionsVec;
      InfoGet(makefile, "AM_RCC_OPTIONS_FILES", rccFilesVec);
      InfoGet(makefile, "AM_RCC_OPTIONS_OPTIONS", rccOptionsVec);
      if (rccFilesVec.size() == rccOptionsVec.size()) {
        for (std::vector<std::string>::iterator
               fileIt = rccFilesVec.begin(),
               optionIt = rccOptionsVec.begin();
             fileIt != rccFilesVec.end(); ++fileIt, ++optionIt) {
          // Replace item separator
          cmSystemTools::ReplaceString(*optionIt,
                                       cmQtAutoGeneratorCommon::listSep, ";");
          this->RccOptions[*fileIt] = *optionIt;
        }
      } else {
        this->LogError(
          "AutoGen: Error: RCC files/options lists size missmatch in:\n" +
          Quoted(filename));
        return false;
      }
    }
    // File lists
    {
      std::vector<std::string> rccInputLists;
      InfoGet(makefile, "AM_RCC_INPUTS", rccInputLists);
      if (this->RccSources.size() == rccInputLists.size()) {
        for (std::vector<std::string>::iterator
               fileIt = this->RccSources.begin(),
               inputIt = rccInputLists.begin();
             fileIt != this->RccSources.end(); ++fileIt, ++inputIt) {
          // Remove braces
          *inputIt = inputIt->substr(1, inputIt->size() - 2);
          // Replace item separator
          cmSystemTools::ReplaceString(*inputIt,
                                       cmQtAutoGeneratorCommon::listSep, ";");
          std::vector<std::string> rccInputFiles;
          cmSystemTools::ExpandListArgument(*inputIt, rccInputFiles);
          this->RccInputs[*fileIt] = rccInputFiles;
        }
      } else {
        this->LogError(
          "AutoGen: Error: RCC sources/inputs lists size missmatch in:\n" +
          Quoted(filename));
        return false;
      }
    }
  }

  return true;
}

void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile)
{
  // Compose current settings strings
  {
    cmCryptoHash crypt(cmCryptoHash::AlgoSHA256);
    const std::string sep(" ~~~ ");
    if (this->MocEnabled()) {
      std::string str;
      str += this->MocExecutable;
      str += sep;
      str += JoinOptionsList(this->MocDefinitions);
      str += sep;
      str += JoinOptionsList(this->MocIncludePaths);
      str += sep;
      str += JoinOptionsList(this->MocOptions);
      str += sep;
      str += this->IncludeProjectDirsBefore ? "TRUE" : "FALSE";
      str += sep;
      str += JoinOptionsList(this->MocPredefsCmd);
      str += sep;
      this->SettingsStringMoc = crypt.HashString(str);
    }
    if (this->UicEnabled()) {
      std::string str;
      str += this->UicExecutable;
      str += sep;
      str += JoinOptionsList(this->UicTargetOptions);
      str += sep;
      str += JoinOptionsMap(this->UicOptions);
      str += sep;
      this->SettingsStringUic = crypt.HashString(str);
    }
    if (this->RccEnabled()) {
      std::string str;
      str += this->RccExecutable;
      str += sep;
      str += JoinOptionsMap(this->RccOptions);
      str += sep;
      this->SettingsStringRcc = crypt.HashString(str);
    }
  }

  // Read old settings
  if (makefile->ReadListFile(this->SettingsFile.c_str())) {
    if (!SettingsMatch(makefile, SettingsKeyMoc, this->SettingsStringMoc)) {
      this->MocSettingsChanged = true;
    }
    if (!SettingsMatch(makefile, SettingsKeyUic, this->SettingsStringUic)) {
      this->UicSettingsChanged = true;
    }
    if (!SettingsMatch(makefile, SettingsKeyRcc, this->SettingsStringRcc)) {
      this->RccSettingsChanged = 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 (this->AnySettingsChanged()) {
      cmSystemTools::RemoveFile(this->SettingsFile);
    }
  } else {
    // If the file could not be read re-generate everythiung.
    this->MocSettingsChanged = true;
    this->UicSettingsChanged = true;
    this->RccSettingsChanged = true;
  }
}

bool cmQtAutoGenerators::SettingsFileWrite()
{
  bool success = true;
  // Only write if any setting changed
  if (this->AnySettingsChanged()) {
    if (this->Verbose) {
      this->LogInfo("AutoGen: Writing settings file " +
                    Quoted(this->SettingsFile));
    }
    // Compose settings file content
    std::string settings;
    SettingAppend(settings, SettingsKeyMoc, this->SettingsStringMoc);
    SettingAppend(settings, SettingsKeyUic, this->SettingsStringUic);
    SettingAppend(settings, SettingsKeyRcc, this->SettingsStringRcc);
    // Write settings file
    if (!this->FileWrite("AutoGen", this->SettingsFile, settings)) {
      this->LogError("AutoGen: Error: Could not write old settings file " +
                     Quoted(this->SettingsFile));
      // Remove old settings file to trigger a full rebuild on the next run
      cmSystemTools::RemoveFile(this->SettingsFile);
      success = false;
    }
  }
  return success;
}

void cmQtAutoGenerators::Init(cmMakefile* makefile)
{
  // Mocs compilation file
  this->MocCompFileRel = "mocs_compilation";
  this->MocCompFileRel += this->ConfigSuffix;
  this->MocCompFileRel += ".cpp";
  this->MocCompFileAbs = cmSystemTools::CollapseCombinedPath(
    this->AutogenBuildDir, this->MocCompFileRel);

  // Mocs include directory
  this->AutogenIncludeDir = "include";
  this->AutogenIncludeDir += this->ConfigSuffix;
  this->AutogenIncludeDir += "/";

  // Moc predefs file
  if (!this->MocPredefsCmd.empty()) {
    this->MocPredefsFileRel = "moc_predefs.h";
    this->MocPredefsFileAbs = cmSystemTools::CollapseCombinedPath(
      this->AutogenBuildDir, this->MocPredefsFileRel);
  }

  // Init file path checksum generator
  FPathChecksum.setupParentDirs(this->CurrentSourceDir, this->CurrentBinaryDir,
                                this->ProjectSourceDir,
                                this->ProjectBinaryDir);

  // Acquire header extensions
  this->HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions();

  // Sort include directories on demand
  if (this->IncludeProjectDirsBefore) {
    // Move strings to temporary list
    std::list<std::string> includes;
    includes.insert(includes.end(), this->MocIncludePaths.begin(),
                    this->MocIncludePaths.end());
    this->MocIncludePaths.clear();
    this->MocIncludePaths.reserve(includes.size());
    // Append project directories only
    {
      const char* movePaths[2] = { this->ProjectBinaryDir.c_str(),
                                   this->ProjectSourceDir.c_str() };
      for (const char* const* mpit = cmArrayBegin(movePaths);
           mpit != cmArrayEnd(movePaths); ++mpit) {
        std::list<std::string>::iterator it = includes.begin();
        while (it != includes.end()) {
          const std::string& path = *it;
          if (cmsys::SystemTools::StringStartsWith(path, *mpit)) {
            this->MocIncludePaths.push_back(path);
            it = includes.erase(it);
          } else {
            ++it;
          }
        }
      }
    }
    // Append remaining directories
    this->MocIncludePaths.insert(this->MocIncludePaths.end(), includes.begin(),
                                 includes.end());
  }
  // Compose moc includes list
  {
    std::set<std::string> frameworkPaths;
    for (std::vector<std::string>::const_iterator it =
           this->MocIncludePaths.begin();
         it != this->MocIncludePaths.end(); ++it) {
      const std::string& path = *it;
      this->MocIncludes.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;
        cmsys::SystemTools::SplitPath(path, pathComponents);
        std::string frameworkPath = cmsys::SystemTools::JoinPath(
          pathComponents.begin(), pathComponents.end() - 2);
        frameworkPaths.insert(frameworkPath);
      }
    }
    // Append framework includes
    for (std::set<std::string>::const_iterator it = frameworkPaths.begin();
         it != frameworkPaths.end(); ++it) {
      this->MocIncludes.push_back("-F");
      this->MocIncludes.push_back(*it);
    }
  }
}

bool cmQtAutoGenerators::RunAutogen()
{
  // the program goes through all .cpp files to see which moc files are
  // included. It is not really interesting how the moc file is named, but
  // what file the moc is created from. Once a moc is included the same moc
  // may not be included in the mocs_compilation_$<CONFIG>.cpp file anymore.
  // OTOH if there's a header containing Q_OBJECT where no corresponding
  // moc file is included anywhere a moc_<filename>.cpp file is created and
  // included in the mocs_compilation_$<CONFIG>.cpp file.

  // key = moc source filepath, value = moc output filepath
  std::map<std::string, std::string> mocsIncluded;
  std::map<std::string, std::string> mocsNotIncluded;
  std::map<std::string, std::set<std::string> > mocDepends;
  std::map<std::string, std::vector<std::string> > uisIncluded;
  // collects all headers which may need to be mocced
  std::set<std::string> mocHeaderFiles;
  std::set<std::string> uicHeaderFiles;

  // Parse sources
  for (std::vector<std::string>::const_iterator it = this->Sources.begin();
       it != this->Sources.end(); ++it) {
    const std::string& absFilename = cmsys::SystemTools::GetRealPath(*it);
    // Parse source file for MOC/UIC
    if (!this->ParseSourceFile(absFilename, mocsIncluded, mocDepends,
                               uisIncluded, this->MocRelaxedMode)) {
      return false;
    }
    // Find additional headers
    this->SearchHeadersForSourceFile(absFilename, mocHeaderFiles,
                                     uicHeaderFiles);
  }

  // Parse headers
  for (std::vector<std::string>::const_iterator it = this->Headers.begin();
       it != this->Headers.end(); ++it) {
    const std::string& headerName = cmsys::SystemTools::GetRealPath(*it);
    if (!this->MocSkip(headerName)) {
      mocHeaderFiles.insert(headerName);
    }
    if (!this->UicSkip(headerName)) {
      uicHeaderFiles.insert(headerName);
    }
  }
  if (!this->ParseHeaders(mocHeaderFiles, uicHeaderFiles, mocsIncluded,
                          mocsNotIncluded, mocDepends, uisIncluded)) {
    return false;
  };

  // Generate files
  if (!this->MocGenerateAll(mocsIncluded, mocsNotIncluded, mocDepends)) {
    return false;
  }
  if (!this->UicGenerateAll(uisIncluded)) {
    return false;
  }
  if (!this->RccGenerateAll()) {
    return false;
  }

  return true;
}

/**
 * @brief Tests if the C++ content requires moc processing
 * @return True if moc is required
 */
bool cmQtAutoGenerators::MocRequired(const std::string& contentText,
                                     std::string* macroName)
{
  for (unsigned int ii = 0; ii != cmArraySize(this->MocMacroFilters); ++ii) {
    MocMacroFilter& filter = this->MocMacroFilters[ii];
    // Run a simple find string operation before the expensive
    // regular expression check
    if (contentText.find(filter.first) != std::string::npos) {
      if (filter.second.find(contentText)) {
        // Return macro name on demand
        if (macroName != CM_NULLPTR) {
          *macroName = filter.first;
        }
        return true;
      }
    }
  }
  return false;
}

void cmQtAutoGenerators::MocFindDepends(
  const std::string& absFilename, const std::string& contentText,
  std::map<std::string, std::set<std::string> >& mocDepends)
{
  for (std::vector<MocDependFilter>::iterator fit =
         this->MocDependFilters.begin();
       fit != this->MocDependFilters.end(); ++fit) {
    MocDependFilter& filter = *fit;
    // Run a simple find string operation before the expensive
    // regular expression check
    if (contentText.find(filter.key) != std::string::npos) {
      // Run regular expression check loop
      const std::string sourcePath = SubDirPrefix(absFilename);
      const char* contentChars = contentText.c_str();
      while (filter.regExp.find(contentChars)) {
        // Evaluate match
        const std::string match = filter.regExp.match(1);
        if (!match.empty()) {
          // Find the dependency file
          std::string incFile;
          if (this->MocFindIncludedFile(incFile, sourcePath, match)) {
            mocDepends[absFilename].insert(incFile);
            if (this->Verbose) {
              this->LogInfo("AutoMoc: Found dependency:\n  " +
                            Quoted(absFilename) + "\n  " + Quoted(incFile));
            }
          } else {
            this->LogWarning("AutoMoc: Warning: " + Quoted(absFilename) +
                             "\n" + "Could not find dependency file " +
                             Quoted(match));
          }
        }
        contentChars += filter.regExp.end();
      }
    }
  }
}

/**
 * @brief Tests if the file should be ignored for moc scanning
 * @return True if the file should be ignored
 */
bool cmQtAutoGenerators::MocSkip(const std::string& absFilename) const
{
  if (this->MocEnabled()) {
    // Test if the file name is on the skip list
    if (!ListContains(this->MocSkipList, absFilename)) {
      return false;
    }
  }
  return true;
}

/**
 * @brief Tests if the file name is in the skip list
 */
bool cmQtAutoGenerators::UicSkip(const std::string& absFilename) const
{
  if (this->UicEnabled()) {
    // Test if the file name is on the skip list
    if (!ListContains(this->UicSkipList, absFilename)) {
      return false;
    }
  }
  return true;
}

/**
 * @return True on success
 */
bool cmQtAutoGenerators::ParseSourceFile(
  const std::string& absFilename,
  std::map<std::string, std::string>& mocsIncluded,
  std::map<std::string, std::set<std::string> >& mocDepends,
  std::map<std::string, std::vector<std::string> >& uisIncluded, bool relaxed)
{
  std::string contentText;
  bool success = ReadAll(contentText, absFilename);
  if (success) {
    if (!contentText.empty()) {
      // Parse source contents for MOC
      if (success && !this->MocSkip(absFilename)) {
        success = this->MocParseSourceContent(
          absFilename, contentText, mocsIncluded, mocDepends, relaxed);
      }
      // Parse source contents for UIC
      if (success && !this->UicSkip(absFilename)) {
        this->UicParseContent(absFilename, contentText, uisIncluded);
      }
    } else {
      std::ostringstream ost;
      ost << "AutoGen: Warning: The file is empty:\n"
          << Quoted(absFilename) << "\n";
      this->LogWarning(ost.str());
    }
  } else {
    std::ostringstream ost;
    ost << "AutoGen: Error: Could not read file:\n" << Quoted(absFilename);
    this->LogError(ost.str());
  }
  return success;
}

void cmQtAutoGenerators::UicParseContent(
  const std::string& absFilename, const std::string& contentText,
  std::map<std::string, std::vector<std::string> >& uisIncluded)
{
  if (this->Verbose) {
    this->LogInfo("AutoUic: Checking " + absFilename);
  }

  const char* contentChars = contentText.c_str();
  if (strstr(contentChars, "ui_") != CM_NULLPTR) {
    while (this->UicRegExpInclude.find(contentChars)) {
      uisIncluded[absFilename].push_back(this->UicRegExpInclude.match(1));
      contentChars += this->UicRegExpInclude.end();
    }
  }
}

/**
 * @return True on success
 */
bool cmQtAutoGenerators::MocParseSourceContent(
  const std::string& absFilename, const std::string& contentText,
  std::map<std::string, std::string>& mocsIncluded,
  std::map<std::string, std::set<std::string> >& mocDepends, bool relaxed)
{
  if (this->Verbose) {
    this->LogInfo("AutoMoc: Checking " + absFilename);
  }

  const std::string scannedFileAbsPath = SubDirPrefix(absFilename);
  const std::string scannedFileBasename =
    cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);

  std::string macroName;
  const bool requiresMoc = this->MocRequired(contentText, &macroName);
  bool ownDotMocIncluded = false;
  std::string ownMocUnderscoreInclude;
  std::string ownMocUnderscoreHeader;

  // first a simple string check for "moc" is *much* faster than the regexp,
  // and if the string search already fails, we don't have to try the
  // expensive regexp
  const char* contentChars = contentText.c_str();
  if (strstr(contentChars, "moc") != CM_NULLPTR) {
    // Iterate over all included moc files
    while (this->MocRegExpInclude.find(contentChars)) {
      const std::string incString = this->MocRegExpInclude.match(1);
      // Basename of the moc include
      const std::string incSubDir(SubDirPrefix(incString));
      const std::string incBasename =
        cmsys::SystemTools::GetFilenameWithoutLastExtension(incString);

      // If the moc include is of the moc_foo.cpp style we expect
      // the Q_OBJECT class declaration in a header file.
      // If the moc include is of the foo.moc style we need to look for
      // a Q_OBJECT macro in the current source file, if it contains the
      // macro we generate the moc file from the source file.
      if (cmHasLiteralPrefix(incBasename, "moc_")) {
        // Include: moc_FOO.cxx
        // Remove the moc_ part
        const std::string incRealBasename = incBasename.substr(4);
        const std::string headerToMoc =
          this->MocFindHeader(scannedFileAbsPath, incSubDir + incRealBasename);
        if (!headerToMoc.empty()) {
          if (!this->MocSkip(headerToMoc)) {
            // Register moc job
            mocsIncluded[headerToMoc] = incString;
            this->MocFindDepends(headerToMoc, contentText, mocDepends);
            // Store meta information for relaxed mode
            if (relaxed && (incRealBasename == scannedFileBasename)) {
              ownMocUnderscoreInclude = incString;
              ownMocUnderscoreHeader = headerToMoc;
            }
          }
        } else {
          std::ostringstream ost;
          ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n"
              << "The file includes the moc file " << Quoted(incString)
              << ", but could not find header "
              << Quoted(incRealBasename + "{" +
                        JoinExts(this->HeaderExtensions) + "}");
          ;
          this->LogError(ost.str());
          return false;
        }
      } else {
        // Include: FOO.moc
        std::string fileToMoc;
        if (relaxed) {
          // Mode: Relaxed
          if (requiresMoc && (incBasename == scannedFileBasename)) {
            // Include self
            fileToMoc = absFilename;
            ownDotMocIncluded = true;
          } else {
            // In relaxed mode try to find a header instead but issue a warning
            const std::string headerToMoc =
              this->MocFindHeader(scannedFileAbsPath, incSubDir + incBasename);
            if (!headerToMoc.empty()) {
              if (!this->MocSkip(headerToMoc)) {
                // This is for KDE4 compatibility:
                fileToMoc = headerToMoc;
                if (!requiresMoc && (incBasename == scannedFileBasename)) {
                  std::ostringstream ost;
                  ost
                    << "AutoMoc: Warning: " << Quoted(absFilename) << "\n"
                    << "The file includes the moc file " << Quoted(incString)
                    << ", but does not contain a Q_OBJECT or Q_GADGET macro.\n"
                    << "Running moc on " << Quoted(headerToMoc) << "!\n"
                    << "Include " << Quoted("moc_" + incBasename + ".cpp")
                    << " for a compatibility with strict mode (see "
                       "CMAKE_AUTOMOC_RELAXED_MODE).\n";
                  this->LogWarning(ost.str());
                } else {
                  std::ostringstream ost;
                  ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n"
                      << "The file includes the moc file " << Quoted(incString)
                      << " instead of "
                      << Quoted("moc_" + incBasename + ".cpp") << ".\n"
                      << "Running moc on " << Quoted(headerToMoc) << "!\n"
                      << "Include " << Quoted("moc_" + incBasename + ".cpp")
                      << " for compatibility with strict mode (see "
                         "CMAKE_AUTOMOC_RELAXED_MODE).\n";
                  this->LogWarning(ost.str());
                }
              }
            } else {
              std::ostringstream ost;
              ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n"
                  << "The file includes the moc file " << Quoted(incString)
                  << ", which seems to be the moc file from a different "
                     "source file. CMake also could not find a matching "
                     "header.";
              this->LogError(ost.str());
              return false;
            }
          }
        } else {
          // Mode: Strict
          if (incBasename == scannedFileBasename) {
            // Include self
            fileToMoc = absFilename;
            ownDotMocIncluded = true;
            // Accept but issue a warning if moc isn't required
            if (!requiresMoc) {
              std::ostringstream ost;
              ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n"
                  << "The file includes the moc file " << Quoted(incString)
                  << ", but does not contain a Q_OBJECT or Q_GADGET "
                     "macro.";
              this->LogWarning(ost.str());
            }
          } else {
            // Don't allow FOO.moc include other than self in strict mode
            std::ostringstream ost;
            ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n"
                << "The file includes the moc file " << Quoted(incString)
                << ", which seems to be the moc file from a different "
                   "source file. This is not supported. Include "
                << Quoted(scannedFileBasename + ".moc")
                << " to run moc on this source file.";
            this->LogError(ost.str());
            return false;
          }
        }
        if (!fileToMoc.empty()) {
          mocsIncluded[fileToMoc] = incString;
          this->MocFindDepends(fileToMoc, contentText, mocDepends);
        }
      }
      // Forward content pointer
      contentChars += this->MocRegExpInclude.end();
    }
  }

  if (requiresMoc && !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.
    if (relaxed && !ownMocUnderscoreInclude.empty()) {
      // This is for KDE4 compatibility:
      std::ostringstream ost;
      ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n"
          << "The file contains a " << macroName
          << " macro, but does not include "
          << Quoted(scannedFileBasename + ".moc") << ", but instead includes "
          << Quoted(ownMocUnderscoreInclude) << ".\n"
          << "Running moc on " << Quoted(absFilename) << "!\n"
          << "Better include " << Quoted(scannedFileBasename + ".moc")
          << " for compatibility with strict mode (see "
             "CMAKE_AUTOMOC_RELAXED_MODE).";
      this->LogWarning(ost.str());

      // Use scanned source file instead of scanned header file as moc source
      mocsIncluded[absFilename] = ownMocUnderscoreInclude;
      this->MocFindDepends(absFilename, contentText, mocDepends);
      // Remove
      mocsIncluded.erase(ownMocUnderscoreHeader);
    } else {
      // Otherwise always error out since it will not compile:
      std::ostringstream ost;
      ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n"
          << "The file contains a " << macroName
          << " macro, but does not include "
          << Quoted(scannedFileBasename + ".moc") << "!\n"
          << "Consider adding the include or enabling SKIP_AUTOMOC for this "
             "file.";
      this->LogError(ost.str());
      return false;
    }
  }

  return true;
}

void cmQtAutoGenerators::MocParseHeaderContent(
  const std::string& absFilename, const std::string& contentText,
  std::map<std::string, std::string>& mocsNotIncluded,
  std::map<std::string, std::set<std::string> >& mocDepends)
{
  // Log
  if (this->Verbose) {
    this->LogInfo("AutoMoc: Checking " + absFilename);
  }
  if (this->MocRequired(contentText)) {
    // Register moc job
    mocsNotIncluded[absFilename] =
      this->ChecksumedPath(absFilename, "moc_", this->ConfigSuffix + ".cpp");
    this->MocFindDepends(absFilename, contentText, mocDepends);
  }
}

void cmQtAutoGenerators::SearchHeadersForSourceFile(
  const std::string& absFilename, std::set<std::string>& mocHeaderFiles,
  std::set<std::string>& uicHeaderFiles) const
{
  std::string basepaths[2];
  {
    std::string bpath = SubDirPrefix(absFilename);
    bpath += cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);
    // search for default header files and private header files
    basepaths[0] = bpath;
    basepaths[1] = bpath + "_p";
  }

  for (const std::string* bpit = cmArrayBegin(basepaths);
       bpit != cmArrayEnd(basepaths); ++bpit) {
    std::string headerName;
    if (this->FindHeader(headerName, *bpit)) {
      // Moc headers
      if (!this->MocSkip(absFilename) && !this->MocSkip(headerName)) {
        mocHeaderFiles.insert(headerName);
      }
      // Uic headers
      if (!this->UicSkip(absFilename) && !this->UicSkip(headerName)) {
        uicHeaderFiles.insert(headerName);
      }
    }
  }
}

bool cmQtAutoGenerators::ParseHeaders(
  const std::set<std::string>& mocHeaderFiles,
  const std::set<std::string>& uicHeaderFiles,
  const std::map<std::string, std::string>& mocsIncluded,
  std::map<std::string, std::string>& mocsNotIncluded,
  std::map<std::string, std::set<std::string> >& mocDepends,
  std::map<std::string, std::vector<std::string> >& uisIncluded)
{
  bool success = true;
  // Merged header files list to read files only once
  std::set<std::string> headerFiles;
  headerFiles.insert(mocHeaderFiles.begin(), mocHeaderFiles.end());
  headerFiles.insert(uicHeaderFiles.begin(), uicHeaderFiles.end());

  for (std::set<std::string>::const_iterator hIt = headerFiles.begin();
       hIt != headerFiles.end(); ++hIt) {
    const std::string& headerName = *hIt;
    std::string contentText;
    if (ReadAll(contentText, headerName)) {
      // Parse header content for MOC
      if ((mocHeaderFiles.find(headerName) != mocHeaderFiles.end()) &&
          (mocsIncluded.find(headerName) == mocsIncluded.end())) {
        this->MocParseHeaderContent(headerName, contentText, mocsNotIncluded,
                                    mocDepends);
      }
      // Parse header content for UIC
      if (uicHeaderFiles.find(headerName) != uicHeaderFiles.end()) {
        this->UicParseContent(headerName, contentText, uisIncluded);
      }
    } else {
      std::ostringstream ost;
      ost << "AutoGen: Error: Could not read header file:\n"
          << Quoted(headerName);
      this->LogError(ost.str());
      success = false;
      break;
    }
  }
  return success;
}

bool cmQtAutoGenerators::MocGenerateAll(
  const std::map<std::string, std::string>& mocsIncluded,
  const std::map<std::string, std::string>& mocsNotIncluded,
  const std::map<std::string, std::set<std::string> >& mocDepends)
{
  if (!this->MocEnabled()) {
    return true;
  }

  // Look for name collisions
  {
    std::multimap<std::string, std::string> collisions;
    // Test merged map of included and notIncluded
    std::map<std::string, std::string> mergedMocs(mocsIncluded);
    mergedMocs.insert(mocsNotIncluded.begin(), mocsNotIncluded.end());
    if (this->NameCollisionTest(mergedMocs, collisions)) {
      std::ostringstream ost;
      ost << "AutoMoc: Error: "
             "The same moc file will be generated "
             "from different sources.\n"
             "To avoid this error either\n"
             "- rename the source files or\n"
             "- do not include the (moc_NAME.cpp|NAME.moc) file";
      this->LogErrorNameCollision(ost.str(), collisions);
      return false;
    }
  }

  // Generate moc_predefs
  if (!this->MocPredefsCmd.empty()) {
    if (this->MocSettingsChanged ||
        FileAbsentOrOlder(this->MocPredefsFileAbs, this->SettingsFile)) {
      this->LogBold("Generating MOC predefs " + this->MocPredefsFileRel);

      std::string output;
      {
        // Compose command
        std::vector<std::string> cmd = this->MocPredefsCmd;
        // Add includes
        cmd.insert(cmd.end(), this->MocIncludes.begin(),
                   this->MocIncludes.end());
        // Add definitions
        for (std::vector<std::string>::const_iterator it =
               this->MocDefinitions.begin();
             it != this->MocDefinitions.end(); ++it) {
          cmd.push_back("-D" + (*it));
        }
        // Add options
        cmd.insert(cmd.end(), this->MocOptions.begin(),
                   this->MocOptions.end());
        // Execute command
        if (!this->RunCommand(cmd, output, false)) {
          {
            std::ostringstream ost;
            ost << "AutoMoc: Error: moc predefs generation command failed\n";
            ost << "AutoMoc: Command:\n" << QuotedCommand(cmd) << "\n";
            ost << "AutoMoc: Command output:\n" << output << "\n";
            this->LogError(ost.str());
          }
          return false;
        }
      }
      // (Re)write predefs file only on demand
      if (this->FileDiffers(this->MocPredefsFileAbs, output)) {
        if (this->FileWrite("AutoMoc", this->MocPredefsFileAbs, output)) {
          this->MocPredefsChanged = true;
        } else {
          return false;
        }
      }
    }
  }

  // Generate moc files that are included by source files.
  for (std::map<std::string, std::string>::const_iterator it =
         mocsIncluded.begin();
       it != mocsIncluded.end(); ++it) {
    if (!this->MocGenerateFile(it->first, it->second, mocDepends, true)) {
      if (this->MocRunFailed) {
        return false;
      }
    }
  }

  // Generate moc files that are _not_ included by source files.
  bool mocCompFileGenerated = false;
  for (std::map<std::string, std::string>::const_iterator it =
         mocsNotIncluded.begin();
       it != mocsNotIncluded.end(); ++it) {
    if (this->MocGenerateFile(it->first, it->second, mocDepends, false)) {
      mocCompFileGenerated = true;
    } else {
      if (this->MocRunFailed) {
        return false;
      }
    }
  }

  // Compose mocs compilation file content
  std::string automocSource;
  {
    std::ostringstream ost;
    ost << "/* This file is autogenerated, do not edit*/\n";
    if (mocsNotIncluded.empty()) {
      // Dummy content
      ost << "enum some_compilers { need_more_than_nothing };\n";
    } else {
      // Valid content
      for (std::map<std::string, std::string>::const_iterator it =
             mocsNotIncluded.begin();
           it != mocsNotIncluded.end(); ++it) {
        ost << "#include \"" << it->second << "\"\n";
      }
    }
    automocSource = ost.str();
  }

  if (this->FileDiffers(this->MocCompFileAbs, automocSource)) {
    // Actually write mocs compilation file
    this->LogBold("Generating MOC compilation " + this->MocCompFileRel);
    if (!this->FileWrite("AutoMoc", this->MocCompFileAbs, automocSource)) {
      return false;
    }
  } else if (mocCompFileGenerated) {
    // Only touch mocs compilation file
    if (this->Verbose) {
      this->LogInfo("Touching MOC compilation " + this->MocCompFileRel);
    }
    cmSystemTools::Touch(this->MocCompFileAbs, false);
  }

  return true;
}

/**
 * @return True if a moc file was created. False may indicate an error.
 */
bool cmQtAutoGenerators::MocGenerateFile(
  const std::string& sourceFile, const std::string& mocFileName,
  const std::map<std::string, std::set<std::string> >& mocDepends,
  bool included)
{
  bool mocGenerated = false;
  bool generateMoc = this->MocSettingsChanged || this->MocPredefsChanged;

  const std::string mocFileRel =
    included ? (this->AutogenIncludeDir + mocFileName) : mocFileName;
  const std::string mocFileAbs =
    cmSystemTools::CollapseCombinedPath(this->AutogenBuildDir, mocFileRel);

  if (!generateMoc) {
    // Test if the source file is newer that the build file
    generateMoc = FileAbsentOrOlder(mocFileAbs, sourceFile);
    if (!generateMoc) {
      // Test if a dependency file changed
      std::map<std::string, std::set<std::string> >::const_iterator dit =
        mocDepends.find(sourceFile);
      if (dit != mocDepends.end()) {
        for (std::set<std::string>::const_iterator fit = dit->second.begin();
             fit != dit->second.end(); ++fit) {
          if (FileAbsentOrOlder(mocFileAbs, *fit)) {
            generateMoc = true;
            break;
          }
        }
      }
    }
  }
  if (generateMoc) {
    // Log
    this->LogBold("Generating MOC source " + mocFileRel);

    // Make sure the parent directory exists
    if (this->MakeParentDirectory("AutoMoc", mocFileAbs)) {
      // Compose moc command
      std::vector<std::string> cmd;
      cmd.push_back(this->MocExecutable);
      // Add includes
      cmd.insert(cmd.end(), this->MocIncludes.begin(),
                 this->MocIncludes.end());
      // Add definitions
      for (std::vector<std::string>::const_iterator it =
             this->MocDefinitions.begin();
           it != this->MocDefinitions.end(); ++it) {
        cmd.push_back("-D" + (*it));
      }
      // Add options
      cmd.insert(cmd.end(), this->MocOptions.begin(), this->MocOptions.end());
      // Add predefs include
      if (!this->MocPredefsFileAbs.empty()) {
        cmd.push_back("--include");
        cmd.push_back(this->MocPredefsFileAbs);
      }
      cmd.push_back("-o");
      cmd.push_back(mocFileAbs);
      cmd.push_back(sourceFile);

      // Execute moc command
      std::string output;
      if (this->RunCommand(cmd, output)) {
        // Success
        mocGenerated = true;
      } else {
        // Command failed
        {
          std::ostringstream ost;
          ost << "AutoMoc: Error: moc process failed for\n";
          ost << Quoted(mocFileRel) << "\n";
          ost << "AutoMoc: Command:\n" << QuotedCommand(cmd) << "\n";
          ost << "AutoMoc: Command output:\n" << output << "\n";
          this->LogError(ost.str());
        }
        cmSystemTools::RemoveFile(mocFileAbs);
        this->MocRunFailed = true;
      }
    } else {
      // Parent directory creation failed
      this->MocRunFailed = true;
    }
  }
  return mocGenerated;
}

bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile,
                                             const std::string& sourceFile,
                                             const std::string& includeString)
{
  bool success = false;
  // Search in vicinity of the source
  {
    std::string testPath = SubDirPrefix(sourceFile);
    testPath += includeString;
    if (cmsys::SystemTools::FileExists(testPath.c_str())) {
      absFile = cmsys::SystemTools::GetRealPath(testPath);
      success = true;
    }
  }
  // Search in include directories
  if (!success) {
    for (std::vector<std::string>::const_iterator iit =
           this->UicSearchPaths.begin();
         iit != this->UicSearchPaths.end(); ++iit) {
      const std::string fullPath = ((*iit) + '/' + includeString);
      if (cmsys::SystemTools::FileExists(fullPath.c_str())) {
        absFile = cmsys::SystemTools::GetRealPath(fullPath);
        success = true;
        break;
      }
    }
  }
  return success;
}

bool cmQtAutoGenerators::UicGenerateAll(
  const std::map<std::string, std::vector<std::string> >& uisIncluded)
{
  if (!this->UicEnabled()) {
    return true;
  }

  // single map with input / output names
  std::map<std::string, std::map<std::string, std::string> > sourceGenMap;
  {
    // Collision lookup map
    std::map<std::string, std::string> testMap;
    // Compile maps
    for (std::map<std::string, std::vector<std::string> >::const_iterator sit =
           uisIncluded.begin();
         sit != uisIncluded.end(); ++sit) {
      const std::string& source(sit->first);
      const std::vector<std::string>& sourceIncs(sit->second);
      // insert new source/destination map
      std::map<std::string, std::string>& uiGenMap = sourceGenMap[source];
      for (std::vector<std::string>::const_iterator uit = sourceIncs.begin();
           uit != sourceIncs.end(); ++uit) {
        // Remove ui_ from the begin filename by substr()
        const std::string uiBasePath = SubDirPrefix(*uit);
        const std::string uiBaseName =
          cmsys::SystemTools::GetFilenameWithoutLastExtension(*uit).substr(3);
        const std::string searchFileName = uiBasePath + uiBaseName + ".ui";
        std::string uiInputFile;
        if (UicFindIncludedFile(uiInputFile, source, searchFileName)) {
          std::string uiOutputFile = uiBasePath + "ui_" + uiBaseName + ".h";
          cmSystemTools::ReplaceString(uiOutputFile, "..", "__");
          uiGenMap[uiInputFile] = uiOutputFile;
          testMap[uiInputFile] = uiOutputFile;
        } else {
          this->LogError("AutoUic: Error: " + Quoted(sit->first) +
                         "\nCould not find " + Quoted(searchFileName));
          return false;
        }
      }
    }
    // look for name collisions
    {
      std::multimap<std::string, std::string> collisions;
      if (this->NameCollisionTest(testMap, collisions)) {
        std::ostringstream ost;
        ost << "AutoUic: Error: The same ui_NAME.h file will be generated "
               "from different sources.\n"
               "To avoid this error rename the source files.\n";
        this->LogErrorNameCollision(ost.str(), collisions);
        return false;
      }
    }
  }

  // generate ui files
  for (std::map<std::string,
                std::map<std::string, std::string> >::const_iterator it =
         sourceGenMap.begin();
       it != sourceGenMap.end(); ++it) {
    for (std::map<std::string, std::string>::const_iterator sit =
           it->second.begin();
         sit != it->second.end(); ++sit) {
      if (!this->UicGenerateFile(it->first, sit->first, sit->second)) {
        if (this->UicRunFailed) {
          return false;
        }
      }
    }
  }

  return true;
}

/**
 * @return True if a uic file was created. False may indicate an error.
 */
bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName,
                                         const std::string& uiInputFile,
                                         const std::string& uiOutputFile)
{
  bool uicGenerated = false;
  bool generateUic = this->UicSettingsChanged;

  const std::string uicFileRel = this->AutogenIncludeDir + uiOutputFile;
  const std::string uicFileAbs =
    cmSystemTools::CollapseCombinedPath(this->AutogenBuildDir, uicFileRel);

  if (!generateUic) {
    // Test if the source file is newer that the build file
    generateUic = FileAbsentOrOlder(uicFileAbs, uiInputFile);
  }
  if (generateUic) {
    // Log
    this->LogBold("Generating UIC header " + uicFileRel);

    // Make sure the parent directory exists
    if (this->MakeParentDirectory("AutoUic", uicFileAbs)) {
      // Compose uic command
      std::vector<std::string> cmd;
      cmd.push_back(this->UicExecutable);
      {
        std::vector<std::string> allOpts = this->UicTargetOptions;
        std::map<std::string, std::string>::const_iterator optionIt =
          this->UicOptions.find(uiInputFile);
        if (optionIt != this->UicOptions.end()) {
          std::vector<std::string> fileOpts;
          cmSystemTools::ExpandListArgument(optionIt->second, fileOpts);
          UicMergeOptions(allOpts, fileOpts, (this->QtMajorVersion == "5"));
        }
        cmd.insert(cmd.end(), allOpts.begin(), allOpts.end());
      }
      cmd.push_back("-o");
      cmd.push_back(uicFileAbs);
      cmd.push_back(uiInputFile);

      std::string output;
      if (this->RunCommand(cmd, output)) {
        // Success
        uicGenerated = true;
      } else {
        // Command failed
        {
          std::ostringstream ost;
          ost << "AutoUic: Error: uic process failed for\n";
          ost << Quoted(uicFileRel) << " needed by\n";
          ost << Quoted(realName) << "\n";
          ost << "AutoUic: Command:\n" << QuotedCommand(cmd) << "\n";
          ost << "AutoUic: Command output:\n" << output << "\n";
          this->LogError(ost.str());
        }
        cmSystemTools::RemoveFile(uicFileAbs);
        this->UicRunFailed = true;
      }
    } else {
      // Parent directory creation failed
      this->UicRunFailed = true;
    }
  }
  return uicGenerated;
}

bool cmQtAutoGenerators::RccGenerateAll()
{
  if (!this->RccEnabled()) {
    return true;
  }

  // generate single map with input / output names
  std::map<std::string, std::string> qrcGenMap;
  {
    const std::string qrcPrefix = "qrc_";
    const std::string qrcSuffix = this->ConfigSuffix + ".cpp";
    for (std::vector<std::string>::const_iterator si =
           this->RccSources.begin();
         si != this->RccSources.end(); ++si) {
      const std::string ext =
        cmsys::SystemTools::GetFilenameLastExtension(*si);
      if (ext == ".qrc") {
        qrcGenMap[*si] = this->ChecksumedPath(*si, qrcPrefix, qrcSuffix);
      }
    }
  }

  // look for name collisions
  {
    std::multimap<std::string, std::string> collisions;
    if (this->NameCollisionTest(qrcGenMap, collisions)) {
      std::ostringstream ost;
      ost << "AutoRcc: Error: The same qrc_NAME.cpp file"
             " will be generated from different sources.\n"
             "To avoid this error rename the source .qrc files.\n";
      this->LogErrorNameCollision(ost.str(), collisions);
      return false;
    }
  }

  // generate qrc files
  for (std::map<std::string, std::string>::const_iterator si =
         qrcGenMap.begin();
       si != qrcGenMap.end(); ++si) {
    bool unique = FileNameIsUnique(si->first, qrcGenMap);
    if (!this->RccGenerateFile(si->first, si->second, unique)) {
      if (this->RccRunFailed) {
        return false;
      }
    }
  }
  return true;
}

/**
 * @return True if a rcc file was created. False may indicate an error.
 */
bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile,
                                         const std::string& rccOutputFile,
                                         bool unique_n)
{
  bool rccGenerated = false;
  bool generateRcc = this->RccSettingsChanged;

  const std::string rccBuildFile =
    cmSystemTools::CollapseCombinedPath(this->AutogenBuildDir, rccOutputFile);

  if (!generateRcc) {
    // Test if the resources list file is newer than build file
    generateRcc = FileAbsentOrOlder(rccBuildFile, rccInputFile);
    if (!generateRcc) {
      // Acquire input file list
      std::vector<std::string> readFiles;
      const std::vector<std::string>* files = &this->RccInputs[rccInputFile];
      if (files->empty()) {
        // Read input file list from qrc file
        std::string error;
        if (cmQtAutoGeneratorCommon::RccListInputs(
              this->QtMajorVersion, this->RccExecutable, rccInputFile,
              readFiles, &error)) {
          files = &readFiles;
        } else {
          files = CM_NULLPTR;
          this->LogError(error);
          this->RccRunFailed = true;
        }
      }
      // Test if any input file is newer than the build file
      if (files != CM_NULLPTR) {
        for (std::vector<std::string>::const_iterator it = files->begin();
             it != files->end(); ++it) {
          if (FileAbsentOrOlder(rccBuildFile, *it)) {
            generateRcc = true;
            break;
          }
        }
      }
    }
  }
  if (generateRcc) {
    // Log
    this->LogBold("Generating RCC source " + rccOutputFile);

    // Make sure the parent directory exists
    if (this->MakeParentDirectory("AutoRcc", rccBuildFile)) {
      // Compose symbol name
      std::string symbolName =
        cmsys::SystemTools::GetFilenameWithoutLastExtension(rccInputFile);
      if (!unique_n) {
        symbolName += "_";
        symbolName += FPathChecksum.getPart(rccInputFile);
      }
      // Replace '-' with '_'. The former is valid for
      // file names but not for symbol names.
      std::replace(symbolName.begin(), symbolName.end(), '-', '_');

      // Compose rcc command
      std::vector<std::string> cmd;
      cmd.push_back(this->RccExecutable);
      {
        std::map<std::string, std::string>::const_iterator optionIt =
          this->RccOptions.find(rccInputFile);
        if (optionIt != this->RccOptions.end()) {
          cmSystemTools::ExpandListArgument(optionIt->second, cmd);
        }
      }
      cmd.push_back("-name");
      cmd.push_back(symbolName);
      cmd.push_back("-o");
      cmd.push_back(rccBuildFile);
      cmd.push_back(rccInputFile);

      std::string output;
      if (this->RunCommand(cmd, output)) {
        // Success
        rccGenerated = true;
      } else {
        // Command failed
        {
          std::ostringstream ost;
          ost << "AutoRcc: Error: rcc process failed for\n";
          ost << Quoted(rccOutputFile) << "\n";
          ost << "AutoRcc: Command:\n" << QuotedCommand(cmd) << "\n";
          ost << "AutoRcc: Command output:\n" << output << "\n";
          this->LogError(ost.str());
        }
        cmSystemTools::RemoveFile(rccBuildFile);
        this->RccRunFailed = true;
      }
    } else {
      // Parent directory creation failed
      this->RccRunFailed = true;
    }
  }
  return rccGenerated;
}

void cmQtAutoGenerators::LogErrorNameCollision(
  const std::string& message,
  const std::multimap<std::string, std::string>& collisions) const
{
  typedef std::multimap<std::string, std::string>::const_iterator Iter;

  std::ostringstream ost;
  // Add message
  if (!message.empty()) {
    ost << message;
    if (message[message.size() - 1] != '\n') {
      ost << '\n';
    }
  }
  // Append collision list
  for (Iter it = collisions.begin(); it != collisions.end(); ++it) {
    ost << it->first << " : " << it->second << '\n';
  }
  this->LogError(ost.str());
}

void cmQtAutoGenerators::LogBold(const std::string& message) const
{
  cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue |
                                     cmsysTerminal_Color_ForegroundBold,
                                   message.c_str(), true, this->ColorOutput);
}

void cmQtAutoGenerators::LogInfo(const std::string& message) const
{
  std::string msg(message);
  if (!msg.empty()) {
    if (msg[msg.size() - 1] != '\n') {
      msg.push_back('\n');
    }
    cmSystemTools::Stdout(msg.c_str(), msg.size());
  }
}

void cmQtAutoGenerators::LogWarning(const std::string& message) const
{
  std::string msg(message);
  if (!msg.empty()) {
    if (msg[msg.size() - 1] != '\n') {
      msg.push_back('\n');
    }
    // Append empty line
    msg.push_back('\n');
    cmSystemTools::Stdout(msg.c_str(), msg.size());
  }
}

void cmQtAutoGenerators::LogError(const std::string& message) const
{
  std::string msg(message);
  if (!msg.empty()) {
    if (msg[msg.size() - 1] != '\n') {
      msg.push_back('\n');
    }
    // Append empty line
    msg.push_back('\n');
    cmSystemTools::Stderr(msg.c_str(), msg.size());
  }
}

/**
 * @brief Collects name collisions as output/input pairs
 * @return True if there were collisions
 */
bool cmQtAutoGenerators::NameCollisionTest(
  const std::map<std::string, std::string>& genFiles,
  std::multimap<std::string, std::string>& collisions) const
{
  typedef std::map<std::string, std::string>::const_iterator Iter;
  typedef std::map<std::string, std::string>::value_type VType;
  for (Iter ait = genFiles.begin(); ait != genFiles.end(); ++ait) {
    bool first_match(true);
    for (Iter bit = (++Iter(ait)); bit != genFiles.end(); ++bit) {
      if (ait->second == bit->second) {
        if (first_match) {
          if (collisions.find(ait->second) != collisions.end()) {
            // We already know of this collision from before
            break;
          }
          collisions.insert(VType(ait->second, ait->first));
          first_match = false;
        }
        collisions.insert(VType(bit->second, bit->first));
      }
    }
  }

  return !collisions.empty();
}

/**
 * @brief Generates a file path based on the checksum of the source file path
 * @return The path
 */
std::string cmQtAutoGenerators::ChecksumedPath(
  const std::string& sourceFile, const std::string& basePrefix,
  const std::string& baseSuffix) const
{
  std::string res = FPathChecksum.getPart(sourceFile);
  res += "/";
  res += basePrefix;
  res += cmsys::SystemTools::GetFilenameWithoutLastExtension(sourceFile);
  res += baseSuffix;
  return res;
}

/**
 * @brief Generates the parent directory of the given file on demand
 * @return True on success
 */
bool cmQtAutoGenerators::MakeParentDirectory(const char* logPrefix,
                                             const std::string& filename) const
{
  bool success = true;
  const std::string dirName = cmSystemTools::GetFilenamePath(filename);
  if (!dirName.empty()) {
    success = cmsys::SystemTools::MakeDirectory(dirName);
    if (!success) {
      std::string error = logPrefix;
      error += ": Error: Parent directory creation failed for ";
      error += Quoted(filename);
      this->LogError(error);
    }
  }
  return success;
}

bool cmQtAutoGenerators::FileDiffers(const std::string& filename,
                                     const std::string& content)
{
  bool differs = true;
  {
    std::string oldContents;
    if (ReadAll(oldContents, filename)) {
      differs = (oldContents != content);
    }
  }
  return differs;
}

bool cmQtAutoGenerators::FileWrite(const char* logPrefix,
                                   const std::string& filename,
                                   const std::string& content)
{
  std::string error;
  // Make sure the parent directory exists
  if (this->MakeParentDirectory(logPrefix, filename)) {
    cmsys::ofstream outfile;
    outfile.open(filename.c_str(), std::ios::trunc);
    if (outfile) {
      outfile << content;
      // Check for write errors
      if (!outfile.good()) {
        error = logPrefix;
        error += ": Error writing ";
        error += Quoted(filename);
      }
    } else {
      error = logPrefix;
      error = ": Error opening ";
      error += Quoted(filename);
    }
  }
  if (!error.empty()) {
    this->LogError(error);
    return false;
  }
  return true;
}

/**
 * @brief Runs a command and returns true on success
 * @return True on success
 */
bool cmQtAutoGenerators::RunCommand(const std::vector<std::string>& command,
                                    std::string& output, bool verbose) const
{
  // Log command
  if (this->Verbose) {
    this->LogInfo(QuotedCommand(command));
  }
  // Execute command
  int retVal = 0;
  bool res = cmSystemTools::RunSingleCommand(
    command, &output, &output, &retVal, CM_NULLPTR,
    verbose ? cmSystemTools::OUTPUT_MERGE : cmSystemTools::OUTPUT_NONE);
  return (res && (retVal == 0));
}

/**
 * @brief Tries to find the header file to the given file base path by
 * appending different header extensions
 * @return True on success
 */
bool cmQtAutoGenerators::FindHeader(std::string& header,
                                    const std::string& testBasePath) const
{
  for (std::vector<std::string>::const_iterator ext =
         this->HeaderExtensions.begin();
       ext != this->HeaderExtensions.end(); ++ext) {
    std::string testFilePath(testBasePath);
    testFilePath += '.';
    testFilePath += (*ext);
    if (cmsys::SystemTools::FileExists(testFilePath.c_str())) {
      header = testFilePath;
      return true;
    }
  }
  return false;
}

std::string cmQtAutoGenerators::MocFindHeader(
  const std::string& sourcePath, const std::string& includeBase) const
{
  std::string header;
  // Search in vicinity of the source
  if (!this->FindHeader(header, sourcePath + includeBase)) {
    // Search in include directories
    for (std::vector<std::string>::const_iterator iit =
           this->MocIncludePaths.begin();
         iit != this->MocIncludePaths.end(); ++iit) {
      const std::string fullPath = ((*iit) + '/' + includeBase);
      if (FindHeader(header, fullPath)) {
        break;
      }
    }
  }
  // Sanitize
  if (!header.empty()) {
    header = cmsys::SystemTools::GetRealPath(header);
  }
  return header;
}

bool cmQtAutoGenerators::MocFindIncludedFile(
  std::string& absFile, const std::string& sourcePath,
  const std::string& includeString) const
{
  bool success = false;
  // Search in vicinity of the source
  {
    std::string testPath = sourcePath;
    testPath += includeString;
    if (cmsys::SystemTools::FileExists(testPath.c_str())) {
      absFile = cmsys::SystemTools::GetRealPath(testPath);
      success = true;
    }
  }
  // Search in include directories
  if (!success) {
    for (std::vector<std::string>::const_iterator iit =
           this->MocIncludePaths.begin();
         iit != this->MocIncludePaths.end(); ++iit) {
      const std::string fullPath = ((*iit) + '/' + includeString);
      if (cmsys::SystemTools::FileExists(fullPath.c_str())) {
        absFile = cmsys::SystemTools::GetRealPath(fullPath);
        success = true;
        break;
      }
    }
  }
  return success;
}
