[Cmake-commits] CMake branch, master, updated. v3.15.3-1211-g28a2613

Kitware Robot kwrobot at kitware.com
Thu Sep 26 10:00:22 EDT 2019


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, master has been updated
       via  28a2613dd291c641f17940e3f996bd4cc9b9888d (commit)
       via  d867e058924d348ee5ec5bba867965e8f1f276e2 (commit)
       via  881e3cfbf96c7b4f48304d3dfc07899c2e6703de (commit)
       via  fc36f4410bcdb76ef23a07e5172cb57b41ff5ce3 (commit)
       via  1f0d23546d5721fdd92883da4c4368dad3931393 (commit)
       via  6a05bd3fa6a3f4ecf45c4cc32abc616883998ff9 (commit)
      from  3cb12895f3d99614ac30bd2f7703f721154b7068 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=28a2613dd291c641f17940e3f996bd4cc9b9888d
commit 28a2613dd291c641f17940e3f996bd4cc9b9888d
Merge: 3cb1289 d867e05
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Sep 26 13:56:57 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Thu Sep 26 09:57:15 2019 -0400

    Merge topic 'autogen_json'
    
    d867e05892 Autogen: Use JSON instead of CMake script for info files
    881e3cfbf9 Autogen: Variable renames and cleanups
    fc36f4410b Autogen: Inline GetKnownQtVersions function
    1f0d23546d Autogen: Return unsigned int from GetParallelCPUCount()
    6a05bd3fa6 cm/algorithm: Provide function cm::clamp
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !3859


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d867e058924d348ee5ec5bba867965e8f1f276e2
commit d867e058924d348ee5ec5bba867965e8f1f276e2
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Fri Sep 20 22:39:13 2019 +0200
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Wed Sep 25 10:07:09 2019 -0400

    Autogen: Use JSON instead of CMake script for info files
    
    We used to store information for the _autogen target in a CMake script
    file AutogenInfo.cmake, which was imported by a temporary cmake instance in
    the _autogen target.  This introduced the overhead of creating a temporary
    cmake instance and inherited the limitations of the CMake language which
    only supports lists.
    
    This patch introduces JSON files to pass information to AUTORCC and
    autogen_ targets.  JSON files are more flexible for passing data, e.g. they
    support nested lists.
    
    The patch has the side effects that
    
    - AutogenInfo.cmake is renamed to AutogenInfo.json
    - AutogenOldSettings.txt is renamed to AutogenUsed.txt
    - RCC<qrcBaseName><checksum>Info.cmake is renamed to
      AutoRcc_<qrcBaseName>_<checksum>_Info.json
    - RCC<qrcBaseName><checksum>.lock is renamed to
      AutoRcc_<qrcBaseName>_<checksum>_Lock.lock
    - RCC<qrcBaseName><checksum>Settings.txt is renamed to
      AutoRcc_<qrcBaseName>_<checksum>_Used.txt

diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx
index 57c8825..0f0e864 100644
--- a/Source/cmQtAutoGen.cxx
+++ b/Source/cmQtAutoGen.cxx
@@ -72,7 +72,6 @@ void MergeOptions(std::vector<std::string>& baseOpts,
 // - Class definitions
 
 unsigned int const cmQtAutoGen::ParallelMax = 64;
-std::string const cmQtAutoGen::ListSep = "<<<S>>>";
 
 cm::string_view cmQtAutoGen::GeneratorName(GenT genType)
 {
@@ -162,6 +161,16 @@ std::string cmQtAutoGen::QuotedCommand(std::vector<std::string> const& command)
   return res;
 }
 
+std::string cmQtAutoGen::FileNameWithoutLastExtension(cm::string_view filename)
+{
+  auto slashPos = filename.rfind('/');
+  if (slashPos != cm::string_view::npos) {
+    filename.remove_prefix(slashPos + 1);
+  }
+  auto dotPos = filename.rfind('.');
+  return std::string(filename.substr(0, dotPos));
+}
+
 std::string cmQtAutoGen::ParentDir(cm::string_view filename)
 {
   auto slashPos = filename.rfind('/');
diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h
index c8e4203..d070b79 100644
--- a/Source/cmQtAutoGen.h
+++ b/Source/cmQtAutoGen.h
@@ -62,8 +62,6 @@ public:
     RCC  // AUTORCC
   };
 
-  /// @brief Nested lists separator
-  static std::string const ListSep;
   /// @brief Maximum number of parallel threads/processes in a generator
   static unsigned int const ParallelMax;
 
@@ -81,6 +79,9 @@ public:
 
   static std::string QuotedCommand(std::vector<std::string> const& command);
 
+  /// @brief Returns the file name without path and extension (thread safe)
+  static std::string FileNameWithoutLastExtension(cm::string_view filename);
+
   /// @brief Returns the parent directory of the file (thread safe)
   static std::string ParentDir(cm::string_view filename);
 
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 0329ac7..0d56fe1 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -8,7 +8,7 @@
 #include "cmAlgorithms.h"
 #include "cmCustomCommand.h"
 #include "cmCustomCommandLines.h"
-#include "cmFilePathChecksum.h"
+#include "cmGeneratedFileStream.h"
 #include "cmGeneratorExpression.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalGenerator.h"
@@ -17,7 +17,6 @@
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
-#include "cmOutputConverter.h"
 #include "cmPolicies.h"
 #include "cmSourceFile.h"
 #include "cmSourceFileLocationKind.h"
@@ -27,6 +26,8 @@
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
+#include "cm_jsoncpp_value.h"
+#include "cm_jsoncpp_writer.h"
 #include "cmake.h"
 #include "cmsys/SystemInformation.hxx"
 
@@ -34,6 +35,7 @@
 #include <deque>
 #include <initializer_list>
 #include <map>
+#include <ostream>
 #include <set>
 #include <string>
 #include <unordered_set>
@@ -41,6 +43,7 @@
 #include <vector>
 
 #include <cm/algorithm>
+#include <cm/iterator>
 #include <cm/memory>
 
 namespace {
@@ -157,99 +160,134 @@ std::vector<std::string> SearchPathSanitizer::operator()(
   }
   return res;
 }
-} // End of unnamed namespace
 
-cmQtAutoGenInitializer::InfoWriter::InfoWriter(std::string const& filename)
+/** @brief Writes a CMake info file.  */
+class InfoWriter
 {
-  Ofs_.SetCopyIfDifferent(true);
-  Ofs_.Open(filename, false, true);
-}
+public:
+  // -- Single value
+  void Set(std::string const& key, std::string const& value)
+  {
+    Value_[key] = value;
+  }
+  void SetConfig(std::string const& key,
+                 cmQtAutoGenInitializer::ConfigString const& cfgStr);
+  void SetBool(std::string const& key, bool value) { Value_[key] = value; }
+  void SetUInt(std::string const& key, unsigned int value)
+  {
+    Value_[key] = value;
+  }
+
+  // -- Array utility
+  template <typename CONT>
+  static bool MakeArray(Json::Value& jval, CONT const& container);
+
+  template <typename CONT>
+  static void MakeStringArray(Json::Value& jval, CONT const& container);
+
+  // -- Array value
+  template <typename CONT>
+  void SetArray(std::string const& key, CONT const& container);
+  template <typename CONT>
+  void SetConfigArray(
+    std::string const& key,
+    cmQtAutoGenInitializer::ConfigStrings<CONT> const& cfgStr);
 
-template <class IT>
-std::string cmQtAutoGenInitializer::InfoWriter::ListJoin(IT it_begin,
-                                                         IT it_end)
+  // -- Array of arrays
+  template <typename CONT, typename FUNC>
+  void SetArrayArray(std::string const& key, CONT const& container, FUNC func);
+
+  // -- Save to json file
+  bool Save(std::string const& filename);
+
+private:
+  Json::Value Value_;
+};
+
+void InfoWriter::SetConfig(std::string const& key,
+                           cmQtAutoGenInitializer::ConfigString const& cfgStr)
 {
-  std::string res;
-  for (IT it = it_begin; it != it_end; ++it) {
-    if (it != it_begin) {
-      res += ';';
-    }
-    for (const char* c = it->c_str(); *c; ++c) {
-      if (*c == '"') {
-        // Escape the double quote to avoid ending the argument.
-        res += "\\\"";
-      } else if (*c == '$') {
-        // Escape the dollar to avoid expanding variables.
-        res += "\\$";
-      } else if (*c == '\\') {
-        // Escape the backslash to avoid other escapes.
-        res += "\\\\";
-      } else if (*c == ';') {
-        // Escape the semicolon to avoid list expansion.
-        res += "\\;";
-      } else {
-        // Other characters will be parsed correctly.
-        res += *c;
-      }
-    }
+  Set(key, cfgStr.Default);
+  for (auto const& item : cfgStr.Config) {
+    Set(cmStrCat(key, '_', item.first), item.second);
   }
-  return res;
 }
 
-inline std::string cmQtAutoGenInitializer::InfoWriter::ConfigKey(
-  cm::string_view key, std::string const& config)
+template <typename CONT>
+bool InfoWriter::MakeArray(Json::Value& jval, CONT const& container)
 {
-  return cmStrCat(key, "_", config);
+  jval = Json::arrayValue;
+  std::size_t const listSize = cm::size(container);
+  if (listSize == 0) {
+    return false;
+  }
+  jval.resize(static_cast<unsigned int>(listSize));
+  return true;
 }
 
-void cmQtAutoGenInitializer::InfoWriter::Write(cm::string_view key,
-                                               std::string const& value)
+template <typename CONT>
+void InfoWriter::MakeStringArray(Json::Value& jval, CONT const& container)
 {
-  Ofs_ << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value)
-       << ")\n";
-};
-
-void cmQtAutoGenInitializer::InfoWriter::WriteUInt(cm::string_view key,
-                                                   unsigned int value)
-{
-  Ofs_ << "set(" << key << " " << value << ")\n";
-};
+  if (MakeArray(jval, container)) {
+    Json::ArrayIndex ii = 0;
+    for (std::string const& item : container) {
+      jval[ii++] = item;
+    }
+  }
+}
 
-template <class C>
-void cmQtAutoGenInitializer::InfoWriter::WriteStrings(cm::string_view key,
-                                                      C const& container)
+template <typename CONT>
+void InfoWriter::SetArray(std::string const& key, CONT const& container)
 {
-  Ofs_ << "set(" << key << " \""
-       << ListJoin(container.begin(), container.end()) << "\")\n";
+  MakeStringArray(Value_[key], container);
 }
 
-void cmQtAutoGenInitializer::InfoWriter::WriteConfig(
-  cm::string_view key, std::map<std::string, std::string> const& map)
+template <typename CONT, typename FUNC>
+void InfoWriter::SetArrayArray(std::string const& key, CONT const& container,
+                               FUNC func)
 {
-  for (auto const& item : map) {
-    Write(ConfigKey(key, item.first), item.second);
+  Json::Value& jval = Value_[key];
+  if (MakeArray(jval, container)) {
+    Json::ArrayIndex ii = 0;
+    for (auto const& citem : container) {
+      Json::Value& aval = jval[ii++];
+      aval = Json::arrayValue;
+      func(aval, citem);
+    }
   }
-};
+}
 
-template <class C>
-void cmQtAutoGenInitializer::InfoWriter::WriteConfigStrings(
-  cm::string_view key, std::map<std::string, C> const& map)
+template <typename CONT>
+void InfoWriter::SetConfigArray(
+  std::string const& key,
+  cmQtAutoGenInitializer::ConfigStrings<CONT> const& cfgStr)
 {
-  for (auto const& item : map) {
-    WriteStrings(ConfigKey(key, item.first), item.second);
+  SetArray(key, cfgStr.Default);
+  for (auto const& item : cfgStr.Config) {
+    SetArray(cmStrCat(key, '_', item.first), item.second);
   }
 }
 
-void cmQtAutoGenInitializer::InfoWriter::WriteNestedLists(
-  cm::string_view key, std::vector<std::vector<std::string>> const& lists)
+bool InfoWriter::Save(std::string const& filename)
 {
-  std::vector<std::string> seplist;
-  seplist.reserve(lists.size());
-  for (std::vector<std::string> const& list : lists) {
-    seplist.push_back(cmStrCat("{", ListJoin(list.begin(), list.end()), "}"));
+  cmGeneratedFileStream fileStream;
+  fileStream.SetCopyIfDifferent(true);
+  fileStream.Open(filename, false, true);
+  if (!fileStream) {
+    return false;
   }
-  Write(key, cmJoin(seplist, cmQtAutoGen::ListSep));
-};
+
+  Json::StyledStreamWriter jsonWriter;
+  try {
+    jsonWriter.write(fileStream, Value_);
+  } catch (...) {
+    return false;
+  }
+
+  return fileStream.Close();
+}
+
+} // End of unnamed namespace
 
 cmQtAutoGenInitializer::cmQtAutoGenInitializer(
   cmQtAutoGenGlobalInitializer* globalInitializer,
@@ -261,6 +299,7 @@ cmQtAutoGenInitializer::cmQtAutoGenInitializer(
   , GlobalGen(genTarget->GetGlobalGenerator())
   , LocalGen(genTarget->GetLocalGenerator())
   , Makefile(genTarget->Makefile)
+  , PathCheckSum(genTarget->Makefile)
   , QtVersion(qtVersion)
 {
   AutogenTarget.GlobalTarget = globalAutogenTarget;
@@ -280,12 +319,20 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
   }
 
   // Verbosity
-  this->Verbosity = this->Makefile->GetSafeDefinition("CMAKE_AUTOGEN_VERBOSE");
-  if (!this->Verbosity.empty()) {
-    unsigned long iVerb = 0;
-    if (!cmStrToULong(this->Verbosity, &iVerb)) {
-      // Non numeric verbosity
-      this->Verbosity = cmIsOn(this->Verbosity) ? "1" : "0";
+  {
+    std::string def =
+      this->Makefile->GetSafeDefinition("CMAKE_AUTOGEN_VERBOSE");
+    if (!def.empty()) {
+      unsigned long iVerb = 0;
+      if (cmStrToULong(def, &iVerb)) {
+        // Numeric verbosity
+        this->Verbosity = static_cast<unsigned int>(iVerb);
+      } else {
+        // Non numeric verbosity
+        if (cmIsOn(def)) {
+          this->Verbosity = 1;
+        }
+      }
     }
   }
 
@@ -352,15 +399,9 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
     cmSystemTools::ConvertToUnixSlashes(this->Dir.Work);
 
     // Include directory
-    this->Dir.Include = cmStrCat(this->Dir.Build, "/include");
-    // Per config include directories
-    if (this->MultiConfig) {
-      for (std::string const& cfg : this->ConfigsList) {
-        std::string& dir = this->Dir.ConfigInclude[cfg];
-        dir = cmStrCat(this->Dir.Build, "/include_", cfg);
-      }
-    }
-    this->Dir.IncludeGenExp = this->Dir.Include;
+    ConfigFileNames(this->Dir.Include, cmStrCat(this->Dir.Build, "/include"),
+                    "");
+    this->Dir.IncludeGenExp = this->Dir.Include.Default;
     if (this->MultiConfig) {
       this->Dir.IncludeGenExp += "_$<CONFIG>";
     }
@@ -383,36 +424,31 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
       cmStrCat(this->GenTarget->GetName(), "_autogen");
 
     // Autogen target parallel processing
-    this->AutogenTarget.Parallel =
-      this->GenTarget->GetSafeProperty("AUTOGEN_PARALLEL");
-    if (this->AutogenTarget.Parallel.empty() ||
-        (this->AutogenTarget.Parallel == "AUTO")) {
-      // Autodetect number of CPUs
-      this->AutogenTarget.Parallel = std::to_string(GetParallelCPUCount());
+    {
+      std::string prop = this->GenTarget->GetSafeProperty("AUTOGEN_PARALLEL");
+      if (prop.empty() || (prop == "AUTO")) {
+        // Autodetect number of CPUs
+        this->AutogenTarget.Parallel = GetParallelCPUCount();
+      } else {
+        this->AutogenTarget.Parallel = 1;
+      }
     }
 
     // Autogen target info and settings files
     {
+      // Info file
       this->AutogenTarget.InfoFile =
-        cmStrCat(this->Dir.Info, "/AutogenInfo.cmake");
+        cmStrCat(this->Dir.Info, "/AutogenInfo.json");
 
-      this->AutogenTarget.SettingsFile =
-        cmStrCat(this->Dir.Info, "/AutogenOldSettings.txt");
-
-      if (this->MultiConfig) {
-        for (std::string const& cfg : this->ConfigsList) {
-          std::string& filename = this->AutogenTarget.ConfigSettingsFile[cfg];
-          filename =
-            AppendFilenameSuffix(this->AutogenTarget.SettingsFile, "_" + cfg);
-          this->AddCleanFile(filename);
-        }
-      } else {
-        this->AddCleanFile(this->AutogenTarget.SettingsFile);
-      }
+      // Used settings file
+      ConfigFileNames(this->AutogenTarget.SettingsFile,
+                      cmStrCat(this->Dir.Info, "/AutogenUsed"), ".txt");
+      ConfigFileClean(this->AutogenTarget.SettingsFile);
 
-      this->AutogenTarget.ParseCacheFile =
-        cmStrCat(this->Dir.Info, "/ParseCache.txt");
-      this->AddCleanFile(this->AutogenTarget.ParseCacheFile);
+      // Parse cache file
+      ConfigFileNames(this->AutogenTarget.ParseCacheFile,
+                      cmStrCat(this->Dir.Info, "/ParseCache"), ".txt");
+      ConfigFileClean(this->AutogenTarget.ParseCacheFile);
     }
 
     // Autogen target: Compute user defined dependencies
@@ -435,9 +471,15 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
       }
     }
 
-    // CMAKE_AUTOMOC_RELAXED_MODE deprecation warning
     if (this->Moc.Enabled) {
+      // Path prefix
+      if (cmIsOn(this->GenTarget->GetSafeProperty("AUTOMOC_PATH_PREFIX"))) {
+        this->Moc.PathPrefix = true;
+      }
+
+      // CMAKE_AUTOMOC_RELAXED_MODE
       if (this->Makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE")) {
+        this->Moc.RelaxedMode = true;
         this->Makefile->IssueMessage(
           MessageType::AUTHOR_WARNING,
           cmStrCat("AUTOMOC: CMAKE_AUTOMOC_RELAXED_MODE is "
@@ -445,6 +487,32 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
                    "disabling it and converting the target ",
                    this->GenTarget->GetName(), " to regular mode."));
       }
+
+      // Options
+      cmExpandList(this->GenTarget->GetSafeProperty("AUTOMOC_MOC_OPTIONS"),
+                   this->Moc.Options);
+      // Filters
+      cmExpandList(this->GenTarget->GetSafeProperty("AUTOMOC_MACRO_NAMES"),
+                   this->Moc.MacroNames);
+      {
+        auto filterList = cmExpandedList(
+          this->GenTarget->GetSafeProperty("AUTOMOC_DEPEND_FILTERS"));
+        if ((filterList.size() % 2) != 0) {
+          cmSystemTools::Error(
+            cmStrCat("AutoMoc: AUTOMOC_DEPEND_FILTERS predefs size ",
+                     filterList.size(), " is not a multiple of 2."));
+          return false;
+        }
+        this->Moc.DependFilters.reserve(1 + (filterList.size() / 2));
+        this->Moc.DependFilters.emplace_back(
+          "Q_PLUGIN_METADATA",
+          "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\("
+          "[^\\)]*FILE[ \t]*\"([^\"]+)\"");
+        for (std::size_t ii = 0; ii != filterList.size(); ii += 2) {
+          this->Moc.DependFilters.emplace_back(filterList[ii],
+                                               filterList[ii + 1]);
+        }
+      }
     }
   }
 
@@ -479,20 +547,27 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
 bool cmQtAutoGenInitializer::InitMoc()
 {
   // Mocs compilation file
-  this->Moc.MocsCompilation =
+  this->Moc.CompilationFile =
     cmStrCat(this->Dir.Build, "/mocs_compilation.cpp");
 
-  // Moc predefs command
+  // Moc predefs
   if (this->GenTarget->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") &&
       (this->QtVersion >= IntegerVersion(5, 8))) {
-    this->Moc.PredefsCmd = this->Makefile->GetSafeDefinition(
-      "CMAKE_CXX_COMPILER_PREDEFINES_COMMAND");
+    // Command
+    cmExpandList(this->Makefile->GetSafeDefinition(
+                   "CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"),
+                 this->Moc.PredefsCmd);
+    // Header
+    if (!this->Moc.PredefsCmd.empty()) {
+      ConfigFileNames(this->Moc.PredefsFile,
+                      cmStrCat(this->Dir.Build, "/moc_predefs"), ".h");
+    }
   }
 
   // Moc includes
   {
     SearchPathSanitizer sanitizer(this->Makefile);
-    auto GetIncludeDirs =
+    auto getDirs =
       [this, &sanitizer](std::string const& cfg) -> std::vector<std::string> {
       // Get the include dirs for this target, without stripping the implicit
       // include dirs off, see issue #13667.
@@ -504,22 +579,22 @@ bool cmQtAutoGenInitializer::InitMoc()
     };
 
     // Default configuration include directories
-    this->Moc.Includes = GetIncludeDirs(this->ConfigDefault);
+    this->Moc.Includes.Default = getDirs(this->ConfigDefault);
     // Other configuration settings
     if (this->MultiConfig) {
       for (std::string const& cfg : this->ConfigsList) {
-        std::vector<std::string> dirs = GetIncludeDirs(cfg);
-        if (dirs != this->Moc.Includes) {
-          this->Moc.ConfigIncludes[cfg] = std::move(dirs);
+        std::vector<std::string> dirs = getDirs(cfg);
+        if (dirs == this->Moc.Includes.Default) {
+          continue;
         }
+        this->Moc.Includes.Config[cfg] = std::move(dirs);
       }
     }
   }
 
   // Moc compile definitions
   {
-    auto GetCompileDefinitions =
-      [this](std::string const& cfg) -> std::set<std::string> {
+    auto getDefs = [this](std::string const& cfg) -> std::set<std::string> {
       std::set<std::string> defines;
       this->LocalGen->GetTargetDefines(this->GenTarget, cfg, "CXX", defines);
 #ifdef _WIN32
@@ -532,14 +607,15 @@ bool cmQtAutoGenInitializer::InitMoc()
     };
 
     // Default configuration defines
-    this->Moc.Defines = GetCompileDefinitions(this->ConfigDefault);
+    this->Moc.Defines.Default = getDefs(this->ConfigDefault);
     // Other configuration defines
     if (this->MultiConfig) {
       for (std::string const& cfg : this->ConfigsList) {
-        std::set<std::string> defines = GetCompileDefinitions(cfg);
-        if (defines != this->Moc.Defines) {
-          this->Moc.ConfigDefines[cfg] = std::move(defines);
+        std::set<std::string> defines = getDefs(cfg);
+        if (defines == this->Moc.Defines.Default) {
+          continue;
         }
+        this->Moc.Defines.Config[cfg] = std::move(defines);
       }
     }
   }
@@ -572,23 +648,22 @@ bool cmQtAutoGenInitializer::InitUic()
   }
   // Uic target options
   {
-    auto UicGetOpts =
-      [this](std::string const& cfg) -> std::vector<std::string> {
+    auto getOpts = [this](std::string const& cfg) -> std::vector<std::string> {
       std::vector<std::string> opts;
       this->GenTarget->GetAutoUicOptions(opts, cfg);
       return opts;
     };
 
-    // Default settings
-    this->Uic.Options = UicGetOpts(this->ConfigDefault);
-
-    // Configuration specific settings
+    // Default options
+    this->Uic.Options.Default = getOpts(this->ConfigDefault);
+    // Configuration specific options
     if (this->MultiConfig) {
       for (std::string const& cfg : this->ConfigsList) {
-        std::vector<std::string> options = UicGetOpts(cfg);
-        if (options != this->Uic.Options) {
-          this->Uic.ConfigOptions[cfg] = std::move(options);
+        std::vector<std::string> options = getOpts(cfg);
+        if (options == this->Uic.Options.Default) {
+          continue;
         }
+        this->Uic.Options.Config[cfg] = std::move(options);
       }
     }
   }
@@ -822,8 +897,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
           // Check if the .ui file has uic options
           std::string const uicOpts = sf->GetSafeProperty(kw.AUTOUIC_OPTIONS);
           if (!uicOpts.empty()) {
-            this->Uic.FileFiles.push_back(fullPath);
-            this->Uic.FileOptions.push_back(cmExpandedList(uicOpts));
+            this->Uic.UiFiles.emplace_back(fullPath, cmExpandedList(uicOpts));
           }
         } else {
           // Register skipped .ui file
@@ -887,31 +961,17 @@ bool cmQtAutoGenInitializer::InitScanFiles()
       }
     }
     // Path checksum and file names
-    {
-      cmFilePathChecksum const fpathCheckSum(this->Makefile);
-      for (Qrc& qrc : this->Rcc.Qrcs) {
-        // Path checksum
-        qrc.QrcPathChecksum = fpathCheckSum.getPart(qrc.QrcFile);
-        // Output file name
-        qrc.OutputFile = cmStrCat(this->Dir.Build, '/', qrc.QrcPathChecksum,
-                                  "/qrc_", qrc.QrcName, ".cpp");
-        {
-          cm::string_view const baseSuffix = qrc.Unique
-            ? cm::string_view()
-            : cm::string_view(qrc.QrcPathChecksum);
-          std::string const base =
-            cmStrCat(this->Dir.Info, "/RCC", qrc.QrcName, baseSuffix);
-          qrc.LockFile = cmStrCat(base, ".lock");
-          qrc.InfoFile = cmStrCat(base, "Info.cmake");
-          qrc.SettingsFile = cmStrCat(base, "Settings.txt");
-          if (this->MultiConfig) {
-            for (std::string const& cfg : this->ConfigsList) {
-              qrc.ConfigSettingsFile[cfg] =
-                AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg);
-            }
-          }
-        }
-      }
+    for (Qrc& qrc : this->Rcc.Qrcs) {
+      // Path checksum
+      qrc.QrcPathChecksum = this->PathCheckSum.getPart(qrc.QrcFile);
+      // Output file name
+      qrc.OutputFile = cmStrCat(this->Dir.Build, '/', qrc.QrcPathChecksum,
+                                "/qrc_", qrc.QrcName, ".cpp");
+      std::string const base = cmStrCat(this->Dir.Info, "/AutoRcc_",
+                                        qrc.QrcName, '_', qrc.QrcPathChecksum);
+      qrc.LockFile = cmStrCat(base, "_Lock.lock");
+      qrc.InfoFile = cmStrCat(base, "_Info.json");
+      ConfigFileNames(qrc.SettingsFile, cmStrCat(base, "_Used"), ".txt");
     }
     // rcc options
     for (Qrc& qrc : this->Rcc.Qrcs) {
@@ -959,8 +1019,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
   // Files provided by the autogen target
   std::vector<std::string> autogenProvides;
   if (this->Moc.Enabled) {
-    this->AddGeneratedSource(this->Moc.MocsCompilation, this->Moc, true);
-    autogenProvides.push_back(this->Moc.MocsCompilation);
+    this->AddGeneratedSource(this->Moc.CompilationFile, this->Moc, true);
+    autogenProvides.push_back(this->Moc.CompilationFile);
   }
 
   // Compose target comment
@@ -1214,229 +1274,185 @@ bool cmQtAutoGenInitializer::SetupCustomTargets()
 
 bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
 {
-  InfoWriter ofs(this->AutogenTarget.InfoFile);
-  if (ofs) {
-    // Utility lambdas
-    auto MfDef = [this](const char* key) {
-      return this->Makefile->GetSafeDefinition(key);
-    };
+  // Utility lambdas
+  auto MfDef = [this](std::string const& key) {
+    return this->Makefile->GetSafeDefinition(key);
+  };
 
-    // Write common settings
-    ofs.Write("# Meta\n");
-    ofs.Write("AM_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");
-    ofs.Write("AM_PARALLEL", this->AutogenTarget.Parallel);
-    ofs.Write("AM_VERBOSITY", this->Verbosity);
-
-    ofs.Write("# Directories\n");
-    ofs.Write("AM_CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));
-    ofs.Write("AM_CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));
-    ofs.Write("AM_CMAKE_CURRENT_SOURCE_DIR",
-              MfDef("CMAKE_CURRENT_SOURCE_DIR"));
-    ofs.Write("AM_CMAKE_CURRENT_BINARY_DIR",
-              MfDef("CMAKE_CURRENT_BINARY_DIR"));
-    ofs.Write("AM_BUILD_DIR", this->Dir.Build);
-    ofs.Write("AM_INCLUDE_DIR", this->Dir.Include);
-    ofs.WriteConfig("AM_INCLUDE_DIR", this->Dir.ConfigInclude);
-
-    std::vector<std::string> headers;
-    std::vector<std::string> headersFlags;
-    std::vector<std::string> headersBuildPaths;
-    std::vector<std::string> sources;
-    std::vector<std::string> sourcesFlags;
-    std::set<std::string> moc_skip;
-    std::set<std::string> uic_skip;
-
-    // Filter headers
-    {
-      auto headerCount = this->AutogenTarget.Headers.size();
-      headers.reserve(headerCount);
-      headersFlags.reserve(headerCount);
+  // Filtered headers and sources
+  std::set<std::string> moc_skip;
+  std::set<std::string> uic_skip;
+  std::vector<MUFile const*> headers;
+  std::vector<MUFile const*> sources;
 
-      std::vector<MUFile const*> sortedHeaders;
-      {
-        sortedHeaders.reserve(headerCount);
-        for (auto const& pair : this->AutogenTarget.Headers) {
-          sortedHeaders.emplace_back(pair.second.get());
-        }
-        std::sort(sortedHeaders.begin(), sortedHeaders.end(),
-                  [](MUFile const* a, MUFile const* b) {
-                    return (a->FullPath < b->FullPath);
-                  });
+  // Filter headers
+  {
+    headers.reserve(this->AutogenTarget.Headers.size());
+    for (auto const& pair : this->AutogenTarget.Headers) {
+      MUFile const* const muf = pair.second.get();
+      if (muf->Generated && !this->CMP0071Accept) {
+        continue;
       }
-
-      for (MUFile const* const muf : sortedHeaders) {
-        if (muf->Generated && !this->CMP0071Accept) {
-          continue;
-        }
-        if (muf->SkipMoc) {
-          moc_skip.insert(muf->FullPath);
-        }
-        if (muf->SkipUic) {
-          uic_skip.insert(muf->FullPath);
-        }
-        if (muf->MocIt || muf->UicIt) {
-          headers.emplace_back(muf->FullPath);
-          headersFlags.emplace_back(
-            cmStrCat(muf->MocIt ? 'M' : 'm', muf->UicIt ? 'U' : 'u'));
-        }
+      if (muf->SkipMoc) {
+        moc_skip.insert(muf->FullPath);
       }
-    }
-    // Header build paths
-    {
-      cmFilePathChecksum const fpathCheckSum(this->Makefile);
-      std::unordered_set<std::string> emitted;
-      for (std::string const& hdr : headers) {
-        std::string const basePath =
-          cmStrCat(fpathCheckSum.getPart(hdr), "/moc_",
-                   cmSystemTools::GetFilenameWithoutLastExtension(hdr));
-        std::string suffix;
-        for (int ii = 0; ii != 1024; ++ii) {
-          std::string path = cmStrCat(basePath, suffix, ".cpp");
-          if (emitted.emplace(path).second) {
-            headersBuildPaths.emplace_back(std::move(path));
-            break;
-          }
-          suffix = cmStrCat('_', ii + 1);
-        }
+      if (muf->SkipUic) {
+        uic_skip.insert(muf->FullPath);
+      }
+      if (muf->MocIt || muf->UicIt) {
+        headers.emplace_back(muf);
       }
     }
+    std::sort(headers.begin(), headers.end(),
+              [](MUFile const* a, MUFile const* b) {
+                return (a->FullPath < b->FullPath);
+              });
+  }
 
-    // Filter sources
-    {
-      auto sourcesCount = this->AutogenTarget.Sources.size();
-      sources.reserve(sourcesCount);
-      sourcesFlags.reserve(sourcesCount);
-
-      std::vector<MUFile const*> sorted;
-      sorted.reserve(sourcesCount);
-      for (auto const& pair : this->AutogenTarget.Sources) {
-        sorted.emplace_back(pair.second.get());
+  // Filter sources
+  {
+    sources.reserve(this->AutogenTarget.Sources.size());
+    for (auto const& pair : this->AutogenTarget.Sources) {
+      MUFile const* const muf = pair.second.get();
+      if (muf->Generated && !this->CMP0071Accept) {
+        continue;
       }
-      std::sort(sorted.begin(), sorted.end(),
-                [](MUFile const* a, MUFile const* b) {
-                  return (a->FullPath < b->FullPath);
-                });
-
-      for (MUFile const* const muf : sorted) {
-        if (muf->Generated && !this->CMP0071Accept) {
-          continue;
-        }
-        if (muf->SkipMoc) {
-          moc_skip.insert(muf->FullPath);
-        }
-        if (muf->SkipUic) {
-          uic_skip.insert(muf->FullPath);
-        }
-        if (muf->MocIt || muf->UicIt) {
-          sources.emplace_back(muf->FullPath);
-          sourcesFlags.emplace_back(
-            cmStrCat(muf->MocIt ? 'M' : 'm', muf->UicIt ? 'U' : 'u'));
-        }
+      if (muf->SkipMoc) {
+        moc_skip.insert(muf->FullPath);
+      }
+      if (muf->SkipUic) {
+        uic_skip.insert(muf->FullPath);
+      }
+      if (muf->MocIt || muf->UicIt) {
+        sources.emplace_back(muf);
       }
     }
+    std::sort(sources.begin(), sources.end(),
+              [](MUFile const* a, MUFile const* b) {
+                return (a->FullPath < b->FullPath);
+              });
+  }
 
-    ofs.Write("# Qt\n");
-    ofs.WriteUInt("AM_QT_VERSION_MAJOR", this->QtVersion.Major);
-    ofs.Write("AM_QT_MOC_EXECUTABLE", this->Moc.Executable);
-    ofs.Write("AM_QT_UIC_EXECUTABLE", this->Uic.Executable);
-
-    ofs.Write("# Files\n");
-    ofs.Write("AM_CMAKE_EXECUTABLE", cmSystemTools::GetCMakeCommand());
-    ofs.Write("AM_SETTINGS_FILE", this->AutogenTarget.SettingsFile);
-    ofs.WriteConfig("AM_SETTINGS_FILE",
-                    this->AutogenTarget.ConfigSettingsFile);
-    ofs.Write("AM_PARSE_CACHE_FILE", this->AutogenTarget.ParseCacheFile);
-    ofs.WriteStrings("AM_HEADERS", headers);
-    ofs.WriteStrings("AM_HEADERS_FLAGS", headersFlags);
-    ofs.WriteStrings("AM_HEADERS_BUILD_PATHS", headersBuildPaths);
-    ofs.WriteStrings("AM_SOURCES", sources);
-    ofs.WriteStrings("AM_SOURCES_FLAGS", sourcesFlags);
-
-    // Write moc settings
-    if (this->Moc.Enabled) {
-      ofs.Write("# MOC settings\n");
-      ofs.WriteStrings("AM_MOC_SKIP", moc_skip);
-      ofs.WriteStrings("AM_MOC_DEFINITIONS", this->Moc.Defines);
-      ofs.WriteConfigStrings("AM_MOC_DEFINITIONS", this->Moc.ConfigDefines);
-      ofs.WriteStrings("AM_MOC_INCLUDES", this->Moc.Includes);
-      ofs.WriteConfigStrings("AM_MOC_INCLUDES", this->Moc.ConfigIncludes);
-      ofs.Write("AM_MOC_OPTIONS",
-                this->GenTarget->GetSafeProperty("AUTOMOC_MOC_OPTIONS"));
-      ofs.Write("AM_MOC_RELAXED_MODE", MfDef("CMAKE_AUTOMOC_RELAXED_MODE"));
-      ofs.Write("AM_MOC_PATH_PREFIX",
-                this->GenTarget->GetSafeProperty("AUTOMOC_PATH_PREFIX"));
-      ofs.Write("AM_MOC_MACRO_NAMES",
-                this->GenTarget->GetSafeProperty("AUTOMOC_MACRO_NAMES"));
-      ofs.Write("AM_MOC_DEPEND_FILTERS",
-                this->GenTarget->GetSafeProperty("AUTOMOC_DEPEND_FILTERS"));
-      ofs.Write("AM_MOC_PREDEFS_CMD", this->Moc.PredefsCmd);
-    }
-
-    // Write uic settings
-    if (this->Uic.Enabled) {
-      // Add skipped .ui files
-      uic_skip.insert(this->Uic.SkipUi.begin(), this->Uic.SkipUi.end());
+  // Info writer
+  InfoWriter info;
+
+  // General
+  info.SetBool("MULTI_CONFIG", this->MultiConfig);
+  info.SetUInt("PARALLEL", this->AutogenTarget.Parallel);
+  info.SetUInt("VERBOSITY", this->Verbosity);
+
+  // Directories
+  info.Set("CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));
+  info.Set("CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));
+  info.Set("CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR"));
+  info.Set("CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR"));
+  info.Set("BUILD_DIR", this->Dir.Build);
+  info.SetConfig("INCLUDE_DIR", this->Dir.Include);
+
+  info.SetUInt("QT_VERSION_MAJOR", this->QtVersion.Major);
+  info.Set("QT_MOC_EXECUTABLE", this->Moc.Executable);
+  info.Set("QT_UIC_EXECUTABLE", this->Uic.Executable);
+
+  info.Set("CMAKE_EXECUTABLE", cmSystemTools::GetCMakeCommand());
+  info.SetConfig("SETTINGS_FILE", this->AutogenTarget.SettingsFile);
+  info.SetConfig("PARSE_CACHE_FILE", this->AutogenTarget.ParseCacheFile);
+  info.SetArray("HEADER_EXTENSIONS",
+                this->Makefile->GetCMakeInstance()->GetHeaderExtensions());
+  info.SetArrayArray(
+    "HEADERS", headers, [this](Json::Value& jval, MUFile const* muf) {
+      jval.resize(3u);
+      jval[0u] = muf->FullPath;
+      jval[1u] = cmStrCat(muf->MocIt ? 'M' : 'm', muf->UicIt ? 'U' : 'u');
+      jval[2u] = this->GetMocBuildPath(*muf);
+    });
+  info.SetArrayArray(
+    "SOURCES", sources, [](Json::Value& jval, MUFile const* muf) {
+      jval.resize(2u);
+      jval[0u] = muf->FullPath;
+      jval[1u] = cmStrCat(muf->MocIt ? 'M' : 'm', muf->UicIt ? 'U' : 'u');
+    });
+
+  // Write moc settings
+  if (this->Moc.Enabled) {
+    info.SetArray("MOC_SKIP", moc_skip);
+    info.SetConfigArray("MOC_DEFINITIONS", this->Moc.Defines);
+    info.SetConfigArray("MOC_INCLUDES", this->Moc.Includes);
+    info.SetArray("MOC_OPTIONS", this->Moc.Options);
+    info.SetBool("MOC_RELAXED_MODE", this->Moc.RelaxedMode);
+    info.SetBool("MOC_PATH_PREFIX", this->Moc.PathPrefix);
+    info.SetArray("MOC_MACRO_NAMES", this->Moc.MacroNames);
+    info.SetArrayArray(
+      "MOC_DEPEND_FILTERS", this->Moc.DependFilters,
+      [](Json::Value& jval, std::pair<std::string, std::string> const& pair) {
+        jval.resize(2u);
+        jval[0u] = pair.first;
+        jval[1u] = pair.second;
+      });
+    info.Set("MOC_COMPILATION_FILE", this->Moc.CompilationFile);
+    info.SetArray("MOC_PREDEFS_CMD", this->Moc.PredefsCmd);
+    info.SetConfig("MOC_PREDEFS_FILE", this->Moc.PredefsFile);
+  }
 
-      ofs.Write("# UIC settings\n");
-      ofs.WriteStrings("AM_UIC_SKIP", uic_skip);
-      ofs.WriteStrings("AM_UIC_TARGET_OPTIONS", this->Uic.Options);
-      ofs.WriteConfigStrings("AM_UIC_TARGET_OPTIONS", this->Uic.ConfigOptions);
-      ofs.WriteStrings("AM_UIC_OPTIONS_FILES", this->Uic.FileFiles);
-      ofs.WriteNestedLists("AM_UIC_OPTIONS_OPTIONS", this->Uic.FileOptions);
-      ofs.WriteStrings("AM_UIC_SEARCH_PATHS", this->Uic.SearchPaths);
-    }
-  } else {
-    cmSystemTools::Error(cmStrCat("AutoGen: Could not write file ",
-                                  this->AutogenTarget.InfoFile));
-    return false;
+  // Write uic settings
+  if (this->Uic.Enabled) {
+    // Add skipped .ui files
+    uic_skip.insert(this->Uic.SkipUi.begin(), this->Uic.SkipUi.end());
+
+    info.SetArray("UIC_SKIP", uic_skip);
+    info.SetArrayArray("UIC_UI_FILES", this->Uic.UiFiles,
+                       [](Json::Value& jval, UicT::UiFileT const& uiFile) {
+                         jval.resize(2u);
+                         jval[0u] = uiFile.first;
+                         InfoWriter::MakeStringArray(jval[1u], uiFile.second);
+                       });
+    info.SetConfigArray("UIC_OPTIONS", this->Uic.Options);
+    info.SetArray("UIC_SEARCH_PATHS", this->Uic.SearchPaths);
   }
 
+  info.Save(this->AutogenTarget.InfoFile);
+
   return true;
 }
 
 bool cmQtAutoGenInitializer::SetupWriteRccInfo()
 {
   for (Qrc const& qrc : this->Rcc.Qrcs) {
-    InfoWriter ofs(qrc.InfoFile);
-    if (ofs) {
-      // Utility lambdas
-      auto MfDef = [this](const char* key) {
-        return this->Makefile->GetSafeDefinition(key);
-      };
+    // Utility lambdas
+    auto MfDef = [this](std::string const& key) {
+      return this->Makefile->GetSafeDefinition(key);
+    };
 
-      // Write
-      ofs.Write("# Configurations\n");
-      ofs.Write("ARCC_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");
-      ofs.Write("ARCC_VERBOSITY", this->Verbosity);
-      ofs.Write("# Settings file\n");
-      ofs.Write("ARCC_SETTINGS_FILE", qrc.SettingsFile);
-      ofs.WriteConfig("ARCC_SETTINGS_FILE", qrc.ConfigSettingsFile);
-
-      ofs.Write("# Directories\n");
-      ofs.Write("ARCC_CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));
-      ofs.Write("ARCC_CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));
-      ofs.Write("ARCC_BUILD_DIR", this->Dir.Build);
-      ofs.Write("ARCC_INCLUDE_DIR", this->Dir.Include);
-      ofs.WriteConfig("ARCC_INCLUDE_DIR", this->Dir.ConfigInclude);
-
-      ofs.Write("# Rcc executable\n");
-      ofs.Write("ARCC_RCC_EXECUTABLE", this->Rcc.Executable);
-      ofs.WriteStrings("ARCC_RCC_LIST_OPTIONS",
-                       this->Rcc.ExecutableFeatures->ListOptions);
-
-      ofs.Write("# Rcc job\n");
-      ofs.Write("ARCC_LOCK_FILE", qrc.LockFile);
-      ofs.Write("ARCC_SOURCE", qrc.QrcFile);
-      ofs.Write("ARCC_OUTPUT_CHECKSUM", qrc.QrcPathChecksum);
-      ofs.Write("ARCC_OUTPUT_NAME",
-                cmSystemTools::GetFilenameName(qrc.OutputFile));
-      ofs.WriteStrings("ARCC_OPTIONS", qrc.Options);
-      ofs.WriteStrings("ARCC_INPUTS", qrc.Resources);
-    } else {
-      cmSystemTools::Error(
-        cmStrCat("AutoRcc: Could not write file ", qrc.InfoFile));
-      return false;
-    }
+    InfoWriter info;
+
+    // General
+    info.SetBool("MULTI_CONFIG", this->MultiConfig);
+    info.SetUInt("VERBOSITY", this->Verbosity);
+
+    // Files
+    info.Set("LOCK_FILE", qrc.LockFile);
+    info.SetConfig("SETTINGS_FILE", qrc.SettingsFile);
+
+    // Directories
+    info.Set("CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));
+    info.Set("CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));
+    info.Set("CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR"));
+    info.Set("CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR"));
+    info.Set("BUILD_DIR", this->Dir.Build);
+    info.SetConfig("INCLUDE_DIR", this->Dir.Include);
+
+    // rcc executable
+    info.Set("RCC_EXECUTABLE", this->Rcc.Executable);
+    info.SetArray("RCC_LIST_OPTIONS",
+                  this->Rcc.ExecutableFeatures->ListOptions);
+
+    // qrc file
+    info.Set("SOURCE", qrc.QrcFile);
+    info.Set("OUTPUT_CHECKSUM", qrc.QrcPathChecksum);
+    info.Set("OUTPUT_NAME", cmSystemTools::GetFilenameName(qrc.OutputFile));
+    info.SetArray("OPTIONS", qrc.Options);
+    info.SetArray("INPUTS", qrc.Resources);
+
+    info.Save(qrc.InfoFile);
   }
 
   return true;
@@ -1509,6 +1525,28 @@ void cmQtAutoGenInitializer::AddCleanFile(std::string const& fileName)
                                           fileName.c_str(), false);
 }
 
+void cmQtAutoGenInitializer::ConfigFileNames(ConfigString& configString,
+                                             cm::string_view prefix,
+                                             cm::string_view suffix)
+{
+  configString.Default = cmStrCat(prefix, suffix);
+  if (this->MultiConfig) {
+    for (auto const& cfg : this->ConfigsList) {
+      configString.Config[cfg] = cmStrCat(prefix, '_', cfg, suffix);
+    }
+  }
+}
+
+void cmQtAutoGenInitializer::ConfigFileClean(ConfigString& configString)
+{
+  this->AddCleanFile(configString.Default);
+  if (this->MultiConfig) {
+    for (auto const& pair : configString.Config) {
+      this->AddCleanFile(pair.second);
+    }
+  }
+}
+
 std::pair<cmQtAutoGen::IntegerVersion, unsigned int>
 cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target)
 {
@@ -1581,6 +1619,30 @@ cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target)
   return res;
 }
 
+std::string cmQtAutoGenInitializer::GetMocBuildPath(MUFile const& muf)
+{
+  std::string res;
+  if (!muf.MocIt) {
+    return res;
+  }
+  {
+    std::string const basePath =
+      cmStrCat(this->PathCheckSum.getPart(muf.FullPath), "/moc_",
+               FileNameWithoutLastExtension(muf.FullPath));
+    std::string suffix;
+    constexpr std::size_t num_tries_max = 256;
+    for (std::size_t ii = 0; ii != num_tries_max; ++ii) {
+      res = cmStrCat(basePath, suffix, ".cpp");
+      if (this->Moc.EmittedBuildPaths.emplace(res).second) {
+        break;
+      }
+      // Compute new suffix
+      suffix = cmStrCat('_', ii + 1);
+    }
+  }
+  return res;
+}
+
 bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars,
                                              const std::string& executable,
                                              bool ignoreMissingTarget) const
diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h
index 2411936..0580ddb 100644
--- a/Source/cmQtAutoGenInitializer.h
+++ b/Source/cmQtAutoGenInitializer.h
@@ -4,17 +4,16 @@
 #define cmQtAutoGenInitializer_h
 
 #include "cmConfigure.h" // IWYU pragma: keep
-#include "cmGeneratedFileStream.h"
+#include "cmFilePathChecksum.h"
 #include "cmQtAutoGen.h"
 
 #include <cm/string_view>
 
-#include <map>
 #include <memory>
-#include <ostream>
 #include <set>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 #include <utility>
 #include <vector>
 
@@ -32,6 +31,23 @@ class cmTarget;
 class cmQtAutoGenInitializer : public cmQtAutoGen
 {
 public:
+  /** String value with per configuration variants.  */
+  class ConfigString
+  {
+  public:
+    std::string Default;
+    std::unordered_map<std::string, std::string> Config;
+  };
+
+  /** String values with per configuration variants.  */
+  template <typename C>
+  class ConfigStrings
+  {
+  public:
+    C Default;
+    std::unordered_map<std::string, C> Config;
+  };
+
   /** rcc job.  */
   class Qrc
   {
@@ -41,8 +57,7 @@ public:
     std::string QrcName;
     std::string QrcPathChecksum;
     std::string InfoFile;
-    std::string SettingsFile;
-    std::map<std::string, std::string> ConfigSettingsFile;
+    ConfigString SettingsFile;
     std::string OutputFile;
     bool Generated = false;
     bool Unique = false;
@@ -63,7 +78,7 @@ public:
   };
   using MUFileHandle = std::unique_ptr<MUFile>;
 
-  /** Abstract moc/uic/rcc generator variables base class  */
+  /** Abstract moc/uic/rcc generator variables base class.  */
   struct GenVarsT
   {
     bool Enabled = false;
@@ -81,39 +96,6 @@ public:
       , GenNameUpper(cmQtAutoGen::GeneratorNameUpper(gen)){};
   };
 
-  /** Writes a CMake info file.  */
-  class InfoWriter
-  {
-  public:
-    /** Open the given file.  */
-    InfoWriter(std::string const& filename);
-
-    /** @return True if the file is open.  */
-    explicit operator bool() const { return static_cast<bool>(Ofs_); }
-
-    void Write(cm::string_view text) { Ofs_ << text; }
-    void Write(cm::string_view, std::string const& value);
-    void WriteUInt(cm::string_view, unsigned int value);
-
-    template <class C>
-    void WriteStrings(cm::string_view, C const& container);
-    void WriteConfig(cm::string_view,
-                     std::map<std::string, std::string> const& map);
-    template <class C>
-    void WriteConfigStrings(cm::string_view,
-                            std::map<std::string, C> const& map);
-    void WriteNestedLists(cm::string_view,
-                          std::vector<std::vector<std::string>> const& lists);
-
-  private:
-    template <class IT>
-    static std::string ListJoin(IT it_begin, IT it_end);
-    static std::string ConfigKey(cm::string_view, std::string const& config);
-
-  private:
-    cmGeneratedFileStream Ofs_;
-  };
-
 public:
   /** @return The detected Qt version and the required Qt major version.  */
   static std::pair<IntegerVersion, unsigned int> GetQtVersion(
@@ -153,6 +135,12 @@ private:
                         cm::string_view genNameUpper);
   void AddCleanFile(std::string const& fileName);
 
+  void ConfigFileNames(ConfigString& configString, cm::string_view prefix,
+                       cm::string_view suffix);
+  void ConfigFileClean(ConfigString& configString);
+
+  std::string GetMocBuildPath(MUFile const& muf);
+
   bool GetQtExecutable(GenVarsT& genVars, const std::string& executable,
                        bool ignoreMissingTarget) const;
 
@@ -162,16 +150,17 @@ private:
   cmGlobalGenerator* GlobalGen = nullptr;
   cmLocalGenerator* LocalGen = nullptr;
   cmMakefile* Makefile = nullptr;
+  cmFilePathChecksum const PathCheckSum;
 
   // -- Configuration
   IntegerVersion QtVersion;
+  unsigned int Verbosity = 0;
   bool MultiConfig = false;
+  bool CMP0071Accept = false;
+  bool CMP0071Warn = false;
   std::string ConfigDefault;
   std::vector<std::string> ConfigsList;
-  std::string Verbosity;
   std::string TargetsFolder;
-  bool CMP0071Accept = false;
-  bool CMP0071Warn = false;
 
   /** Common directories.  */
   struct
@@ -179,8 +168,7 @@ private:
     std::string Info;
     std::string Build;
     std::string Work;
-    std::string Include;
-    std::map<std::string, std::string> ConfigInclude;
+    ConfigString Include;
     std::string IncludeGenExp;
   } Dir;
 
@@ -190,12 +178,11 @@ private:
     std::string Name;
     bool GlobalTarget = false;
     // Settings
-    std::string Parallel;
+    unsigned int Parallel = 1;
     // Configuration files
     std::string InfoFile;
-    std::string SettingsFile;
-    std::string ParseCacheFile;
-    std::map<std::string, std::string> ConfigSettingsFile;
+    ConfigString SettingsFile;
+    ConfigString ParseCacheFile;
     // Dependencies
     bool DependOrigin = false;
     std::set<std::string> DependFiles;
@@ -212,26 +199,37 @@ private:
     MocT()
       : GenVarsT(GenT::MOC){};
 
-    std::string PredefsCmd;
-    std::vector<std::string> Includes;
-    std::map<std::string, std::vector<std::string>> ConfigIncludes;
-    std::set<std::string> Defines;
-    std::map<std::string, std::set<std::string>> ConfigDefines;
-    std::string MocsCompilation;
+    bool RelaxedMode = false;
+    bool PathPrefix = false;
+    std::string CompilationFile;
+    // Compiler implicit pre defines
+    std::vector<std::string> PredefsCmd;
+    ConfigString PredefsFile;
+    // Defines
+    ConfigStrings<std::set<std::string>> Defines;
+    // Includes
+    ConfigStrings<std::vector<std::string>> Includes;
+    // Options
+    std::vector<std::string> Options;
+    // Filters
+    std::vector<std::string> MacroNames;
+    std::vector<std::pair<std::string, std::string>> DependFilters;
+    // Utility
+    std::unordered_set<std::string> EmittedBuildPaths;
   } Moc;
 
   /** uic variables.  */
   struct UicT : public GenVarsT
   {
+    using UiFileT = std::pair<std::string, std::vector<std::string>>;
+
     UicT()
       : GenVarsT(GenT::UIC){};
 
     std::set<std::string> SkipUi;
+    std::vector<UiFileT> UiFiles;
+    ConfigStrings<std::vector<std::string>> Options;
     std::vector<std::string> SearchPaths;
-    std::vector<std::string> Options;
-    std::map<std::string, std::vector<std::string>> ConfigOptions;
-    std::vector<std::string> FileFiles;
-    std::vector<std::vector<std::string>> FileOptions;
   } Uic;
 
   /** rcc variables.  */
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
index eb829fa..a9d4fee 100644
--- a/Source/cmQtAutoGenerator.cxx
+++ b/Source/cmQtAutoGenerator.cxx
@@ -2,19 +2,11 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmQtAutoGenerator.h"
 
-#include <cm/memory>
-
-#include "cmsys/FStream.hxx"
-
-#include "cmGlobalGenerator.h"
-#include "cmMakefile.h"
 #include "cmQtAutoGen.h"
-#include "cmState.h"
-#include "cmStateDirectory.h"
-#include "cmStateSnapshot.h"
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
-#include "cmake.h"
+#include "cm_jsoncpp_reader.h"
+#include "cmsys/FStream.hxx"
 
 cmQtAutoGenerator::Logger::Logger()
 {
@@ -44,13 +36,10 @@ cmQtAutoGenerator::Logger::Logger()
 
 cmQtAutoGenerator::Logger::~Logger() = default;
 
-void cmQtAutoGenerator::Logger::RaiseVerbosity(std::string const& value)
+void cmQtAutoGenerator::Logger::RaiseVerbosity(unsigned int value)
 {
-  unsigned long verbosity = 0;
-  if (cmStrToULong(value, &verbosity)) {
-    if (this->Verbosity_ < verbosity) {
-      this->Verbosity_ = static_cast<unsigned int>(verbosity);
-    }
+  if (this->Verbosity_ < value) {
+    this->Verbosity_ = value;
   }
 }
 
@@ -214,7 +203,10 @@ bool cmQtAutoGenerator::FileDiffers(std::string const& filename,
   return differs;
 }
 
-cmQtAutoGenerator::cmQtAutoGenerator() = default;
+cmQtAutoGenerator::cmQtAutoGenerator(GenT genType)
+  : GenType_(genType)
+{
+}
 
 cmQtAutoGenerator::~cmQtAutoGenerator() = default;
 
@@ -223,7 +215,7 @@ bool cmQtAutoGenerator::Run(std::string const& infoFile,
 {
   // Info settings
   InfoFile_ = infoFile;
-  cmSystemTools::ConvertToUnixSlashes(InfoFile_);
+  cmSystemTools::CollapseFullPath(InfoFile_);
   if (!InfoFileTime_.Load(InfoFile_)) {
     cmSystemTools::Stderr(cmStrCat("AutoGen: The info file ",
                                    Quoted(InfoFile_), " is not readable\n"));
@@ -232,29 +224,221 @@ bool cmQtAutoGenerator::Run(std::string const& infoFile,
   InfoDir_ = cmSystemTools::GetFilenamePath(infoFile);
   InfoConfig_ = config;
 
-  bool success = false;
+  // Read info file
   {
-    cmake cm(cmake::RoleScript, cmState::Unknown);
-    cm.SetHomeOutputDirectory(InfoDir());
-    cm.SetHomeDirectory(InfoDir());
-    cm.GetCurrentSnapshot().SetDefaultDefinitions();
-    cmGlobalGenerator gg(&cm);
-
-    cmStateSnapshot snapshot = cm.GetCurrentSnapshot();
-    snapshot.GetDirectory().SetCurrentBinary(InfoDir());
-    snapshot.GetDirectory().SetCurrentSource(InfoDir());
-
-    auto makefile = cm::make_unique<cmMakefile>(&gg, snapshot);
-    // The OLD/WARN behavior for policy CMP0053 caused a speed regression.
-    // https://gitlab.kitware.com/cmake/cmake/issues/17570
-    makefile->SetPolicyVersion("3.9", std::string());
-    gg.SetCurrentMakefile(makefile.get());
-    success = this->Init(makefile.get());
+    cmsys::ifstream ifs(InfoFile_.c_str(), (std::ios::in | std::ios::binary));
+    if (!ifs) {
+      Log().Error(GenType_,
+                  cmStrCat("Could not to open info file ", Quoted(InfoFile_)));
+      return false;
+    }
+    try {
+      ifs >> Info_;
+    } catch (...) {
+      Log().Error(GenType_,
+                  cmStrCat("Could not read info file ", Quoted(InfoFile_)));
+      return false;
+    }
   }
-  if (success) {
-    success = this->Process();
+  // Info: setup logger
+  {
+    unsigned int value = 0;
+    if (!InfoUInt("VERBOSITY", value, false)) {
+      return false;
+    }
+    Logger_.RaiseVerbosity(value);
   }
-  return success;
+  // Info: setup project directories
+  if (!InfoString("CMAKE_SOURCE_DIR", ProjectDirs_.Source, true) ||
+      !InfoString("CMAKE_BINARY_DIR", ProjectDirs_.Binary, true) ||
+      !InfoString("CMAKE_CURRENT_SOURCE_DIR", ProjectDirs_.CurrentSource,
+                  true) ||
+      !InfoString("CMAKE_CURRENT_BINARY_DIR", ProjectDirs_.CurrentBinary,
+                  true)) {
+    return false;
+  }
+
+  if (!this->InitFromInfo()) {
+    return false;
+  }
+  // Clear info
+  Info_ = Json::nullValue;
+
+  return this->Process();
+}
+
+bool cmQtAutoGenerator::LogInfoError(GenT genType,
+                                     cm::string_view message) const
+{
+  this->Log().Error(
+    genType,
+    cmStrCat("Info error in info file\n", Quoted(InfoFile()), ":\n", message));
+  return false;
+}
+
+bool cmQtAutoGenerator::LogInfoError(cm::string_view message) const
+{
+  return LogInfoError(GenType_, message);
+}
+
+bool cmQtAutoGenerator::JsonGetArray(std::vector<std::string>& list,
+                                     Json::Value const& jval)
+{
+  Json::ArrayIndex const arraySize = jval.size();
+  if (arraySize == 0) {
+    return false;
+  }
+
+  bool picked = false;
+  list.reserve(list.size() + arraySize);
+  for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
+    Json::Value const& ival = jval[ii];
+    if (ival.isString()) {
+      list.emplace_back(ival.asString());
+      picked = true;
+    }
+  }
+  return picked;
+}
+
+bool cmQtAutoGenerator::JsonGetArray(std::unordered_set<std::string>& list,
+                                     Json::Value const& jval)
+{
+  Json::ArrayIndex const arraySize = jval.size();
+  if (arraySize == 0) {
+    return false;
+  }
+
+  bool picked = false;
+  list.reserve(list.size() + arraySize);
+  for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
+    Json::Value const& ival = jval[ii];
+    if (ival.isString()) {
+      list.emplace(ival.asString());
+      picked = true;
+    }
+  }
+  return picked;
+}
+
+std::string cmQtAutoGenerator::InfoConfigKey(std::string const& key) const
+{
+  return cmStrCat(key, '_', InfoConfig());
+}
+
+bool cmQtAutoGenerator::InfoString(std::string const& key, std::string& value,
+                                   bool required) const
+{
+  Json::Value const& jval = Info()[key];
+  if (!jval.isString()) {
+    if (!jval.isNull() || required) {
+      return LogInfoError(cmStrCat(key, " is not a string."));
+    }
+  } else {
+    value = jval.asString();
+    if (value.empty() && required) {
+      return LogInfoError(cmStrCat(key, " is empty."));
+    }
+  }
+  return true;
+}
+
+bool cmQtAutoGenerator::InfoStringConfig(std::string const& key,
+                                         std::string& value,
+
+                                         bool required) const
+{
+  { // Try config
+    std::string const configKey = InfoConfigKey(key);
+    Json::Value const& jval = Info_[configKey];
+    if (!jval.isNull()) {
+      if (!jval.isString()) {
+        return LogInfoError(cmStrCat(configKey, " is not a string."));
+      }
+      value = jval.asString();
+      if (required && value.empty()) {
+        return LogInfoError(cmStrCat(configKey, " is empty."));
+      }
+      return true;
+    }
+  }
+  // Try plain
+  return InfoString(key, value, required);
+}
+
+bool cmQtAutoGenerator::InfoBool(std::string const& key, bool& value,
+                                 bool required) const
+{
+  Json::Value const& jval = Info()[key];
+  if (jval.isBool()) {
+    value = jval.asBool();
+  } else {
+    if (!jval.isNull() || required) {
+      return LogInfoError(cmStrCat(key, " is not a boolean."));
+    }
+  }
+  return true;
+}
+
+bool cmQtAutoGenerator::InfoUInt(std::string const& key, unsigned int& value,
+                                 bool required) const
+{
+  Json::Value const& jval = Info()[key];
+  if (jval.isUInt()) {
+    value = jval.asUInt();
+  } else {
+    if (!jval.isNull() || required) {
+      return LogInfoError(cmStrCat(key, " is not an unsigned integer."));
+    }
+  }
+  return true;
+}
+
+bool cmQtAutoGenerator::InfoArray(std::string const& key,
+                                  std::vector<std::string>& list,
+                                  bool required) const
+{
+  Json::Value const& jval = Info()[key];
+  if (!jval.isArray()) {
+    if (!jval.isNull() || required) {
+      return LogInfoError(cmStrCat(key, " is not an array."));
+    }
+  }
+  return JsonGetArray(list, jval) || !required;
+}
+
+bool cmQtAutoGenerator::InfoArray(std::string const& key,
+                                  std::unordered_set<std::string>& list,
+                                  bool required) const
+{
+  Json::Value const& jval = Info()[key];
+  if (!jval.isArray()) {
+    if (!jval.isNull() || required) {
+      return LogInfoError(cmStrCat(key, " is not an array."));
+    }
+  }
+  return JsonGetArray(list, jval) || !required;
+}
+
+bool cmQtAutoGenerator::InfoArrayConfig(std::string const& key,
+                                        std::vector<std::string>& list,
+                                        bool required) const
+{
+  { // Try config
+    std::string const configKey = InfoConfigKey(key);
+    Json::Value const& jval = Info()[configKey];
+    if (!jval.isNull()) {
+      if (!jval.isArray()) {
+        return LogInfoError(cmStrCat(configKey, " is not an array string."));
+      }
+      if (!JsonGetArray(list, jval) && required) {
+        return LogInfoError(cmStrCat(configKey, " is empty."));
+      }
+      return true;
+    }
+  }
+  // Try plain
+  return InfoArray(key, list, required);
 }
 
 std::string cmQtAutoGenerator::SettingsFind(std::string const& content,
diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h
index f60acb0..7f83fc6 100644
--- a/Source/cmQtAutoGenerator.h
+++ b/Source/cmQtAutoGenerator.h
@@ -7,15 +7,15 @@
 
 #include "cmFileTime.h"
 #include "cmQtAutoGen.h"
+#include "cm_jsoncpp_value.h"
 
 #include <cm/string_view>
 
 #include <mutex>
 #include <string>
+#include <unordered_set>
 #include <vector>
 
-class cmMakefile;
-
 /** \class cmQtAutoGenerator
  * \brief Base class for QtAutoGen generators
  */
@@ -34,7 +34,7 @@ public:
     // -- Verbosity
     unsigned int Verbosity() const { return this->Verbosity_; }
     void SetVerbosity(unsigned int value) { this->Verbosity_ = value; }
-    void RaiseVerbosity(std::string const& value);
+    void RaiseVerbosity(unsigned int value);
     bool Verbose() const { return (this->Verbosity_ != 0); }
     void SetVerbose(bool value) { this->Verbosity_ = value ? 1 : 0; }
     // -- Color output
@@ -80,7 +80,7 @@ public:
 
 public:
   // -- Constructors
-  cmQtAutoGenerator();
+  cmQtAutoGenerator(GenT genType);
   virtual ~cmQtAutoGenerator();
 
   cmQtAutoGenerator(cmQtAutoGenerator const&) = delete;
@@ -91,10 +91,39 @@ public:
 
   // -- InfoFile
   std::string const& InfoFile() const { return InfoFile_; }
+  Json::Value const& Info() const { return Info_; }
   cmFileTime const& InfoFileTime() const { return InfoFileTime_; }
   std::string const& InfoDir() const { return InfoDir_; }
   std::string const& InfoConfig() const { return InfoConfig_; }
 
+  bool LogInfoError(GenT genType, cm::string_view message) const;
+  bool LogInfoError(cm::string_view message) const;
+
+  /** Returns true if strings were appended to the list.  */
+  static bool JsonGetArray(std::vector<std::string>& list,
+                           Json::Value const& jval);
+  /** Returns true if strings were found in the JSON array.  */
+  static bool JsonGetArray(std::unordered_set<std::string>& list,
+                           Json::Value const& jval);
+
+  std::string InfoConfigKey(std::string const& key) const;
+
+  /** Returns false if the JSON value isn't a string.  */
+  bool InfoString(std::string const& key, std::string& value,
+                  bool required) const;
+  bool InfoStringConfig(std::string const& key, std::string& value,
+                        bool required) const;
+  bool InfoBool(std::string const& key, bool& value, bool required) const;
+  bool InfoUInt(std::string const& key, unsigned int& value,
+                bool required) const;
+  /** Returns false if the JSON value isn't an array.  */
+  bool InfoArray(std::string const& key, std::vector<std::string>& list,
+                 bool required) const;
+  bool InfoArray(std::string const& key, std::unordered_set<std::string>& list,
+                 bool required) const;
+  bool InfoArrayConfig(std::string const& key, std::vector<std::string>& list,
+                       bool required) const;
+
   // -- Directories
   ProjectDirsT const& ProjectDirs() const { return ProjectDirs_; }
 
@@ -104,16 +133,22 @@ public:
 
 protected:
   // -- Abstract processing interface
-  virtual bool Init(cmMakefile* makefile) = 0;
+  virtual bool InitFromInfo() = 0;
   virtual bool Process() = 0;
-  ProjectDirsT& ProjectDirsRef() { return ProjectDirs_; }
+  // - Utility classes
+  Logger const& Log() const { return Logger_; }
 
 private:
-  // -- Info settings
+  // -- Generator type
+  GenT GenType_;
+  // -- Logging
+  Logger Logger_;
+  // -- Info file
   std::string InfoFile_;
   cmFileTime InfoFileTime_;
   std::string InfoDir_;
   std::string InfoConfig_;
+  Json::Value Info_;
   // -- Directories
   ProjectDirsT ProjectDirs_;
 };
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index 5cd1ba1..5f3cd5f 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -11,19 +11,22 @@
 #include "cmAlgorithms.h"
 #include "cmCryptoHash.h"
 #include "cmGeneratedFileStream.h"
-#include "cmMakefile.h"
 #include "cmQtAutoGen.h"
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
-#include "cmake.h"
+#include "cm_jsoncpp_value.h"
 #include "cmsys/FStream.hxx"
 
 #if defined(__APPLE__)
 #  include <unistd.h>
 #endif
 
-static constexpr std::size_t MocUnderscoreLength = 4; // Length of "moc_"
-static constexpr std::size_t UiUnderscoreLength = 3;  // Length of "ui_"
+namespace {
+
+constexpr std::size_t MocUnderscoreLength = 4; // Length of "moc_"
+constexpr std::size_t UiUnderscoreLength = 3;  // Length of "ui_"
+
+} // End of unnamed namespace
 
 cmQtAutoMocUic::IncludeKeyT::IncludeKeyT(std::string const& key,
                                          std::size_t basePrefixLength)
@@ -1464,10 +1467,10 @@ void cmQtAutoMocUic::JobCompileUicT::Process()
   std::vector<std::string> cmd;
   cmd.push_back(UicConst().Executable);
   {
-    std::vector<std::string> allOpts = UicConst().TargetOptions;
-    auto optionIt = UicConst().Options.find(sourceFile);
-    if (optionIt != UicConst().Options.end()) {
-      UicMergeOptions(allOpts, optionIt->second,
+    std::vector<std::string> allOpts = UicConst().Options;
+    auto optionIt = UicConst().UiFiles.find(sourceFile);
+    if (optionIt != UicConst().UiFiles.end()) {
+      UicMergeOptions(allOpts, optionIt->second.Options,
                       (BaseConst().QtVersionMajor == 5));
     }
     cmAppend(cmd, allOpts);
@@ -1548,338 +1551,310 @@ void cmQtAutoMocUic::JobFinishT::Process()
   Gen()->AbortSuccess();
 }
 
-cmQtAutoMocUic::cmQtAutoMocUic() = default;
+cmQtAutoMocUic::cmQtAutoMocUic()
+  : cmQtAutoGenerator(GenT::GEN)
+{
+}
 cmQtAutoMocUic::~cmQtAutoMocUic() = default;
 
-bool cmQtAutoMocUic::Init(cmMakefile* makefile)
+bool cmQtAutoMocUic::InitFromInfo()
 {
-  // Utility lambdas
-  auto InfoGet = [makefile](cm::string_view key) {
-    return makefile->GetSafeDefinition(std::string(key));
-  };
-  auto InfoGetBool = [makefile](cm::string_view key) {
-    return makefile->IsOn(std::string(key));
-  };
-  auto InfoGetList =
-    [makefile](cm::string_view key) -> std::vector<std::string> {
-    return cmExpandedList(makefile->GetSafeDefinition(std::string(key)));
-  };
-  auto InfoGetLists =
-    [makefile](cm::string_view key) -> std::vector<std::vector<std::string>> {
-    std::vector<std::vector<std::string>> lists;
-    {
-      std::string const value = makefile->GetSafeDefinition(std::string(key));
-      std::string::size_type pos = 0;
-      while (pos < value.size()) {
-        std::string::size_type next = value.find(ListSep, pos);
-        std::string::size_type length =
-          (next != std::string::npos) ? next - pos : value.size() - pos;
-        // Remove enclosing braces
-        if (length >= 2) {
-          std::string::const_iterator itBeg = value.begin() + (pos + 1);
-          std::string::const_iterator itEnd = itBeg + (length - 2);
-          lists.emplace_back(cmExpandedList(std::string(itBeg, itEnd)));
-        }
-        pos += length;
-        pos += ListSep.size();
-      }
-    }
-    return lists;
-  };
-  auto InfoGetConfig = [makefile, this](cm::string_view key) -> std::string {
-    if (const char* valueConf =
-          makefile->GetDefinition(cmStrCat(key, '_', InfoConfig()))) {
-      return std::string(valueConf);
-    }
-    return makefile->GetSafeDefinition(std::string(key));
-  };
-  auto InfoGetConfigList =
-    [&InfoGetConfig](cm::string_view key) -> std::vector<std::string> {
-    return cmExpandedList(InfoGetConfig(key));
-  };
-  auto LogInfoError = [this](cm::string_view msg) -> bool {
-    this->Log().Error(GenT::GEN,
-                      cmStrCat("In ", Quoted(this->InfoFile()), ":\n", msg));
+  // -- Required settings
+  if (!InfoBool("MULTI_CONFIG", BaseConst_.MultiConfig, true) ||
+      !InfoUInt("QT_VERSION_MAJOR", BaseConst_.QtVersionMajor, true) ||
+      !InfoUInt("PARALLEL", BaseConst_.ThreadCount, false) ||
+      !InfoString("BUILD_DIR", BaseConst_.AutogenBuildDir, true) ||
+      !InfoStringConfig("INCLUDE_DIR", BaseConst_.AutogenIncludeDir, true) ||
+      !InfoString("CMAKE_EXECUTABLE", BaseConst_.CMakeExecutable, true) ||
+      !InfoStringConfig("PARSE_CACHE_FILE", BaseConst_.ParseCacheFile, true) ||
+      !InfoStringConfig("SETTINGS_FILE", SettingsFile_, true) ||
+      !InfoArray("HEADER_EXTENSIONS", BaseConst_.HeaderExtensions, true) ||
+      !InfoString("QT_MOC_EXECUTABLE", MocConst_.Executable, false) ||
+      !InfoString("QT_UIC_EXECUTABLE", UicConst_.Executable, false)) {
     return false;
-  };
-  auto MatchSizes = [&LogInfoError](cm::string_view keyA, cm::string_view keyB,
-                                    std::size_t sizeA,
-                                    std::size_t sizeB) -> bool {
-    if (sizeA == sizeB) {
-      return true;
-    }
-    return LogInfoError(cmStrCat("Lists sizes mismatch ", keyA, '(', sizeA,
-                                 ") ", keyB, '(', sizeB, ')'));
-  };
-
-  // -- Read info file
-  if (!makefile->ReadListFile(InfoFile())) {
-    return LogInfoError("File processing failed");
-  }
-
-  // -- Meta
-  Logger_.RaiseVerbosity(InfoGet("AM_VERBOSITY"));
-  BaseConst_.MultiConfig = InfoGetBool("AM_MULTI_CONFIG");
-  {
-    unsigned long num = 1;
-    if (cmStrToULong(InfoGet("AM_PARALLEL"), &num)) {
-      num = std::max<unsigned long>(num, 1);
-      num = std::min<unsigned long>(num, ParallelMax);
-    }
-    WorkerPool_.SetThreadCount(static_cast<unsigned int>(num));
   }
-  BaseConst_.HeaderExtensions =
-    makefile->GetCMakeInstance()->GetHeaderExtensions();
 
-  // - Files and directories
-  ProjectDirsRef().Source = InfoGet("AM_CMAKE_SOURCE_DIR");
-  ProjectDirsRef().Binary = InfoGet("AM_CMAKE_BINARY_DIR");
-  ProjectDirsRef().CurrentSource = InfoGet("AM_CMAKE_CURRENT_SOURCE_DIR");
-  ProjectDirsRef().CurrentBinary = InfoGet("AM_CMAKE_CURRENT_BINARY_DIR");
-  BaseConst_.AutogenBuildDir = InfoGet("AM_BUILD_DIR");
-  if (BaseConst_.AutogenBuildDir.empty()) {
-    return LogInfoError("Autogen build directory missing.");
-  }
-  BaseConst_.AutogenIncludeDir = InfoGetConfig("AM_INCLUDE_DIR");
-  if (BaseConst_.AutogenIncludeDir.empty()) {
-    return LogInfoError("Autogen include directory missing.");
-  }
-  BaseConst_.CMakeExecutable = InfoGetConfig("AM_CMAKE_EXECUTABLE");
-  if (BaseConst_.CMakeExecutable.empty()) {
-    return LogInfoError("CMake executable file name missing.");
-  }
+  // -- Checks
   if (!BaseConst_.CMakeExecutableTime.Load(BaseConst_.CMakeExecutable)) {
     return LogInfoError(cmStrCat("The CMake executable ",
                                  MessagePath(BaseConst_.CMakeExecutable),
                                  " does not exist."));
   }
-  BaseConst_.ParseCacheFile = InfoGetConfig("AM_PARSE_CACHE_FILE");
-  if (BaseConst_.ParseCacheFile.empty()) {
-    return LogInfoError("Parse cache file name missing.");
-  }
 
-  // - Settings file
-  SettingsFile_ = InfoGetConfig("AM_SETTINGS_FILE");
-  if (SettingsFile_.empty()) {
-    return LogInfoError("Settings file name missing.");
-  }
+  // -- Evaluate values
+  BaseConst_.ThreadCount = std::min(BaseConst_.ThreadCount, ParallelMax);
+  WorkerPool_.SetThreadCount(BaseConst_.ThreadCount);
 
-  // - Qt environment
-  {
-    unsigned long qtv = BaseConst_.QtVersionMajor;
-    if (cmStrToULong(InfoGet("AM_QT_VERSION_MAJOR"), &qtv)) {
-      BaseConst_.QtVersionMajor = static_cast<unsigned int>(qtv);
-    }
-  }
-
-  // - Moc
-  MocConst_.Executable = InfoGet("AM_QT_MOC_EXECUTABLE");
-  if (!MocConst().Executable.empty()) {
+  // -- Moc
+  if (!MocConst_.Executable.empty()) {
+    // -- Moc is enabled
     MocConst_.Enabled = true;
-    // Load the executable file time
-    if (!MocConst_.ExecutableTime.Load(MocConst_.Executable)) {
-      return LogInfoError(cmStrCat("The moc executable ",
-                                   MessagePath(MocConst_.Executable),
-                                   " does not exist."));
-    }
-    for (std::string& sfl : InfoGetList("AM_MOC_SKIP")) {
-      MocConst_.SkipList.insert(std::move(sfl));
-    }
-    MocConst_.Definitions = InfoGetConfigList("AM_MOC_DEFINITIONS");
-    MocConst_.IncludePaths = InfoGetConfigList("AM_MOC_INCLUDES");
-    MocConst_.OptionsExtra = InfoGetList("AM_MOC_OPTIONS");
 
-    MocConst_.RelaxedMode = InfoGetBool("AM_MOC_RELAXED_MODE");
-    MocConst_.PathPrefix = InfoGetBool("AM_MOC_PATH_PREFIX");
+    // -- Temporary buffers
+    struct
+    {
+      std::vector<std::string> MacroNames;
+      std::vector<std::string> DependFilters;
+    } tmp;
+
+    // -- Required settings
+    if (!InfoBool("MOC_RELAXED_MODE", MocConst_.RelaxedMode, false) ||
+        !InfoBool("MOC_PATH_PREFIX", MocConst_.PathPrefix, true) ||
+        !InfoArray("MOC_SKIP", MocConst_.SkipList, false) ||
+        !InfoArrayConfig("MOC_DEFINITIONS", MocConst_.Definitions, false) ||
+        !InfoArrayConfig("MOC_INCLUDES", MocConst_.IncludePaths, false) ||
+        !InfoArray("MOC_OPTIONS", MocConst_.OptionsExtra, false) ||
+        !InfoStringConfig("MOC_COMPILATION_FILE", MocConst_.CompFileAbs,
+                          true) ||
+        !InfoArray("MOC_PREDEFS_CMD", MocConst_.PredefsCmd, false) ||
+        !InfoStringConfig("MOC_PREDEFS_FILE", MocConst_.PredefsFileAbs,
+                          !MocConst_.PredefsCmd.empty()) ||
+        !InfoArray("MOC_MACRO_NAMES", tmp.MacroNames, true) ||
+        !InfoArray("MOC_DEPEND_FILTERS", tmp.DependFilters, false)) {
+      return false;
+    }
 
-    for (std::string const& item : InfoGetList("AM_MOC_MACRO_NAMES")) {
+    // -- Evaluate settings
+    for (std::string const& item : tmp.MacroNames) {
       MocConst_.MacroFilters.emplace_back(
         item, ("[\n][ \t]*{?[ \t]*" + item).append("[^a-zA-Z0-9_]"));
     }
+    // Dependency filters
     {
-      auto addFilter = [this, &LogInfoError](std::string const& key,
-                                             std::string const& exp) -> bool {
-        auto filterErr = [&LogInfoError, &key,
-                          &exp](cm::string_view err) -> bool {
-          return LogInfoError(cmStrCat("AUTOMOC_DEPEND_FILTERS: ", err, '\n',
-                                       "  Key: ", Quoted(key), '\n',
-                                       "  Exp: ", Quoted(exp), '\n'));
+      Json::Value const& val = Info()["MOC_DEPEND_FILTERS"];
+      if (!val.isArray()) {
+        return LogInfoError("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 = [this, ii](bool test,
+                                    cm::string_view message) -> bool {
+          if (!test) {
+            this->LogInfoError(
+              cmStrCat("MOC_DEPEND_FILTERS filter ", ii, ": ", message));
+          }
+          return !test;
         };
-        if (key.empty()) {
-          return filterErr("Key is empty");
+
+        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;
         }
-        if (exp.empty()) {
-          return filterErr("Regular expression is empty");
+
+        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;
         }
-        this->MocConst_.DependFilters.emplace_back(key, exp);
-        if (!this->MocConst_.DependFilters.back().Exp.is_valid()) {
-          return filterErr("Regular expression compiling failed");
+
+        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;
         }
-        return true;
-      };
 
-      // Insert default filter for Q_PLUGIN_METADATA
-      if (BaseConst().QtVersionMajor != 4) {
-        if (!addFilter("Q_PLUGIN_METADATA",
-                       "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\("
-                       "[^\\)]*FILE[ \t]*\"([^\"]+)\"")) {
+        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;
         }
       }
-      // Insert user defined dependency filters
-      std::vector<std::string> flts = InfoGetList("AM_MOC_DEPEND_FILTERS");
-      if ((flts.size() % 2) != 0) {
-        return LogInfoError(
-          "AUTOMOC_DEPEND_FILTERS list size is not a multiple of 2");
+    }
+    // Check if moc executable exists (by reading the file time)
+    if (!MocConst_.ExecutableTime.Load(MocConst_.Executable)) {
+      return LogInfoError(cmStrCat("The moc executable ",
+                                   MessagePath(MocConst_.Executable),
+                                   " does not exist."));
+    }
+  }
+
+  // -- Uic
+  if (!UicConst_.Executable.empty()) {
+    // Uic is enabled
+    UicConst_.Enabled = true;
+
+    // -- Required settings
+    if (!InfoArray("UIC_SKIP", UicConst_.SkipList, false) ||
+        !InfoArray("UIC_SEARCH_PATHS", UicConst_.SearchPaths, false) ||
+        !InfoArrayConfig("UIC_OPTIONS", UicConst_.Options, false)) {
+      return false;
+    }
+    // .ui files
+    {
+      Json::Value const& val = Info()["UIC_UI_FILES"];
+      if (!val.isArray()) {
+        return LogInfoError("UIC_UI_FILES JSON value is not an array.");
       }
-      for (auto itC = flts.begin(), itE = flts.end(); itC != itE; itC += 2) {
-        if (!addFilter(*itC, *(itC + 1))) {
+      Json::ArrayIndex const arraySize = val.size();
+      for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
+        // Test entry closure
+        auto testEntry = [this, ii](bool test,
+                                    cm::string_view message) -> bool {
+          if (!test) {
+            this->LogInfoError(
+              cmStrCat("UIC_UI_FILES entry ", ii, ": ", message));
+          }
+          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()];
+        JsonGetArray(uiFile.Options, entryOptions);
       }
     }
-    MocConst_.PredefsCmd = InfoGetList("AM_MOC_PREDEFS_CMD");
-  }
 
-  // - Uic
-  UicConst_.Executable = InfoGet("AM_QT_UIC_EXECUTABLE");
-  if (!UicConst().Executable.empty()) {
-    UicConst_.Enabled = true;
-    // Load the executable file time
+    // -- Evaluate settings
+    // Check if uic executable exists (by reading the file time)
     if (!UicConst_.ExecutableTime.Load(UicConst_.Executable)) {
       return LogInfoError(cmStrCat("The uic executable ",
                                    MessagePath(UicConst_.Executable),
                                    " does not exist."));
     }
-    for (std::string& sfl : InfoGetList("AM_UIC_SKIP")) {
-      UicConst_.SkipList.insert(std::move(sfl));
-    }
-    UicConst_.SearchPaths = InfoGetList("AM_UIC_SEARCH_PATHS");
-    UicConst_.TargetOptions = InfoGetConfigList("AM_UIC_TARGET_OPTIONS");
-    {
-      cm::string_view const keyFiles = "AM_UIC_OPTIONS_FILES";
-      cm::string_view const keyOpts = "AM_UIC_OPTIONS_OPTIONS";
-      auto sources = InfoGetList(keyFiles);
-      auto options = InfoGetLists(keyOpts);
-      if (!MatchSizes(keyFiles, keyOpts, sources.size(), options.size())) {
-        return false;
-      }
-      auto fitEnd = sources.cend();
-      auto fit = sources.begin();
-      auto oit = options.begin();
-      while (fit != fitEnd) {
-        UicConst_.Options[*fit] = std::move(*oit);
-        ++fit;
-        ++oit;
-      }
-    }
   }
 
-  // Headers
+  // -- Headers
   {
-    // Get file lists
-    cm::string_view const keyFiles = "AM_HEADERS";
-    cm::string_view const keyFlags = "AM_HEADERS_FLAGS";
-    std::vector<std::string> files = InfoGetList(keyFiles);
-    std::vector<std::string> flags = InfoGetList(keyFlags);
-    std::vector<std::string> builds;
-    if (!MatchSizes(keyFiles, keyFlags, files.size(), flags.size())) {
-      return false;
-    }
-    if (MocConst().Enabled) {
-      cm::string_view const keyPaths = "AM_HEADERS_BUILD_PATHS";
-      builds = InfoGetList(keyPaths);
-      if (!MatchSizes(keyFiles, keyPaths, files.size(), builds.size())) {
+    Json::Value const& val = Info()["HEADERS"];
+    if (!val.isArray()) {
+      return LogInfoError("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 = [this, ii](bool test, cm::string_view message) -> bool {
+        if (!test) {
+          this->LogInfoError(cmStrCat("HEADERS entry ", ii, ": ", message));
+        }
+        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;
       }
-    }
 
-    // Process file lists
-    for (std::size_t ii = 0; ii != files.size(); ++ii) {
-      std::string& fileName(files[ii]);
-      std::string const& fileFlags(flags[ii]);
-      if (fileFlags.size() != 2) {
-        LogInfoError(cmStrCat("Invalid flags string size ", fileFlags.size(),
-                              "in ", keyFlags));
+      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(fileName)) {
-        LogInfoError(cmStrCat("The header file ", this->MessagePath(fileName),
+      if (!fileTime.Load(name)) {
+        LogInfoError(cmStrCat("The header file ", this->MessagePath(name),
                               " does not exist."));
         return false;
       }
 
-      SourceFileHandleT sourceHandle = std::make_shared<SourceFileT>(fileName);
+      SourceFileHandleT sourceHandle = std::make_shared<SourceFileT>(name);
       sourceHandle->FileTime = fileTime;
       sourceHandle->IsHeader = true;
-      sourceHandle->Moc = (fileFlags[0] == 'M');
-      sourceHandle->Uic = (fileFlags[1] == 'U');
-
+      sourceHandle->Moc = (flags[0] == 'M');
+      sourceHandle->Uic = (flags[1] == 'U');
       if (sourceHandle->Moc && MocConst().Enabled) {
-        sourceHandle->BuildPath = std::move(builds[ii]);
-        if (sourceHandle->BuildPath.empty()) {
-          return LogInfoError("Header file build path is empty");
+        if (build.empty()) {
+          return LogInfoError(
+            cmStrCat("Header file ", ii, " build path is empty"));
         }
+        sourceHandle->BuildPath = std::move(build);
       }
-      BaseEval().Headers.emplace(std::move(fileName), std::move(sourceHandle));
+      BaseEval().Headers.emplace(std::move(name), std::move(sourceHandle));
     }
   }
 
-  // Sources
+  // -- Sources
   {
-    cm::string_view const keyFiles = "AM_SOURCES";
-    cm::string_view const keyFlags = "AM_SOURCES_FLAGS";
-    std::vector<std::string> files = InfoGetList(keyFiles);
-    std::vector<std::string> flags = InfoGetList(keyFlags);
-    if (!MatchSizes(keyFiles, keyFlags, files.size(), flags.size())) {
-      return false;
-    }
+    Json::Value const& val = Info()["SOURCES"];
+    if (!val.isArray()) {
+      return LogInfoError("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 = [this, ii](bool test, cm::string_view message) -> bool {
+        if (!test) {
+          this->LogInfoError(cmStrCat("SOURCES entry ", ii, ": ", message));
+        }
+        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;
+      }
 
-    // Process file lists
-    for (std::size_t ii = 0; ii != files.size(); ++ii) {
-      std::string& fileName(files[ii]);
-      std::string const& fileFlags(flags[ii]);
-      if (fileFlags.size() != 2) {
-        LogInfoError(cmStrCat("Invalid flags string size ", fileFlags.size(),
-                              "in ", keyFlags));
+      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(fileName)) {
-        LogInfoError(cmStrCat("The source file ", this->MessagePath(fileName),
+      if (!fileTime.Load(name)) {
+        LogInfoError(cmStrCat("The source file ", this->MessagePath(name),
                               " does not exist."));
         return false;
       }
 
-      SourceFileHandleT sourceHandle = std::make_shared<SourceFileT>(fileName);
+      SourceFileHandleT sourceHandle = std::make_shared<SourceFileT>(name);
       sourceHandle->FileTime = fileTime;
       sourceHandle->IsHeader = false;
-      sourceHandle->Moc = (fileFlags[0] == 'M');
-      sourceHandle->Uic = (fileFlags[1] == 'U');
-      BaseEval().Sources.emplace(std::move(fileName), std::move(sourceHandle));
+      sourceHandle->Moc = (flags[0] == 'M');
+      sourceHandle->Uic = (flags[1] == 'U');
+      BaseEval().Sources.emplace(std::move(name), std::move(sourceHandle));
     }
   }
 
-  // Init derived information
-  // ------------------------
-
+  // -- Init derived information
   // Moc variables
   if (MocConst().Enabled) {
-    // Mocs compilation file
-    MocConst_.CompFileAbs = AbsoluteBuildPath("mocs_compilation.cpp");
-
-    // Moc predefs file
-    if (!MocConst_.PredefsCmd.empty()) {
-      std::string pathRel;
-      if (BaseConst_.MultiConfig) {
-        pathRel = cmStrCat("moc_predefs_", InfoConfig(), ".h");
-      } else {
-        pathRel = "moc_predefs.h";
-      }
-      MocConst_.PredefsFileAbs = AbsoluteBuildPath(pathRel);
-    }
-
     // Compose moc includes list
     {
       // Compute framework paths
@@ -2031,11 +2006,11 @@ void cmQtAutoMocUic::SettingsFileRead()
     if (UicConst().Enabled) {
       cryptoHash.Initialize();
       cha(UicConst().Executable);
-      std::for_each(UicConst().TargetOptions.begin(),
-                    UicConst().TargetOptions.end(), cha);
-      for (const auto& item : UicConst().Options) {
+      std::for_each(UicConst().Options.begin(), UicConst().Options.end(), cha);
+      for (const auto& item : UicConst().UiFiles) {
         cha(item.first);
-        std::for_each(item.second.begin(), item.second.end(), cha);
+        auto const& opts = item.second.Options;
+        std::for_each(opts.begin(), opts.end(), cha);
       }
       SettingsStringUic_ = cryptoHash.FinalizeHex();
     }
@@ -2080,7 +2055,7 @@ bool cmQtAutoMocUic::SettingsFileWrite()
     if (Log().Verbose()) {
       Log().Info(
         GenT::GEN,
-        cmStrCat("Writing settings file ", MessagePath(SettingsFile_)));
+        cmStrCat("Writing the settings file ", MessagePath(SettingsFile_)));
     }
     // Compose settings file content
     std::string content;
diff --git a/Source/cmQtAutoMocUic.h b/Source/cmQtAutoMocUic.h
index f37d923..7101b8f 100644
--- a/Source/cmQtAutoMocUic.h
+++ b/Source/cmQtAutoMocUic.h
@@ -25,8 +25,6 @@
 #include <utility>
 #include <vector>
 
-class cmMakefile;
-
 /** \class cmQtAutoMocUic
  * \brief AUTOMOC and AUTOUIC generator
  */
@@ -42,17 +40,21 @@ public:
 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() = default;
 
-    KeyExpT(const char* key, const char* exp)
-      : Key(key)
-      , Exp(exp)
-    {
-    }
-
     KeyExpT(std::string key, std::string const& exp)
       : Key(std::move(key))
       , Exp(exp)
@@ -63,16 +65,6 @@ public:
     cmsys::RegularExpression Exp;
   };
 
-  /** 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
-  };
-
   /** Source file parsing cache.  */
   class ParseCacheT
   {
@@ -169,6 +161,7 @@ public:
     // - Config
     bool MultiConfig = false;
     unsigned int QtVersionMajor = 4;
+    unsigned int ThreadCount = 0;
     // - Directories
     std::string AutogenBuildDir;
     std::string AutogenIncludeDir;
@@ -252,6 +245,12 @@ public:
   class UicSettingsT
   {
   public:
+    struct UiFile
+    {
+      std::vector<std::string> Options;
+    };
+
+  public:
     UicSettingsT();
     ~UicSettingsT();
 
@@ -267,8 +266,8 @@ public:
     cmFileTime ExecutableTime;
     std::string Executable;
     std::unordered_set<std::string> SkipList;
-    std::vector<std::string> TargetOptions;
-    std::map<std::string, std::vector<std::string>> Options;
+    std::vector<std::string> Options;
+    std::unordered_map<std::string, UiFile> UiFiles;
     std::vector<std::string> SearchPaths;
     cmsys::RegularExpression RegExpInclude;
   };
@@ -523,10 +522,8 @@ public:
   std::string CollapseFullPathTS(std::string const& path) const;
 
 private:
-  // -- Utility accessors
-  Logger const& Log() const { return Logger_; }
   // -- Abstract processing interface
-  bool Init(cmMakefile* makefile) override;
+  bool InitFromInfo() override;
   void InitJobs();
   bool Process() override;
   // -- Settings file
@@ -541,8 +538,6 @@ private:
   bool CreateDirectories();
 
 private:
-  // -- Utility
-  Logger Logger_;
   // -- Settings
   BaseSettingsT BaseConst_;
   BaseEvalT BaseEval_;
diff --git a/Source/cmQtAutoRcc.cxx b/Source/cmQtAutoRcc.cxx
index 1bf8ca4..b0b15d4 100644
--- a/Source/cmQtAutoRcc.cxx
+++ b/Source/cmQtAutoRcc.cxx
@@ -6,7 +6,6 @@
 #include "cmCryptoHash.h"
 #include "cmDuration.h"
 #include "cmFileLockResult.h"
-#include "cmMakefile.h"
 #include "cmProcessOutput.h"
 #include "cmQtAutoGen.h"
 #include "cmStringAlgorithms.h"
@@ -16,112 +15,49 @@
 
 #include <algorithm>
 
-cmQtAutoRcc::cmQtAutoRcc() = default;
+cmQtAutoRcc::cmQtAutoRcc()
+  : cmQtAutoGenerator(GenT::RCC)
+{
+}
 cmQtAutoRcc::~cmQtAutoRcc() = default;
 
-bool cmQtAutoRcc::Init(cmMakefile* makefile)
+bool cmQtAutoRcc::InitFromInfo()
 {
-  // -- Utility lambdas
-  auto InfoGet = [makefile](cm::string_view key) {
-    return makefile->GetSafeDefinition(std::string(key));
-  };
-  auto InfoGetList =
-    [makefile](cm::string_view key) -> std::vector<std::string> {
-    return cmExpandedList(makefile->GetSafeDefinition(std::string(key)));
-  };
-  auto InfoGetConfig = [makefile, this](cm::string_view key) -> std::string {
-    if (const char* valueConf =
-          makefile->GetDefinition(cmStrCat(key, '_', InfoConfig()))) {
-      return std::string(valueConf);
-    }
-    return makefile->GetSafeDefinition(std::string(key));
-  };
-  auto InfoGetConfigList =
-    [&InfoGetConfig](cm::string_view key) -> std::vector<std::string> {
-    return cmExpandedList(InfoGetConfig(key));
-  };
-  auto LogInfoError = [this](cm::string_view msg) -> bool {
-    this->Log().Error(
-      GenT::RCC, cmStrCat("In ", MessagePath(this->InfoFile()), ":\n", msg));
+  // -- Required settings
+  if (!InfoBool("MULTI_CONFIG", MultiConfig_, true) ||
+      !InfoString("BUILD_DIR", AutogenBuildDir_, true) ||
+      !InfoStringConfig("INCLUDE_DIR", IncludeDir_, true) ||
+      !InfoString("RCC_EXECUTABLE", RccExecutable_, true) ||
+      !InfoArray("RCC_LIST_OPTIONS", RccListOptions_, false) ||
+      !InfoString("LOCK_FILE", LockFile_, true) ||
+      !InfoStringConfig("SETTINGS_FILE", SettingsFile_, true) ||
+      !InfoString("SOURCE", QrcFile_, true) ||
+      !InfoString("OUTPUT_CHECKSUM", RccPathChecksum_, true) ||
+      !InfoString("OUTPUT_NAME", RccFileName_, true) ||
+      !InfoArray("OPTIONS", Options_, false) ||
+      !InfoArray("INPUTS", Inputs_, false)) {
     return false;
-  };
-
-  // -- Read info file
-  if (!makefile->ReadListFile(InfoFile())) {
-    return LogInfoError("File processing failed.");
   }
 
-  // - Configurations
-  Logger_.RaiseVerbosity(InfoGet("ARCC_VERBOSITY"));
-  MultiConfig_ = makefile->IsOn("ARCC_MULTI_CONFIG");
-
-  // - Directories
-  ProjectDirsRef().Source = InfoGet("ARCC_CMAKE_SOURCE_DIR");
-  ProjectDirsRef().Binary = InfoGet("ARCC_CMAKE_BINARY_DIR");
-  AutogenBuildDir_ = InfoGet("ARCC_BUILD_DIR");
-  if (AutogenBuildDir_.empty()) {
-    return LogInfoError("Build directory empty.");
-  }
-
-  IncludeDir_ = InfoGetConfig("ARCC_INCLUDE_DIR");
-  if (IncludeDir_.empty()) {
-    return LogInfoError("Include directory empty.");
-  }
-
-  // - Rcc executable
-  RccExecutable_ = InfoGet("ARCC_RCC_EXECUTABLE");
-  if (!RccExecutableTime_.Load(RccExecutable_)) {
-    return LogInfoError(cmStrCat(
-      "The rcc executable ", MessagePath(RccExecutable_), " does not exist."));
-  }
-  RccListOptions_ = InfoGetList("ARCC_RCC_LIST_OPTIONS");
-
-  // - Job
-  LockFile_ = InfoGet("ARCC_LOCK_FILE");
-  QrcFile_ = InfoGet("ARCC_SOURCE");
+  // -- Derive information
   QrcFileName_ = cmSystemTools::GetFilenameName(QrcFile_);
   QrcFileDir_ = cmSystemTools::GetFilenamePath(QrcFile_);
-  RccPathChecksum_ = InfoGet("ARCC_OUTPUT_CHECKSUM");
-  RccFileName_ = InfoGet("ARCC_OUTPUT_NAME");
-  Options_ = InfoGetConfigList("ARCC_OPTIONS");
-  Inputs_ = InfoGetList("ARCC_INPUTS");
-
-  // - Settings file
-  SettingsFile_ = InfoGetConfig("ARCC_SETTINGS_FILE");
-
-  // - Validity checks
-  if (LockFile_.empty()) {
-    return LogInfoError("Lock file name missing.");
-  }
-  if (SettingsFile_.empty()) {
-    return LogInfoError("Settings file name missing.");
-  }
-  if (AutogenBuildDir_.empty()) {
-    return LogInfoError("Autogen build directory missing.");
-  }
-  if (RccExecutable_.empty()) {
-    return LogInfoError("rcc executable missing.");
-  }
-  if (QrcFile_.empty()) {
-    return LogInfoError("rcc input file missing.");
-  }
-  if (RccFileName_.empty()) {
-    return LogInfoError("rcc output file missing.");
-  }
-
-  // Init derived information
-  // ------------------------
-
   RccFilePublic_ =
     cmStrCat(AutogenBuildDir_, '/', RccPathChecksum_, '/', RccFileName_);
 
-  // Compute rcc output file name
+  // rcc output file name
   if (IsMultiConfig()) {
     RccFileOutput_ = cmStrCat(IncludeDir_, '/', MultiConfigOutput());
   } else {
     RccFileOutput_ = RccFilePublic_;
   }
 
+  // -- Checks
+  if (!RccExecutableTime_.Load(RccExecutable_)) {
+    return LogInfoError(cmStrCat(
+      "The rcc executable ", MessagePath(RccExecutable_), " does not exist."));
+  }
+
   return true;
 }
 
diff --git a/Source/cmQtAutoRcc.h b/Source/cmQtAutoRcc.h
index 5d3bd6a..945b68f 100644
--- a/Source/cmQtAutoRcc.h
+++ b/Source/cmQtAutoRcc.h
@@ -12,8 +12,6 @@
 #include <string>
 #include <vector>
 
-class cmMakefile;
-
 /** \class cmQtAutoRcc
  * \brief AUTORCC generator
  */
@@ -28,12 +26,11 @@ public:
 
 private:
   // -- Utility
-  Logger const& Log() const { return Logger_; }
   bool IsMultiConfig() const { return MultiConfig_; }
   std::string MultiConfigOutput() const;
 
   // -- Abstract processing interface
-  bool Init(cmMakefile* makefile) override;
+  bool InitFromInfo() override;
   bool Process() override;
   // -- Settings file
   bool SettingsFileRead();
@@ -47,8 +44,6 @@ private:
   bool GenerateWrapper();
 
 private:
-  // -- Logging
-  Logger Logger_;
   // -- Config settings
   bool MultiConfig_ = false;
   // -- Directories

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=881e3cfbf96c7b4f48304d3dfc07899c2e6703de
commit 881e3cfbf96c7b4f48304d3dfc07899c2e6703de
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Mon Sep 23 13:21:10 2019 +0200
Commit:     Sebastian Holtermann <sebholt at xwmw.org>
CommitDate: Wed Sep 25 10:31:06 2019 +0200

    Autogen: Variable renames and cleanups

diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h
index 2a28c1e..c8e4203 100644
--- a/Source/cmQtAutoGen.h
+++ b/Source/cmQtAutoGen.h
@@ -17,7 +17,7 @@
 class cmQtAutoGen
 {
 public:
-  /// @brief Integer version
+  /** Integer version.  */
   struct IntegerVersion
   {
     unsigned int Major = 0;
@@ -43,6 +43,7 @@ public:
     }
   };
 
+  /** Compiler features.  */
   class CompilerFeatures
   {
   public:
@@ -52,7 +53,7 @@ public:
   };
   using CompilerFeaturesHandle = std::shared_ptr<CompilerFeatures>;
 
-  /// @brief AutoGen generator type
+  /** AutoGen generator type.  */
   enum class GenT
   {
     GEN, // AUTOGEN
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 3aba19d..0329ac7 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -123,7 +123,7 @@ bool StaticLibraryCycle(cmGeneratorTarget const* targetOrigin,
   return cycle;
 }
 
-/** Sanitizes file search paths */
+/** Sanitizes file search paths.  */
 class SearchPathSanitizer
 {
 public:
@@ -353,9 +353,6 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
 
     // Include directory
     this->Dir.Include = cmStrCat(this->Dir.Build, "/include");
-    if (this->MultiConfig) {
-      this->Dir.Include += "_$<CONFIG>";
-    }
     // Per config include directories
     if (this->MultiConfig) {
       for (std::string const& cfg : this->ConfigsList) {
@@ -363,6 +360,10 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
         dir = cmStrCat(this->Dir.Build, "/include_", cfg);
       }
     }
+    this->Dir.IncludeGenExp = this->Dir.Include;
+    if (this->MultiConfig) {
+      this->Dir.IncludeGenExp += "_$<CONFIG>";
+    }
   }
 
   // Moc, Uic and _autogen target settings
@@ -454,7 +455,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
 
   // Add autogen include directory to the origin target INCLUDE_DIRECTORIES
   if (this->MocOrUicEnabled() || (this->Rcc.Enabled && this->MultiConfig)) {
-    this->GenTarget->AddIncludeDirectory(this->Dir.Include, true);
+    this->GenTarget->AddIncludeDirectory(this->Dir.IncludeGenExp, true);
   }
 
   // Scan files
@@ -889,13 +890,15 @@ bool cmQtAutoGenInitializer::InitScanFiles()
     {
       cmFilePathChecksum const fpathCheckSum(this->Makefile);
       for (Qrc& qrc : this->Rcc.Qrcs) {
-        qrc.PathChecksum = fpathCheckSum.getPart(qrc.QrcFile);
-        // RCC output file name
-        qrc.RccFile = cmStrCat(this->Dir.Build, '/', qrc.PathChecksum, "/qrc_",
-                               qrc.QrcName, ".cpp");
+        // Path checksum
+        qrc.QrcPathChecksum = fpathCheckSum.getPart(qrc.QrcFile);
+        // Output file name
+        qrc.OutputFile = cmStrCat(this->Dir.Build, '/', qrc.QrcPathChecksum,
+                                  "/qrc_", qrc.QrcName, ".cpp");
         {
-          cm::string_view const baseSuffix =
-            qrc.Unique ? cm::string_view() : cm::string_view(qrc.PathChecksum);
+          cm::string_view const baseSuffix = qrc.Unique
+            ? cm::string_view()
+            : cm::string_view(qrc.QrcPathChecksum);
           std::string const base =
             cmStrCat(this->Dir.Info, "/RCC", qrc.QrcName, baseSuffix);
           qrc.LockFile = cmStrCat(base, ".lock");
@@ -910,7 +913,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
         }
       }
     }
-    // RCC options
+    // rcc options
     for (Qrc& qrc : this->Rcc.Qrcs) {
       // Target options
       std::vector<std::string> opts = optionsTarget;
@@ -920,7 +923,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
         // Replace '-' with '_'. The former is not valid for symbol names.
         std::replace(name.begin(), name.end(), '-', '_');
         if (!qrc.Unique) {
-          name += cmStrCat('_', qrc.PathChecksum);
+          name += cmStrCat('_', qrc.QrcPathChecksum);
         }
         std::vector<std::string> nameOpts;
         nameOpts.emplace_back("-name");
@@ -931,7 +934,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
       RccMergeOptions(opts, qrc.Options, modernQt);
       qrc.Options = std::move(opts);
     }
-    // RCC resources
+    // rcc resources
     for (Qrc& qrc : this->Rcc.Qrcs) {
       if (!qrc.Generated) {
         std::string error;
@@ -1099,10 +1102,10 @@ bool cmQtAutoGenInitializer::InitRccTargets()
     // Register info file as generated by CMake
     this->Makefile->AddCMakeOutputFile(qrc.InfoFile);
     // Register file at target
-    this->AddGeneratedSource(qrc.RccFile, this->Rcc);
+    this->AddGeneratedSource(qrc.OutputFile, this->Rcc);
 
     std::vector<std::string> ccOutput;
-    ccOutput.push_back(qrc.RccFile);
+    ccOutput.push_back(qrc.OutputFile);
 
     std::vector<std::string> ccDepends;
     // Add the .qrc and info file to the custom command dependencies
@@ -1132,7 +1135,7 @@ bool cmQtAutoGenInitializer::InitRccTargets()
       {
         ccName = cmStrCat(this->GenTarget->GetName(), "_arcc_", qrc.QrcName);
         if (!qrc.Unique) {
-          ccName += cmStrCat('_', qrc.PathChecksum);
+          ccName += cmStrCat('_', qrc.QrcPathChecksum);
         }
 
         cmTarget* autoRccTarget = this->Makefile->AddUtilityCommand(
@@ -1424,9 +1427,9 @@ bool cmQtAutoGenInitializer::SetupWriteRccInfo()
       ofs.Write("# Rcc job\n");
       ofs.Write("ARCC_LOCK_FILE", qrc.LockFile);
       ofs.Write("ARCC_SOURCE", qrc.QrcFile);
-      ofs.Write("ARCC_OUTPUT_CHECKSUM", qrc.PathChecksum);
+      ofs.Write("ARCC_OUTPUT_CHECKSUM", qrc.QrcPathChecksum);
       ofs.Write("ARCC_OUTPUT_NAME",
-                cmSystemTools::GetFilenameName(qrc.RccFile));
+                cmSystemTools::GetFilenameName(qrc.OutputFile));
       ofs.WriteStrings("ARCC_OPTIONS", qrc.Options);
       ofs.WriteStrings("ARCC_INPUTS", qrc.Resources);
     } else {
diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h
index 7ce9fad..2411936 100644
--- a/Source/cmQtAutoGenInitializer.h
+++ b/Source/cmQtAutoGenInitializer.h
@@ -26,29 +26,31 @@ class cmQtAutoGenGlobalInitializer;
 class cmSourceFile;
 class cmTarget;
 
-/// @brief Initializes the QtAutoGen generators
+/** \class cmQtAutoGenerator
+ * \brief Initializes the QtAutoGen generators
+ */
 class cmQtAutoGenInitializer : public cmQtAutoGen
 {
 public:
-  /// @brief Rcc job information
+  /** rcc job.  */
   class Qrc
   {
   public:
     std::string LockFile;
     std::string QrcFile;
     std::string QrcName;
-    std::string PathChecksum;
+    std::string QrcPathChecksum;
     std::string InfoFile;
     std::string SettingsFile;
     std::map<std::string, std::string> ConfigSettingsFile;
-    std::string RccFile;
+    std::string OutputFile;
     bool Generated = false;
     bool Unique = false;
     std::vector<std::string> Options;
     std::vector<std::string> Resources;
   };
 
-  /// @brief Moc/Uic file
+  /** moc and/or uic file.  */
   struct MUFile
   {
     std::string FullPath;
@@ -61,7 +63,7 @@ public:
   };
   using MUFileHandle = std::unique_ptr<MUFile>;
 
-  /// @brief Abstract moc/uic/rcc generator variables base class
+  /** Abstract moc/uic/rcc generator variables base class  */
   struct GenVarsT
   {
     bool Enabled = false;
@@ -74,20 +76,19 @@ public:
     std::string Executable;
     CompilerFeaturesHandle ExecutableFeatures;
 
-    /// @brief Constructor
     GenVarsT(GenT gen)
       : Gen(gen)
       , GenNameUpper(cmQtAutoGen::GeneratorNameUpper(gen)){};
   };
 
-  /// @brief Writes a CMake info file
+  /** Writes a CMake info file.  */
   class InfoWriter
   {
   public:
-    /// @brief Open the given file
+    /** Open the given file.  */
     InfoWriter(std::string const& filename);
 
-    /// @return True if the file is open
+    /** @return True if the file is open.  */
     explicit operator bool() const { return static_cast<bool>(Ofs_); }
 
     void Write(cm::string_view text) { Ofs_ << text; }
@@ -114,7 +115,7 @@ public:
   };
 
 public:
-  /// @return The detected Qt version and the required Qt major version
+  /** @return The detected Qt version and the required Qt major version.  */
   static std::pair<IntegerVersion, unsigned int> GetQtVersion(
     cmGeneratorTarget const* genTarget);
 
@@ -128,7 +129,7 @@ public:
   bool SetupCustomTargets();
 
 private:
-  /// @brief If moc or uic is enabled, the autogen target will be generated
+  /** If moc or uic is enabled, the autogen target will be generated.  */
   bool MocOrUicEnabled() const
   {
     return (this->Moc.Enabled || this->Uic.Enabled);
@@ -162,7 +163,7 @@ private:
   cmLocalGenerator* LocalGen = nullptr;
   cmMakefile* Makefile = nullptr;
 
-  // Configuration
+  // -- Configuration
   IntegerVersion QtVersion;
   bool MultiConfig = false;
   std::string ConfigDefault;
@@ -172,7 +173,7 @@ private:
   bool CMP0071Accept = false;
   bool CMP0071Warn = false;
 
-  /// @brief Common directories
+  /** Common directories.  */
   struct
   {
     std::string Info;
@@ -180,9 +181,10 @@ private:
     std::string Work;
     std::string Include;
     std::map<std::string, std::string> ConfigInclude;
+    std::string IncludeGenExp;
   } Dir;
 
-  /// @brief Autogen target variables
+  /** Autogen target variables.  */
   struct
   {
     std::string Name;
@@ -204,45 +206,42 @@ private:
     std::vector<MUFile*> FilesGenerated;
   } AutogenTarget;
 
-  /// @brief Moc only variables
+  /** moc variables.  */
   struct MocT : public GenVarsT
   {
+    MocT()
+      : GenVarsT(GenT::MOC){};
+
     std::string PredefsCmd;
     std::vector<std::string> Includes;
     std::map<std::string, std::vector<std::string>> ConfigIncludes;
     std::set<std::string> Defines;
     std::map<std::string, std::set<std::string>> ConfigDefines;
     std::string MocsCompilation;
-
-    /// @brief Constructor
-    MocT()
-      : GenVarsT(GenT::MOC){};
   } Moc;
 
-  /// @brief Uic only variables
+  /** uic variables.  */
   struct UicT : public GenVarsT
   {
+    UicT()
+      : GenVarsT(GenT::UIC){};
+
     std::set<std::string> SkipUi;
     std::vector<std::string> SearchPaths;
     std::vector<std::string> Options;
     std::map<std::string, std::vector<std::string>> ConfigOptions;
     std::vector<std::string> FileFiles;
     std::vector<std::vector<std::string>> FileOptions;
-
-    /// @brief Constructor
-    UicT()
-      : GenVarsT(GenT::UIC){};
   } Uic;
 
-  /// @brief Rcc only variables
+  /** rcc variables.  */
   struct RccT : public GenVarsT
   {
-    bool GlobalTarget = false;
-    std::vector<Qrc> Qrcs;
-
-    /// @brief Constructor
     RccT()
       : GenVarsT(GenT::RCC){};
+
+    bool GlobalTarget = false;
+    std::vector<Qrc> Qrcs;
   } Rcc;
 };
 
diff --git a/Source/cmQtAutoMocUic.h b/Source/cmQtAutoMocUic.h
index 15b66ca..f37d923 100644
--- a/Source/cmQtAutoMocUic.h
+++ b/Source/cmQtAutoMocUic.h
@@ -78,9 +78,8 @@ public:
   {
   public:
     // -- Types
-    /**
-     * Entry of the file parsing cache
-     */
+
+    /** Entry of the file parsing cache.  */
     struct FileT
     {
       void Clear();
diff --git a/Source/cmQtAutoRcc.h b/Source/cmQtAutoRcc.h
index 636a667..5d3bd6a 100644
--- a/Source/cmQtAutoRcc.h
+++ b/Source/cmQtAutoRcc.h
@@ -14,7 +14,9 @@
 
 class cmMakefile;
 
-// @brief AUTORCC generator
+/** \class cmQtAutoRcc
+ * \brief AUTORCC generator
+ */
 class cmQtAutoRcc : public cmQtAutoGenerator
 {
 public:
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 211fd4c..bf856d7 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -1058,18 +1058,18 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
 #ifndef CMAKE_BOOTSTRAP
     if ((args[1] == "cmake_autogen") && (args.size() >= 4)) {
       cmQtAutoMocUic autoGen;
-      std::string const& infoDir = args[2];
+      std::string const& infoFile = args[2];
       std::string const& config = args[3];
-      return autoGen.Run(infoDir, config) ? 0 : 1;
+      return autoGen.Run(infoFile, config) ? 0 : 1;
     }
     if ((args[1] == "cmake_autorcc") && (args.size() >= 3)) {
-      cmQtAutoRcc autoGen;
+      cmQtAutoRcc autoRcc;
       std::string const& infoFile = args[2];
       std::string config;
       if (args.size() > 3) {
         config = args[3];
       }
-      return autoGen.Run(infoFile, config) ? 0 : 1;
+      return autoRcc.Run(infoFile, config) ? 0 : 1;
     }
 #endif
 

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fc36f4410bcdb76ef23a07e5172cb57b41ff5ce3
commit fc36f4410bcdb76ef23a07e5172cb57b41ff5ce3
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Mon Sep 23 11:52:21 2019 +0200
Commit:     Sebastian Holtermann <sebholt at xwmw.org>
CommitDate: Wed Sep 25 10:31:06 2019 +0200

    Autogen: Inline GetKnownQtVersions function

diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index d595eec..3aba19d 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -1506,64 +1506,60 @@ void cmQtAutoGenInitializer::AddCleanFile(std::string const& fileName)
                                           fileName.c_str(), false);
 }
 
-static unsigned int CharPtrToUInt(const char* const input)
-{
-  unsigned long tmp = 0;
-  if (input != nullptr && cmStrToULong(input, &tmp)) {
-    return static_cast<unsigned int>(tmp);
-  }
-  return 0;
-}
-
-static std::vector<cmQtAutoGen::IntegerVersion> GetKnownQtVersions(
-  cmGeneratorTarget const* genTarget)
+std::pair<cmQtAutoGen::IntegerVersion, unsigned int>
+cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target)
 {
-  // Qt version variable prefixes
-  static std::initializer_list<
-    std::pair<cm::string_view, cm::string_view>> const keys{
-    { "Qt6Core_VERSION_MAJOR", "Qt6Core_VERSION_MINOR" },
-    { "Qt5Core_VERSION_MAJOR", "Qt5Core_VERSION_MINOR" },
-    { "QT_VERSION_MAJOR", "QT_VERSION_MINOR" },
-  };
-
-  std::vector<cmQtAutoGen::IntegerVersion> result;
-  result.reserve(keys.size() * 2);
-
-  // Adds a version to the result (nullptr safe)
-  auto addVersion = [&result](const char* major, const char* minor) {
-    cmQtAutoGen::IntegerVersion ver(CharPtrToUInt(major),
-                                    CharPtrToUInt(minor));
-    if (ver.Major != 0) {
-      result.emplace_back(ver);
+  // Converts a char ptr to an unsigned int value
+  auto toUInt = [](const char* const input) -> unsigned int {
+    unsigned long tmp = 0;
+    if (input != nullptr && cmStrToULong(input, &tmp)) {
+      return static_cast<unsigned int>(tmp);
     }
+    return 0u;
   };
 
-  cmMakefile* makefile = genTarget->Makefile;
+  // Initialize return value to a default
+  std::pair<IntegerVersion, unsigned int> res(
+    IntegerVersion(),
+    toUInt(target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION",
+                                                           "")));
 
-  // Read versions from variables
-  for (auto const& keyPair : keys) {
-    addVersion(makefile->GetDefinition(std::string(keyPair.first)),
-               makefile->GetDefinition(std::string(keyPair.second)));
-  }
+  // Acquire known Qt versions
+  std::vector<cmQtAutoGen::IntegerVersion> knownQtVersions;
+  {
+    // Qt version variable prefixes
+    static std::initializer_list<
+      std::pair<cm::string_view, cm::string_view>> const keys{
+      { "Qt6Core_VERSION_MAJOR", "Qt6Core_VERSION_MINOR" },
+      { "Qt5Core_VERSION_MAJOR", "Qt5Core_VERSION_MINOR" },
+      { "QT_VERSION_MAJOR", "QT_VERSION_MINOR" },
+    };
 
-  // Read versions from directory properties
-  for (auto const& keyPair : keys) {
-    addVersion(makefile->GetProperty(std::string(keyPair.first)),
-               makefile->GetProperty(std::string(keyPair.second)));
-  }
+    knownQtVersions.reserve(keys.size() * 2);
 
-  return result;
-}
+    // Adds a version to the result (nullptr safe)
+    auto addVersion = [&knownQtVersions, &toUInt](const char* major,
+                                                  const char* minor) {
+      cmQtAutoGen::IntegerVersion ver(toUInt(major), toUInt(minor));
+      if (ver.Major != 0) {
+        knownQtVersions.emplace_back(ver);
+      }
+    };
 
-std::pair<cmQtAutoGen::IntegerVersion, unsigned int>
-cmQtAutoGenInitializer::GetQtVersion(cmGeneratorTarget const* target)
-{
-  std::pair<IntegerVersion, unsigned int> res(
-    IntegerVersion(),
-    CharPtrToUInt(target->GetLinkInterfaceDependentStringProperty(
-      "QT_MAJOR_VERSION", "")));
+    // Read versions from variables
+    for (auto const& keyPair : keys) {
+      addVersion(target->Makefile->GetDefinition(std::string(keyPair.first)),
+                 target->Makefile->GetDefinition(std::string(keyPair.second)));
+    }
+
+    // Read versions from directory properties
+    for (auto const& keyPair : keys) {
+      addVersion(target->Makefile->GetProperty(std::string(keyPair.first)),
+                 target->Makefile->GetProperty(std::string(keyPair.second)));
+    }
+  }
 
-  auto knownQtVersions = GetKnownQtVersions(target);
+  // Evaluate known Qt versions
   if (!knownQtVersions.empty()) {
     if (res.second == 0) {
       // No specific version was requested by the target:

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1f0d23546d5721fdd92883da4c4368dad3931393
commit 1f0d23546d5721fdd92883da4c4368dad3931393
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Tue Sep 24 11:34:49 2019 +0200
Commit:     Sebastian Holtermann <sebholt at xwmw.org>
CommitDate: Wed Sep 25 10:31:06 2019 +0200

    Autogen: Return unsigned int from GetParallelCPUCount()

diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 9045722..d595eec 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -30,7 +30,6 @@
 #include "cmake.h"
 #include "cmsys/SystemInformation.hxx"
 
-#include <algorithm>
 #include <cstddef>
 #include <deque>
 #include <initializer_list>
@@ -41,20 +40,20 @@
 #include <utility>
 #include <vector>
 
+#include <cm/algorithm>
 #include <cm/memory>
 
 namespace {
 
-std::size_t GetParallelCPUCount()
+unsigned int GetParallelCPUCount()
 {
-  static std::size_t count = 0;
+  static unsigned int count = 0;
   // Detect only on the first call
   if (count == 0) {
     cmsys::SystemInformation info;
     info.RunCPUCheck();
-    count = info.GetNumberOfPhysicalCPU();
-    count = std::max<std::size_t>(count, 1);
-    count = std::min<std::size_t>(count, cmQtAutoGen::ParallelMax);
+    count =
+      cm::clamp(info.GetNumberOfPhysicalCPU(), 1u, cmQtAutoGen::ParallelMax);
   }
   return count;
 }

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6a05bd3fa6a3f4ecf45c4cc32abc616883998ff9
commit 6a05bd3fa6a3f4ecf45c4cc32abc616883998ff9
Author:     Regina Pfeifer <regina at mailbox.org>
AuthorDate: Tue Sep 24 07:01:03 2019 +0000
Commit:     Sebastian Holtermann <sebholt at xwmw.org>
CommitDate: Wed Sep 25 10:30:58 2019 +0200

    cm/algorithm: Provide function cm::clamp

diff --git a/Utilities/std/cm/algorithm b/Utilities/std/cm/algorithm
new file mode 100644
index 0000000..8ade99c
--- /dev/null
+++ b/Utilities/std/cm/algorithm
@@ -0,0 +1,38 @@
+// -*-c++-*-
+// vim: set ft=cpp:
+
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cm_algorithm
+#define cm_algorithm
+
+#include <algorithm> // IWYU pragma: export
+#include <cassert>
+
+namespace cm {
+
+#if __cplusplus >= 201703L || defined(_MSVC_LANG) && _MSVC_LANG >= 201703L
+
+using std::clamp;
+
+#else
+
+template <typename T>
+T const& clamp(T const& v, T const& lo, T const& hi)
+{
+  assert(!(hi < lo));
+  return (v < lo) ? lo : (hi < v) ? hi : v;
+}
+
+template <typename T, typename Comp>
+T const& clamp(T const& v, T const& lo, T const& hi, Comp comp)
+{
+  assert(!comp(hi, lo));
+  return comp(v, lo) ? lo : comp(hi, v) ? hi : v;
+}
+
+#endif
+
+} // namespace cm
+
+#endif

-----------------------------------------------------------------------

Summary of changes:
 Source/cmQtAutoGen.cxx            |  11 +-
 Source/cmQtAutoGen.h              |  10 +-
 Source/cmQtAutoGenInitializer.cxx | 902 ++++++++++++++++++++------------------
 Source/cmQtAutoGenInitializer.h   | 159 ++++---
 Source/cmQtAutoGenerator.cxx      | 260 +++++++++--
 Source/cmQtAutoGenerator.h        |  49 ++-
 Source/cmQtAutoMocUic.cxx         | 513 +++++++++++-----------
 Source/cmQtAutoMocUic.h           |  50 +--
 Source/cmQtAutoRcc.cxx            | 116 ++---
 Source/cmQtAutoRcc.h              |  11 +-
 Source/cmcmd.cxx                  |   8 +-
 Utilities/std/cm/algorithm        |  38 ++
 12 files changed, 1177 insertions(+), 950 deletions(-)
 create mode 100644 Utilities/std/cm/algorithm


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list