Merge topic 'irsl-intel-1041-folder'

8e7e7af5 IRSL: Install the 1041 folder for Intel compilers

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !1509
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f14f62f..fafe536 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -251,7 +251,12 @@
   endif()
   set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND}")
 
-  # provide definitions for targets that require a rebuild once .clang-tidy changes
+  # Create a preprocessor definition that depends on .clang-tidy content so
+  # the compile command will change when .clang-tidy changes.  This ensures
+  # that a subsequent build re-runs clang-tidy on all sources even if they
+  # do not otherwise need to be recompiled.  Nothing actually uses this
+  # definition.  We add it to targets on which we run clang-tidy just to
+  # get the build dependency on the .clang-tidy file.
   file(SHA1 ${CMAKE_CURRENT_SOURCE_DIR}/.clang-tidy clang_tidy_sha1)
   set(CLANG_TIDY_DEFINITIONS "CLANG_TIDY_SHA1=${clang_tidy_sha1}")
   unset(clang_tidy_sha1)
@@ -267,7 +272,7 @@
     message(FATAL_ERROR "CMake_RUN_IWYU is ON but include-what-you-use is not found!")
   endif()
   set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE
-    "${IWYU_COMMAND};-Xiwyu;--mapping_file=${CMake_SOURCE_DIR}/Utilities/IWYU/mapping.imp")
+    "${IWYU_COMMAND};-Xiwyu;--mapping_file=${CMake_SOURCE_DIR}/Utilities/IWYU/mapping.imp;-w")
 endif()
 
 
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index c81ba59..96d5c7d 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -51,6 +51,14 @@
 to determine whether to report an error on use of deprecated macros or
 functions.
 
+Policies Introduced by CMake 3.11
+=================================
+
+.. toctree::
+   :maxdepth: 1
+
+   CMP0072: FindOpenGL prefers GLVND by default when available. </policy/CMP0072>
+
 Policies Introduced by CMake 3.10
 =================================
 
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index 1927c37..0451466 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -290,6 +290,7 @@
    /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY
    /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG
    /variable/CMAKE_CONFIG_POSTFIX
+   /variable/CMAKE_CUDA_SEPARABLE_COMPILATION
    /variable/CMAKE_DEBUG_POSTFIX
    /variable/CMAKE_ENABLE_EXPORTS
    /variable/CMAKE_EXE_LINKER_FLAGS
diff --git a/Help/policy/CMP0072.rst b/Help/policy/CMP0072.rst
new file mode 100644
index 0000000..3abbad7
--- /dev/null
+++ b/Help/policy/CMP0072.rst
@@ -0,0 +1,26 @@
+CMP0072
+-------
+
+:module:`FindOpenGL` prefers GLVND by default when available.
+
+The :module:`FindOpenGL` module provides an ``OpenGL::GL`` target and an
+``OPENGL_LIBRARIES`` variable for projects to use for legacy GL interfaces.
+When both a legacy GL library (e.g. ``libGL.so``) and GLVND libraries
+for OpenGL and GLX (e.g. ``libOpenGL.so`` and ``libGLX.so``) are available,
+the module must choose between them.  It documents an ``OpenGL_GL_PREFERENCE``
+variable that can be used to specify an explicit preference.  When no such
+preference is set, the module must choose a default preference.
+
+CMake 3.11 and above prefer to choose GLVND libraries.  This policy provides
+compatibility with projects that expect the legacy GL library to be used.
+
+The ``OLD`` behavior for this policy is to set ``OpenGL_GL_PREFERENCE`` to
+``LEGACY``.  The ``NEW`` behavior for this policy is to set
+``OpenGL_GL_PREFERENCE`` to ``GLVND``.
+
+This policy was introduced in CMake version 3.11.  CMake version
+|release| warns when the policy is not set and uses ``OLD`` behavior.
+Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW``
+explicitly.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/prop_tgt/COMPILE_FLAGS.rst b/Help/prop_tgt/COMPILE_FLAGS.rst
index 1a5389e..8fe651b 100644
--- a/Help/prop_tgt/COMPILE_FLAGS.rst
+++ b/Help/prop_tgt/COMPILE_FLAGS.rst
@@ -8,4 +8,4 @@
 to pass additional preprocessor definitions.
 
 This property is deprecated.  Use the :prop_tgt:`COMPILE_OPTIONS`
-property or the command:`target_compile_options` command instead.
+property or the :command:`target_compile_options` command instead.
diff --git a/Help/prop_tgt/CUDA_SEPARABLE_COMPILATION.rst b/Help/prop_tgt/CUDA_SEPARABLE_COMPILATION.rst
index 1c7dd80..d306d7f 100644
--- a/Help/prop_tgt/CUDA_SEPARABLE_COMPILATION.rst
+++ b/Help/prop_tgt/CUDA_SEPARABLE_COMPILATION.rst
@@ -11,3 +11,7 @@
 .. code-block:: cmake
 
   set_property(TARGET myexe PROPERTY CUDA_SEPARABLE_COMPILATION ON)
+
+This property is initialized by the value of the
+:variable:`CMAKE_CUDA_SEPARABLE_COMPILATION` variable if it is set when a
+target is created.
diff --git a/Help/release/dev/FindOpenGL-glvnd-policy.rst b/Help/release/dev/FindOpenGL-glvnd-policy.rst
new file mode 100644
index 0000000..3348acf
--- /dev/null
+++ b/Help/release/dev/FindOpenGL-glvnd-policy.rst
@@ -0,0 +1,5 @@
+FindOpenGL-glvnd-policy
+-----------------------
+
+* The :module:`FindOpenGL` module now prefers GLVND libraries if available.
+  See policy :policy:`CMP0072`.
diff --git a/Help/release/dev/cuda-sep-comp-var.rst b/Help/release/dev/cuda-sep-comp-var.rst
new file mode 100644
index 0000000..23536ef
--- /dev/null
+++ b/Help/release/dev/cuda-sep-comp-var.rst
@@ -0,0 +1,6 @@
+cuda-sep-comp-var
+-----------------
+
+* A :variable:`CMAKE_CUDA_SEPARABLE_COMPILATION` variable was added to
+  initialize the :prop_tgt:`CUDA_SEPARABLE_COMPILATION` target property
+  on targets when they are created.
diff --git a/Help/variable/CMAKE_CUDA_SEPARABLE_COMPILATION.rst b/Help/variable/CMAKE_CUDA_SEPARABLE_COMPILATION.rst
new file mode 100644
index 0000000..eef92fb
--- /dev/null
+++ b/Help/variable/CMAKE_CUDA_SEPARABLE_COMPILATION.rst
@@ -0,0 +1,6 @@
+CMAKE_CUDA_SEPARABLE_COMPILATION
+--------------------------------
+
+Default value for :prop_tgt:`CUDA_SEPARABLE_COMPILATION` target property.
+This variable is used to initialize the property on each target as it is
+created.
diff --git a/Modules/AutoRccInfo.cmake.in b/Modules/AutoRccInfo.cmake.in
new file mode 100644
index 0000000..5457a6f
--- /dev/null
+++ b/Modules/AutoRccInfo.cmake.in
@@ -0,0 +1,11 @@
+# Meta
+set(ARCC_MULTI_CONFIG @_multi_config@)
+# Directories and files
+set(ARCC_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/")
+set(ARCC_CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@/")
+set(ARCC_CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@/")
+set(ARCC_CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/")
+set(ARCC_BUILD_DIR @_build_dir@)
+# Qt environment
+set(ARCC_RCC_EXECUTABLE @_qt_rcc_executable@)
+set(ARCC_RCC_LIST_OPTIONS @_qt_rcc_list_options@)
diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in
index 7f4b398..9a4a06d 100644
--- a/Modules/AutogenInfo.cmake.in
+++ b/Modules/AutogenInfo.cmake.in
@@ -9,12 +9,11 @@
 set(AM_BUILD_DIR @_build_dir@)
 set(AM_SOURCES @_sources@)
 set(AM_HEADERS @_headers@)
+set(AM_SETTINGS_FILE @_settings_file@)
 # Qt environment
 set(AM_QT_VERSION_MAJOR @_qt_version_major@)
-set(AM_QT_VERSION_MINOR @_qt_version_minor@)
 set(AM_QT_MOC_EXECUTABLE @_qt_moc_executable@)
 set(AM_QT_UIC_EXECUTABLE @_qt_uic_executable@)
-set(AM_QT_RCC_EXECUTABLE @_qt_rcc_executable@)
 # MOC settings
 set(AM_MOC_SKIP @_moc_skip@)
 set(AM_MOC_DEFINITIONS @_moc_compile_defs@)
@@ -30,8 +29,3 @@
 set(AM_UIC_OPTIONS_FILES @_qt_uic_options_files@)
 set(AM_UIC_OPTIONS_OPTIONS @_qt_uic_options_options@)
 set(AM_UIC_SEARCH_PATHS @_uic_search_paths@)
-# RCC settings
-set(AM_RCC_SOURCES @_rcc_files@)
-set(AM_RCC_BUILDS @_rcc_builds@)
-set(AM_RCC_OPTIONS @_rcc_options@)
-set(AM_RCC_INPUTS @_rcc_inputs@)
diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake
index ea7dc02..812917f 100644
--- a/Modules/CPack.cmake
+++ b/Modules/CPack.cmake
@@ -338,7 +338,7 @@
         set(value "${${var}}")
       endif()
 
-      string(APPEND commands "\nSET(${var} \"${value}\")")
+      string(APPEND commands "\nset(${var} \"${value}\")")
     endif()
   endforeach()
 
diff --git a/Modules/CPackComponent.cmake b/Modules/CPackComponent.cmake
index 2374fbd..6c122e5 100644
--- a/Modules/CPackComponent.cmake
+++ b/Modules/CPackComponent.cmake
@@ -66,7 +66,7 @@
 #  the component differently depending on the value of this variable:
 #
 #  * ONE_PER_GROUP (default): creates one package file per component group
-#  * ALL_COMPONENTS_IN_ONE : creates a single package with all (requested) component
+#  * ALL_COMPONENTS_IN_ONE : creates a single package with all (requested) components
 #  * IGNORE : creates one package per component, i.e. IGNORE component group
 #
 #  One can specify different grouping for different CPack generator by
diff --git a/Modules/FindImageMagick.cmake b/Modules/FindImageMagick.cmake
index 7d5534b..c16bbf2 100644
--- a/Modules/FindImageMagick.cmake
+++ b/Modules/FindImageMagick.cmake
@@ -196,24 +196,33 @@
   if(component STREQUAL "Magick++")
     FIND_IMAGEMAGICK_API(Magick++ Magick++.h
       Magick++ CORE_RL_Magick++_
+      Magick++-6 Magick++-7
       Magick++-Q8 Magick++-Q16 Magick++-Q16HDRI Magick++-Q8HDRI
+      Magick++-6.Q64 Magick++-6.Q32 Magick++-6.Q64HDRI Magick++-6.Q32HDRI
       Magick++-6.Q16 Magick++-6.Q8 Magick++-6.Q16HDRI Magick++-6.Q8HDRI
+      Magick++-7.Q64 Magick++-7.Q32 Magick++-7.Q64HDRI Magick++-7.Q32HDRI
       Magick++-7.Q16 Magick++-7.Q8 Magick++-7.Q16HDRI Magick++-7.Q8HDRI
       )
     list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_Magick++_LIBRARY)
   elseif(component STREQUAL "MagickWand")
     FIND_IMAGEMAGICK_API(MagickWand "wand/MagickWand.h;MagickWand/MagickWand.h"
       Wand MagickWand CORE_RL_wand_
+      MagickWand-6 MagickWand-7
       MagickWand-Q16 MagickWand-Q8 MagickWand-Q16HDRI MagickWand-Q8HDRI
+      MagickWand-6.Q64 MagickWand-6.Q32 MagickWand-6.Q64HDRI MagickWand-6.Q32HDRI
       MagickWand-6.Q16 MagickWand-6.Q8 MagickWand-6.Q16HDRI MagickWand-6.Q8HDRI
+      MagickWand-7.Q64 MagickWand-7.Q32 MagickWand-7.Q64HDRI MagickWand-7.Q32HDRI
       MagickWand-7.Q16 MagickWand-7.Q8 MagickWand-7.Q16HDRI MagickWand-7.Q8HDRI
       )
     list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_MagickWand_LIBRARY)
   elseif(component STREQUAL "MagickCore")
     FIND_IMAGEMAGICK_API(MagickCore "magick/MagickCore.h;MagickCore/MagickCore.h"
       Magick MagickCore CORE_RL_magick_
+      MagickCore-6 MagickCore-7
       MagickCore-Q16 MagickCore-Q8 MagickCore-Q16HDRI MagickCore-Q8HDRI
+      MagickCore-6.Q64 MagickCore-6.Q32 MagickCore-6.Q64HDRI MagickCore-6.Q32HDRI
       MagickCore-6.Q16 MagickCore-6.Q8 MagickCore-6.Q16HDRI MagickCore-6.Q8HDRI
+      MagickCore-7.Q64 MagickCore-7.Q32 MagickCore-7.Q64HDRI MagickCore-7.Q32HDRI
       MagickCore-7.Q16 MagickCore-7.Q8 MagickCore-7.Q16HDRI MagickCore-7.Q8HDRI
       )
     list(APPEND ImageMagick_REQUIRED_VARS ImageMagick_MagickCore_LIBRARY)
diff --git a/Modules/FindOpenGL.cmake b/Modules/FindOpenGL.cmake
index 9063492..91db5af 100644
--- a/Modules/FindOpenGL.cmake
+++ b/Modules/FindOpenGL.cmake
@@ -99,11 +99,13 @@
 #  If the GLVND OpenGL and GLX libraries are available, prefer them.
 #  This forces ``OPENGL_gl_LIBRARY`` to be empty.
 #  This is the default if components were requested (since components
-#  correspond to GLVND libraries).
+#  correspond to GLVND libraries) or if policy :policy:`CMP0072` is
+#  set to ``NEW``.
 #
 # ``LEGACY``
 #  Prefer to use the legacy libGL library, if available.
-#  This is the default if no components were requested.
+#  This is the default if no components were requested and
+#  policy :policy:`CMP0072` is not set to ``NEW``.
 #
 # For EGL targets the client must rely on GLVND support on the user's system.
 # Linking should use the ``OpenGL::OpenGL OpenGL::EGL`` targets.  Using GLES*
@@ -220,6 +222,7 @@
           /usr/shlib /usr/X11R6/lib
   )
 
+  set(_OpenGL_GL_POLICY_WARN 0)
   if(NOT DEFINED OpenGL_GL_PREFERENCE)
     set(OpenGL_GL_PREFERENCE "")
   endif()
@@ -237,8 +240,17 @@
     set(OpenGL_GL_PREFERENCE "GLVND")
   else()
     # No preference was explicitly specified and no GLVND components were
-    # requested.  Prefer libGL for legacy GL.
-    set(OpenGL_GL_PREFERENCE "LEGACY")
+    # requested.  Use a policy to choose the default.
+    cmake_policy(GET CMP0072 _OpenGL_GL_POLICY)
+    if("x${_OpenGL_GL_POLICY}x" STREQUAL "xNEWx")
+      set(OpenGL_GL_PREFERENCE "GLVND")
+    else()
+      set(OpenGL_GL_PREFERENCE "LEGACY")
+      if("x${_OpenGL_GL_POLICY}x" STREQUAL "xx")
+        set(_OpenGL_GL_POLICY_WARN 1)
+      endif()
+    endif()
+    unset(_OpenGL_GL_POLICY)
   endif()
 
   if("x${OpenGL_GL_PREFERENCE}x" STREQUAL "xGLVNDx" AND OPENGL_opengl_LIBRARY AND OPENGL_glx_LIBRARY)
@@ -257,6 +269,23 @@
       )
   endif()
 
+  if(_OpenGL_GL_POLICY_WARN AND OPENGL_gl_LIBRARY AND OPENGL_opengl_LIBRARY AND OPENGL_glx_LIBRARY)
+    message(AUTHOR_WARNING
+      "Policy CMP0072 is not set: FindOpenGL prefers GLVND by default when available.  "
+      "Run \"cmake --help-policy CMP0072\" for policy details.  "
+      "Use the cmake_policy command to set the policy and suppress this warning."
+      "\n"
+      "FindOpenGL found both a legacy GL library:\n"
+      "  OPENGL_gl_LIBRARY: ${OPENGL_gl_LIBRARY}\n"
+      "and GLVND libraries for OpenGL and GLX:\n"
+      "  OPENGL_opengl_LIBRARY: ${OPENGL_opengl_LIBRARY}\n"
+      "  OPENGL_glx_LIBRARY: ${OPENGL_glx_LIBRARY}\n"
+      "OpenGL_GL_PREFERENCE has not been set to \"GLVND\" or \"LEGACY\", so for "
+      "compatibility with CMake 3.10 and below the legacy GL library will be used."
+      )
+  endif()
+  unset(_OpenGL_GL_POLICY_WARN)
+
   # FPHSA cannot handle "this OR that is required", so we conditionally set what
   # it must look for.  First clear any previous config we might have done:
   set(_OpenGL_REQUIRED_VARS)
diff --git a/Modules/FindQt4.cmake b/Modules/FindQt4.cmake
index c67d0be..714e4af 100644
--- a/Modules/FindQt4.cmake
+++ b/Modules/FindQt4.cmake
@@ -709,13 +709,19 @@
   if (QT_LIBRARY_DIR AND NOT QT_PLUGINS_DIR  OR  QT_QMAKE_CHANGED)
     _qt4_query_qmake(QT_INSTALL_PLUGINS qt_plugins_dir)
     set(QT_PLUGINS_DIR NOTFOUND)
+    set(qt_cross_paths)
     foreach(qt_cross_path ${CMAKE_FIND_ROOT_PATH})
       set(qt_cross_paths ${qt_cross_paths} "${qt_cross_path}/plugins")
     endforeach()
-    find_path(QT_PLUGINS_DIR NAMES accessible imageformats sqldrivers codecs designer
+    find_path(QT_PLUGINS_DIR
+      NAMES accessible bearer codecs designer graphicssystems iconengines imageformats inputmethods qmltooling script sqldrivers
       HINTS ${qt_cross_paths} ${qt_plugins_dir}
       DOC "The location of the Qt plugins"
       NO_CMAKE_FIND_ROOT_PATH)
+    # If no plugins were installed, set QT_PLUGINS_DIR to ${qt_plugins_dir}
+    if(NOT QT_PLUGINS_DIR AND qt_plugins_dir)
+      set(QT_PLUGINS_DIR ${qt_plugins_dir} CACHE PATH "The location of the Qt plugins")
+    endif()
   endif ()
 
   # ask qmake for the translations directory
@@ -729,6 +735,7 @@
     _qt4_query_qmake(QT_INSTALL_IMPORTS qt_imports_dir)
     if(qt_imports_dir)
       set(QT_IMPORTS_DIR NOTFOUND)
+      set(qt_cross_paths)
       foreach(qt_cross_path ${CMAKE_FIND_ROOT_PATH})
         set(qt_cross_paths ${qt_cross_paths} "${qt_cross_path}/imports")
       endforeach()
@@ -738,6 +745,10 @@
         NO_CMAKE_FIND_ROOT_PATH
         NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_SYSTEM_ENVIRONMENT_PATH
         NO_CMAKE_SYSTEM_PATH)
+      # If the imports folder is empty, set QT_IMPORTS_DIR to ${qt_imports_dir}
+      if(NOT QT_IMPORTS_DIR AND qt_imports_dir)
+        set(QT_IMPORTS_DIR ${qt_imports_dir} CACHE PATH "The location of the Qt imports")
+      endif()
       mark_as_advanced(QT_IMPORTS_DIR)
     endif()
   endif ()
diff --git a/Modules/FindwxWidgets.cmake b/Modules/FindwxWidgets.cmake
index e08afe4..e21ec38 100644
--- a/Modules/FindwxWidgets.cmake
+++ b/Modules/FindwxWidgets.cmake
@@ -751,7 +751,7 @@
     #-----------------------------------------------------------------
     # Support cross-compiling, only search in the target platform.
     find_program(wxWidgets_CONFIG_EXECUTABLE
-      NAMES wx-config wx-config-3.1 wx-config-3.0 wx-config-2.9 wx-config-2.8
+      NAMES $ENV{WX_CONFIG} wx-config wx-config-3.1 wx-config-3.0 wx-config-2.9 wx-config-2.8
       DOC "Location of wxWidgets library configuration provider binary (wx-config)."
       ONLY_CMAKE_FIND_ROOT_PATH
       )
@@ -964,8 +964,9 @@
 #=====================================================================
 
 # Resource file compiler.
-find_program(wxWidgets_wxrc_EXECUTABLE wxrc
-  ${wxWidgets_ROOT_DIR}/utils/wxrc/vc_msw
+find_program(wxWidgets_wxrc_EXECUTABLE
+  NAMES $ENV{WXRC_CMD} wxrc
+  PATHS ${wxWidgets_ROOT_DIR}/utils/wxrc/vc_msw
   DOC "Location of wxWidgets resource file compiler binary (wxrc)"
   )
 
diff --git a/Modules/FindwxWindows.cmake b/Modules/FindwxWindows.cmake
index 054a1bf..115cdc6 100644
--- a/Modules/FindwxWindows.cmake
+++ b/Modules/FindwxWindows.cmake
@@ -617,7 +617,8 @@
 
     # wx-config should be in your path anyhow, usually no need to set WXWIN or
     # search in ../wx or ../../wx
-    find_program(CMAKE_WXWINDOWS_WXCONFIG_EXECUTABLE wx-config
+    find_program(CMAKE_WXWINDOWS_WXCONFIG_EXECUTABLE
+      NAMES $ENV{WX_CONFIG} wx-config
       HINTS
         ENV WXWIN
         $ENV{WXWIN}/bin
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 54e5063..6c60675 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -311,11 +311,14 @@
   cmPropertyMap.h
   cmQtAutoGen.cxx
   cmQtAutoGen.h
-  cmQtAutoGenDigest.h
+  cmQtAutoGenerator.cxx
+  cmQtAutoGenerator.h
   cmQtAutoGeneratorInitializer.cxx
   cmQtAutoGeneratorInitializer.h
-  cmQtAutoGenerators.cxx
-  cmQtAutoGenerators.h
+  cmQtAutoGeneratorMocUic.cxx
+  cmQtAutoGeneratorMocUic.h
+  cmQtAutoGeneratorRcc.cxx
+  cmQtAutoGeneratorRcc.h
   cmRST.cxx
   cmRST.h
   cmScriptGenerator.h
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 3b1068f..8b19b84 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,5 +1,5 @@
 # CMake version number components.
 set(CMake_VERSION_MAJOR 3)
 set(CMake_VERSION_MINOR 10)
-set(CMake_VERSION_PATCH 20171118)
+set(CMake_VERSION_PATCH 20171121)
 #set(CMake_VERSION_RC 1)
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index 4ad4831..f25c9c3 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -407,7 +407,7 @@
 
   // Remember start build time
   this->StartBuild = this->CTest->CurrentTime();
-  this->StartBuildTime = cmSystemTools::GetTime();
+  this->StartBuildTime = std::chrono::system_clock::now();
   int retVal = 0;
   int res = cmsysProcess_State_Exited;
   if (!this->CTest->GetShowOnly()) {
@@ -421,7 +421,7 @@
 
   // Remember end build time and calculate elapsed time
   this->EndBuild = this->CTest->CurrentTime();
-  this->EndBuildTime = cmSystemTools::GetTime();
+  this->EndBuildTime = std::chrono::system_clock::now();
   auto elapsed_build_time =
     std::chrono::steady_clock::now() - elapsed_time_start;
 
@@ -488,8 +488,7 @@
   this->CTest->GenerateSubprojectsOutput(xml);
   xml.StartElement("Build");
   xml.Element("StartDateTime", this->StartBuild);
-  xml.Element("StartBuildTime",
-              static_cast<unsigned int>(this->StartBuildTime));
+  xml.Element("StartBuildTime", this->StartBuildTime);
   xml.Element("BuildCommand", this->GetMakeCommand());
 }
 
@@ -644,7 +643,7 @@
   xml.EndElement(); // Log
 
   xml.Element("EndDateTime", this->EndBuild);
-  xml.Element("EndBuildTime", static_cast<unsigned int>(this->EndBuildTime));
+  xml.Element("EndBuildTime", this->EndBuildTime);
   xml.Element(
     "ElapsedMinutes",
     std::chrono::duration_cast<std::chrono::minutes>(elapsed_build_time)
diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h
index 9a29d6d..d1b9b2e 100644
--- a/Source/CTest/cmCTestBuildHandler.h
+++ b/Source/CTest/cmCTestBuildHandler.h
@@ -94,8 +94,8 @@
 
   std::string StartBuild;
   std::string EndBuild;
-  double StartBuildTime;
-  double EndBuildTime;
+  std::chrono::system_clock::time_point StartBuildTime;
+  std::chrono::system_clock::time_point EndBuildTime;
 
   std::vector<std::string> CustomErrorMatches;
   std::vector<std::string> CustomErrorExceptions;
diff --git a/Source/CTest/cmCTestConfigureHandler.cxx b/Source/CTest/cmCTestConfigureHandler.cxx
index e732f9f..ab77986 100644
--- a/Source/CTest/cmCTestConfigureHandler.cxx
+++ b/Source/CTest/cmCTestConfigureHandler.cxx
@@ -4,7 +4,6 @@
 
 #include "cmCTest.h"
 #include "cmGeneratedFileStream.h"
-#include "cmSystemTools.h"
 #include "cmXMLWriter.h"
 
 #include <chrono>
@@ -57,8 +56,7 @@
       return 1;
     }
     std::string start_time = this->CTest->CurrentTime();
-    unsigned int start_time_time =
-      static_cast<unsigned int>(cmSystemTools::GetTime());
+    auto start_time_time = std::chrono::system_clock::now();
 
     cmGeneratedFileStream ofs;
     this->StartLogFile("Configure", ofs);
@@ -84,8 +82,7 @@
       xml.Element("Log", output);
       xml.Element("ConfigureStatus", retVal);
       xml.Element("EndDateTime", this->CTest->CurrentTime());
-      xml.Element("EndConfigureTime",
-                  static_cast<unsigned int>(cmSystemTools::GetTime()));
+      xml.Element("EndConfigureTime", std::chrono::system_clock::now());
       xml.Element("ElapsedMinutes",
                   std::chrono::duration_cast<std::chrono::minutes>(
                     std::chrono::steady_clock::now() - elapsed_time_start)
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index 85f6ce9..bbfe9bd 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -175,14 +175,13 @@
   this->CTest->StartXML(xml, this->AppendXML);
   xml.StartElement("CoverageLog");
   xml.Element("StartDateTime", this->CTest->CurrentTime());
-  xml.Element("StartTime",
-              static_cast<unsigned int>(cmSystemTools::GetTime()));
+  xml.Element("StartTime", std::chrono::system_clock::now());
 }
 
 void cmCTestCoverageHandler::EndCoverageLogXML(cmXMLWriter& xml)
 {
   xml.Element("EndDateTime", this->CTest->CurrentTime());
-  xml.Element("EndTime", static_cast<unsigned int>(cmSystemTools::GetTime()));
+  xml.Element("EndTime", std::chrono::system_clock::now());
   xml.EndElement(); // CoverageLog
   this->CTest->EndXML(xml);
 }
@@ -283,8 +282,7 @@
   }
 
   std::string coverage_start_time = this->CTest->CurrentTime();
-  unsigned int coverage_start_time_time =
-    static_cast<unsigned int>(cmSystemTools::GetTime());
+  auto coverage_start_time_time = std::chrono::system_clock::now();
   std::string sourceDir =
     this->CTest->GetCTestConfiguration("SourceDirectory");
   std::string binaryDir = this->CTest->GetCTestConfiguration("BuildDirectory");
@@ -622,8 +620,7 @@
   covSumXML.Element("LOC", total_lines);
   covSumXML.Element("PercentCoverage", percent_coverage);
   covSumXML.Element("EndDateTime", end_time);
-  covSumXML.Element("EndTime",
-                    static_cast<unsigned int>(cmSystemTools::GetTime()));
+  covSumXML.Element("EndTime", std::chrono::system_clock::now());
   covSumXML.Element("ElapsedMinutes",
                     std::chrono::duration_cast<std::chrono::minutes>(
                       std::chrono::steady_clock::now() - elapsed_time_start)
@@ -1970,8 +1967,7 @@
   std::string coverage_start_time = this->CTest->CurrentTime();
   xml.StartElement("Coverage");
   xml.Element("StartDateTime", coverage_start_time);
-  xml.Element("StartTime",
-              static_cast<unsigned int>(cmSystemTools::GetTime()));
+  xml.Element("StartTime", std::chrono::system_clock::now());
   std::string stdline;
   std::string errline;
   // expected output:
@@ -2092,7 +2088,7 @@
   xml.Element("LOC", total_functions);
   xml.Element("PercentCoverage", SAFEDIV(percent_coverage, number_files));
   xml.Element("EndDateTime", end_time);
-  xml.Element("EndTime", static_cast<unsigned int>(cmSystemTools::GetTime()));
+  xml.Element("EndTime", std::chrono::system_clock::now());
   xml.Element("ElapsedMinutes",
               std::chrono::duration_cast<std::chrono::minutes>(
                 std::chrono::steady_clock::now() - elapsed_time_start)
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index 6534fd1..86fee7a 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -1069,6 +1069,8 @@
   if (subproject) {
     str << "subproject=" << curl.Escape(subproject) << "&";
   }
+  auto timeNow =
+    std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
   str << "stamp=" << curl.Escape(this->CTest->GetCurrentTag()) << "-"
       << curl.Escape(this->CTest->GetTestModelString()) << "&"
       << "model=" << curl.Escape(this->CTest->GetTestModelString()) << "&"
@@ -1077,8 +1079,8 @@
       << "site=" << curl.Escape(this->CTest->GetCTestConfiguration("Site"))
       << "&"
       << "track=" << curl.Escape(this->CTest->GetTestModelString()) << "&"
-      << "starttime=" << static_cast<int>(cmSystemTools::GetTime()) << "&"
-      << "endtime=" << static_cast<int>(cmSystemTools::GetTime()) << "&"
+      << "starttime=" << timeNow << "&"
+      << "endtime=" << timeNow << "&"
       << "datafilesmd5[0]=" << md5sum << "&"
       << "type=" << curl.Escape(typeString);
   std::string fields = str.str();
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index b814e35..e7c719c 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -1204,7 +1204,7 @@
 {
   this->ComputeTestList();
   this->StartTest = this->CTest->CurrentTime();
-  this->StartTestTime = static_cast<unsigned int>(cmSystemTools::GetTime());
+  this->StartTestTime = std::chrono::system_clock::now();
   auto elapsed_time_start = std::chrono::steady_clock::now();
 
   cmCTestMultiProcessHandler* parallel = this->CTest->GetBatchJobs()
@@ -1271,7 +1271,7 @@
   }
   delete parallel;
   this->EndTest = this->CTest->CurrentTime();
-  this->EndTestTime = static_cast<unsigned int>(cmSystemTools::GetTime());
+  this->EndTestTime = std::chrono::system_clock::now();
   this->ElapsedTestingTime =
     std::chrono::steady_clock::now() - elapsed_time_start;
   *this->LogFile << "End testing: " << this->CTest->CurrentTime() << std::endl;
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index af85e72..8572e7b 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -207,8 +207,8 @@
   std::vector<std::string> CustomTestsIgnore;
   std::string StartTest;
   std::string EndTest;
-  unsigned int StartTestTime;
-  unsigned int EndTestTime;
+  std::chrono::system_clock::time_point StartTestTime;
+  std::chrono::system_clock::time_point EndTestTime;
   bool MemCheck;
   int CustomMaximumPassedTestOutputSize;
   int CustomMaximumFailedTestOutputSize;
diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx
index 2bd0253..f86d4a3 100644
--- a/Source/CTest/cmCTestUpdateHandler.cxx
+++ b/Source/CTest/cmCTestUpdateHandler.cxx
@@ -177,8 +177,7 @@
     return -1;
   }
   std::string start_time = this->CTest->CurrentTime();
-  unsigned int start_time_time =
-    static_cast<unsigned int>(cmSystemTools::GetTime());
+  auto start_time_time = std::chrono::system_clock::now();
   auto elapsed_time_start = std::chrono::steady_clock::now();
 
   bool updated = vc->Update();
@@ -226,7 +225,7 @@
   cmCTestOptionalLog(this->CTest, DEBUG, "End" << std::endl, this->Quiet);
   std::string end_time = this->CTest->CurrentTime();
   xml.Element("EndDateTime", end_time);
-  xml.Element("EndTime", static_cast<unsigned int>(cmSystemTools::GetTime()));
+  xml.Element("EndTime", std::chrono::system_clock::now());
   xml.Element("ElapsedMinutes",
               std::chrono::duration_cast<std::chrono::minutes>(
                 std::chrono::steady_clock::now() - elapsed_time_start)
diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx
index 847a416..fcdc632 100644
--- a/Source/cmAuxSourceDirectoryCommand.cxx
+++ b/Source/cmAuxSourceDirectoryCommand.cxx
@@ -54,10 +54,8 @@
         std::string ext = file.substr(dotpos + 1);
         std::string base = file.substr(0, dotpos);
         // Process only source files
-        std::vector<std::string> const& srcExts =
-          this->Makefile->GetCMakeInstance()->GetSourceExtensions();
-        if (!base.empty() &&
-            std::find(srcExts.begin(), srcExts.end(), ext) != srcExts.end()) {
+        auto cm = this->Makefile->GetCMakeInstance();
+        if (!base.empty() && cm->IsSourceExtension(ext)) {
           std::string fullname = templateDirectory;
           fullname += "/";
           fullname += file;
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 92da9ab..d358e3d 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -12,7 +12,7 @@
 #include "cmsys/String.hxx"
 #include "cmsys/SystemInformation.hxx"
 #include <algorithm>
-#include <cstdint>
+#include <chrono>
 #include <ctype.h>
 #include <iostream>
 #include <map>
@@ -1418,7 +1418,7 @@
     std::string note_time = this->CurrentTime();
     xml.StartElement("Note");
     xml.Attribute("Name", file);
-    xml.Element("Time", static_cast<uint64_t>(cmSystemTools::GetTime()));
+    xml.Element("Time", std::chrono::system_clock::now());
     xml.Element("DateTime", note_time);
     xml.StartElement("Text");
     cmsys::ifstream ifs(file.c_str());
diff --git a/Source/cmConnection.cxx b/Source/cmConnection.cxx
index f482412..28ba12c 100644
--- a/Source/cmConnection.cxx
+++ b/Source/cmConnection.cxx
@@ -97,11 +97,10 @@
   this->RawReadBuffer += data;
   if (BufferStrategy) {
     std::string packet = BufferStrategy->BufferMessage(this->RawReadBuffer);
-    do {
+    while (!packet.empty()) {
       ProcessRequest(packet);
       packet = BufferStrategy->BufferMessage(this->RawReadBuffer);
-    } while (!packet.empty());
-
+    }
   } else {
     ProcessRequest(this->RawReadBuffer);
     this->RawReadBuffer.clear();
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index 9c9b75b..76fc8f1 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -345,8 +345,7 @@
   all_files_map_t allFiles;
   std::vector<std::string> cFiles;
 
-  std::vector<std::string> const& srcExts =
-    this->GlobalGenerator->GetCMakeInstance()->GetSourceExtensions();
+  auto cm = this->GlobalGenerator->GetCMakeInstance();
 
   for (cmLocalGenerator* lg : lgs) {
     cmMakefile* makefile = lg->GetMakefile();
@@ -377,12 +376,7 @@
             std::string lang = s->GetLanguage();
             if (lang == "C" || lang == "CXX") {
               std::string const& srcext = s->GetExtension();
-              for (std::string const& ext : srcExts) {
-                if (srcext == ext) {
-                  isCFile = true;
-                  break;
-                }
-              }
+              isCFile = cm->IsSourceExtension(srcext);
             }
 
             std::string const& fullPath = s->GetFullPath();
diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx
index 5a02d54..383942b 100644
--- a/Source/cmExtraCodeLiteGenerator.cxx
+++ b/Source/cmExtraCodeLiteGenerator.cxx
@@ -198,8 +198,7 @@
   std::map<std::string, cmSourceFile*>& cFiles,
   std::set<std::string>& otherFiles)
 {
-  const std::vector<std::string>& srcExts =
-    this->GlobalGenerator->GetCMakeInstance()->GetSourceExtensions();
+  auto cm = this->GlobalGenerator->GetCMakeInstance();
 
   std::string projectType;
   switch (gt->GetType()) {
@@ -233,12 +232,7 @@
         std::string lang = s->GetLanguage();
         if (lang == "C" || lang == "CXX") {
           std::string const& srcext = s->GetExtension();
-          for (std::string const& ext : srcExts) {
-            if (srcext == ext) {
-              isCFile = true;
-              break;
-            }
-          }
+          isCFile = cm->IsSourceExtension(srcext);
         }
 
         // then put it accordingly into one of the two containers
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index a31e415..b3e3393 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -489,7 +489,7 @@
     char const* sourceFullPath = (*si)->GetFullPath().c_str();
     cmSourceGroup* sourceGroup =
       this->Makefile->FindSourceGroup(sourceFullPath, sourceGroups);
-    std::string sgPath(sourceGroup->GetFullName());
+    std::string sgPath = sourceGroup->GetFullName();
     cmSystemTools::ConvertToUnixSlashes(sgPath);
     cmGlobalGhsMultiGenerator::AddFilesUpToPath(
       this->GetFolderBuildStreams(), &this->FolderBuildStreams,
@@ -608,7 +608,7 @@
   cmSourceGroup* sourceGroup =
     localGhsMultiGenerator->GetMakefile()->FindSourceGroup(sourceFullPath,
                                                            sourceGroups);
-  std::string const sgPath(sourceGroup->GetFullName());
+  std::string const& sgPath = sourceGroup->GetFullName();
   dir_max += sgPath;
   dir_max += "/Objs/libs/";
   dir_max += generatorTarget->Target->GetName();
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index eba95f5..6e903fb 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1314,7 +1314,10 @@
 #ifdef CMAKE_BUILD_WITH_CMAKE
   // Iterate through all targets and set up automoc for those which have
   // the AUTOMOC, AUTOUIC or AUTORCC property set
-  cmQtAutoGenDigestUPV autogenDigests = this->CreateQtAutoGeneratorsTargets();
+  auto autogenInits = this->CreateQtAutoGenInitializers();
+  for (auto& autoGen : autogenInits) {
+    autoGen->InitCustomTargets();
+  }
 #endif
 
   // Add generator specific helper commands
@@ -1335,10 +1338,11 @@
   }
 
 #ifdef CMAKE_BUILD_WITH_CMAKE
-  for (cmQtAutoGenDigestUP const& digest : autogenDigests) {
-    cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(*digest);
+  for (auto& autoGen : autogenInits) {
+    autoGen->SetupCustomTargets();
+    autoGen.reset(nullptr);
   }
-  autogenDigests.clear();
+  autogenInits.clear();
 #endif
 
   for (cmLocalGenerator* localGen : this->LocalGenerators) {
@@ -1469,9 +1473,10 @@
   return true;
 }
 
-cmQtAutoGenDigestUPV cmGlobalGenerator::CreateQtAutoGeneratorsTargets()
+std::vector<std::unique_ptr<cmQtAutoGeneratorInitializer>>
+cmGlobalGenerator::CreateQtAutoGenInitializers()
 {
-  cmQtAutoGenDigestUPV autogenDigests;
+  std::vector<std::unique_ptr<cmQtAutoGeneratorInitializer>> autogenInits;
 
 #ifdef CMAKE_BUILD_WITH_CMAKE
   for (cmLocalGenerator* localGen : this->LocalGenerators) {
@@ -1507,25 +1512,12 @@
         continue;
       }
 
-      {
-        cmQtAutoGenDigestUP digest(new cmQtAutoGenDigest(target));
-        digest->QtVersionMajor = std::move(qtVersionMajor);
-        digest->QtVersionMinor =
-          cmQtAutoGeneratorInitializer::GetQtMinorVersion(
-            target, digest->QtVersionMajor);
-        digest->MocEnabled = mocEnabled;
-        digest->UicEnabled = uicEnabled;
-        digest->RccEnabled = rccEnabled;
-        autogenDigests.emplace_back(std::move(digest));
-      }
+      autogenInits.emplace_back(new cmQtAutoGeneratorInitializer(
+        target, mocEnabled, uicEnabled, rccEnabled, qtVersionMajor));
     }
   }
-  // Initialize autogen targets
-  for (const cmQtAutoGenDigestUP& digest : autogenDigests) {
-    cmQtAutoGeneratorInitializer::InitializeAutogenTarget(*digest);
-  }
 #endif
-  return autogenDigests;
+  return autogenInits;
 }
 
 cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer(
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 8fcb533..99f33e5 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -15,7 +15,6 @@
 
 #include "cmCustomCommandLines.h"
 #include "cmExportSetMap.h"
-#include "cmQtAutoGenDigest.h"
 #include "cmStateSnapshot.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
@@ -33,6 +32,7 @@
 class cmLocalGenerator;
 class cmMakefile;
 class cmOutputConverter;
+class cmQtAutoGeneratorInitializer;
 class cmSourceFile;
 class cmStateDirectory;
 class cmake;
@@ -433,7 +433,8 @@
   virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const;
 
   // Qt auto generators
-  cmQtAutoGenDigestUPV CreateQtAutoGeneratorsTargets();
+  std::vector<std::unique_ptr<cmQtAutoGeneratorInitializer>>
+  CreateQtAutoGenInitializers();
 
   std::string SelectMakeProgram(const std::string& makeProgram,
                                 const std::string& makeDefault = "") const;
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index dfc1bed..41fe5d2 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -2797,13 +2797,13 @@
   // If it's the default source group (empty name) then put the source file
   // directly in the tgroup...
   //
-  if (std::string(sg->GetFullName()).empty()) {
+  if (sg->GetFullName().empty()) {
     this->GroupNameMap[s] = tgroup;
     return tgroup;
   }
 
   // It's a recursive folder structure, let's find the real parent group
-  if (std::string(sg->GetFullName()) != std::string(sg->GetName())) {
+  if (sg->GetFullName() != sg->GetName()) {
     std::string curr_folder = target;
     curr_folder += "/";
     for (auto const& folder :
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index beb80f2..f01ed7a 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -1600,7 +1600,7 @@
   }
 
   // If the group has a name, write the header.
-  std::string name = sg->GetName();
+  std::string const& name = sg->GetName();
   if (!name.empty()) {
     this->WriteVCProjBeginGroup(fout, name.c_str(), "");
   }
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 4109b90..0855e79 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -1950,7 +1950,7 @@
 
   // first look for source group starting with the same as the one we want
   for (cmSourceGroup const& srcGroup : this->SourceGroups) {
-    std::string sgName = srcGroup.GetName();
+    std::string const& sgName = srcGroup.GetName();
     if (sgName == name[0]) {
       sg = const_cast<cmSourceGroup*>(&srcGroup);
       break;
@@ -2014,7 +2014,8 @@
   }
   // build the whole source group path
   for (++i; i <= lastElement; ++i) {
-    sg->AddChild(cmSourceGroup(name[i].c_str(), nullptr, sg->GetFullName()));
+    sg->AddChild(
+      cmSourceGroup(name[i].c_str(), nullptr, sg->GetFullName().c_str()));
     sg = sg->LookupChild(name[i].c_str());
   }
 
@@ -3120,9 +3121,16 @@
 cmSourceFile* cmMakefile::GetSource(const std::string& sourceName) const
 {
   cmSourceFileLocation sfl(this, sourceName);
-  for (cmSourceFile* sf : this->SourceFiles) {
-    if (sf->Matches(sfl)) {
-      return sf;
+  auto name = this->GetCMakeInstance()->StripExtension(sfl.GetName());
+#if defined(_WIN32) || defined(__APPLE__)
+  name = cmSystemTools::LowerCase(name);
+#endif
+  auto sfsi = this->SourceFileSearchIndex.find(name);
+  if (sfsi != this->SourceFileSearchIndex.end()) {
+    for (auto sf : sfsi->second) {
+      if (sf->Matches(sfl)) {
+        return sf;
+      }
     }
   }
   return nullptr;
@@ -3136,6 +3144,14 @@
     sf->SetProperty("GENERATED", "1");
   }
   this->SourceFiles.push_back(sf);
+
+  auto name =
+    this->GetCMakeInstance()->StripExtension(sf->GetLocation().GetName());
+#if defined(_WIN32) || defined(__APPLE__)
+  name = cmSystemTools::LowerCase(name);
+#endif
+  this->SourceFileSearchIndex[name].push_back(sf);
+
   return sf;
 }
 
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 6867c02..7c27aef 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -821,7 +821,18 @@
   // libraries, classes, and executables
   mutable cmTargets Targets;
   std::map<std::string, std::string> AliasTargets;
-  std::vector<cmSourceFile*> SourceFiles;
+
+  typedef std::vector<cmSourceFile*> SourceFileVec;
+  SourceFileVec SourceFiles;
+
+  // Because cmSourceFile names are compared in a fuzzy way (see
+  // cmSourceFileLocation::Match()) we can't have a straight mapping from
+  // filename to cmSourceFile.  To make lookups more efficient we store the
+  // Name portion of the cmSourceFileLocation and then compare on the list of
+  // cmSourceFiles that might match that name.  Note that on platforms which
+  // have a case-insensitive filesystem we store the key in all lowercase.
+  typedef std::unordered_map<std::string, SourceFileVec> SourceFileMap;
+  SourceFileMap SourceFileSearchIndex;
 
   // Tests
   std::map<std::string, cmTest*> Tests;
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index f614dca..c39f927 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -211,7 +211,10 @@
          "Define file(GENERATE) behavior for relative paths.", 3, 10, 0,      \
          cmPolicies::WARN)                                                    \
   SELECT(POLICY, CMP0071, "Let AUTOMOC and AUTOUIC process GENERATED files.", \
-         3, 10, 0, cmPolicies::WARN)
+         3, 10, 0, cmPolicies::WARN)                                          \
+  SELECT(POLICY, CMP0072,                                                     \
+         "FindOpenGL prefers GLVND by default when available.", 3, 11, 0,     \
+         cmPolicies::WARN)
 
 #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
 #define CM_FOR_EACH_POLICY_ID(POLICY)                                         \
diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx
index 9dc77ac..b9dd392 100644
--- a/Source/cmQtAutoGen.cxx
+++ b/Source/cmQtAutoGen.cxx
@@ -80,16 +80,6 @@
   baseOpts.insert(baseOpts.end(), extraOpts.begin(), extraOpts.end());
 }
 
-static std::string utilStripCR(std::string const& line)
-{
-  // Strip CR characters rcc may have printed (possibly more than one!).
-  std::string::size_type cr = line.find('\r');
-  if (cr != std::string::npos) {
-    return line.substr(0, cr);
-  }
-  return line;
-}
-
 /// @brief Reads the resource files list from from a .qrc file - Qt4 version
 /// @return True if the .qrc file was successfully parsed
 static bool RccListInputsQt4(std::string const& fileName,
@@ -107,10 +97,10 @@
       qrcContents = osst.str();
     } else {
       if (errorMessage != nullptr) {
-        std::ostringstream ost;
-        ost << "rcc file not readable:\n"
-            << "  " << cmQtAutoGen::Quoted(fileName) << "\n";
-        *errorMessage = ost.str();
+        std::string& err = *errorMessage;
+        err = "rcc file not readable:\n  ";
+        err += cmQtAutoGen::Quoted(fileName);
+        err += "\n";
       }
       allGood = false;
     }
@@ -146,6 +136,7 @@
 /// @brief Reads the resource files list from from a .qrc file - Qt5 version
 /// @return True if the .qrc file was successfully parsed
 static bool RccListInputsQt5(std::string const& rccCommand,
+                             std::vector<std::string> const& rccListOptions,
                              std::string const& fileName,
                              std::vector<std::string>& files,
                              std::string* errorMessage)
@@ -155,24 +146,6 @@
     return false;
   }
 
-  // Read rcc features
-  bool hasDashDashList = false;
-  {
-    std::vector<std::string> command;
-    command.push_back(rccCommand);
-    command.push_back("--help");
-    std::string rccStdOut;
-    std::string rccStdErr;
-    int retVal = 0;
-    bool result = cmSystemTools::RunSingleCommand(
-      command, &rccStdOut, &rccStdErr, &retVal, nullptr,
-      cmSystemTools::OUTPUT_NONE, 0.0, cmProcessOutput::Auto);
-    if (result && retVal == 0 &&
-        rccStdOut.find("--list") != std::string::npos) {
-      hasDashDashList = true;
-    }
-  }
-
   std::string const fileDir = cmSystemTools::GetFilenamePath(fileName);
   std::string const fileNameName = cmSystemTools::GetFilenameName(fileName);
 
@@ -184,7 +157,8 @@
   {
     std::vector<std::string> command;
     command.push_back(rccCommand);
-    command.push_back(hasDashDashList ? "--list" : "-list");
+    command.insert(command.end(), rccListOptions.begin(),
+                   rccListOptions.end());
     command.push_back(fileNameName);
     result = cmSystemTools::RunSingleCommand(
       command, &rccStdOut, &rccStdErr, &retVal, fileDir.c_str(),
@@ -192,22 +166,32 @@
   }
   if (!result || retVal) {
     if (errorMessage != nullptr) {
-      std::ostringstream ost;
-      ost << "rcc list process failed for\n  " << cmQtAutoGen::Quoted(fileName)
-          << "\n"
-          << rccStdOut << "\n"
-          << rccStdErr << "\n";
-      *errorMessage = ost.str();
+      std::string& err = *errorMessage;
+      err = "rcc list process failed for:\n  ";
+      err += cmQtAutoGen::Quoted(fileName);
+      err += "\n";
+      err += rccStdOut;
+      err += "\n";
+      err += rccStdErr;
+      err += "\n";
     }
     return false;
   }
 
+  // Lambda to strip CR characters
+  auto StripCR = [](std::string& line) {
+    std::string::size_type cr = line.find('\r');
+    if (cr != std::string::npos) {
+      line = line.substr(0, cr);
+    }
+  };
+
   // Parse rcc std output
   {
     std::istringstream ostr(rccStdOut);
     std::string oline;
     while (std::getline(ostr, oline)) {
-      oline = utilStripCR(oline);
+      StripCR(oline);
       if (!oline.empty()) {
         files.push_back(oline);
       }
@@ -218,17 +202,17 @@
     std::istringstream estr(rccStdErr);
     std::string eline;
     while (std::getline(estr, eline)) {
-      eline = utilStripCR(eline);
+      StripCR(eline);
       if (cmHasLiteralPrefix(eline, "RCC: Error in")) {
         static std::string searchString = "Cannot find file '";
 
         std::string::size_type pos = eline.find(searchString);
         if (pos == std::string::npos) {
           if (errorMessage != nullptr) {
-            std::ostringstream ost;
-            ost << "rcc lists unparsable output:\n"
-                << cmQtAutoGen::Quoted(eline) << "\n";
-            *errorMessage = ost.str();
+            std::string& err = *errorMessage;
+            err = "rcc lists unparsable output:\n";
+            err += cmQtAutoGen::Quoted(eline);
+            err += "\n";
           }
           return false;
         }
@@ -349,25 +333,26 @@
   MergeOptions(baseOpts, newOpts, valueOpts, isQt5);
 }
 
-bool cmQtAutoGen::RccListInputs(std::string const& qtMajorVersion,
-                                std::string const& rccCommand,
+bool cmQtAutoGen::RccListInputs(std::string const& rccCommand,
+                                std::vector<std::string> const& rccListOptions,
                                 std::string const& fileName,
                                 std::vector<std::string>& files,
                                 std::string* errorMessage)
 {
   bool allGood = false;
   if (cmSystemTools::FileExists(fileName.c_str())) {
-    if (qtMajorVersion == "4") {
+    if (rccListOptions.empty()) {
       allGood = RccListInputsQt4(fileName, files, errorMessage);
     } else {
-      allGood = RccListInputsQt5(rccCommand, fileName, files, errorMessage);
+      allGood = RccListInputsQt5(rccCommand, rccListOptions, fileName, files,
+                                 errorMessage);
     }
   } else {
     if (errorMessage != nullptr) {
-      std::ostringstream ost;
-      ost << "rcc file does not exist:\n"
-          << "  " << cmQtAutoGen::Quoted(fileName) << "\n";
-      *errorMessage = ost.str();
+      std::string& err = *errorMessage;
+      err = "rcc resource file does not exist:\n  ";
+      err += cmQtAutoGen::Quoted(fileName);
+      err += "\n";
     }
   }
   return allGood;
diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h
index acc092f..e769e93 100644
--- a/Source/cmQtAutoGen.h
+++ b/Source/cmQtAutoGen.h
@@ -61,9 +61,9 @@
 
   /// @brief Reads the resource files list from from a .qrc file
   /// @arg fileName Must be the absolute path of the .qrc file
-  /// @return True if the rcc file was successfully parsed
-  static bool RccListInputs(std::string const& qtMajorVersion,
-                            std::string const& rccCommand,
+  /// @return True if the rcc file was successfully read
+  static bool RccListInputs(std::string const& rccCommand,
+                            std::vector<std::string> const& rccListOptions,
                             std::string const& fileName,
                             std::vector<std::string>& files,
                             std::string* errorMessage = nullptr);
diff --git a/Source/cmQtAutoGenDigest.h b/Source/cmQtAutoGenDigest.h
deleted file mode 100644
index 677c397..0000000
--- a/Source/cmQtAutoGenDigest.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#ifndef cmQtAutoGenDigest_h
-#define cmQtAutoGenDigest_h
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include <memory>
-#include <string>
-#include <vector>
-
-class cmGeneratorTarget;
-
-class cmQtAutoGenDigestQrc
-{
-public:
-  cmQtAutoGenDigestQrc()
-    : Generated(false)
-    , Unique(false)
-  {
-  }
-
-public:
-  std::string QrcFile;
-  std::string QrcName;
-  std::string PathChecksum;
-  std::string RccFile;
-  bool Generated;
-  bool Unique;
-  std::vector<std::string> Options;
-  std::vector<std::string> Resources;
-};
-
-/** \class cmQtAutoGenDigest
- * \brief Filtered set of QtAutogen variables for a specific target
- */
-class cmQtAutoGenDigest
-{
-public:
-  cmQtAutoGenDigest(cmGeneratorTarget* target)
-    : Target(target)
-    , MocEnabled(false)
-    , UicEnabled(false)
-    , RccEnabled(false)
-  {
-  }
-
-public:
-  cmGeneratorTarget* Target;
-  std::string QtVersionMajor;
-  std::string QtVersionMinor;
-  bool MocEnabled;
-  bool UicEnabled;
-  bool RccEnabled;
-  std::vector<std::string> Headers;
-  std::vector<std::string> Sources;
-  std::vector<cmQtAutoGenDigestQrc> Qrcs;
-};
-
-// Utility types
-typedef std::unique_ptr<cmQtAutoGenDigest> cmQtAutoGenDigestUP;
-typedef std::vector<cmQtAutoGenDigestUP> cmQtAutoGenDigestUPV;
-
-#endif
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
new file mode 100644
index 0000000..52193af
--- /dev/null
+++ b/Source/cmQtAutoGenerator.cxx
@@ -0,0 +1,320 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmQtAutoGen.h"
+#include "cmQtAutoGenerator.h"
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/Terminal.h"
+
+#include "cmAlgorithms.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+// -- Static functions
+
+static std::string HeadLine(std::string const& title)
+{
+  std::string head = title;
+  head += '\n';
+  head.append(head.size() - 1, '-');
+  head += '\n';
+  return head;
+}
+
+static std::string QuotedCommand(std::vector<std::string> const& command)
+{
+  std::string res;
+  for (std::string const& item : command) {
+    if (!res.empty()) {
+      res.push_back(' ');
+    }
+    std::string const cesc = cmQtAutoGen::Quoted(item);
+    if (item.empty() || (cesc.size() > (item.size() + 2)) ||
+        (cesc.find(' ') != std::string::npos)) {
+      res += cesc;
+    } else {
+      res += item;
+    }
+  }
+  return res;
+}
+
+// -- Class methods
+
+cmQtAutoGenerator::cmQtAutoGenerator()
+  : Verbose(cmSystemTools::HasEnv("VERBOSE"))
+  , ColorOutput(true)
+{
+  {
+    std::string colorEnv;
+    cmSystemTools::GetEnv("COLOR", colorEnv);
+    if (!colorEnv.empty()) {
+      this->ColorOutput = cmSystemTools::IsOn(colorEnv.c_str());
+    }
+  }
+}
+
+bool cmQtAutoGenerator::Run(std::string const& infoFile,
+                            std::string const& config)
+{
+  // Info settings
+  this->InfoFile = infoFile;
+  cmSystemTools::ConvertToUnixSlashes(this->InfoFile);
+  this->InfoDir = cmSystemTools::GetFilenamePath(infoFile);
+  this->InfoConfig = config;
+
+  cmake cm(cmake::RoleScript);
+  cm.SetHomeOutputDirectory(this->InfoDir);
+  cm.SetHomeDirectory(this->InfoDir);
+  cm.GetCurrentSnapshot().SetDefaultDefinitions();
+  cmGlobalGenerator gg(&cm);
+
+  cmStateSnapshot snapshot = cm.GetCurrentSnapshot();
+  snapshot.GetDirectory().SetCurrentBinary(this->InfoDir);
+  snapshot.GetDirectory().SetCurrentSource(this->InfoDir);
+
+  auto makefile = cm::make_unique<cmMakefile>(&gg, snapshot);
+  gg.SetCurrentMakefile(makefile.get());
+
+  return this->Process(makefile.get());
+}
+
+void cmQtAutoGenerator::LogBold(std::string const& message) const
+{
+  cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue |
+                                     cmsysTerminal_Color_ForegroundBold,
+                                   message.c_str(), true, this->ColorOutput);
+}
+
+void cmQtAutoGenerator::LogInfo(cmQtAutoGen::Generator genType,
+                                std::string const& message) const
+{
+  std::string msg = cmQtAutoGen::GeneratorName(genType);
+  msg += ": ";
+  msg += message;
+  if (msg.back() != '\n') {
+    msg.push_back('\n');
+  }
+  cmSystemTools::Stdout(msg.c_str(), msg.size());
+}
+
+void cmQtAutoGenerator::LogWarning(cmQtAutoGen::Generator genType,
+                                   std::string const& message) const
+{
+  std::string msg = cmQtAutoGen::GeneratorName(genType);
+  msg += " warning:";
+  if (message.find('\n') == std::string::npos) {
+    // Single line message
+    msg.push_back(' ');
+  } else {
+    // Multi line message
+    msg.push_back('\n');
+  }
+  // Message
+  msg += message;
+  if (msg.back() != '\n') {
+    msg.push_back('\n');
+  }
+  msg.push_back('\n');
+  cmSystemTools::Stdout(msg.c_str(), msg.size());
+}
+
+void cmQtAutoGenerator::LogFileWarning(cmQtAutoGen::Generator genType,
+                                       std::string const& filename,
+                                       std::string const& message) const
+{
+  std::string msg = "  ";
+  msg += cmQtAutoGen::Quoted(filename);
+  msg.push_back('\n');
+  // Message
+  msg += message;
+  this->LogWarning(genType, msg);
+}
+
+void cmQtAutoGenerator::LogError(cmQtAutoGen::Generator genType,
+                                 std::string const& message) const
+{
+  std::string msg;
+  msg.push_back('\n');
+  msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " error");
+  // Message
+  msg += message;
+  if (msg.back() != '\n') {
+    msg.push_back('\n');
+  }
+  msg.push_back('\n');
+  cmSystemTools::Stderr(msg.c_str(), msg.size());
+}
+
+void cmQtAutoGenerator::LogFileError(cmQtAutoGen::Generator genType,
+                                     std::string const& filename,
+                                     std::string const& message) const
+{
+  std::string emsg = "  ";
+  emsg += cmQtAutoGen::Quoted(filename);
+  emsg += '\n';
+  // Message
+  emsg += message;
+  this->LogError(genType, emsg);
+}
+
+void cmQtAutoGenerator::LogCommandError(
+  cmQtAutoGen::Generator genType, std::string const& message,
+  std::vector<std::string> const& command, std::string const& output) const
+{
+  std::string msg;
+  msg.push_back('\n');
+  msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " subprocess error");
+  msg += message;
+  if (msg.back() != '\n') {
+    msg.push_back('\n');
+  }
+  msg.push_back('\n');
+  msg += HeadLine("Command");
+  msg += QuotedCommand(command);
+  if (msg.back() != '\n') {
+    msg.push_back('\n');
+  }
+  msg.push_back('\n');
+  msg += HeadLine("Output");
+  msg += output;
+  if (msg.back() != '\n') {
+    msg.push_back('\n');
+  }
+  msg.push_back('\n');
+  cmSystemTools::Stderr(msg.c_str(), msg.size());
+}
+
+/**
+ * @brief Generates the parent directory of the given file on demand
+ * @return True on success
+ */
+bool cmQtAutoGenerator::MakeParentDirectory(cmQtAutoGen::Generator genType,
+                                            std::string const& filename) const
+{
+  bool success = true;
+  std::string const dirName = cmSystemTools::GetFilenamePath(filename);
+  if (!dirName.empty()) {
+    if (!cmSystemTools::MakeDirectory(dirName)) {
+      this->LogFileError(genType, filename,
+                         "Could not create parent directory");
+      success = false;
+    }
+  }
+  return success;
+}
+
+/**
+ * @brief Tests if buildFile is older than sourceFile
+ * @return True if buildFile  is older than sourceFile.
+ *         False may indicate an error.
+ */
+bool cmQtAutoGenerator::FileIsOlderThan(std::string const& buildFile,
+                                        std::string const& sourceFile,
+                                        std::string* error)
+{
+  int result = 0;
+  if (cmSystemTools::FileTimeCompare(buildFile, sourceFile, &result)) {
+    return (result < 0);
+  }
+  if (error != nullptr) {
+    error->append(
+      "File modification time comparison failed for the files\n  ");
+    error->append(cmQtAutoGen::Quoted(buildFile));
+    error->append("\nand\n  ");
+    error->append(cmQtAutoGen::Quoted(sourceFile));
+  }
+  return false;
+}
+
+bool cmQtAutoGenerator::FileRead(std::string& content,
+                                 std::string const& filename,
+                                 std::string* error)
+{
+  bool success = false;
+  if (cmSystemTools::FileExists(filename)) {
+    std::size_t const length = cmSystemTools::FileLength(filename);
+    cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary));
+    if (ifs) {
+      content.resize(length);
+      ifs.read(&content.front(), content.size());
+      if (ifs) {
+        success = true;
+      } else {
+        content.clear();
+        if (error != nullptr) {
+          error->append("Reading from the file failed.");
+        }
+      }
+    } else if (error != nullptr) {
+      error->append("Opening the file for reading failed.");
+    }
+  } else if (error != nullptr) {
+    error->append("The file does not exist.");
+  }
+  return success;
+}
+
+bool cmQtAutoGenerator::FileWrite(cmQtAutoGen::Generator genType,
+                                  std::string const& filename,
+                                  std::string const& content)
+{
+  std::string error;
+  // Make sure the parent directory exists
+  if (this->MakeParentDirectory(genType, filename)) {
+    cmsys::ofstream outfile;
+    outfile.open(filename.c_str(),
+                 (std::ios::out | std::ios::binary | std::ios::trunc));
+    if (outfile) {
+      outfile << content;
+      // Check for write errors
+      if (!outfile.good()) {
+        error = "File writing failed";
+      }
+    } else {
+      error = "Opening file for writing failed";
+    }
+  }
+  if (!error.empty()) {
+    this->LogFileError(genType, filename, error);
+    return false;
+  }
+  return true;
+}
+
+bool cmQtAutoGenerator::FileDiffers(std::string const& filename,
+                                    std::string const& content)
+{
+  bool differs = true;
+  {
+    std::string oldContents;
+    if (this->FileRead(oldContents, filename)) {
+      differs = (oldContents != content);
+    }
+  }
+  return differs;
+}
+
+/**
+ * @brief Runs a command and returns true on success
+ * @return True on success
+ */
+bool cmQtAutoGenerator::RunCommand(std::vector<std::string> const& command,
+                                   std::string& output) const
+{
+  // Log command
+  if (this->Verbose) {
+    std::string qcmd = QuotedCommand(command);
+    qcmd.push_back('\n');
+    cmSystemTools::Stdout(qcmd.c_str(), qcmd.size());
+  }
+  // Execute command
+  int retVal = 0;
+  bool res = cmSystemTools::RunSingleCommand(
+    command, &output, &output, &retVal, nullptr, cmSystemTools::OUTPUT_NONE);
+  return (res && (retVal == 0));
+}
diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h
new file mode 100644
index 0000000..285340d
--- /dev/null
+++ b/Source/cmQtAutoGenerator.h
@@ -0,0 +1,76 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmQtAutoGenerator_h
+#define cmQtAutoGenerator_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmQtAutoGen.h"
+
+#include <string>
+#include <vector>
+
+class cmMakefile;
+
+class cmQtAutoGenerator
+{
+  CM_DISABLE_COPY(cmQtAutoGenerator)
+public:
+  cmQtAutoGenerator();
+  virtual ~cmQtAutoGenerator() = default;
+  bool Run(std::string const& infoFile, std::string const& config);
+
+  std::string const& GetInfoFile() const { return InfoFile; }
+  std::string const& GetInfoDir() const { return InfoDir; }
+  std::string const& GetInfoConfig() const { return InfoConfig; }
+  bool GetVerbose() const { return Verbose; }
+
+protected:
+  // -- Central processing
+  virtual bool Process(cmMakefile* makefile) = 0;
+
+  // -- Log info
+  void LogBold(std::string const& message) const;
+  void LogInfo(cmQtAutoGen::Generator genType,
+               std::string const& message) const;
+  // -- Log warning
+  void LogWarning(cmQtAutoGen::Generator genType,
+                  std::string const& message) const;
+  void LogFileWarning(cmQtAutoGen::Generator genType,
+                      std::string const& filename,
+                      std::string const& message) const;
+  // -- Log error
+  void LogError(cmQtAutoGen::Generator genType,
+                std::string const& message) const;
+  void LogFileError(cmQtAutoGen::Generator genType,
+                    std::string const& filename,
+                    std::string const& message) const;
+  void LogCommandError(cmQtAutoGen::Generator genType,
+                       std::string const& message,
+                       std::vector<std::string> const& command,
+                       std::string const& output) const;
+  // -- Utility
+  bool MakeParentDirectory(cmQtAutoGen::Generator genType,
+                           std::string const& filename) const;
+  bool FileIsOlderThan(std::string const& buildFile,
+                       std::string const& sourceFile,
+                       std::string* error = nullptr);
+  bool FileRead(std::string& content, std::string const& filename,
+                std::string* error = nullptr);
+  bool FileWrite(cmQtAutoGen::Generator genType, std::string const& filename,
+                 std::string const& content);
+  bool FileDiffers(std::string const& filename, std::string const& content);
+  bool RunCommand(std::vector<std::string> const& command,
+                  std::string& output) const;
+
+private:
+  // -- Info settings
+  std::string InfoFile;
+  std::string InfoDir;
+  std::string InfoConfig;
+  // -- Settings
+  bool Verbose;
+  bool ColorOutput;
+};
+
+#endif
diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx
index c7550e6..d9a5a9a 100644
--- a/Source/cmQtAutoGeneratorInitializer.cxx
+++ b/Source/cmQtAutoGeneratorInitializer.cxx
@@ -14,6 +14,7 @@
 #include "cmMakefile.h"
 #include "cmOutputConverter.h"
 #include "cmPolicies.h"
+#include "cmProcessOutput.h"
 #include "cmSourceFile.h"
 #include "cmSourceGroup.h"
 #include "cmState.h"
@@ -51,118 +52,6 @@
   return std::string(SafeString(sf->GetProperty(key)));
 }
 
-static cmQtAutoGen::MultiConfig AutogenMultiConfig(
-  cmGlobalGenerator* globalGen)
-{
-  if (!globalGen->IsMultiConfig()) {
-    return cmQtAutoGen::SINGLE;
-  }
-
-  // FIXME: Xcode does not support per-config sources, yet.
-  //        (EXCLUDED_SOURCE_FILE_NAMES)
-  // if (globalGen->GetName().find("Xcode") != std::string::npos) {
-  //  return cmQtAutoGen::FULL;
-  //}
-
-  // FIXME: Visual Studio does not support per-config sources, yet.
-  //        (EXCLUDED_SOURCE_FILE_NAMES)
-  // if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
-  //  return cmQtAutoGen::FULL;
-  //}
-
-  return cmQtAutoGen::WRAP;
-}
-
-static std::string GetAutogenTargetName(cmGeneratorTarget const* target)
-{
-  std::string autogenTargetName = target->GetName();
-  autogenTargetName += "_autogen";
-  return autogenTargetName;
-}
-
-static std::string GetAutogenTargetFilesDir(cmGeneratorTarget const* target)
-{
-  cmMakefile* makefile = target->Target->GetMakefile();
-  std::string targetDir = makefile->GetCurrentBinaryDirectory();
-  targetDir += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();
-  targetDir += "/";
-  targetDir += GetAutogenTargetName(target);
-  targetDir += ".dir";
-  return targetDir;
-}
-
-static std::string GetAutogenTargetBuildDir(cmGeneratorTarget const* target)
-{
-  std::string targetDir = GetSafeProperty(target, "AUTOGEN_BUILD_DIR");
-  if (targetDir.empty()) {
-    cmMakefile* makefile = target->Target->GetMakefile();
-    targetDir = makefile->GetCurrentBinaryDirectory();
-    targetDir += "/";
-    targetDir += GetAutogenTargetName(target);
-  }
-  return targetDir;
-}
-
-std::string cmQtAutoGeneratorInitializer::GetQtMajorVersion(
-  cmGeneratorTarget const* target)
-{
-  cmMakefile* makefile = target->Target->GetMakefile();
-  std::string qtMajor = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
-  if (qtMajor.empty()) {
-    qtMajor = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
-  }
-  const char* targetQtVersion =
-    target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "");
-  if (targetQtVersion != nullptr) {
-    qtMajor = targetQtVersion;
-  }
-  return qtMajor;
-}
-
-std::string cmQtAutoGeneratorInitializer::GetQtMinorVersion(
-  cmGeneratorTarget const* target, std::string const& qtVersionMajor)
-{
-  cmMakefile* makefile = target->Target->GetMakefile();
-  std::string qtMinor;
-  if (qtVersionMajor == "5") {
-    qtMinor = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR");
-  }
-  if (qtMinor.empty()) {
-    qtMinor = makefile->GetSafeDefinition("QT_VERSION_MINOR");
-  }
-
-  const char* targetQtVersion =
-    target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", "");
-  if (targetQtVersion != nullptr) {
-    qtMinor = targetQtVersion;
-  }
-  return qtMinor;
-}
-
-static bool QtVersionGreaterOrEqual(std::string const& major,
-                                    std::string const& minor,
-                                    unsigned long requestMajor,
-                                    unsigned long requestMinor)
-{
-  unsigned long majorUL(0);
-  unsigned long minorUL(0);
-  if (cmSystemTools::StringToULong(major.c_str(), &majorUL) &&
-      cmSystemTools::StringToULong(minor.c_str(), &minorUL)) {
-    return (majorUL > requestMajor) ||
-      (majorUL == requestMajor && minorUL >= requestMinor);
-  }
-  return false;
-}
-
-static void GetConfigs(cmMakefile* makefile, std::string& configDefault,
-                       std::vector<std::string>& configsList)
-{
-  configDefault = makefile->GetConfigurations(configsList);
-  if (configsList.empty()) {
-    configsList.push_back(configDefault);
-  }
-}
-
 static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
                                  std::string const& value)
 {
@@ -258,48 +147,24 @@
                            false);
 }
 
-static std::vector<std::string> AddGeneratedSource(
-  cmGeneratorTarget* target, std::string const& filename,
-  cmQtAutoGen::MultiConfig multiConfig,
-  const std::vector<std::string>& configsList, cmQtAutoGen::Generator genType)
+static std::string FileProjectRelativePath(cmMakefile* makefile,
+                                           std::string const& fileName)
 {
-  std::vector<std::string> genFiles;
-  // Register source file in makefile and source group
-  if (multiConfig != cmQtAutoGen::FULL) {
-    genFiles.push_back(filename);
-  } else {
-    for (std::string const& cfg : configsList) {
-      genFiles.push_back(
-        cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg));
-    }
-  }
+  std::string res;
   {
-    cmMakefile* makefile = target->Target->GetMakefile();
-    for (std::string const& genFile : genFiles) {
-      {
-        cmSourceFile* gFile = makefile->GetOrCreateSource(genFile, true);
-        gFile->SetProperty("GENERATED", "1");
-        gFile->SetProperty("SKIP_AUTOGEN", "On");
-      }
-      AddToSourceGroup(makefile, genFile, genType);
+    std::string pSource = cmSystemTools::RelativePath(
+      makefile->GetCurrentSourceDirectory(), fileName.c_str());
+    std::string pBinary = cmSystemTools::RelativePath(
+      makefile->GetCurrentBinaryDirectory(), fileName.c_str());
+    if (pSource.size() < pBinary.size()) {
+      res = std::move(pSource);
+    } else if (pBinary.size() < fileName.size()) {
+      res = std::move(pBinary);
+    } else {
+      res = fileName;
     }
   }
-
-  // Add source file to target
-  if (multiConfig != cmQtAutoGen::FULL) {
-    target->AddSource(filename);
-  } else {
-    for (std::string const& cfg : configsList) {
-      std::string src = "$<$<CONFIG:";
-      src += cfg;
-      src += ">:";
-      src += cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg);
-      src += ">";
-      target->AddSource(src);
-    }
-  }
-
-  return genFiles;
+  return res;
 }
 
 /* @brief Tests if targetDepend is a STATIC_LIBRARY and if any of its
@@ -346,23 +211,271 @@
   return cycle;
 }
 
-struct cmQtAutoGenSetup
+cmQtAutoGeneratorInitializer::cmQtAutoGeneratorInitializer(
+  cmGeneratorTarget* target, bool mocEnabled, bool uicEnabled, bool rccEnabled,
+  std::string const& qtVersionMajor)
+  : Target(target)
+  , MocEnabled(mocEnabled)
+  , UicEnabled(uicEnabled)
+  , RccEnabled(rccEnabled)
+  , QtVersionMajor(qtVersionMajor)
+  , MultiConfig(cmQtAutoGen::WRAP)
 {
-  std::set<std::string> MocSkip;
-  std::set<std::string> UicSkip;
+  this->QtVersionMinor = cmQtAutoGeneratorInitializer::GetQtMinorVersion(
+    target, this->QtVersionMajor);
+}
 
-  std::map<std::string, std::string> ConfigMocIncludes;
-  std::map<std::string, std::string> ConfigMocDefines;
-  std::map<std::string, std::string> ConfigUicOptions;
-};
-
-static void SetupAcquireSkipFiles(cmQtAutoGenDigest const& digest,
-                                  cmQtAutoGenSetup& setup)
+void cmQtAutoGeneratorInitializer::InitCustomTargets()
 {
-  // Read skip files from makefile sources
+  cmMakefile* makefile = this->Target->Target->GetMakefile();
+  cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
+  cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator();
+
+  // Configurations
+  this->ConfigDefault = makefile->GetConfigurations(this->ConfigsList);
+  if (this->ConfigsList.empty()) {
+    this->ConfigsList.push_back(this->ConfigDefault);
+  }
+
+  // Multi configuration
   {
-    const std::vector<cmSourceFile*>& allSources =
-      digest.Target->Makefile->GetSourceFiles();
+    if (!globalGen->IsMultiConfig()) {
+      this->MultiConfig = cmQtAutoGen::SINGLE;
+    }
+
+    // FIXME: Xcode does not support per-config sources, yet.
+    //        (EXCLUDED_SOURCE_FILE_NAMES)
+    // if (globalGen->GetName().find("Xcode") != std::string::npos) {
+    //  return cmQtAutoGen::FULL;
+    //}
+
+    // FIXME: Visual Studio does not support per-config sources, yet.
+    //        (EXCLUDED_SOURCE_FILE_NAMES)
+    // if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
+    //  return cmQtAutoGen::FULL;
+    //}
+  }
+
+  // Autogen target name
+  this->AutogenTargetName = this->Target->GetName();
+  this->AutogenTargetName += "_autogen";
+
+  // Autogen directories
+  {
+    // Collapsed current binary directory
+    std::string const cbd = cmSystemTools::CollapseFullPath(
+      "", makefile->GetCurrentBinaryDirectory());
+
+    // Autogen info dir
+    this->DirInfo = cbd;
+    this->DirInfo += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();
+    this->DirInfo += "/";
+    this->DirInfo += this->AutogenTargetName;
+    this->DirInfo += ".dir";
+    cmSystemTools::ConvertToUnixSlashes(this->DirInfo);
+
+    // Autogen build dir
+    this->DirBuild = GetSafeProperty(this->Target, "AUTOGEN_BUILD_DIR");
+    if (this->DirBuild.empty()) {
+      this->DirBuild = cbd;
+      this->DirBuild += "/";
+      this->DirBuild += this->AutogenTargetName;
+    }
+    cmSystemTools::ConvertToUnixSlashes(this->DirBuild);
+
+    // Working directory
+    this->DirWork = cbd;
+    cmSystemTools::ConvertToUnixSlashes(this->DirWork);
+  }
+
+  // Autogen files
+  {
+    this->AutogenInfoFile = this->DirInfo;
+    this->AutogenInfoFile += "/AutogenInfo.cmake";
+
+    this->AutogenSettingsFile = this->DirInfo;
+    this->AutogenSettingsFile += "/AutogenOldSettings.cmake";
+  }
+
+  // Autogen target FOLDER property
+  {
+    const char* folder =
+      makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER");
+    if (folder == nullptr) {
+      folder =
+        makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER");
+    }
+    // Inherit FOLDER property from target (#13688)
+    if (folder == nullptr) {
+      folder = SafeString(this->Target->Target->GetProperty("FOLDER"));
+    }
+    if (folder != nullptr) {
+      this->AutogenFolder = folder;
+    }
+  }
+
+  std::set<std::string> autogenDependFiles;
+  std::set<cmTarget*> autogenDependTargets;
+  std::vector<std::string> autogenProvides;
+
+  // Remove build directories on cleanup
+  AddCleanFile(makefile, this->DirBuild);
+  // Remove old settings on cleanup
+  {
+    std::string base = this->DirInfo;
+    base += "/AutogenOldSettings";
+    if (this->MultiConfig == cmQtAutoGen::SINGLE) {
+      AddCleanFile(makefile, base.append(".cmake"));
+    } else {
+      for (std::string const& cfg : this->ConfigsList) {
+        std::string filename = base;
+        filename += "_";
+        filename += cfg;
+        filename += ".cmake";
+        AddCleanFile(makefile, filename);
+      }
+    }
+  }
+
+  // Add moc compilation to generated files list
+  if (this->MocEnabled) {
+    std::string const mocsComp = this->DirBuild + "/mocs_compilation.cpp";
+    auto files = this->AddGeneratedSource(mocsComp, cmQtAutoGen::MOC);
+    for (std::string& file : files) {
+      autogenProvides.push_back(std::move(file));
+    }
+  }
+
+  // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES
+  if (this->MocEnabled || this->UicEnabled) {
+    std::string includeDir = this->DirBuild + "/include";
+    if (this->MultiConfig != cmQtAutoGen::SINGLE) {
+      includeDir += "_$<CONFIG>";
+    }
+    this->Target->AddIncludeDirectory(includeDir, true);
+  }
+
+  // Acquire rcc executable and features
+  if (this->RccEnabled) {
+    {
+      std::string err;
+      if (this->QtVersionMajor == "5") {
+        cmGeneratorTarget* tgt =
+          localGen->FindGeneratorTargetToUse("Qt5::rcc");
+        if (tgt != nullptr) {
+          this->RccExecutable = SafeString(tgt->ImportedGetLocation(""));
+        } else {
+          err = "AUTORCC: Qt5::rcc target not found";
+        }
+      } else if (QtVersionMajor == "4") {
+        cmGeneratorTarget* tgt =
+          localGen->FindGeneratorTargetToUse("Qt4::rcc");
+        if (tgt != nullptr) {
+          this->RccExecutable = SafeString(tgt->ImportedGetLocation(""));
+        } else {
+          err = "AUTORCC: Qt4::rcc target not found";
+        }
+      } else {
+        err = "The AUTORCC feature supports only Qt 4 and Qt 5";
+      }
+      if (!err.empty()) {
+        err += " (";
+        err += this->Target->GetName();
+        err += ")";
+        cmSystemTools::Error(err.c_str());
+      }
+    }
+    // Detect if rcc supports (-)-list
+    if (!this->RccExecutable.empty() && (this->QtVersionMajor == "5")) {
+      std::vector<std::string> command;
+      command.push_back(this->RccExecutable);
+      command.push_back("--help");
+      std::string rccStdOut;
+      std::string rccStdErr;
+      int retVal = 0;
+      bool result = cmSystemTools::RunSingleCommand(
+        command, &rccStdOut, &rccStdErr, &retVal, nullptr,
+        cmSystemTools::OUTPUT_NONE, 0.0, cmProcessOutput::Auto);
+      if (result && retVal == 0 &&
+          rccStdOut.find("--list") != std::string::npos) {
+        this->RccListOptions.push_back("--list");
+      } else {
+        this->RccListOptions.push_back("-list");
+      }
+    }
+  }
+
+  // Extract relevant source files
+  std::vector<std::string> generatedSources;
+  std::vector<std::string> generatedHeaders;
+  {
+    std::string const qrcExt = "qrc";
+    std::vector<cmSourceFile*> srcFiles;
+    this->Target->GetConfigCommonSourceFiles(srcFiles);
+    for (cmSourceFile* sf : srcFiles) {
+      if (sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
+        continue;
+      }
+      // sf->GetExtension() is only valid after sf->GetFullPath() ...
+      std::string const& fPath = sf->GetFullPath();
+      std::string const& ext = sf->GetExtension();
+      // Register generated files that will be scanned by moc or uic
+      if (this->MocEnabled || this->UicEnabled) {
+        cmSystemTools::FileFormat const fileType =
+          cmSystemTools::GetFileFormat(ext.c_str());
+        if ((fileType == cmSystemTools::CXX_FILE_FORMAT) ||
+            (fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
+          std::string const absPath = cmSystemTools::GetRealPath(fPath);
+          if ((this->MocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) ||
+              (this->UicEnabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) {
+            // Register source
+            const bool generated = sf->GetPropertyAsBool("GENERATED");
+            if (fileType == cmSystemTools::HEADER_FILE_FORMAT) {
+              if (generated) {
+                generatedHeaders.push_back(absPath);
+              } else {
+                this->Headers.push_back(absPath);
+              }
+            } else {
+              if (generated) {
+                generatedSources.push_back(absPath);
+              } else {
+                this->Sources.push_back(absPath);
+              }
+            }
+          }
+        }
+      }
+      // Register rcc enabled files
+      if (this->RccEnabled && (ext == qrcExt) &&
+          !sf->GetPropertyAsBool("SKIP_AUTORCC")) {
+        // Register qrc file
+        {
+          Qrc qrc;
+          qrc.QrcFile = cmSystemTools::GetRealPath(fPath);
+          qrc.QrcName =
+            cmSystemTools::GetFilenameWithoutLastExtension(qrc.QrcFile);
+          qrc.Generated = sf->GetPropertyAsBool("GENERATED");
+          // RCC options
+          {
+            std::string const opts = GetSafeProperty(sf, "AUTORCC_OPTIONS");
+            if (!opts.empty()) {
+              cmSystemTools::ExpandListArgument(opts, qrc.Options);
+            }
+          }
+          this->Qrcs.push_back(std::move(qrc));
+        }
+      }
+    }
+    // cmGeneratorTarget::GetConfigCommonSourceFiles computes the target's
+    // sources meta data cache. Clear it so that OBJECT library targets that
+    // are AUTOGEN initialized after this target get their added
+    // mocs_compilation.cpp source acknowledged by this target.
+    this->Target->ClearSourcesCache();
+  }
+  // Read skip files from makefile sources
+  if (this->MocEnabled || this->UicEnabled) {
+    const std::vector<cmSourceFile*>& allSources = makefile->GetSourceFiles();
     for (cmSourceFile* sf : allSources) {
       // sf->GetExtension() is only valid after sf->GetFullPath() ...
       std::string const& fPath = sf->GetFullPath();
@@ -373,458 +486,21 @@
         continue;
       }
       const bool skipAll = sf->GetPropertyAsBool("SKIP_AUTOGEN");
-      const bool mocSkip = digest.MocEnabled &&
-        (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC"));
-      const bool uicSkip = digest.UicEnabled &&
-        (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC"));
+      const bool mocSkip =
+        this->MocEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC"));
+      const bool uicSkip =
+        this->UicEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC"));
       if (mocSkip || uicSkip) {
         std::string const absFile = cmSystemTools::GetRealPath(fPath);
         if (mocSkip) {
-          setup.MocSkip.insert(absFile);
+          this->MocSkip.insert(absFile);
         }
         if (uicSkip) {
-          setup.UicSkip.insert(absFile);
+          this->UicSkip.insert(absFile);
         }
       }
     }
   }
-}
-
-static void SetupAutoTargetMoc(cmQtAutoGenDigest const& digest,
-                               std::string const& configDefault,
-                               std::vector<std::string> const& configsList,
-                               cmQtAutoGenSetup& setup)
-{
-  cmGeneratorTarget const* target = digest.Target;
-  cmLocalGenerator* localGen = target->GetLocalGenerator();
-  cmMakefile* makefile = target->Target->GetMakefile();
-
-  AddDefinitionEscaped(makefile, "_moc_skip", setup.MocSkip);
-  AddDefinitionEscaped(makefile, "_moc_options",
-                       GetSafeProperty(target, "AUTOMOC_MOC_OPTIONS"));
-  AddDefinitionEscaped(makefile, "_moc_relaxed_mode",
-                       makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE"
-                                                                    : "FALSE");
-  AddDefinitionEscaped(makefile, "_moc_macro_names",
-                       GetSafeProperty(target, "AUTOMOC_MACRO_NAMES"));
-  AddDefinitionEscaped(makefile, "_moc_depend_filters",
-                       GetSafeProperty(target, "AUTOMOC_DEPEND_FILTERS"));
-
-  // Compiler predefines
-  if (target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES")) {
-    if (QtVersionGreaterOrEqual(digest.QtVersionMajor, digest.QtVersionMinor,
-                                5, 8)) {
-      AddDefinitionEscaped(
-        makefile, "_moc_predefs_cmd",
-        makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"));
-    }
-  }
-  // Moc includes and compile definitions
-  {
-    auto GetIncludeDirs = [target,
-                           localGen](std::string const& cfg) -> std::string {
-      // Get the include dirs for this target, without stripping the implicit
-      // include dirs off, see
-      // https://gitlab.kitware.com/cmake/cmake/issues/13667
-      std::vector<std::string> includeDirs;
-      localGen->GetIncludeDirectories(includeDirs, target, "CXX", cfg, false);
-      return cmJoin(includeDirs, ";");
-    };
-    auto GetCompileDefinitions =
-      [target, localGen](std::string const& cfg) -> std::string {
-      std::set<std::string> defines;
-      localGen->AddCompileDefinitions(defines, target, cfg, "CXX");
-      return cmJoin(defines, ";");
-    };
-
-    // Default configuration settings
-    std::string const includeDirs = GetIncludeDirs(configDefault);
-    std::string const compileDefs = GetCompileDefinitions(configDefault);
-    // Other configuration settings
-    for (std::string const& cfg : configsList) {
-      {
-        std::string const configIncludeDirs = GetIncludeDirs(cfg);
-        if (configIncludeDirs != includeDirs) {
-          setup.ConfigMocIncludes[cfg] = configIncludeDirs;
-        }
-      }
-      {
-        std::string const configCompileDefs = GetCompileDefinitions(cfg);
-        if (configCompileDefs != compileDefs) {
-          setup.ConfigMocDefines[cfg] = configCompileDefs;
-        }
-      }
-    }
-    AddDefinitionEscaped(makefile, "_moc_include_dirs", includeDirs);
-    AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs);
-  }
-
-  // Moc executable
-  {
-    std::string mocExec;
-    std::string err;
-
-    if (digest.QtVersionMajor == "5") {
-      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::moc");
-      if (tgt != nullptr) {
-        mocExec = SafeString(tgt->ImportedGetLocation(""));
-      } else {
-        err = "AUTOMOC: Qt5::moc target not found";
-      }
-    } else if (digest.QtVersionMajor == "4") {
-      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::moc");
-      if (tgt != nullptr) {
-        mocExec = SafeString(tgt->ImportedGetLocation(""));
-      } else {
-        err = "AUTOMOC: Qt4::moc target not found";
-      }
-    } else {
-      err = "The AUTOMOC feature supports only Qt 4 and Qt 5";
-    }
-
-    if (err.empty()) {
-      AddDefinitionEscaped(makefile, "_qt_moc_executable", mocExec);
-    } else {
-      err += " (" + target->GetName() + ")";
-      cmSystemTools::Error(err.c_str());
-    }
-  }
-}
-
-static void SetupAutoTargetUic(cmQtAutoGenDigest const& digest,
-                               std::string const& config,
-                               std::vector<std::string> const& configs,
-                               cmQtAutoGenSetup& setup)
-{
-  cmGeneratorTarget const* target = digest.Target;
-  cmMakefile* makefile = target->Target->GetMakefile();
-
-  // Uic search paths
-  {
-    std::vector<std::string> uicSearchPaths;
-    {
-      std::string const usp = GetSafeProperty(target, "AUTOUIC_SEARCH_PATHS");
-      if (!usp.empty()) {
-        cmSystemTools::ExpandListArgument(usp, uicSearchPaths);
-        std::string const srcDir = makefile->GetCurrentSourceDirectory();
-        for (std::string& path : uicSearchPaths) {
-          path = cmSystemTools::CollapseFullPath(path, srcDir);
-        }
-      }
-    }
-    AddDefinitionEscaped(makefile, "_uic_search_paths", uicSearchPaths);
-  }
-  // Uic target options
-  {
-    auto UicGetOpts = [target](std::string const& cfg) -> std::string {
-      std::vector<std::string> opts;
-      target->GetAutoUicOptions(opts, cfg);
-      return cmJoin(opts, ";");
-    };
-
-    // Default settings
-    std::string const uicOpts = UicGetOpts(config);
-    AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts);
-
-    // Configuration specific settings
-    for (std::string const& cfg : configs) {
-      std::string const configUicOpts = UicGetOpts(cfg);
-      if (configUicOpts != uicOpts) {
-        setup.ConfigUicOptions[cfg] = configUicOpts;
-      }
-    }
-  }
-  // .ui files skip and options
-  {
-    std::vector<std::string> uiFileFiles;
-    std::vector<std::vector<std::string>> uiFileOptions;
-    {
-      std::string const uiExt = "ui";
-      for (cmSourceFile* sf : makefile->GetSourceFiles()) {
-        // sf->GetExtension() is only valid after sf->GetFullPath() ...
-        std::string const& fPath = sf->GetFullPath();
-        if (sf->GetExtension() == uiExt) {
-          std::string const absFile = cmSystemTools::GetRealPath(fPath);
-          // Check if the file should be skipped
-          if (sf->GetPropertyAsBool("SKIP_AUTOUIC") ||
-              sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
-            setup.UicSkip.insert(absFile);
-          }
-          // Check if the files has uic options
-          std::string const uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS");
-          if (!uicOpts.empty()) {
-            // Check if file isn't skipped
-            if (setup.UicSkip.count(absFile) == 0) {
-              uiFileFiles.push_back(absFile);
-              std::vector<std::string> optsVec;
-              cmSystemTools::ExpandListArgument(uicOpts, optsVec);
-              uiFileOptions.push_back(std::move(optsVec));
-            }
-          }
-        }
-      }
-    }
-    AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles);
-    AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions);
-  }
-
-  AddDefinitionEscaped(makefile, "_uic_skip", setup.UicSkip);
-
-  // Uic executable
-  {
-    std::string err;
-    std::string uicExec;
-
-    cmLocalGenerator* localGen = target->GetLocalGenerator();
-    if (digest.QtVersionMajor == "5") {
-      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::uic");
-      if (tgt != nullptr) {
-        uicExec = SafeString(tgt->ImportedGetLocation(""));
-      } else {
-        // Project does not use Qt5Widgets, but has AUTOUIC ON anyway
-      }
-    } else if (digest.QtVersionMajor == "4") {
-      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::uic");
-      if (tgt != nullptr) {
-        uicExec = SafeString(tgt->ImportedGetLocation(""));
-      } else {
-        err = "AUTOUIC: Qt4::uic target not found";
-      }
-    } else {
-      err = "The AUTOUIC feature supports only Qt 4 and Qt 5";
-    }
-
-    if (err.empty()) {
-      AddDefinitionEscaped(makefile, "_qt_uic_executable", uicExec);
-    } else {
-      err += " (" + target->GetName() + ")";
-      cmSystemTools::Error(err.c_str());
-    }
-  }
-}
-
-static std::string RccGetExecutable(cmGeneratorTarget const* target,
-                                    std::string const& qtMajorVersion)
-{
-  std::string rccExec;
-  std::string err;
-
-  cmLocalGenerator* localGen = target->GetLocalGenerator();
-  if (qtMajorVersion == "5") {
-    cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::rcc");
-    if (tgt != nullptr) {
-      rccExec = SafeString(tgt->ImportedGetLocation(""));
-    } else {
-      err = "AUTORCC: Qt5::rcc target not found";
-    }
-  } else if (qtMajorVersion == "4") {
-    cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::rcc");
-    if (tgt != nullptr) {
-      rccExec = SafeString(tgt->ImportedGetLocation(""));
-    } else {
-      err = "AUTORCC: Qt4::rcc target not found";
-    }
-  } else {
-    err = "The AUTORCC feature supports only Qt 4 and Qt 5";
-  }
-
-  if (!err.empty()) {
-    err += " (" + target->GetName() + ")";
-    cmSystemTools::Error(err.c_str());
-  }
-  return rccExec;
-}
-
-static void SetupAutoTargetRcc(cmQtAutoGenDigest const& digest)
-{
-  std::vector<std::string> rccFiles;
-  std::vector<std::string> rccBuilds;
-  std::vector<std::vector<std::string>> rccOptions;
-  std::vector<std::vector<std::string>> rccInputs;
-
-  for (cmQtAutoGenDigestQrc const& qrcDigest : digest.Qrcs) {
-    rccFiles.push_back(qrcDigest.QrcFile);
-    rccBuilds.push_back(qrcDigest.RccFile);
-    rccOptions.push_back(qrcDigest.Options);
-    rccInputs.push_back(qrcDigest.Resources);
-  }
-
-  cmMakefile* makefile = digest.Target->Target->GetMakefile();
-  AddDefinitionEscaped(makefile, "_qt_rcc_executable",
-                       RccGetExecutable(digest.Target, digest.QtVersionMajor));
-  AddDefinitionEscaped(makefile, "_rcc_files", rccFiles);
-  AddDefinitionEscaped(makefile, "_rcc_builds", rccBuilds);
-  AddDefinitionEscaped(makefile, "_rcc_options", rccOptions);
-  AddDefinitionEscaped(makefile, "_rcc_inputs", rccInputs);
-}
-
-void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
-  cmQtAutoGenDigest& digest)
-{
-  cmGeneratorTarget* target = digest.Target;
-  cmMakefile* makefile = target->Target->GetMakefile();
-  cmLocalGenerator* localGen = target->GetLocalGenerator();
-  cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator();
-
-  std::string const autogenTargetName = GetAutogenTargetName(target);
-  std::string const autogenInfoDir = GetAutogenTargetFilesDir(target);
-  std::string const autogenBuildDir = GetAutogenTargetBuildDir(target);
-  std::string const workingDirectory =
-    cmSystemTools::CollapseFullPath("", makefile->GetCurrentBinaryDirectory());
-
-  cmQtAutoGen::MultiConfig const multiConfig = AutogenMultiConfig(globalGen);
-  std::string configDefault;
-  std::vector<std::string> configsList;
-  GetConfigs(makefile, configDefault, configsList);
-
-  std::set<std::string> autogenDependFiles;
-  std::set<cmTarget*> autogenDependTargets;
-  std::vector<std::string> autogenProvides;
-
-  // Remove build directories on cleanup
-  AddCleanFile(makefile, autogenBuildDir);
-  // Remove old settings on cleanup
-  {
-    std::string base = autogenInfoDir + "/AutogenOldSettings";
-    if (multiConfig == cmQtAutoGen::SINGLE) {
-      AddCleanFile(makefile, base.append(".cmake"));
-    } else {
-      for (std::string const& cfg : configsList) {
-        std::string filename = base;
-        filename += "_";
-        filename += cfg;
-        filename += ".cmake";
-        AddCleanFile(makefile, filename);
-      }
-    }
-  }
-
-  // Compose command lines
-  cmCustomCommandLines commandLines;
-  {
-    cmCustomCommandLine currentLine;
-    currentLine.push_back(cmSystemTools::GetCMakeCommand());
-    currentLine.push_back("-E");
-    currentLine.push_back("cmake_autogen");
-    currentLine.push_back(autogenInfoDir);
-    currentLine.push_back("$<CONFIGURATION>");
-    commandLines.push_back(currentLine);
-  }
-
-  // Compose target comment
-  std::string autogenComment;
-  {
-    std::vector<std::string> toolNames;
-    if (digest.MocEnabled) {
-      toolNames.emplace_back("MOC");
-    }
-    if (digest.UicEnabled) {
-      toolNames.emplace_back("UIC");
-    }
-    if (digest.RccEnabled) {
-      toolNames.emplace_back("RCC");
-    }
-
-    std::string tools = toolNames.front();
-    toolNames.erase(toolNames.begin());
-    if (!toolNames.empty()) {
-      while (toolNames.size() > 1) {
-        tools += ", ";
-        tools += toolNames.front();
-        toolNames.erase(toolNames.begin());
-      }
-      tools += " and " + toolNames.front();
-    }
-    autogenComment = "Automatic " + tools + " for target " + target->GetName();
-  }
-
-  // Add moc compilation to generated files list
-  if (digest.MocEnabled) {
-    std::string const mocsComp = autogenBuildDir + "/mocs_compilation.cpp";
-    auto files = AddGeneratedSource(target, mocsComp, multiConfig, configsList,
-                                    cmQtAutoGen::MOC);
-    for (std::string& file : files) {
-      autogenProvides.push_back(std::move(file));
-    }
-  }
-
-  // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES
-  if (digest.MocEnabled || digest.UicEnabled) {
-    std::string includeDir = autogenBuildDir + "/include";
-    if (multiConfig != cmQtAutoGen::SINGLE) {
-      includeDir += "_$<CONFIG>";
-    }
-    target->AddIncludeDirectory(includeDir, true);
-  }
-
-  // Extract relevant source files
-  std::vector<std::string> generatedSources;
-  std::vector<std::string> generatedHeaders;
-  {
-    std::string const qrcExt = "qrc";
-    std::vector<cmSourceFile*> srcFiles;
-    target->GetConfigCommonSourceFiles(srcFiles);
-    for (cmSourceFile* sf : srcFiles) {
-      if (sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
-        continue;
-      }
-      // sf->GetExtension() is only valid after sf->GetFullPath() ...
-      std::string const& fPath = sf->GetFullPath();
-      std::string const& ext = sf->GetExtension();
-      // Register generated files that will be scanned by moc or uic
-      if (digest.MocEnabled || digest.UicEnabled) {
-        cmSystemTools::FileFormat const fileType =
-          cmSystemTools::GetFileFormat(ext.c_str());
-        if ((fileType == cmSystemTools::CXX_FILE_FORMAT) ||
-            (fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
-          std::string const absPath = cmSystemTools::GetRealPath(fPath);
-          if ((digest.MocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) ||
-              (digest.UicEnabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) {
-            // Register source
-            const bool generated = sf->GetPropertyAsBool("GENERATED");
-            if (fileType == cmSystemTools::HEADER_FILE_FORMAT) {
-              if (generated) {
-                generatedHeaders.push_back(absPath);
-              } else {
-                digest.Headers.push_back(absPath);
-              }
-            } else {
-              if (generated) {
-                generatedSources.push_back(absPath);
-              } else {
-                digest.Sources.push_back(absPath);
-              }
-            }
-          }
-        }
-      }
-      // Register rcc enabled files
-      if (digest.RccEnabled && (ext == qrcExt) &&
-          !sf->GetPropertyAsBool("SKIP_AUTORCC")) {
-        // Register qrc file
-        {
-          cmQtAutoGenDigestQrc qrcDigest;
-          qrcDigest.QrcFile = cmSystemTools::GetRealPath(fPath);
-          qrcDigest.QrcName =
-            cmSystemTools::GetFilenameWithoutLastExtension(qrcDigest.QrcFile);
-          qrcDigest.Generated = sf->GetPropertyAsBool("GENERATED");
-          // RCC options
-          {
-            std::string const opts = GetSafeProperty(sf, "AUTORCC_OPTIONS");
-            if (!opts.empty()) {
-              cmSystemTools::ExpandListArgument(opts, qrcDigest.Options);
-            }
-          }
-          digest.Qrcs.push_back(std::move(qrcDigest));
-        }
-      }
-    }
-    // cmGeneratorTarget::GetConfigCommonSourceFiles computes the target's
-    // sources meta data cache. Clear it so that OBJECT library targets that
-    // are AUTOGEN initialized after this target get their added
-    // mocs_compilation.cpp source acknowledged by this target.
-    target->ClearSourcesCache();
-  }
 
   // Process GENERATED sources and headers
   if (!generatedSources.empty() || !generatedHeaders.empty()) {
@@ -832,7 +508,7 @@
     bool policyAccept = false;
     bool policyWarn = false;
     cmPolicies::PolicyStatus const CMP0071_status =
-      target->Makefile->GetPolicyStatus(cmPolicies::CMP0071);
+      makefile->GetPolicyStatus(cmPolicies::CMP0071);
     switch (CMP0071_status) {
       case cmPolicies::WARN:
         policyWarn = true;
@@ -851,11 +527,11 @@
     if (policyAccept) {
       // Accept GENERATED sources
       for (std::string const& absFile : generatedHeaders) {
-        digest.Headers.push_back(absFile);
+        this->Headers.push_back(absFile);
         autogenDependFiles.insert(absFile);
       }
       for (std::string const& absFile : generatedSources) {
-        digest.Sources.push_back(absFile);
+        this->Sources.push_back(absFile);
         autogenDependFiles.insert(absFile);
       }
     } else {
@@ -865,13 +541,13 @@
         msg += "\n";
         std::string tools;
         std::string property;
-        if (digest.MocEnabled && digest.UicEnabled) {
+        if (this->MocEnabled && this->UicEnabled) {
           tools = "AUTOMOC and AUTOUIC";
           property = "SKIP_AUTOGEN";
-        } else if (digest.MocEnabled) {
+        } else if (this->MocEnabled) {
           tools = "AUTOMOC";
           property = "SKIP_AUTOMOC";
-        } else if (digest.UicEnabled) {
+        } else if (this->UicEnabled) {
           tools = "AUTOUIC";
           property = "SKIP_AUTOUIC";
         }
@@ -896,57 +572,74 @@
         makefile->IssueMessage(cmake::AUTHOR_WARNING, msg);
       }
     }
+    // Clear lists
+    generatedSources.clear();
+    generatedHeaders.clear();
   }
   // Sort headers and sources
-  std::sort(digest.Headers.begin(), digest.Headers.end());
-  std::sort(digest.Sources.begin(), digest.Sources.end());
+  if (this->MocEnabled || this->UicEnabled) {
+    std::sort(this->Headers.begin(), this->Headers.end());
+    std::sort(this->Sources.begin(), this->Sources.end());
+  }
 
   // Process qrc files
-  if (!digest.Qrcs.empty()) {
-    const bool QtV5 = (digest.QtVersionMajor == "5");
-    std::string const rcc = RccGetExecutable(target, digest.QtVersionMajor);
+  if (!this->Qrcs.empty()) {
+    const bool QtV5 = (this->QtVersionMajor == "5");
     // Target rcc options
     std::vector<std::string> optionsTarget;
     cmSystemTools::ExpandListArgument(
-      GetSafeProperty(target, "AUTORCC_OPTIONS"), optionsTarget);
+      GetSafeProperty(this->Target, "AUTORCC_OPTIONS"), optionsTarget);
 
     // Check if file name is unique
-    for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
-      qrcDigest.Unique = true;
-      for (cmQtAutoGenDigestQrc const& qrcDig2 : digest.Qrcs) {
-        if ((&qrcDigest != &qrcDig2) &&
-            (qrcDigest.QrcName == qrcDig2.QrcName)) {
-          qrcDigest.Unique = false;
+    for (Qrc& qrc : this->Qrcs) {
+      qrc.Unique = true;
+      for (Qrc const& qrc2 : this->Qrcs) {
+        if ((&qrc != &qrc2) && (qrc.QrcName == qrc2.QrcName)) {
+          qrc.Unique = false;
           break;
         }
       }
     }
-    // Path checksum
+    // Path checksum and file names
     {
       cmFilePathChecksum const fpathCheckSum(makefile);
-      for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
-        qrcDigest.PathChecksum = fpathCheckSum.getPart(qrcDigest.QrcFile);
+      for (Qrc& qrc : this->Qrcs) {
+        qrc.PathChecksum = fpathCheckSum.getPart(qrc.QrcFile);
         // RCC output file name
-        std::string rccFile = autogenBuildDir + "/";
-        rccFile += qrcDigest.PathChecksum;
-        rccFile += "/qrc_";
-        rccFile += qrcDigest.QrcName;
-        rccFile += ".cpp";
-        qrcDigest.RccFile = std::move(rccFile);
+        {
+          std::string rccFile = this->DirBuild + "/";
+          rccFile += qrc.PathChecksum;
+          rccFile += "/qrc_";
+          rccFile += qrc.QrcName;
+          rccFile += ".cpp";
+          qrc.RccFile = std::move(rccFile);
+        }
+        {
+          std::string base = this->DirInfo;
+          base += "/RCC";
+          base += qrc.QrcName;
+          if (!qrc.Unique) {
+            base += qrc.PathChecksum;
+          }
+          qrc.InfoFile = base;
+          qrc.InfoFile += "Info.cmake";
+          qrc.SettingsFile = base;
+          qrc.SettingsFile += "Settings.cmake";
+        }
       }
     }
     // RCC options
-    for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
+    for (Qrc& qrc : this->Qrcs) {
       // Target options
       std::vector<std::string> opts = optionsTarget;
       // Merge computed "-name XYZ" option
       {
-        std::string name = qrcDigest.QrcName;
+        std::string name = qrc.QrcName;
         // Replace '-' with '_'. The former is not valid for symbol names.
         std::replace(name.begin(), name.end(), '-', '_');
-        if (!qrcDigest.Unique) {
+        if (!qrc.Unique) {
           name += "_";
-          name += qrcDigest.PathChecksum;
+          name += qrc.PathChecksum;
         }
         std::vector<std::string> nameOpts;
         nameOpts.emplace_back("-name");
@@ -954,254 +647,324 @@
         cmQtAutoGen::RccMergeOptions(opts, nameOpts, QtV5);
       }
       // Merge file option
-      cmQtAutoGen::RccMergeOptions(opts, qrcDigest.Options, QtV5);
-      qrcDigest.Options = std::move(opts);
+      cmQtAutoGen::RccMergeOptions(opts, qrc.Options, QtV5);
+      qrc.Options = std::move(opts);
     }
-    for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
+    for (Qrc& qrc : this->Qrcs) {
       // Register file at target
+      std::vector<std::string> const ccOutput =
+        this->AddGeneratedSource(qrc.RccFile, cmQtAutoGen::RCC);
+
+      cmCustomCommandLines commandLines;
       {
-        auto files = AddGeneratedSource(target, qrcDigest.RccFile, multiConfig,
-                                        configsList, cmQtAutoGen::RCC);
-        for (std::string& file : files) {
-          autogenProvides.push_back(std::move(file));
-        }
+        cmCustomCommandLine currentLine;
+        currentLine.push_back(cmSystemTools::GetCMakeCommand());
+        currentLine.push_back("-E");
+        currentLine.push_back("cmake_autorcc");
+        currentLine.push_back(qrc.InfoFile);
+        currentLine.push_back("$<CONFIGURATION>");
+        commandLines.push_back(std::move(currentLine));
       }
-      // Dependencies
-      if (qrcDigest.Generated) {
-        // Add the GENERATED .qrc file to the dependencies
-        autogenDependFiles.insert(qrcDigest.QrcFile);
-      } else {
-        // Add the resource files to the dependencies
+      std::string ccComment = "Automatic RCC for ";
+      ccComment += FileProjectRelativePath(makefile, qrc.QrcFile);
+
+      if (qrc.Generated) {
+        // Create custom rcc target
+        std::string ccName;
         {
-          std::string error;
-          if (cmQtAutoGen::RccListInputs(digest.QtVersionMajor, rcc,
-                                         qrcDigest.QrcFile,
-                                         qrcDigest.Resources, &error)) {
-            for (std::string const& fileName : qrcDigest.Resources) {
-              autogenDependFiles.insert(fileName);
-            }
-          } else {
-            cmSystemTools::Error(error.c_str());
+          ccName = this->Target->GetName();
+          ccName += "_arcc_";
+          ccName += qrc.QrcName;
+          if (!qrc.Unique) {
+            ccName += "_";
+            ccName += qrc.PathChecksum;
+          }
+          std::vector<std::string> ccDepends;
+          // Add the .qrc file to the custom target dependencies
+          ccDepends.push_back(qrc.QrcFile);
+
+          cmTarget* autoRccTarget = makefile->AddUtilityCommand(
+            ccName, true, this->DirWork.c_str(), ccOutput, ccDepends,
+            commandLines, false, ccComment.c_str());
+          // Create autogen generator target
+          localGen->AddGeneratorTarget(
+            new cmGeneratorTarget(autoRccTarget, localGen));
+
+          // Set FOLDER property in autogen target
+          if (!this->AutogenFolder.empty()) {
+            autoRccTarget->SetProperty("FOLDER", this->AutogenFolder.c_str());
           }
         }
-        // Run cmake again when .qrc file changes
-        makefile->AddCMakeDependFile(qrcDigest.QrcFile);
-      }
-    }
-  }
+        // Add autogen target to the origin target dependencies
+        this->Target->Target->AddUtility(ccName, makefile);
+      } else {
+        // Create custom rcc command
+        {
+          std::vector<std::string> ccByproducts;
+          std::vector<std::string> ccDepends;
+          // Add the .qrc file to the custom command dependencies
+          ccDepends.push_back(qrc.QrcFile);
 
-  // Add user defined autogen target dependencies
-  {
-    std::string const deps = GetSafeProperty(target, "AUTOGEN_TARGET_DEPENDS");
-    if (!deps.empty()) {
-      std::vector<std::string> extraDeps;
-      cmSystemTools::ExpandListArgument(deps, extraDeps);
-      for (std::string const& depName : extraDeps) {
-        // Allow target and file dependencies
-        auto* depTarget = makefile->FindTargetToUse(depName);
-        if (depTarget != nullptr) {
-          autogenDependTargets.insert(depTarget);
-        } else {
-          autogenDependFiles.insert(depName);
-        }
-      }
-    }
-  }
-
-  // Use PRE_BUILD on demand
-  bool usePRE_BUILD = false;
-  if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
-    // Under VS use a PRE_BUILD event instead of a separate target to
-    // reduce the number of targets loaded into the IDE.
-    // This also works around a VS 11 bug that may skip updating the target:
-    //  https://connect.microsoft.com/VisualStudio/feedback/details/769495
-    usePRE_BUILD = true;
-  }
-  // Disable PRE_BUILD in some cases
-  if (usePRE_BUILD) {
-    // Cannot use PRE_BUILD with file depends
-    if (!autogenDependFiles.empty()) {
-      usePRE_BUILD = false;
-    }
-  }
-  // Create the autogen target/command
-  if (usePRE_BUILD) {
-    // Add additional autogen target dependencies to origin target
-    for (cmTarget* depTarget : autogenDependTargets) {
-      target->Target->AddUtility(depTarget->GetName(), makefile);
-    }
-
-    // Add the pre-build command directly to bypass the OBJECT_LIBRARY
-    // rejection in cmMakefile::AddCustomCommandToTarget because we know
-    // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case.
-    //
-    // PRE_BUILD does not support file dependencies!
-    const std::vector<std::string> no_output;
-    const std::vector<std::string> no_deps;
-    cmCustomCommand cc(makefile, no_output, autogenProvides, no_deps,
-                       commandLines, autogenComment.c_str(),
-                       workingDirectory.c_str());
-    cc.SetEscapeOldStyle(false);
-    cc.SetEscapeAllowMakeVars(true);
-    target->Target->AddPreBuildCommand(cc);
-  } else {
-
-    // Convert file dependencies std::set to std::vector
-    std::vector<std::string> autogenDepends(autogenDependFiles.begin(),
-                                            autogenDependFiles.end());
-
-    // Add link library target dependencies to the autogen target dependencies
-    for (std::string const& config : configsList) {
-      cmLinkImplementationLibraries const* libs =
-        target->GetLinkImplementationLibraries(config);
-      if (libs != nullptr) {
-        for (cmLinkItem const& item : libs->Libraries) {
-          cmGeneratorTarget const* libTarget = item.Target;
-          if ((libTarget != nullptr) &&
-              !StaticLibraryCycle(target, libTarget, config)) {
-            std::string util;
-            if (configsList.size() > 1) {
-              util += "$<$<CONFIG:";
-              util += config;
-              util += ">:";
+          // Add the resource files to the dependencies
+          {
+            std::string error;
+            if (cmQtAutoGen::RccListInputs(this->RccExecutable,
+                                           this->RccListOptions, qrc.QrcFile,
+                                           qrc.Resources, &error)) {
+              for (std::string const& fileName : qrc.Resources) {
+                // Add resource file to the custom command dependencies
+                ccDepends.push_back(fileName);
+              }
+            } else {
+              cmSystemTools::Error(error.c_str());
             }
-            util += libTarget->GetName();
-            if (configsList.size() > 1) {
-              util += ">";
-            }
-            autogenDepends.push_back(util);
           }
+          makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends,
+                                             /*main_dependency*/ std::string(),
+                                             commandLines, ccComment.c_str(),
+                                             this->DirWork.c_str());
         }
+        // Reconfigure when .qrc file changes
+        makefile->AddCMakeDependFile(qrc.QrcFile);
       }
     }
+  }
 
-    // Create autogen target
-    cmTarget* autogenTarget = makefile->AddUtilityCommand(
-      autogenTargetName, true, workingDirectory.c_str(),
-      /*byproducts=*/autogenProvides, autogenDepends, commandLines, false,
-      autogenComment.c_str());
-    // Create autogen generator target
-    localGen->AddGeneratorTarget(
-      new cmGeneratorTarget(autogenTarget, localGen));
-
-    // Forward origin utilities to autogen target
-    for (std::string const& depName : target->Target->GetUtilities()) {
-      autogenTarget->AddUtility(depName, makefile);
-    }
-    // Add additional autogen target dependencies to autogen target
-    for (cmTarget* depTarget : autogenDependTargets) {
-      autogenTarget->AddUtility(depTarget->GetName(), makefile);
-    }
-
-    // Set FOLDER property in autogen target
+  // Create _autogen target
+  if (this->MocEnabled || this->UicEnabled) {
+    // Add user defined autogen target dependencies
     {
-      const char* autogenFolder =
-        makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER");
-      if (autogenFolder == nullptr) {
-        autogenFolder =
-          makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER");
-      }
-      // Inherit FOLDER property from target (#13688)
-      if (autogenFolder == nullptr) {
-        autogenFolder = SafeString(target->Target->GetProperty("FOLDER"));
-      }
-      if ((autogenFolder != nullptr) && (*autogenFolder != '\0')) {
-        autogenTarget->SetProperty("FOLDER", autogenFolder);
+      std::string const deps =
+        GetSafeProperty(this->Target, "AUTOGEN_TARGET_DEPENDS");
+      if (!deps.empty()) {
+        std::vector<std::string> extraDeps;
+        cmSystemTools::ExpandListArgument(deps, extraDeps);
+        for (std::string const& depName : extraDeps) {
+          // Allow target and file dependencies
+          auto* depTarget = makefile->FindTargetToUse(depName);
+          if (depTarget != nullptr) {
+            autogenDependTargets.insert(depTarget);
+          } else {
+            autogenDependFiles.insert(depName);
+          }
+        }
       }
     }
 
-    // Add autogen target to the origin target dependencies
-    target->Target->AddUtility(autogenTargetName, makefile);
+    // Compose target comment
+    std::string autogenComment;
+    {
+      std::string tools;
+      if (this->MocEnabled) {
+        tools += "MOC";
+      }
+      if (this->UicEnabled) {
+        if (!tools.empty()) {
+          tools += " and ";
+        }
+        tools += "UIC";
+      }
+      autogenComment = "Automatic ";
+      autogenComment += tools;
+      autogenComment += " for target ";
+      autogenComment += this->Target->GetName();
+    }
+
+    // Compose command lines
+    cmCustomCommandLines commandLines;
+    {
+      cmCustomCommandLine currentLine;
+      currentLine.push_back(cmSystemTools::GetCMakeCommand());
+      currentLine.push_back("-E");
+      currentLine.push_back("cmake_autogen");
+      currentLine.push_back(this->AutogenInfoFile);
+      currentLine.push_back("$<CONFIGURATION>");
+      commandLines.push_back(std::move(currentLine));
+    }
+
+    // Use PRE_BUILD on demand
+    bool usePRE_BUILD = false;
+    if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
+      // Under VS use a PRE_BUILD event instead of a separate target to
+      // reduce the number of targets loaded into the IDE.
+      // This also works around a VS 11 bug that may skip updating the target:
+      //  https://connect.microsoft.com/VisualStudio/feedback/details/769495
+      usePRE_BUILD = true;
+    }
+    // Disable PRE_BUILD in some cases
+    if (usePRE_BUILD) {
+      // Cannot use PRE_BUILD with file depends
+      if (!autogenDependFiles.empty()) {
+        usePRE_BUILD = false;
+      }
+    }
+    // Create the autogen target/command
+    if (usePRE_BUILD) {
+      // Add additional autogen target dependencies to origin target
+      for (cmTarget* depTarget : autogenDependTargets) {
+        this->Target->Target->AddUtility(depTarget->GetName(), makefile);
+      }
+
+      // Add the pre-build command directly to bypass the OBJECT_LIBRARY
+      // rejection in cmMakefile::AddCustomCommandToTarget because we know
+      // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case.
+      //
+      // PRE_BUILD does not support file dependencies!
+      const std::vector<std::string> no_output;
+      const std::vector<std::string> no_deps;
+      cmCustomCommand cc(makefile, no_output, autogenProvides, no_deps,
+                         commandLines, autogenComment.c_str(),
+                         this->DirWork.c_str());
+      cc.SetEscapeOldStyle(false);
+      cc.SetEscapeAllowMakeVars(true);
+      this->Target->Target->AddPreBuildCommand(cc);
+    } else {
+
+      // Convert file dependencies std::set to std::vector
+      std::vector<std::string> autogenDepends(autogenDependFiles.begin(),
+                                              autogenDependFiles.end());
+
+      // Add link library target dependencies to the autogen target
+      // dependencies
+      for (std::string const& config : this->ConfigsList) {
+        cmLinkImplementationLibraries const* libs =
+          this->Target->GetLinkImplementationLibraries(config);
+        if (libs != nullptr) {
+          for (cmLinkItem const& item : libs->Libraries) {
+            cmGeneratorTarget const* libTarget = item.Target;
+            if ((libTarget != nullptr) &&
+                !StaticLibraryCycle(this->Target, libTarget, config)) {
+              std::string util;
+              if (this->ConfigsList.size() > 1) {
+                util += "$<$<CONFIG:";
+                util += config;
+                util += ">:";
+              }
+              util += libTarget->GetName();
+              if (this->ConfigsList.size() > 1) {
+                util += ">";
+              }
+              autogenDepends.push_back(util);
+            }
+          }
+        }
+      }
+
+      // Create autogen target
+      cmTarget* autogenTarget = makefile->AddUtilityCommand(
+        this->AutogenTargetName, true, this->DirWork.c_str(),
+        /*byproducts=*/autogenProvides, autogenDepends, commandLines, false,
+        autogenComment.c_str());
+      // Create autogen generator target
+      localGen->AddGeneratorTarget(
+        new cmGeneratorTarget(autogenTarget, localGen));
+
+      // Forward origin utilities to autogen target
+      for (std::string const& depName : this->Target->Target->GetUtilities()) {
+        autogenTarget->AddUtility(depName, makefile);
+      }
+      // Add additional autogen target dependencies to autogen target
+      for (cmTarget* depTarget : autogenDependTargets) {
+        autogenTarget->AddUtility(depTarget->GetName(), makefile);
+      }
+
+      // Set FOLDER property in autogen target
+      if (!this->AutogenFolder.empty()) {
+        autogenTarget->SetProperty("FOLDER", this->AutogenFolder.c_str());
+      }
+
+      // Add autogen target to the origin target dependencies
+      this->Target->Target->AddUtility(this->AutogenTargetName, makefile);
+    }
   }
 }
 
-void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
-  cmQtAutoGenDigest const& digest)
+void cmQtAutoGeneratorInitializer::SetupCustomTargets()
 {
-  cmGeneratorTarget const* target = digest.Target;
-  cmMakefile* makefile = target->Target->GetMakefile();
-  cmQtAutoGen::MultiConfig const multiConfig =
-    AutogenMultiConfig(target->GetGlobalGenerator());
+  cmMakefile* makefile = this->Target->Target->GetMakefile();
 
   // forget the variables added here afterwards again:
   cmMakefile::ScopePushPop varScope(makefile);
   static_cast<void>(varScope);
 
-  // Configurations
-  std::string configDefault;
-  std::vector<std::string> configsList;
+  // Configuration suffixes
   std::map<std::string, std::string> configSuffixes;
-  {
-    configDefault = makefile->GetConfigurations(configsList);
-    if (configsList.empty()) {
-      configsList.push_back("");
-    }
+  for (std::string const& cfg : this->ConfigsList) {
+    std::string& suffix = configSuffixes[cfg];
+    suffix = "_";
+    suffix += cfg;
   }
-  for (std::string const& cfg : configsList) {
-    configSuffixes[cfg] = "_" + cfg;
-  }
-
-  // Configurations settings buffers
-  cmQtAutoGenSetup setup;
 
   // Basic setup
   AddDefinitionEscaped(makefile, "_multi_config",
-                       cmQtAutoGen::MultiConfigName(multiConfig));
-  AddDefinitionEscaped(makefile, "_build_dir",
-                       GetAutogenTargetBuildDir(target));
-  AddDefinitionEscaped(makefile, "_sources", digest.Sources);
-  AddDefinitionEscaped(makefile, "_headers", digest.Headers);
-  AddDefinitionEscaped(makefile, "_qt_version_major", digest.QtVersionMajor);
-  AddDefinitionEscaped(makefile, "_qt_version_minor", digest.QtVersionMinor);
-  {
-    if (digest.MocEnabled || digest.UicEnabled) {
-      SetupAcquireSkipFiles(digest, setup);
-      if (digest.MocEnabled) {
-        SetupAutoTargetMoc(digest, configDefault, configsList, setup);
-      }
-      if (digest.UicEnabled) {
-        SetupAutoTargetUic(digest, configDefault, configsList, setup);
-      }
+                       cmQtAutoGen::MultiConfigName(this->MultiConfig));
+  AddDefinitionEscaped(makefile, "_build_dir", this->DirBuild);
+
+  if (this->MocEnabled || this->UicEnabled) {
+    AddDefinitionEscaped(makefile, "_qt_version_major", this->QtVersionMajor);
+    AddDefinitionEscaped(makefile, "_settings_file",
+                         this->AutogenSettingsFile);
+    AddDefinitionEscaped(makefile, "_sources", this->Sources);
+    AddDefinitionEscaped(makefile, "_headers", this->Headers);
+
+    if (this->MocEnabled) {
+      this->SetupCustomTargetsMoc();
     }
-    if (digest.RccEnabled) {
-      SetupAutoTargetRcc(digest);
+    if (this->UicEnabled) {
+      this->SetupCustomTargetsUic();
     }
   }
+  if (this->RccEnabled) {
+    AddDefinitionEscaped(makefile, "_qt_rcc_executable", this->RccExecutable);
+    AddDefinitionEscaped(makefile, "_qt_rcc_list_options",
+                         this->RccListOptions);
+  }
 
-  // Generate info file
-  {
-    std::string const infoDir = GetAutogenTargetFilesDir(target);
-    if (!cmSystemTools::MakeDirectory(infoDir)) {
-      std::string emsg = ("Could not create directory: ");
-      emsg += cmQtAutoGen::Quoted(infoDir);
-      cmSystemTools::Error(emsg.c_str());
-    }
-    std::string const infoFile = infoDir + "/AutogenInfo.cmake";
-    {
-      std::string infoFileIn = cmSystemTools::GetCMakeRoot();
-      infoFileIn += "/Modules/AutogenInfo.cmake.in";
-      makefile->ConfigureFile(infoFileIn.c_str(), infoFile.c_str(), false,
-                              true, false);
-    }
+  // Create info directory on demand
+  if (!cmSystemTools::MakeDirectory(this->DirInfo)) {
+    std::string emsg = ("Could not create directory: ");
+    emsg += cmQtAutoGen::Quoted(this->DirInfo);
+    cmSystemTools::Error(emsg.c_str());
+  }
 
-    // Append custom definitions to info file
-    // --------------------------------------
-
-    // Ensure we have write permission in case .in was read-only.
+  auto ReOpenInfoFile = [](cmsys::ofstream& ofs,
+                           std::string const& fileName) -> bool {
+    // Ensure we have write permission
     mode_t perm = 0;
 #if defined(_WIN32) && !defined(__CYGWIN__)
     mode_t mode_write = S_IWRITE;
 #else
     mode_t mode_write = S_IWUSR;
 #endif
-    cmSystemTools::GetPermissions(infoFile, perm);
+    cmSystemTools::GetPermissions(fileName, perm);
     if (!(perm & mode_write)) {
-      cmSystemTools::SetPermissions(infoFile, perm | mode_write);
+      cmSystemTools::SetPermissions(fileName, perm | mode_write);
     }
 
-    // Open and write file
-    cmsys::ofstream ofs(infoFile.c_str(), std::ios::app);
-    if (ofs) {
+    ofs.open(fileName.c_str(), std::ios::app);
+    if (!ofs) {
+      // File open error
+      std::string error = "Internal CMake error when trying to open file: ";
+      error += cmQtAutoGen::Quoted(fileName);
+      error += " for writing.";
+      cmSystemTools::Error(error.c_str());
+    }
+    return static_cast<bool>(ofs);
+  };
+
+  // Generate autogen target info file
+  if (this->MocEnabled || this->UicEnabled) {
+    {
+      std::string infoFileIn = cmSystemTools::GetCMakeRoot();
+      infoFileIn += "/Modules/AutogenInfo.cmake.in";
+      makefile->ConfigureFile(
+        infoFileIn.c_str(), this->AutogenInfoFile.c_str(), false, true, false);
+    }
+
+    // Append custom definitions to info file
+    // --------------------------------------
+    cmsys::ofstream ofs;
+    if (ReOpenInfoFile(ofs, this->AutogenInfoFile)) {
       auto OfsWriteMap = [&ofs](
         const char* key, std::map<std::string, std::string> const& map) {
         for (auto const& item : map) {
@@ -1211,15 +974,372 @@
       };
       ofs << "# Configurations options\n";
       OfsWriteMap("AM_CONFIG_SUFFIX", configSuffixes);
-      OfsWriteMap("AM_MOC_DEFINITIONS", setup.ConfigMocDefines);
-      OfsWriteMap("AM_MOC_INCLUDES", setup.ConfigMocIncludes);
-      OfsWriteMap("AM_UIC_TARGET_OPTIONS", setup.ConfigUicOptions);
-    } else {
-      // File open error
-      std::string error = "Internal CMake error when trying to open file: ";
-      error += cmQtAutoGen::Quoted(infoFile);
-      error += " for writing.";
-      cmSystemTools::Error(error.c_str());
+      OfsWriteMap("AM_MOC_DEFINITIONS", this->ConfigMocDefines);
+      OfsWriteMap("AM_MOC_INCLUDES", this->ConfigMocIncludes);
+      OfsWriteMap("AM_UIC_TARGET_OPTIONS", this->ConfigUicOptions);
+      // Settings files (only require for multi configuration generators)
+      if (this->MultiConfig != cmQtAutoGen::SINGLE) {
+        std::map<std::string, std::string> settingsFiles;
+        for (std::string const& cfg : this->ConfigsList) {
+          settingsFiles[cfg] = cmQtAutoGen::AppendFilenameSuffix(
+            this->AutogenSettingsFile, "_" + cfg);
+        }
+        OfsWriteMap("AM_SETTINGS_FILE", settingsFiles);
+      }
     }
   }
+
+  // Generate auto RCC info files
+  if (this->RccEnabled) {
+    std::string infoFileIn = cmSystemTools::GetCMakeRoot();
+    infoFileIn += "/Modules/AutoRccInfo.cmake.in";
+    for (Qrc const& qrc : this->Qrcs) {
+      // Configure info file
+      makefile->ConfigureFile(infoFileIn.c_str(), qrc.InfoFile.c_str(), false,
+                              true, false);
+
+      // Append custom definitions to info file
+      // --------------------------------------
+      cmsys::ofstream ofs;
+      if (ReOpenInfoFile(ofs, qrc.InfoFile)) {
+        {
+          ofs << "# Job\n";
+          auto OfsWrite = [&ofs](const char* key, std::string const& value) {
+            ofs << "set(" << key << " "
+                << cmOutputConverter::EscapeForCMake(value) << ")\n";
+
+          };
+          OfsWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile);
+          OfsWrite("ARCC_SOURCE", qrc.QrcFile);
+          OfsWrite("ARCC_OUTPUT", qrc.RccFile);
+          OfsWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";"));
+          OfsWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";"));
+        }
+        {
+          ofs << "# Configurations options\n";
+          auto OfsWriteMap = [&ofs](
+            const char* key, std::map<std::string, std::string> const& map) {
+            for (auto const& item : map) {
+              ofs << "set(" << key << "_" << item.first << " "
+                  << cmOutputConverter::EscapeForCMake(item.second) << ")\n";
+            }
+          };
+          OfsWriteMap("ARCC_CONFIG_SUFFIX", configSuffixes);
+
+          // Settings files (only require for multi configuration generators)
+          if (this->MultiConfig != cmQtAutoGen::SINGLE) {
+            std::map<std::string, std::string> settingsFiles;
+            for (std::string const& cfg : this->ConfigsList) {
+              settingsFiles[cfg] =
+                cmQtAutoGen::AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg);
+            }
+            OfsWriteMap("ARCC_SETTINGS_FILE", settingsFiles);
+          }
+        }
+      } else {
+        break;
+      }
+    }
+  }
+}
+
+void cmQtAutoGeneratorInitializer::SetupCustomTargetsMoc()
+{
+  cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
+  cmMakefile* makefile = this->Target->Target->GetMakefile();
+
+  AddDefinitionEscaped(makefile, "_moc_skip", this->MocSkip);
+  AddDefinitionEscaped(makefile, "_moc_options",
+                       GetSafeProperty(this->Target, "AUTOMOC_MOC_OPTIONS"));
+  AddDefinitionEscaped(makefile, "_moc_relaxed_mode",
+                       makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE"
+                                                                    : "FALSE");
+  AddDefinitionEscaped(makefile, "_moc_macro_names",
+                       GetSafeProperty(this->Target, "AUTOMOC_MACRO_NAMES"));
+  AddDefinitionEscaped(
+    makefile, "_moc_depend_filters",
+    GetSafeProperty(this->Target, "AUTOMOC_DEPEND_FILTERS"));
+
+  // Compiler predefines
+  if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") &&
+      this->QtVersionGreaterOrEqual(5, 8)) {
+    AddDefinitionEscaped(
+      makefile, "_moc_predefs_cmd",
+      makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"));
+  }
+  // Moc includes and compile definitions
+  {
+    auto GetIncludeDirs = [this,
+                           localGen](std::string const& cfg) -> std::string {
+      // Get the include dirs for this target, without stripping the implicit
+      // include dirs off, see
+      // https://gitlab.kitware.com/cmake/cmake/issues/13667
+      std::vector<std::string> includeDirs;
+      localGen->GetIncludeDirectories(includeDirs, this->Target, "CXX", cfg,
+                                      false);
+      return cmJoin(includeDirs, ";");
+    };
+    auto GetCompileDefinitions =
+      [this, localGen](std::string const& cfg) -> std::string {
+      std::set<std::string> defines;
+      localGen->AddCompileDefinitions(defines, this->Target, cfg, "CXX");
+      return cmJoin(defines, ";");
+    };
+
+    // Default configuration settings
+    std::string const includeDirs = GetIncludeDirs(this->ConfigDefault);
+    std::string const compileDefs = GetCompileDefinitions(this->ConfigDefault);
+    // Other configuration settings
+    for (std::string const& cfg : this->ConfigsList) {
+      {
+        std::string const configIncludeDirs = GetIncludeDirs(cfg);
+        if (configIncludeDirs != includeDirs) {
+          this->ConfigMocIncludes[cfg] = configIncludeDirs;
+        }
+      }
+      {
+        std::string const configCompileDefs = GetCompileDefinitions(cfg);
+        if (configCompileDefs != compileDefs) {
+          this->ConfigMocDefines[cfg] = configCompileDefs;
+        }
+      }
+    }
+    AddDefinitionEscaped(makefile, "_moc_include_dirs", includeDirs);
+    AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs);
+  }
+
+  // Moc executable
+  {
+    std::string mocExec;
+    std::string err;
+
+    if (this->QtVersionMajor == "5") {
+      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::moc");
+      if (tgt != nullptr) {
+        mocExec = SafeString(tgt->ImportedGetLocation(""));
+      } else {
+        err = "AUTOMOC: Qt5::moc target not found";
+      }
+    } else if (this->QtVersionMajor == "4") {
+      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::moc");
+      if (tgt != nullptr) {
+        mocExec = SafeString(tgt->ImportedGetLocation(""));
+      } else {
+        err = "AUTOMOC: Qt4::moc target not found";
+      }
+    } else {
+      err = "The AUTOMOC feature supports only Qt 4 and Qt 5";
+    }
+
+    if (err.empty()) {
+      AddDefinitionEscaped(makefile, "_qt_moc_executable", mocExec);
+    } else {
+      err += " (";
+      err += this->Target->GetName();
+      err += ")";
+      cmSystemTools::Error(err.c_str());
+    }
+  }
+}
+
+void cmQtAutoGeneratorInitializer::SetupCustomTargetsUic()
+{
+  cmMakefile* makefile = this->Target->Target->GetMakefile();
+
+  // Uic search paths
+  {
+    std::vector<std::string> uicSearchPaths;
+    {
+      std::string const usp =
+        GetSafeProperty(this->Target, "AUTOUIC_SEARCH_PATHS");
+      if (!usp.empty()) {
+        cmSystemTools::ExpandListArgument(usp, uicSearchPaths);
+        std::string const srcDir = makefile->GetCurrentSourceDirectory();
+        for (std::string& path : uicSearchPaths) {
+          path = cmSystemTools::CollapseFullPath(path, srcDir);
+        }
+      }
+    }
+    AddDefinitionEscaped(makefile, "_uic_search_paths", uicSearchPaths);
+  }
+  // Uic target options
+  {
+    auto UicGetOpts = [this](std::string const& cfg) -> std::string {
+      std::vector<std::string> opts;
+      this->Target->GetAutoUicOptions(opts, cfg);
+      return cmJoin(opts, ";");
+    };
+
+    // Default settings
+    std::string const uicOpts = UicGetOpts(this->ConfigDefault);
+    AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts);
+
+    // Configuration specific settings
+    for (std::string const& cfg : this->ConfigsList) {
+      std::string const configUicOpts = UicGetOpts(cfg);
+      if (configUicOpts != uicOpts) {
+        this->ConfigUicOptions[cfg] = configUicOpts;
+      }
+    }
+  }
+  // .ui files skip and options
+  {
+    std::vector<std::string> uiFileFiles;
+    std::vector<std::vector<std::string>> uiFileOptions;
+    {
+      std::string const uiExt = "ui";
+      for (cmSourceFile* sf : makefile->GetSourceFiles()) {
+        // sf->GetExtension() is only valid after sf->GetFullPath() ...
+        std::string const& fPath = sf->GetFullPath();
+        if (sf->GetExtension() == uiExt) {
+          std::string const absFile = cmSystemTools::GetRealPath(fPath);
+          // Check if the .ui file should be skipped
+          if (sf->GetPropertyAsBool("SKIP_AUTOUIC") ||
+              sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
+            this->UicSkip.insert(absFile);
+          }
+          // Check if the .ui file has uic options
+          std::string const uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS");
+          if (!uicOpts.empty()) {
+            // Check if file isn't skipped
+            if (this->UicSkip.count(absFile) == 0) {
+              uiFileFiles.push_back(absFile);
+              std::vector<std::string> optsVec;
+              cmSystemTools::ExpandListArgument(uicOpts, optsVec);
+              uiFileOptions.push_back(std::move(optsVec));
+            }
+          }
+        }
+      }
+    }
+    AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles);
+    AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions);
+  }
+
+  AddDefinitionEscaped(makefile, "_uic_skip", this->UicSkip);
+
+  // Uic executable
+  {
+    std::string err;
+    std::string uicExec;
+
+    cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
+    if (this->QtVersionMajor == "5") {
+      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::uic");
+      if (tgt != nullptr) {
+        uicExec = SafeString(tgt->ImportedGetLocation(""));
+      } else {
+        // Project does not use Qt5Widgets, but has AUTOUIC ON anyway
+      }
+    } else if (this->QtVersionMajor == "4") {
+      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::uic");
+      if (tgt != nullptr) {
+        uicExec = SafeString(tgt->ImportedGetLocation(""));
+      } else {
+        err = "AUTOUIC: Qt4::uic target not found";
+      }
+    } else {
+      err = "The AUTOUIC feature supports only Qt 4 and Qt 5";
+    }
+
+    if (err.empty()) {
+      AddDefinitionEscaped(makefile, "_qt_uic_executable", uicExec);
+    } else {
+      err += " (";
+      err += this->Target->GetName();
+      err += ")";
+      cmSystemTools::Error(err.c_str());
+    }
+  }
+}
+
+std::vector<std::string> cmQtAutoGeneratorInitializer::AddGeneratedSource(
+  std::string const& filename, cmQtAutoGen::Generator genType)
+{
+  std::vector<std::string> genFiles;
+  // Register source file in makefile and source group
+  if (this->MultiConfig != cmQtAutoGen::FULL) {
+    genFiles.push_back(filename);
+  } else {
+    for (std::string const& cfg : this->ConfigsList) {
+      genFiles.push_back(
+        cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg));
+    }
+  }
+  {
+    cmMakefile* makefile = this->Target->Target->GetMakefile();
+    for (std::string const& genFile : genFiles) {
+      {
+        cmSourceFile* gFile = makefile->GetOrCreateSource(genFile, true);
+        gFile->SetProperty("GENERATED", "1");
+        gFile->SetProperty("SKIP_AUTOGEN", "On");
+      }
+      AddToSourceGroup(makefile, genFile, genType);
+    }
+  }
+
+  // Add source file to target
+  if (this->MultiConfig != cmQtAutoGen::FULL) {
+    this->Target->AddSource(filename);
+  } else {
+    for (std::string const& cfg : this->ConfigsList) {
+      std::string src = "$<$<CONFIG:";
+      src += cfg;
+      src += ">:";
+      src += cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg);
+      src += ">";
+      this->Target->AddSource(src);
+    }
+  }
+
+  return genFiles;
+}
+
+std::string cmQtAutoGeneratorInitializer::GetQtMajorVersion(
+  cmGeneratorTarget const* target)
+{
+  cmMakefile* makefile = target->Target->GetMakefile();
+  std::string qtMajor = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
+  if (qtMajor.empty()) {
+    qtMajor = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
+  }
+  const char* targetQtVersion =
+    target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "");
+  if (targetQtVersion != nullptr) {
+    qtMajor = targetQtVersion;
+  }
+  return qtMajor;
+}
+
+std::string cmQtAutoGeneratorInitializer::GetQtMinorVersion(
+  cmGeneratorTarget const* target, std::string const& qtVersionMajor)
+{
+  cmMakefile* makefile = target->Target->GetMakefile();
+  std::string qtMinor;
+  if (qtVersionMajor == "5") {
+    qtMinor = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR");
+  }
+  if (qtMinor.empty()) {
+    qtMinor = makefile->GetSafeDefinition("QT_VERSION_MINOR");
+  }
+
+  const char* targetQtVersion =
+    target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", "");
+  if (targetQtVersion != nullptr) {
+    qtMinor = targetQtVersion;
+  }
+  return qtMinor;
+}
+
+bool cmQtAutoGeneratorInitializer::QtVersionGreaterOrEqual(
+  unsigned long requestMajor, unsigned long requestMinor) const
+{
+  unsigned long majorUL(0);
+  unsigned long minorUL(0);
+  if (cmSystemTools::StringToULong(this->QtVersionMajor.c_str(), &majorUL) &&
+      cmSystemTools::StringToULong(this->QtVersionMinor.c_str(), &minorUL)) {
+    return (majorUL > requestMajor) ||
+      (majorUL == requestMajor && minorUL >= requestMinor);
+  }
+  return false;
 }
diff --git a/Source/cmQtAutoGeneratorInitializer.h b/Source/cmQtAutoGeneratorInitializer.h
index b8a5ae4..e06e1c4 100644
--- a/Source/cmQtAutoGeneratorInitializer.h
+++ b/Source/cmQtAutoGeneratorInitializer.h
@@ -4,9 +4,12 @@
 #define cmQtAutoGeneratorInitializer_h
 
 #include "cmConfigure.h" // IWYU pragma: keep
-#include "cmQtAutoGenDigest.h"
+#include "cmQtAutoGen.h"
 
+#include <map>
+#include <set>
 #include <string>
+#include <vector>
 
 class cmGeneratorTarget;
 
@@ -17,8 +20,78 @@
   static std::string GetQtMinorVersion(cmGeneratorTarget const* target,
                                        std::string const& qtVersionMajor);
 
-  static void InitializeAutogenTarget(cmQtAutoGenDigest& digest);
-  static void SetupAutoGenerateTarget(cmQtAutoGenDigest const& digest);
+  class Qrc
+  {
+  public:
+    Qrc()
+      : Generated(false)
+      , Unique(false)
+    {
+    }
+
+  public:
+    std::string QrcFile;
+    std::string QrcName;
+    std::string PathChecksum;
+    std::string InfoFile;
+    std::string SettingsFile;
+    std::string RccFile;
+    bool Generated;
+    bool Unique;
+    std::vector<std::string> Options;
+    std::vector<std::string> Resources;
+  };
+
+public:
+  cmQtAutoGeneratorInitializer(cmGeneratorTarget* target, bool mocEnabled,
+                               bool uicEnabled, bool rccEnabled,
+                               std::string const& qtVersionMajor);
+
+  void InitCustomTargets();
+  void SetupCustomTargets();
+
+private:
+  void SetupCustomTargetsMoc();
+  void SetupCustomTargetsUic();
+
+  std::vector<std::string> AddGeneratedSource(std::string const& filename,
+                                              cmQtAutoGen::Generator genType);
+
+  bool QtVersionGreaterOrEqual(unsigned long requestMajor,
+                               unsigned long requestMinor) const;
+
+private:
+  cmGeneratorTarget* Target;
+  bool MocEnabled;
+  bool UicEnabled;
+  bool RccEnabled;
+  // Qt
+  std::string QtVersionMajor;
+  std::string QtVersionMinor;
+  std::string RccExecutable;
+  std::vector<std::string> RccListOptions;
+  // Configurations
+  std::string ConfigDefault;
+  std::vector<std::string> ConfigsList;
+  cmQtAutoGen::MultiConfig MultiConfig;
+  // Names
+  std::string AutogenTargetName;
+  std::string AutogenFolder;
+  std::string AutogenInfoFile;
+  std::string AutogenSettingsFile;
+  // Directories
+  std::string DirInfo;
+  std::string DirBuild;
+  std::string DirWork;
+  // Sources
+  std::vector<std::string> Headers;
+  std::vector<std::string> Sources;
+  std::set<std::string> MocSkip;
+  std::set<std::string> UicSkip;
+  std::map<std::string, std::string> ConfigMocIncludes;
+  std::map<std::string, std::string> ConfigMocDefines;
+  std::map<std::string, std::string> ConfigUicOptions;
+  std::vector<Qrc> Qrcs;
 };
 
 #endif
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGeneratorMocUic.cxx
similarity index 69%
rename from Source/cmQtAutoGenerators.cxx
rename to Source/cmQtAutoGeneratorMocUic.cxx
index 28a8df1..0de02b5 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGeneratorMocUic.cxx
@@ -1,10 +1,8 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmQtAutoGen.h"
-#include "cmQtAutoGenerators.h"
+#include "cmQtAutoGeneratorMocUic.h"
 
-#include "cmsys/FStream.hxx"
-#include "cmsys/Terminal.h"
 #include <algorithm>
 #include <array>
 #include <list>
@@ -15,12 +13,8 @@
 
 #include "cmAlgorithms.h"
 #include "cmCryptoHash.h"
-#include "cmFilePathChecksum.h"
-#include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
 #include "cmOutputConverter.h"
-#include "cmStateDirectory.h"
-#include "cmStateSnapshot.h"
 #include "cmSystemTools.h"
 #include "cmake.h"
 
@@ -32,37 +26,9 @@
 
 static const char* SettingsKeyMoc = "AM_MOC_SETTINGS_HASH";
 static const char* SettingsKeyUic = "AM_UIC_SETTINGS_HASH";
-static const char* SettingsKeyRcc = "AM_RCC_SETTINGS_HASH";
 
 // -- Static functions
 
-static std::string HeadLine(std::string const& title)
-{
-  std::string head = title;
-  head += '\n';
-  head.append(head.size() - 1, '-');
-  head += '\n';
-  return head;
-}
-
-static std::string QuotedCommand(std::vector<std::string> const& command)
-{
-  std::string res;
-  for (std::string const& item : command) {
-    if (!res.empty()) {
-      res.push_back(' ');
-    }
-    std::string const cesc = cmQtAutoGen::Quoted(item);
-    if (item.empty() || (cesc.size() > (item.size() + 2)) ||
-        (cesc.find(' ') != std::string::npos)) {
-      res += cesc;
-    } else {
-      res += item;
-    }
-  }
-  return res;
-}
-
 static std::string SubDirPrefix(std::string const& fileName)
 {
   std::string res(cmSystemTools::GetFilenamePath(fileName));
@@ -72,56 +38,6 @@
   return res;
 }
 
-static bool ReadFile(std::string& content, std::string const& filename,
-                     std::string* error = nullptr)
-{
-  bool success = false;
-  if (cmSystemTools::FileExists(filename)) {
-    std::size_t const length = cmSystemTools::FileLength(filename);
-    cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary));
-    if (ifs) {
-      content.resize(length);
-      ifs.read(&content.front(), content.size());
-      if (ifs) {
-        success = true;
-      } else {
-        content.clear();
-        if (error != nullptr) {
-          error->append("Reading from the file failed.");
-        }
-      }
-    } else if (error != nullptr) {
-      error->append("Opening the file for reading failed.");
-    }
-  } else if (error != nullptr) {
-    error->append("The file does not exist.");
-  }
-  return success;
-}
-
-/**
- * @brief Tests if buildFile is older than sourceFile
- * @return True if buildFile  is older than sourceFile.
- *         False may indicate an error.
- */
-static bool FileIsOlderThan(std::string const& buildFile,
-                            std::string const& sourceFile,
-                            std::string* error = nullptr)
-{
-  int result = 0;
-  if (cmSystemTools::FileTimeCompare(buildFile, sourceFile, &result)) {
-    return (result < 0);
-  }
-  if (error != nullptr) {
-    error->append(
-      "File modification time comparison failed for the files\n  ");
-    error->append(cmQtAutoGen::Quoted(buildFile));
-    error->append("\nand\n  ");
-    error->append(cmQtAutoGen::Quoted(sourceFile));
-  }
-  return false;
-}
-
 static bool ListContains(std::vector<std::string> const& list,
                          std::string const& entry)
 {
@@ -130,25 +46,15 @@
 
 // -- Class methods
 
-cmQtAutoGenerators::cmQtAutoGenerators()
+cmQtAutoGeneratorMocUic::cmQtAutoGeneratorMocUic()
   : MultiConfig(cmQtAutoGen::WRAP)
   , IncludeProjectDirsBefore(false)
-  , Verbose(cmSystemTools::HasEnv("VERBOSE"))
-  , ColorOutput(true)
+  , QtVersionMajor(4)
   , MocSettingsChanged(false)
   , MocPredefsChanged(false)
   , MocRelaxedMode(false)
   , UicSettingsChanged(false)
-  , RccSettingsChanged(false)
 {
-  {
-    std::string colorEnv;
-    cmSystemTools::GetEnv("COLOR", colorEnv);
-    if (!colorEnv.empty()) {
-      this->ColorOutput = cmSystemTools::IsOn(colorEnv.c_str());
-    }
-  }
-
   // Precompile regular expressions
   this->MocRegExpInclude.compile(
     "[\n][ \t]*#[ \t]*include[ \t]+"
@@ -157,39 +63,7 @@
                                  "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
 }
 
-bool cmQtAutoGenerators::Run(std::string const& targetDirectory,
-                             std::string const& config)
-{
-  cmake cm(cmake::RoleScript);
-  cm.SetHomeOutputDirectory(targetDirectory);
-  cm.SetHomeDirectory(targetDirectory);
-  cm.GetCurrentSnapshot().SetDefaultDefinitions();
-  cmGlobalGenerator gg(&cm);
-
-  cmStateSnapshot snapshot = cm.GetCurrentSnapshot();
-  snapshot.GetDirectory().SetCurrentBinary(targetDirectory);
-  snapshot.GetDirectory().SetCurrentSource(targetDirectory);
-
-  auto makefile = cm::make_unique<cmMakefile>(&gg, snapshot);
-  gg.SetCurrentMakefile(makefile.get());
-
-  bool success = false;
-  if (this->InitInfoFile(makefile.get(), targetDirectory, config)) {
-    // Read latest settings
-    this->SettingsFileRead(makefile.get());
-    if (this->Process()) {
-      // Write current settings
-      if (this->SettingsFileWrite()) {
-        success = true;
-      }
-    }
-  }
-  return success;
-}
-
-bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile,
-                                      std::string const& targetDirectory,
-                                      std::string const& config)
+bool cmQtAutoGeneratorMocUic::InitInfoFile(cmMakefile* makefile)
 {
   // -- Meta
   this->HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions();
@@ -233,12 +107,12 @@
     }
     return lists;
   };
-  auto InfoGetConfig = [makefile, &config](const char* key) -> std::string {
+  auto InfoGetConfig = [makefile, this](const char* key) -> std::string {
     const char* valueConf = nullptr;
     {
       std::string keyConf = key;
       keyConf += '_';
-      keyConf += config;
+      keyConf += this->GetInfoConfig();
       valueConf = makefile->GetDefinition(keyConf);
     }
     if (valueConf == nullptr) {
@@ -254,11 +128,8 @@
   };
 
   // -- Read info file
-  this->InfoFile = cmSystemTools::CollapseFullPath(targetDirectory);
-  cmSystemTools::ConvertToUnixSlashes(this->InfoFile);
-  this->InfoFile += "/AutogenInfo.cmake";
-  if (!makefile->ReadListFile(this->InfoFile.c_str())) {
-    this->LogFileError(cmQtAutoGen::GEN, this->InfoFile,
+  if (!makefile->ReadListFile(this->GetInfoFile().c_str())) {
+    this->LogFileError(cmQtAutoGen::GEN, this->GetInfoFile(),
                        "File processing failed");
     return false;
   }
@@ -268,7 +139,14 @@
   this->ConfigSuffix = InfoGetConfig("AM_CONFIG_SUFFIX");
   if (this->ConfigSuffix.empty()) {
     this->ConfigSuffix = "_";
-    this->ConfigSuffix += config;
+    this->ConfigSuffix += this->GetInfoConfig();
+  }
+
+  this->SettingsFile = InfoGetConfig("AM_SETTINGS_FILE");
+  if (this->SettingsFile.empty()) {
+    this->LogFileError(cmQtAutoGen::GEN, this->GetInfoFile(),
+                       "Settings file name missing");
+    return false;
   }
 
   // - Files and directories
@@ -280,25 +158,18 @@
     InfoGetBool("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE");
   this->AutogenBuildDir = InfoGet("AM_BUILD_DIR");
   if (this->AutogenBuildDir.empty()) {
-    this->LogFileError(cmQtAutoGen::GEN, this->InfoFile,
+    this->LogFileError(cmQtAutoGen::GEN, this->GetInfoFile(),
                        "Autogen build directory missing");
     return false;
   }
 
   // - Qt environment
-  this->QtMajorVersion = InfoGet("AM_QT_VERSION_MAJOR");
-  this->QtMinorVersion = InfoGet("AM_QT_VERSION_MINOR");
+  if (!cmSystemTools::StringToULong(InfoGet("AM_QT_VERSION_MAJOR"),
+                                    &this->QtVersionMajor)) {
+    this->QtVersionMajor = 4;
+  }
   this->MocExecutable = InfoGet("AM_QT_MOC_EXECUTABLE");
   this->UicExecutable = InfoGet("AM_QT_UIC_EXECUTABLE");
-  this->RccExecutable = InfoGet("AM_QT_RCC_EXECUTABLE");
-
-  // Check Qt version
-  if ((this->QtMajorVersion != "4") && (this->QtMajorVersion != "5")) {
-    this->LogFileError(cmQtAutoGen::GEN, this->InfoFile,
-                       "Unsupported Qt version: " +
-                         cmQtAutoGen::Quoted(this->QtMajorVersion));
-    return false;
-  }
 
   // - Moc
   if (this->MocEnabled()) {
@@ -327,7 +198,7 @@
       std::vector<std::string> const mocDependFilters =
         InfoGetList("AM_MOC_DEPEND_FILTERS");
       // Insert Q_PLUGIN_METADATA dependency filter
-      if (this->QtMajorVersion != "4") {
+      if (this->QtVersionMajor != 4) {
         this->MocDependFilterPush("Q_PLUGIN_METADATA",
                                   "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\("
                                   "[^\\)]*FILE[ \t]*\"([^\"]+)\"");
@@ -344,7 +215,7 @@
         }
       } else {
         this->LogFileError(
-          cmQtAutoGen::MOC, this->InfoFile,
+          cmQtAutoGen::MOC, this->GetInfoFile(),
           "AUTOMOC_DEPEND_FILTERS list size is not a multiple of 2");
         return false;
       }
@@ -365,7 +236,7 @@
         std::ostringstream ost;
         ost << "files/options lists sizes missmatch (" << sources.size() << "/"
             << options.size() << ")";
-        this->LogFileError(cmQtAutoGen::UIC, this->InfoFile, ost.str());
+        this->LogFileError(cmQtAutoGen::UIC, this->GetInfoFile(), ost.str());
         return false;
       }
       auto fitEnd = sources.cend();
@@ -379,53 +250,6 @@
     }
   }
 
-  // - Rcc
-  if (this->RccEnabled()) {
-    // File lists
-    auto sources = InfoGetList("AM_RCC_SOURCES");
-    auto builds = InfoGetList("AM_RCC_BUILDS");
-    auto options = InfoGetLists("AM_RCC_OPTIONS");
-    auto inputs = InfoGetLists("AM_RCC_INPUTS");
-
-    if (sources.size() != builds.size()) {
-      std::ostringstream ost;
-      ost << "sources, builds lists sizes missmatch (" << sources.size() << "/"
-          << builds.size() << ")";
-      this->LogFileError(cmQtAutoGen::RCC, this->InfoFile, ost.str());
-      return false;
-    }
-    if (sources.size() != options.size()) {
-      std::ostringstream ost;
-      ost << "sources, options lists sizes missmatch (" << sources.size()
-          << "/" << options.size() << ")";
-      this->LogFileError(cmQtAutoGen::RCC, this->InfoFile, ost.str());
-      return false;
-    }
-    if (sources.size() != inputs.size()) {
-      std::ostringstream ost;
-      ost << "sources, inputs lists sizes missmatch (" << sources.size() << "/"
-          << inputs.size() << ")";
-      this->LogFileError(cmQtAutoGen::RCC, this->InfoFile, ost.str());
-      return false;
-    }
-    {
-      auto srcItEnd = sources.end();
-      auto srcIt = sources.begin();
-      auto bldIt = builds.begin();
-      auto optIt = options.begin();
-      auto inpIt = inputs.begin();
-      while (srcIt != srcItEnd) {
-        this->RccJobs.push_back(RccJob{ std::move(*srcIt), std::move(*bldIt),
-                                        std::move(*optIt),
-                                        std::move(*inpIt) });
-        ++srcIt;
-        ++bldIt;
-        ++optIt;
-        ++inpIt;
-      }
-    }
-  }
-
   // Initialize source file jobs
   {
     // Utility lambdas
@@ -585,21 +409,10 @@
     }
   }
 
-  // - Old settings file
-  {
-    this->SettingsFile = cmSystemTools::CollapseFullPath(targetDirectory);
-    cmSystemTools::ConvertToUnixSlashes(this->SettingsFile);
-    this->SettingsFile += "/AutogenOldSettings";
-    if (this->MultiConfig != cmQtAutoGen::SINGLE) {
-      this->SettingsFile += this->ConfigSuffix;
-    }
-    this->SettingsFile += ".cmake";
-  }
-
   return true;
 }
 
-void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile)
+void cmQtAutoGeneratorMocUic::SettingsFileRead(cmMakefile* makefile)
 {
   // Compose current settings strings
   {
@@ -631,20 +444,6 @@
       str += sep;
       this->SettingsStringUic = crypt.HashString(str);
     }
-    if (this->RccEnabled()) {
-      std::string str;
-      str += this->RccExecutable;
-      for (const RccJob& rccJob : this->RccJobs) {
-        str += sep;
-        str += rccJob.QrcFile;
-        str += sep;
-        str += rccJob.RccFile;
-        str += sep;
-        str += cmJoin(rccJob.Options, ";");
-      }
-      str += sep;
-      this->SettingsStringRcc = crypt.HashString(str);
-    }
   }
 
   // Read old settings
@@ -659,9 +458,6 @@
       if (!SMatch(SettingsKeyUic, this->SettingsStringUic)) {
         this->UicSettingsChanged = true;
       }
-      if (!SMatch(SettingsKeyRcc, this->SettingsStringRcc)) {
-        this->RccSettingsChanged = true;
-      }
     }
     // In case any setting changed remove the old settings file.
     // This triggers a full rebuild on the next run if the current
@@ -673,16 +469,15 @@
     // If the file could not be read re-generate everythiung.
     this->MocSettingsChanged = true;
     this->UicSettingsChanged = true;
-    this->RccSettingsChanged = true;
   }
 }
 
-bool cmQtAutoGenerators::SettingsFileWrite()
+bool cmQtAutoGeneratorMocUic::SettingsFileWrite()
 {
   bool success = true;
   // Only write if any setting changed
   if (this->SettingsChanged()) {
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       this->LogInfo(cmQtAutoGen::GEN, "Writing settings file " +
                       cmQtAutoGen::Quoted(this->SettingsFile));
     }
@@ -699,7 +494,6 @@
       };
       SettingAppend(SettingsKeyMoc, this->SettingsStringMoc);
       SettingAppend(SettingsKeyUic, this->SettingsStringUic);
-      SettingAppend(SettingsKeyRcc, this->SettingsStringRcc);
     }
     // Write settings file
     if (!this->FileWrite(cmQtAutoGen::GEN, this->SettingsFile, settings)) {
@@ -713,7 +507,7 @@
   return success;
 }
 
-bool cmQtAutoGenerators::Process()
+bool cmQtAutoGeneratorMocUic::Process(cmMakefile* makefile)
 {
   // the program goes through all .cpp files to see which moc files are
   // included. It is not really interesting how the moc file is named, but
@@ -723,6 +517,12 @@
   // moc file is included anywhere a moc_<filename>.cpp file is created and
   // included in the mocs_compilation.cpp file.
 
+  if (!this->InitInfoFile(makefile)) {
+    return false;
+  }
+  // Read latest settings
+  this->SettingsFileRead(makefile);
+
   // Create AUTOGEN include directory
   {
     std::string const incDirAbs = cmSystemTools::CollapseCombinedPath(
@@ -758,7 +558,8 @@
   if (!this->UicGenerateAll()) {
     return false;
   }
-  if (!this->RccGenerateAll()) {
+
+  if (!this->SettingsFileWrite()) {
     return false;
   }
 
@@ -768,12 +569,12 @@
 /**
  * @return True on success
  */
-bool cmQtAutoGenerators::ParseSourceFile(std::string const& absFilename,
-                                         const SourceJob& job)
+bool cmQtAutoGeneratorMocUic::ParseSourceFile(std::string const& absFilename,
+                                              const SourceJob& job)
 {
   std::string contentText;
   std::string error;
-  bool success = ReadFile(contentText, absFilename, &error);
+  bool success = this->FileRead(contentText, absFilename, &error);
   if (success) {
     if (!contentText.empty()) {
       if (job.Moc) {
@@ -796,12 +597,12 @@
 /**
  * @return True on success
  */
-bool cmQtAutoGenerators::ParseHeaderFile(std::string const& absFilename,
-                                         const SourceJob& job)
+bool cmQtAutoGeneratorMocUic::ParseHeaderFile(std::string const& absFilename,
+                                              const SourceJob& job)
 {
   std::string contentText;
   std::string error;
-  bool success = ReadFile(contentText, absFilename, &error);
+  bool success = this->FileRead(contentText, absFilename, &error);
   if (success) {
     if (!contentText.empty()) {
       if (job.Moc) {
@@ -824,7 +625,7 @@
 /**
  * @return True on success
  */
-bool cmQtAutoGenerators::ParsePostprocess()
+bool cmQtAutoGeneratorMocUic::ParsePostprocess()
 {
   bool success = true;
   // Read missing dependencies
@@ -832,7 +633,7 @@
     if (!item->DependsValid) {
       std::string content;
       std::string error;
-      if (ReadFile(content, item->SourceFile, &error)) {
+      if (this->FileRead(content, item->SourceFile, &error)) {
         this->MocFindDepends(item->SourceFile, content, item->Depends);
         item->DependsValid = true;
       } else {
@@ -855,7 +656,7 @@
  * @brief Tests if the file should be ignored for moc scanning
  * @return True if the file should be ignored
  */
-bool cmQtAutoGenerators::MocSkip(std::string const& absFilename) const
+bool cmQtAutoGeneratorMocUic::MocSkip(std::string const& absFilename) const
 {
   if (this->MocEnabled()) {
     // Test if the file name is on the skip list
@@ -870,8 +671,8 @@
  * @brief Tests if the C++ content requires moc processing
  * @return True if moc is required
  */
-bool cmQtAutoGenerators::MocRequired(std::string const& contentText,
-                                     std::string* macroName)
+bool cmQtAutoGeneratorMocUic::MocRequired(std::string const& contentText,
+                                          std::string* macroName)
 {
   for (KeyRegExp& filter : this->MocMacroFilters) {
     // Run a simple find string operation before the expensive
@@ -889,7 +690,7 @@
   return false;
 }
 
-std::string cmQtAutoGenerators::MocStringMacros() const
+std::string cmQtAutoGeneratorMocUic::MocStringMacros() const
 {
   std::string res;
   const auto itB = this->MocMacroFilters.cbegin();
@@ -911,7 +712,7 @@
   return res;
 }
 
-std::string cmQtAutoGenerators::MocStringHeaders(
+std::string cmQtAutoGeneratorMocUic::MocStringHeaders(
   std::string const& fileBase) const
 {
   std::string res = fileBase;
@@ -921,7 +722,7 @@
   return res;
 }
 
-std::string cmQtAutoGenerators::MocFindIncludedHeader(
+std::string cmQtAutoGeneratorMocUic::MocFindIncludedHeader(
   std::string const& sourcePath, std::string const& includeBase) const
 {
   std::string header;
@@ -944,7 +745,7 @@
   return header;
 }
 
-bool cmQtAutoGenerators::MocFindIncludedFile(
+bool cmQtAutoGeneratorMocUic::MocFindIncludedFile(
   std::string& absFile, std::string const& sourcePath,
   std::string const& includeString) const
 {
@@ -974,8 +775,8 @@
   return success;
 }
 
-bool cmQtAutoGenerators::MocDependFilterPush(std::string const& key,
-                                             std::string const& regExp)
+bool cmQtAutoGeneratorMocUic::MocDependFilterPush(std::string const& key,
+                                                  std::string const& regExp)
 {
   std::string error;
   if (!key.empty()) {
@@ -1009,9 +810,9 @@
   return true;
 }
 
-void cmQtAutoGenerators::MocFindDepends(std::string const& absFilename,
-                                        std::string const& contentText,
-                                        std::set<std::string>& depends)
+void cmQtAutoGeneratorMocUic::MocFindDepends(std::string const& absFilename,
+                                             std::string const& contentText,
+                                             std::set<std::string>& depends)
 {
   if (this->MocDependFilters.empty() && contentText.empty()) {
     return;
@@ -1040,7 +841,7 @@
       std::string incFile;
       if (this->MocFindIncludedFile(incFile, sourcePath, match)) {
         depends.insert(incFile);
-        if (this->Verbose) {
+        if (this->GetVerbose()) {
           this->LogInfo(cmQtAutoGen::MOC, "Found dependency:\n  " +
                           cmQtAutoGen::Quoted(absFilename) + "\n  " +
                           cmQtAutoGen::Quoted(incFile));
@@ -1057,10 +858,10 @@
 /**
  * @return True on success
  */
-bool cmQtAutoGenerators::MocParseSourceContent(std::string const& absFilename,
-                                               std::string const& contentText)
+bool cmQtAutoGeneratorMocUic::MocParseSourceContent(
+  std::string const& absFilename, std::string const& contentText)
 {
-  if (this->Verbose) {
+  if (this->GetVerbose()) {
     this->LogInfo(cmQtAutoGen::MOC, "Checking: " + absFilename);
   }
 
@@ -1296,10 +1097,10 @@
   return true;
 }
 
-void cmQtAutoGenerators::MocParseHeaderContent(std::string const& absFilename,
-                                               std::string const& contentText)
+void cmQtAutoGeneratorMocUic::MocParseHeaderContent(
+  std::string const& absFilename, std::string const& contentText)
 {
-  if (this->Verbose) {
+  if (this->GetVerbose()) {
     this->LogInfo(cmQtAutoGen::MOC, "Checking: " + absFilename);
   }
 
@@ -1329,7 +1130,7 @@
   }
 }
 
-bool cmQtAutoGenerators::MocGenerateAll()
+bool cmQtAutoGeneratorMocUic::MocGenerateAll()
 {
   if (!this->MocEnabled()) {
     return true;
@@ -1384,7 +1185,7 @@
   if (!this->MocPredefsCmd.empty()) {
     if (this->MocSettingsChanged ||
         !cmSystemTools::FileExists(this->MocPredefsFileAbs)) {
-      if (this->Verbose) {
+      if (this->GetVerbose()) {
         this->LogBold("Generating MOC predefs " + this->MocPredefsFileRel);
       }
 
@@ -1419,7 +1220,7 @@
         }
       } else {
         // Touch to update the time stamp
-        if (this->Verbose) {
+        if (this->GetVerbose()) {
           this->LogInfo(cmQtAutoGen::MOC,
                         "Touching moc_predefs " + this->MocPredefsFileRel);
         }
@@ -1470,7 +1271,7 @@
 
     if (this->FileDiffers(this->MocCompFileAbs, mocs)) {
       // Actually write mocs compilation file
-      if (this->Verbose) {
+      if (this->GetVerbose()) {
         this->LogBold("Generating MOC compilation " + this->MocCompFileRel);
       }
       if (!this->FileWrite(cmQtAutoGen::MOC, this->MocCompFileAbs, mocs)) {
@@ -1480,7 +1281,7 @@
       }
     } else if (autoNameGenerated) {
       // Only touch mocs compilation file
-      if (this->Verbose) {
+      if (this->GetVerbose()) {
         this->LogInfo(cmQtAutoGen::MOC,
                       "Touching mocs compilation " + this->MocCompFileRel);
       }
@@ -1494,8 +1295,8 @@
 /**
  * @return True on success
  */
-bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob,
-                                         bool* generated)
+bool cmQtAutoGeneratorMocUic::MocGenerateFile(const MocJobAuto& mocJob,
+                                              bool* generated)
 {
   bool success = true;
 
@@ -1505,7 +1306,7 @@
   bool generate = false;
   std::string generateReason;
   if (!generate && !cmSystemTools::FileExists(mocFileAbs.c_str())) {
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       generateReason = "Generating ";
       generateReason += cmQtAutoGen::Quoted(mocFileAbs);
       generateReason += " from its source file ";
@@ -1515,7 +1316,7 @@
     generate = true;
   }
   if (!generate && this->MocSettingsChanged) {
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       generateReason = "Generating ";
       generateReason += cmQtAutoGen::Quoted(mocFileAbs);
       generateReason += " from ";
@@ -1525,7 +1326,7 @@
     generate = true;
   }
   if (!generate && this->MocPredefsChanged) {
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       generateReason = "Generating ";
       generateReason += cmQtAutoGen::Quoted(mocFileAbs);
       generateReason += " from ";
@@ -1537,7 +1338,7 @@
   if (!generate) {
     std::string error;
     if (FileIsOlderThan(mocFileAbs, mocJob.SourceFile, &error)) {
-      if (this->Verbose) {
+      if (this->GetVerbose()) {
         generateReason = "Generating ";
         generateReason += cmQtAutoGen::Quoted(mocFileAbs);
         generateReason += " because it's older than its source file ";
@@ -1556,7 +1357,7 @@
     std::string error;
     for (std::string const& depFile : mocJob.Depends) {
       if (FileIsOlderThan(mocFileAbs, depFile, &error)) {
-        if (this->Verbose) {
+        if (this->GetVerbose()) {
           generateReason = "Generating ";
           generateReason += cmQtAutoGen::Quoted(mocFileAbs);
           generateReason += " from ";
@@ -1577,7 +1378,7 @@
 
   if (generate) {
     // Log
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       this->LogBold("Generating MOC source " + mocJob.BuildFileRel);
       this->LogInfo(cmQtAutoGen::MOC, generateReason);
     }
@@ -1627,7 +1428,7 @@
 /**
  * @brief Tests if the file name is in the skip list
  */
-bool cmQtAutoGenerators::UicSkip(std::string const& absFilename) const
+bool cmQtAutoGeneratorMocUic::UicSkip(std::string const& absFilename) const
 {
   if (this->UicEnabled()) {
     // Test if the file name is on the skip list
@@ -1638,10 +1439,10 @@
   return true;
 }
 
-bool cmQtAutoGenerators::UicParseContent(std::string const& absFilename,
-                                         std::string const& contentText)
+bool cmQtAutoGeneratorMocUic::UicParseContent(std::string const& absFilename,
+                                              std::string const& contentText)
 {
-  if (this->Verbose) {
+  if (this->GetVerbose()) {
     this->LogInfo(cmQtAutoGen::UIC, "Checking: " + absFilename);
   }
 
@@ -1689,9 +1490,9 @@
   return true;
 }
 
-bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile,
-                                             std::string const& sourceFile,
-                                             std::string const& includeString)
+bool cmQtAutoGeneratorMocUic::UicFindIncludedFile(
+  std::string& absFile, std::string const& sourceFile,
+  std::string const& includeString)
 {
   bool success = false;
   std::string searchFile =
@@ -1753,7 +1554,7 @@
   return success;
 }
 
-bool cmQtAutoGenerators::UicGenerateAll()
+bool cmQtAutoGeneratorMocUic::UicGenerateAll()
 {
   if (!this->UicEnabled()) {
     return true;
@@ -1817,7 +1618,7 @@
 /**
  * @return True on success
  */
-bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob)
+bool cmQtAutoGeneratorMocUic::UicGenerateFile(const UicJob& uicJob)
 {
   bool success = true;
 
@@ -1827,7 +1628,7 @@
   bool generate = false;
   std::string generateReason;
   if (!generate && !cmSystemTools::FileExists(uicFileAbs.c_str())) {
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       generateReason = "Generating ";
       generateReason += cmQtAutoGen::Quoted(uicFileAbs);
       generateReason += " from its source file ";
@@ -1837,7 +1638,7 @@
     generate = true;
   }
   if (!generate && this->UicSettingsChanged) {
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       generateReason = "Generating ";
       generateReason += cmQtAutoGen::Quoted(uicFileAbs);
       generateReason += " from ";
@@ -1849,7 +1650,7 @@
   if (!generate) {
     std::string error;
     if (FileIsOlderThan(uicFileAbs, uicJob.SourceFile, &error)) {
-      if (this->Verbose) {
+      if (this->GetVerbose()) {
         generateReason = "Generating ";
         generateReason += cmQtAutoGen::Quoted(uicFileAbs);
         generateReason += " because it's older than its source file ";
@@ -1865,7 +1666,7 @@
   }
   if (generate) {
     // Log
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       this->LogBold("Generating UIC header " + uicJob.BuildFileRel);
       this->LogInfo(cmQtAutoGen::UIC, generateReason);
     }
@@ -1880,7 +1681,7 @@
         auto optionIt = this->UicOptions.find(uicJob.SourceFile);
         if (optionIt != this->UicOptions.end()) {
           cmQtAutoGen::UicMergeOptions(allOpts, optionIt->second,
-                                       (this->QtMajorVersion == "5"));
+                                       (this->QtVersionMajor == 5));
         }
         cmd.insert(cmd.end(), allOpts.begin(), allOpts.end());
       }
@@ -1911,413 +1712,13 @@
   return success;
 }
 
-bool cmQtAutoGenerators::RccGenerateAll()
-{
-  if (!this->RccEnabled()) {
-    return true;
-  }
-
-  // Generate rcc files
-  for (const RccJob& rccJob : this->RccJobs) {
-    if (!this->RccGenerateFile(rccJob)) {
-      return false;
-    }
-  }
-  return true;
-}
-
-/**
- * @return True on success
- */
-bool cmQtAutoGenerators::RccGenerateFile(const RccJob& rccJob)
-{
-  bool success = true;
-  bool rccGenerated = false;
-
-  std::string rccFileAbs;
-  {
-    std::string suffix;
-    switch (this->MultiConfig) {
-      case cmQtAutoGen::SINGLE:
-        break;
-      case cmQtAutoGen::WRAP:
-        suffix = "_CMAKE";
-        suffix += this->ConfigSuffix;
-        suffix += "_";
-        break;
-      case cmQtAutoGen::FULL:
-        suffix = this->ConfigSuffix;
-        break;
-    }
-    rccFileAbs = cmQtAutoGen::AppendFilenameSuffix(rccJob.RccFile, suffix);
-  }
-  std::string const rccFileRel = cmSystemTools::RelativePath(
-    this->AutogenBuildDir.c_str(), rccFileAbs.c_str());
-
-  // Check if regeneration is required
-  bool generate = false;
-  std::string generateReason;
-  if (!cmSystemTools::FileExists(rccJob.QrcFile)) {
-    {
-      std::string error = "Could not find the file\n  ";
-      error += cmQtAutoGen::Quoted(rccJob.QrcFile);
-      this->LogError(cmQtAutoGen::RCC, error);
-    }
-    success = false;
-  }
-  if (success && !generate && !cmSystemTools::FileExists(rccFileAbs.c_str())) {
-    if (this->Verbose) {
-      generateReason = "Generating ";
-      generateReason += cmQtAutoGen::Quoted(rccFileAbs);
-      generateReason += " from its source file ";
-      generateReason += cmQtAutoGen::Quoted(rccJob.QrcFile);
-      generateReason += " because it doesn't exist";
-    }
-    generate = true;
-  }
-  if (success && !generate && this->RccSettingsChanged) {
-    if (this->Verbose) {
-      generateReason = "Generating ";
-      generateReason += cmQtAutoGen::Quoted(rccFileAbs);
-      generateReason += " from ";
-      generateReason += cmQtAutoGen::Quoted(rccJob.QrcFile);
-      generateReason += " because the RCC settings changed";
-    }
-    generate = true;
-  }
-  if (success && !generate) {
-    std::string error;
-    if (FileIsOlderThan(rccFileAbs, rccJob.QrcFile, &error)) {
-      if (this->Verbose) {
-        generateReason = "Generating ";
-        generateReason += cmQtAutoGen::Quoted(rccFileAbs);
-        generateReason += " because it is older than ";
-        generateReason += cmQtAutoGen::Quoted(rccJob.QrcFile);
-      }
-      generate = true;
-    } else {
-      if (!error.empty()) {
-        this->LogError(cmQtAutoGen::RCC, error);
-        success = false;
-      }
-    }
-  }
-  if (success && !generate) {
-    // Acquire input file list
-    std::vector<std::string> readFiles;
-    std::vector<std::string> const* files = nullptr;
-    if (!rccJob.Inputs.empty()) {
-      files = &rccJob.Inputs;
-    } else {
-      // Read input file list from qrc file
-      std::string error;
-      if (cmQtAutoGen::RccListInputs(this->QtMajorVersion, this->RccExecutable,
-                                     rccJob.QrcFile, readFiles, &error)) {
-        files = &readFiles;
-      } else {
-        this->LogFileError(cmQtAutoGen::RCC, rccJob.QrcFile, error);
-        success = false;
-      }
-    }
-    // Test if any input file is newer than the build file
-    if (files != nullptr) {
-      std::string error;
-      for (std::string const& resFile : *files) {
-        if (!cmSystemTools::FileExists(resFile.c_str())) {
-          error = "Could not find the file\n  ";
-          error += cmQtAutoGen::Quoted(resFile);
-          error += "\nwhich is listed in\n  ";
-          error += cmQtAutoGen::Quoted(rccJob.QrcFile);
-          break;
-        }
-        if (FileIsOlderThan(rccFileAbs, resFile, &error)) {
-          if (this->Verbose) {
-            generateReason = "Generating ";
-            generateReason += cmQtAutoGen::Quoted(rccFileAbs);
-            generateReason += " from ";
-            generateReason += cmQtAutoGen::Quoted(rccJob.QrcFile);
-            generateReason += " because it is older than ";
-            generateReason += cmQtAutoGen::Quoted(resFile);
-          }
-          generate = true;
-          break;
-        }
-        if (!error.empty()) {
-          break;
-        }
-      }
-      // Print error
-      if (!error.empty()) {
-        this->LogError(cmQtAutoGen::RCC, error);
-        success = false;
-      }
-    }
-  }
-  // Regenerate on demand
-  if (generate) {
-    // Log
-    if (this->Verbose) {
-      this->LogBold("Generating RCC source " + rccFileRel);
-      this->LogInfo(cmQtAutoGen::RCC, generateReason);
-    }
-
-    // Make sure the parent directory exists
-    if (this->MakeParentDirectory(cmQtAutoGen::RCC, rccFileAbs)) {
-      // Compose rcc command
-      std::vector<std::string> cmd;
-      cmd.push_back(this->RccExecutable);
-      cmd.insert(cmd.end(), rccJob.Options.begin(), rccJob.Options.end());
-      cmd.push_back("-o");
-      cmd.push_back(rccFileAbs);
-      cmd.push_back(rccJob.QrcFile);
-
-      std::string output;
-      if (this->RunCommand(cmd, output)) {
-        // Success
-        rccGenerated = true;
-      } else {
-        {
-          std::string emsg = "rcc failed for\n  ";
-          emsg += cmQtAutoGen::Quoted(rccJob.QrcFile);
-          this->LogCommandError(cmQtAutoGen::RCC, emsg, cmd, output);
-        }
-        cmSystemTools::RemoveFile(rccFileAbs);
-        success = false;
-      }
-    } else {
-      // Parent directory creation failed
-      success = false;
-    }
-  }
-
-  // Generate a wrapper source file on demand
-  if (success && (this->MultiConfig == cmQtAutoGen::WRAP)) {
-    // Wrapper file name
-    std::string const& wrapperFileAbs = rccJob.RccFile;
-    std::string const wrapperFileRel = cmSystemTools::RelativePath(
-      this->AutogenBuildDir.c_str(), wrapperFileAbs.c_str());
-    // Wrapper file content
-    std::string content = "// This is an autogenerated configuration "
-                          "wrapper file. Changes will be overwritten.\n"
-                          "#include \"";
-    content += cmSystemTools::GetFilenameName(rccFileRel);
-    content += "\"\n";
-    // Write content to file
-    if (this->FileDiffers(wrapperFileAbs, content)) {
-      // Write new wrapper file
-      if (this->Verbose) {
-        this->LogBold("Generating RCC wrapper " + wrapperFileRel);
-      }
-      if (!this->FileWrite(cmQtAutoGen::RCC, wrapperFileAbs, content)) {
-        this->LogFileError(cmQtAutoGen::RCC, wrapperFileAbs,
-                           "rcc wrapper file writing failed");
-        success = false;
-      }
-    } else if (rccGenerated) {
-      // Just touch the wrapper file
-      if (this->Verbose) {
-        this->LogInfo(cmQtAutoGen::RCC,
-                      "Touching RCC wrapper " + wrapperFileRel);
-      }
-      cmSystemTools::Touch(wrapperFileAbs, false);
-    }
-  }
-
-  return success;
-}
-
-void cmQtAutoGenerators::LogBold(std::string const& message) const
-{
-  cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue |
-                                     cmsysTerminal_Color_ForegroundBold,
-                                   message.c_str(), true, this->ColorOutput);
-}
-
-void cmQtAutoGenerators::LogInfo(cmQtAutoGen::Generator genType,
-                                 std::string const& message) const
-{
-  std::string msg = cmQtAutoGen::GeneratorName(genType);
-  msg += ": ";
-  msg += message;
-  if (msg.back() != '\n') {
-    msg.push_back('\n');
-  }
-  cmSystemTools::Stdout(msg.c_str(), msg.size());
-}
-
-void cmQtAutoGenerators::LogWarning(cmQtAutoGen::Generator genType,
-                                    std::string const& message) const
-{
-  std::string msg = cmQtAutoGen::GeneratorName(genType);
-  msg += " warning:";
-  if (message.find('\n') == std::string::npos) {
-    // Single line message
-    msg.push_back(' ');
-  } else {
-    // Multi line message
-    msg.push_back('\n');
-  }
-  // Message
-  msg += message;
-  if (msg.back() != '\n') {
-    msg.push_back('\n');
-  }
-  msg.push_back('\n');
-  cmSystemTools::Stdout(msg.c_str(), msg.size());
-}
-
-void cmQtAutoGenerators::LogFileWarning(cmQtAutoGen::Generator genType,
-                                        std::string const& filename,
-                                        std::string const& message) const
-{
-  std::string msg = "  ";
-  msg += cmQtAutoGen::Quoted(filename);
-  msg.push_back('\n');
-  // Message
-  msg += message;
-  this->LogWarning(genType, msg);
-}
-
-void cmQtAutoGenerators::LogError(cmQtAutoGen::Generator genType,
-                                  std::string const& message) const
-{
-  std::string msg;
-  msg.push_back('\n');
-  msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " error");
-  // Message
-  msg += message;
-  if (msg.back() != '\n') {
-    msg.push_back('\n');
-  }
-  msg.push_back('\n');
-  cmSystemTools::Stderr(msg.c_str(), msg.size());
-}
-
-void cmQtAutoGenerators::LogFileError(cmQtAutoGen::Generator genType,
-                                      std::string const& filename,
-                                      std::string const& message) const
-{
-  std::string emsg = "  ";
-  emsg += cmQtAutoGen::Quoted(filename);
-  emsg += '\n';
-  // Message
-  emsg += message;
-  this->LogError(genType, emsg);
-}
-
-void cmQtAutoGenerators::LogCommandError(
-  cmQtAutoGen::Generator genType, std::string const& message,
-  std::vector<std::string> const& command, std::string const& output) const
-{
-  std::string msg;
-  msg.push_back('\n');
-  msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " subprocess error");
-  msg += message;
-  if (msg.back() != '\n') {
-    msg.push_back('\n');
-  }
-  msg.push_back('\n');
-  msg += HeadLine("Command");
-  msg += QuotedCommand(command);
-  if (msg.back() != '\n') {
-    msg.push_back('\n');
-  }
-  msg.push_back('\n');
-  msg += HeadLine("Output");
-  msg += output;
-  if (msg.back() != '\n') {
-    msg.push_back('\n');
-  }
-  msg.push_back('\n');
-  cmSystemTools::Stderr(msg.c_str(), msg.size());
-}
-
-/**
- * @brief Generates the parent directory of the given file on demand
- * @return True on success
- */
-bool cmQtAutoGenerators::MakeParentDirectory(cmQtAutoGen::Generator genType,
-                                             std::string const& filename) const
-{
-  bool success = true;
-  std::string const dirName = cmSystemTools::GetFilenamePath(filename);
-  if (!dirName.empty()) {
-    if (!cmSystemTools::MakeDirectory(dirName)) {
-      this->LogFileError(genType, filename,
-                         "Could not create parent directory");
-      success = false;
-    }
-  }
-  return success;
-}
-
-bool cmQtAutoGenerators::FileDiffers(std::string const& filename,
-                                     std::string const& content)
-{
-  bool differs = true;
-  {
-    std::string oldContents;
-    if (ReadFile(oldContents, filename)) {
-      differs = (oldContents != content);
-    }
-  }
-  return differs;
-}
-
-bool cmQtAutoGenerators::FileWrite(cmQtAutoGen::Generator genType,
-                                   std::string const& filename,
-                                   std::string const& content)
-{
-  std::string error;
-  // Make sure the parent directory exists
-  if (this->MakeParentDirectory(genType, filename)) {
-    cmsys::ofstream outfile;
-    outfile.open(filename.c_str(),
-                 (std::ios::out | std::ios::binary | std::ios::trunc));
-    if (outfile) {
-      outfile << content;
-      // Check for write errors
-      if (!outfile.good()) {
-        error = "File writing failed";
-      }
-    } else {
-      error = "Opening file for writing failed";
-    }
-  }
-  if (!error.empty()) {
-    this->LogFileError(genType, filename, error);
-    return false;
-  }
-  return true;
-}
-
-/**
- * @brief Runs a command and returns true on success
- * @return True on success
- */
-bool cmQtAutoGenerators::RunCommand(std::vector<std::string> const& command,
-                                    std::string& output) const
-{
-  // Log command
-  if (this->Verbose) {
-    std::string qcmd = QuotedCommand(command);
-    qcmd.push_back('\n');
-    cmSystemTools::Stdout(qcmd.c_str(), qcmd.size());
-  }
-  // Execute command
-  int retVal = 0;
-  bool res = cmSystemTools::RunSingleCommand(
-    command, &output, &output, &retVal, nullptr, cmSystemTools::OUTPUT_NONE);
-  return (res && (retVal == 0));
-}
-
 /**
  * @brief Tries to find the header file to the given file base path by
  * appending different header extensions
  * @return True on success
  */
-bool cmQtAutoGenerators::FindHeader(std::string& header,
-                                    std::string const& testBasePath) const
+bool cmQtAutoGeneratorMocUic::FindHeader(std::string& header,
+                                         std::string const& testBasePath) const
 {
   for (std::string const& ext : this->HeaderExtensions) {
     std::string testFilePath(testBasePath);
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGeneratorMocUic.h
similarity index 68%
rename from Source/cmQtAutoGenerators.h
rename to Source/cmQtAutoGeneratorMocUic.h
index a7bb538..d510939 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGeneratorMocUic.h
@@ -1,12 +1,13 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
-#ifndef cmQtAutoGenerators_h
-#define cmQtAutoGenerators_h
+#ifndef cmQtAutoGeneratorMocUic_h
+#define cmQtAutoGeneratorMocUic_h
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmFilePathChecksum.h"
 #include "cmQtAutoGen.h"
+#include "cmQtAutoGenerator.h"
 #include "cmsys/RegularExpression.hxx"
 
 #include <map>
@@ -17,12 +18,11 @@
 
 class cmMakefile;
 
-class cmQtAutoGenerators
+class cmQtAutoGeneratorMocUic : public cmQtAutoGenerator
 {
-  CM_DISABLE_COPY(cmQtAutoGenerators)
+  CM_DISABLE_COPY(cmQtAutoGeneratorMocUic)
 public:
-  cmQtAutoGenerators();
-  bool Run(std::string const& targetDirectory, std::string const& config);
+  cmQtAutoGeneratorMocUic();
 
 private:
   // -- Types
@@ -80,30 +80,19 @@
     std::string IncludeString;
   };
 
-  /// @brief RCC job
-  struct RccJob
-  {
-    std::string QrcFile;
-    std::string RccFile;
-    std::vector<std::string> Options;
-    std::vector<std::string> Inputs;
-  };
-
   // -- Initialization
-  bool InitInfoFile(cmMakefile* makefile, std::string const& targetDirectory,
-                    std::string const& config);
+  bool InitInfoFile(cmMakefile* makefile);
 
   // -- Settings file
   void SettingsFileRead(cmMakefile* makefile);
   bool SettingsFileWrite();
   bool SettingsChanged() const
   {
-    return (this->MocSettingsChanged || this->RccSettingsChanged ||
-            this->UicSettingsChanged);
+    return (this->MocSettingsChanged || this->UicSettingsChanged);
   }
 
   // -- Central processing
-  bool Process();
+  bool Process(cmMakefile* makefile) override;
 
   // -- Source parsing
   bool ParseSourceFile(std::string const& absFilename, const SourceJob& job);
@@ -146,54 +135,17 @@
   bool UicGenerateAll();
   bool UicGenerateFile(const UicJob& uicJob);
 
-  // -- Rcc
-  bool RccEnabled() const { return !this->RccExecutable.empty(); }
-  bool RccGenerateAll();
-  bool RccGenerateFile(const RccJob& rccJob);
-
-  // -- Log info
-  void LogBold(std::string const& message) const;
-  void LogInfo(cmQtAutoGen::Generator genType,
-               std::string const& message) const;
-  // -- Log warning
-  void LogWarning(cmQtAutoGen::Generator genType,
-                  std::string const& message) const;
-  void LogFileWarning(cmQtAutoGen::Generator genType,
-                      std::string const& filename,
-                      std::string const& message) const;
-  // -- Log error
-  void LogError(cmQtAutoGen::Generator genType,
-                std::string const& message) const;
-  void LogFileError(cmQtAutoGen::Generator genType,
-                    std::string const& filename,
-                    std::string const& message) const;
-  void LogCommandError(cmQtAutoGen::Generator genType,
-                       std::string const& message,
-                       std::vector<std::string> const& command,
-                       std::string const& output) const;
-
   // -- Utility
-  bool MakeParentDirectory(cmQtAutoGen::Generator genType,
-                           std::string const& filename) const;
-  bool FileDiffers(std::string const& filename, std::string const& content);
-  bool FileWrite(cmQtAutoGen::Generator genType, std::string const& filename,
-                 std::string const& content);
   bool FindHeader(std::string& header, std::string const& testBasePath) const;
-  bool RunCommand(std::vector<std::string> const& command,
-                  std::string& output) const;
 
   // -- Meta
-  std::string InfoFile;
   std::string ConfigSuffix;
   cmQtAutoGen::MultiConfig MultiConfig;
   // -- Settings
   bool IncludeProjectDirsBefore;
-  bool Verbose;
-  bool ColorOutput;
   std::string SettingsFile;
   std::string SettingsStringMoc;
   std::string SettingsStringUic;
-  std::string SettingsStringRcc;
   // -- Directories
   std::string ProjectSourceDir;
   std::string ProjectBinaryDir;
@@ -202,11 +154,9 @@
   std::string AutogenBuildDir;
   std::string AutogenIncludeDir;
   // -- Qt environment
-  std::string QtMajorVersion;
-  std::string QtMinorVersion;
+  unsigned long QtVersionMajor;
   std::string MocExecutable;
   std::string UicExecutable;
-  std::string RccExecutable;
   // -- File lists
   std::map<std::string, SourceJob> HeaderJobs;
   std::map<std::string, SourceJob> SourceJobs;
@@ -240,9 +190,6 @@
   std::vector<std::string> UicSearchPaths;
   cmsys::RegularExpression UicRegExpInclude;
   std::vector<std::unique_ptr<UicJob>> UicJobs;
-  // -- Rcc
-  bool RccSettingsChanged;
-  std::vector<RccJob> RccJobs;
 };
 
 #endif
diff --git a/Source/cmQtAutoGeneratorRcc.cxx b/Source/cmQtAutoGeneratorRcc.cxx
new file mode 100644
index 0000000..3c9f1a8
--- /dev/null
+++ b/Source/cmQtAutoGeneratorRcc.cxx
@@ -0,0 +1,425 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmQtAutoGen.h"
+#include "cmQtAutoGeneratorRcc.h"
+
+#include "cmAlgorithms.h"
+#include "cmCryptoHash.h"
+#include "cmMakefile.h"
+#include "cmOutputConverter.h"
+#include "cmSystemTools.h"
+
+// -- Static variables
+
+static const char* SettingsKeyRcc = "ARCC_SETTINGS_HASH";
+
+// -- Class methods
+
+cmQtAutoGeneratorRcc::cmQtAutoGeneratorRcc()
+  : MultiConfig(cmQtAutoGen::WRAP)
+  , SettingsChanged(false)
+{
+}
+
+bool cmQtAutoGeneratorRcc::InfoFileRead(cmMakefile* makefile)
+{
+  // Utility lambdas
+  auto InfoGet = [makefile](const char* key) {
+    return makefile->GetSafeDefinition(key);
+  };
+  auto InfoGetList = [makefile](const char* key) -> std::vector<std::string> {
+    std::vector<std::string> list;
+    cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list);
+    return list;
+  };
+  auto InfoGetConfig = [makefile, this](const char* key) -> std::string {
+    const char* valueConf = nullptr;
+    {
+      std::string keyConf = key;
+      keyConf += '_';
+      keyConf += this->GetInfoConfig();
+      valueConf = makefile->GetDefinition(keyConf);
+    }
+    if (valueConf == nullptr) {
+      valueConf = makefile->GetSafeDefinition(key);
+    }
+    return std::string(valueConf);
+  };
+  auto InfoGetConfigList =
+    [&InfoGetConfig](const char* key) -> std::vector<std::string> {
+    std::vector<std::string> list;
+    cmSystemTools::ExpandListArgument(InfoGetConfig(key), list);
+    return list;
+  };
+
+  // -- Read info file
+  if (!makefile->ReadListFile(this->GetInfoFile().c_str())) {
+    this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
+                       "File processing failed");
+    return false;
+  }
+
+  // -- Meta
+  this->MultiConfig =
+    cmQtAutoGen::MultiConfigType(InfoGet("ARCC_MULTI_CONFIG"));
+  this->ConfigSuffix = InfoGetConfig("ARCC_CONFIG_SUFFIX");
+  if (this->ConfigSuffix.empty()) {
+    this->ConfigSuffix = "_";
+    this->ConfigSuffix += this->GetInfoConfig();
+  }
+
+  this->SettingsFile = InfoGetConfig("ARCC_SETTINGS_FILE");
+
+  // - Files and directories
+  this->ProjectSourceDir = InfoGet("ARCC_CMAKE_SOURCE_DIR");
+  this->ProjectBinaryDir = InfoGet("ARCC_CMAKE_BINARY_DIR");
+  this->CurrentSourceDir = InfoGet("ARCC_CMAKE_CURRENT_SOURCE_DIR");
+  this->CurrentBinaryDir = InfoGet("ARCC_CMAKE_CURRENT_BINARY_DIR");
+  this->AutogenBuildDir = InfoGet("ARCC_BUILD_DIR");
+
+  // - Qt environment
+  this->RccExecutable = InfoGet("ARCC_RCC_EXECUTABLE");
+  this->RccListOptions = InfoGetList("ARCC_RCC_LIST_OPTIONS");
+
+  // - Job
+  this->QrcFile = InfoGet("ARCC_SOURCE");
+  this->RccFile = InfoGet("ARCC_OUTPUT");
+  this->Options = InfoGetConfigList("ARCC_OPTIONS");
+  this->Inputs = InfoGetList("ARCC_INPUTS");
+
+  // - Validity checks
+  if (this->SettingsFile.empty()) {
+    this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
+                       "Settings file name missing");
+    return false;
+  }
+  if (this->AutogenBuildDir.empty()) {
+    this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
+                       "Autogen build directory missing");
+    return false;
+  }
+  if (this->RccExecutable.empty()) {
+    this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
+                       "rcc executable missing");
+    return false;
+  }
+  if (this->QrcFile.empty()) {
+    this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
+                       "rcc input file missing");
+    return false;
+  }
+  if (this->RccFile.empty()) {
+    this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
+                       "rcc output file missing");
+    return false;
+  }
+
+  // Init derived information
+  // ------------------------
+
+  // Init file path checksum generator
+  this->FilePathChecksum.setupParentDirs(
+    this->CurrentSourceDir, this->CurrentBinaryDir, this->ProjectSourceDir,
+    this->ProjectBinaryDir);
+
+  return true;
+}
+
+void cmQtAutoGeneratorRcc::SettingsFileRead(cmMakefile* makefile)
+{
+  // Compose current settings strings
+  {
+    cmCryptoHash crypt(cmCryptoHash::AlgoSHA256);
+    std::string const sep(" ~~~ ");
+    {
+      std::string str;
+      str += this->RccExecutable;
+      str += sep;
+      str += cmJoin(this->RccListOptions, ";");
+      str += sep;
+      str += this->QrcFile;
+      str += sep;
+      str += this->RccFile;
+      str += sep;
+      str += cmJoin(this->Options, ";");
+      str += sep;
+      str += cmJoin(this->Inputs, ";");
+      str += sep;
+      this->SettingsString = crypt.HashString(str);
+    }
+  }
+
+  // Read old settings
+  if (makefile->ReadListFile(this->SettingsFile.c_str())) {
+    {
+      auto SMatch = [makefile](const char* key, std::string const& value) {
+        return (value == makefile->GetSafeDefinition(key));
+      };
+      if (!SMatch(SettingsKeyRcc, this->SettingsString)) {
+        this->SettingsChanged = true;
+      }
+    }
+    // In case any setting changed remove the old settings file.
+    // This triggers a full rebuild on the next run if the current
+    // build is aborted before writing the current settings in the end.
+    if (this->SettingsChanged) {
+      cmSystemTools::RemoveFile(this->SettingsFile);
+    }
+  } else {
+    // If the file could not be read re-generate everythiung.
+    this->SettingsChanged = true;
+  }
+}
+
+bool cmQtAutoGeneratorRcc::SettingsFileWrite()
+{
+  bool success = true;
+  // Only write if any setting changed
+  if (this->SettingsChanged) {
+    if (this->GetVerbose()) {
+      this->LogInfo(cmQtAutoGen::RCC, "Writing settings file " +
+                      cmQtAutoGen::Quoted(this->SettingsFile));
+    }
+    // Compose settings file content
+    std::string settings;
+    {
+      auto SettingAppend = [&settings](const char* key,
+                                       std::string const& value) {
+        settings += "set(";
+        settings += key;
+        settings += " ";
+        settings += cmOutputConverter::EscapeForCMake(value);
+        settings += ")\n";
+      };
+      SettingAppend(SettingsKeyRcc, this->SettingsString);
+    }
+    // Write settings file
+    if (!this->FileWrite(cmQtAutoGen::RCC, this->SettingsFile, settings)) {
+      this->LogFileError(cmQtAutoGen::RCC, this->SettingsFile,
+                         "Settings file writing failed");
+      // Remove old settings file to trigger a full rebuild on the next run
+      cmSystemTools::RemoveFile(this->SettingsFile);
+      success = false;
+    }
+  }
+  return success;
+}
+
+bool cmQtAutoGeneratorRcc::Process(cmMakefile* makefile)
+{
+  // Read info file
+  if (!this->InfoFileRead(makefile)) {
+    return false;
+  }
+  // Read latest settings
+  this->SettingsFileRead(makefile);
+  // Generate rcc file
+  if (!this->RccGenerate()) {
+    return false;
+  }
+  // Write latest settings
+  if (!this->SettingsFileWrite()) {
+    return false;
+  }
+  return true;
+}
+
+/**
+ * @return True on success
+ */
+bool cmQtAutoGeneratorRcc::RccGenerate()
+{
+  bool success = true;
+  bool rccGenerated = false;
+
+  std::string rccFileAbs;
+  {
+    std::string suffix;
+    switch (this->MultiConfig) {
+      case cmQtAutoGen::SINGLE:
+        break;
+      case cmQtAutoGen::WRAP:
+        suffix = "_CMAKE";
+        suffix += this->ConfigSuffix;
+        suffix += "_";
+        break;
+      case cmQtAutoGen::FULL:
+        suffix = this->ConfigSuffix;
+        break;
+    }
+    rccFileAbs = cmQtAutoGen::AppendFilenameSuffix(this->RccFile, suffix);
+  }
+  std::string const rccFileRel = cmSystemTools::RelativePath(
+    this->AutogenBuildDir.c_str(), rccFileAbs.c_str());
+
+  // Check if regeneration is required
+  bool generate = false;
+  std::string generateReason;
+  if (!cmSystemTools::FileExists(this->QrcFile)) {
+    {
+      std::string error = "Could not find the file\n  ";
+      error += cmQtAutoGen::Quoted(this->QrcFile);
+      this->LogError(cmQtAutoGen::RCC, error);
+    }
+    success = false;
+  }
+  if (success && !generate && !cmSystemTools::FileExists(rccFileAbs.c_str())) {
+    if (this->GetVerbose()) {
+      generateReason = "Generating ";
+      generateReason += cmQtAutoGen::Quoted(rccFileAbs);
+      generateReason += " from its source file ";
+      generateReason += cmQtAutoGen::Quoted(this->QrcFile);
+      generateReason += " because it doesn't exist";
+    }
+    generate = true;
+  }
+  if (success && !generate && this->SettingsChanged) {
+    if (this->GetVerbose()) {
+      generateReason = "Generating ";
+      generateReason += cmQtAutoGen::Quoted(rccFileAbs);
+      generateReason += " from ";
+      generateReason += cmQtAutoGen::Quoted(this->QrcFile);
+      generateReason += " because the RCC settings changed";
+    }
+    generate = true;
+  }
+  if (success && !generate) {
+    std::string error;
+    if (FileIsOlderThan(rccFileAbs, this->QrcFile, &error)) {
+      if (this->GetVerbose()) {
+        generateReason = "Generating ";
+        generateReason += cmQtAutoGen::Quoted(rccFileAbs);
+        generateReason += " because it is older than ";
+        generateReason += cmQtAutoGen::Quoted(this->QrcFile);
+      }
+      generate = true;
+    } else {
+      if (!error.empty()) {
+        this->LogError(cmQtAutoGen::RCC, error);
+        success = false;
+      }
+    }
+  }
+  if (success && !generate) {
+    // Acquire input file list
+    std::vector<std::string> readFiles;
+    std::vector<std::string> const* files = nullptr;
+    if (!this->Inputs.empty()) {
+      files = &this->Inputs;
+    } else {
+      // Read input file list from qrc file
+      std::string error;
+      if (cmQtAutoGen::RccListInputs(this->RccExecutable, this->RccListOptions,
+                                     this->QrcFile, readFiles, &error)) {
+        files = &readFiles;
+      } else {
+        this->LogFileError(cmQtAutoGen::RCC, this->QrcFile, error);
+        success = false;
+      }
+    }
+    // Test if any input file is newer than the build file
+    if (files != nullptr) {
+      std::string error;
+      for (std::string const& resFile : *files) {
+        if (!cmSystemTools::FileExists(resFile.c_str())) {
+          error = "Could not find the file\n  ";
+          error += cmQtAutoGen::Quoted(resFile);
+          error += "\nwhich is listed in\n  ";
+          error += cmQtAutoGen::Quoted(this->QrcFile);
+          break;
+        }
+        if (FileIsOlderThan(rccFileAbs, resFile, &error)) {
+          if (this->GetVerbose()) {
+            generateReason = "Generating ";
+            generateReason += cmQtAutoGen::Quoted(rccFileAbs);
+            generateReason += " from ";
+            generateReason += cmQtAutoGen::Quoted(this->QrcFile);
+            generateReason += " because it is older than ";
+            generateReason += cmQtAutoGen::Quoted(resFile);
+          }
+          generate = true;
+          break;
+        }
+        if (!error.empty()) {
+          break;
+        }
+      }
+      // Print error
+      if (!error.empty()) {
+        this->LogError(cmQtAutoGen::RCC, error);
+        success = false;
+      }
+    }
+  }
+  // Regenerate on demand
+  if (generate) {
+    // Log
+    if (this->GetVerbose()) {
+      this->LogBold("Generating RCC source " + rccFileRel);
+      this->LogInfo(cmQtAutoGen::RCC, generateReason);
+    }
+
+    // Make sure the parent directory exists
+    if (this->MakeParentDirectory(cmQtAutoGen::RCC, rccFileAbs)) {
+      // Compose rcc command
+      std::vector<std::string> cmd;
+      cmd.push_back(this->RccExecutable);
+      cmd.insert(cmd.end(), this->Options.begin(), this->Options.end());
+      cmd.push_back("-o");
+      cmd.push_back(rccFileAbs);
+      cmd.push_back(this->QrcFile);
+
+      std::string output;
+      if (this->RunCommand(cmd, output)) {
+        // Success
+        rccGenerated = true;
+      } else {
+        {
+          std::string emsg = "rcc failed for\n  ";
+          emsg += cmQtAutoGen::Quoted(this->QrcFile);
+          this->LogCommandError(cmQtAutoGen::RCC, emsg, cmd, output);
+        }
+        cmSystemTools::RemoveFile(rccFileAbs);
+        success = false;
+      }
+    } else {
+      // Parent directory creation failed
+      success = false;
+    }
+  }
+
+  // Generate a wrapper source file on demand
+  if (success && (this->MultiConfig == cmQtAutoGen::WRAP)) {
+    // Wrapper file name
+    std::string const& wrapperFileAbs = this->RccFile;
+    std::string const wrapperFileRel = cmSystemTools::RelativePath(
+      this->AutogenBuildDir.c_str(), wrapperFileAbs.c_str());
+    // Wrapper file content
+    std::string content = "// This is an autogenerated configuration "
+                          "wrapper file. Changes will be overwritten.\n"
+                          "#include \"";
+    content += cmSystemTools::GetFilenameName(rccFileRel);
+    content += "\"\n";
+    // Write content to file
+    if (this->FileDiffers(wrapperFileAbs, content)) {
+      // Write new wrapper file
+      if (this->GetVerbose()) {
+        this->LogBold("Generating RCC wrapper " + wrapperFileRel);
+      }
+      if (!this->FileWrite(cmQtAutoGen::RCC, wrapperFileAbs, content)) {
+        this->LogFileError(cmQtAutoGen::RCC, wrapperFileAbs,
+                           "rcc wrapper file writing failed");
+        success = false;
+      }
+    } else if (rccGenerated) {
+      // Just touch the wrapper file
+      if (this->GetVerbose()) {
+        this->LogInfo(cmQtAutoGen::RCC,
+                      "Touching RCC wrapper " + wrapperFileRel);
+      }
+      cmSystemTools::Touch(wrapperFileAbs, false);
+    }
+  }
+
+  return success;
+}
diff --git a/Source/cmQtAutoGeneratorRcc.h b/Source/cmQtAutoGeneratorRcc.h
new file mode 100644
index 0000000..0e3f690
--- /dev/null
+++ b/Source/cmQtAutoGeneratorRcc.h
@@ -0,0 +1,56 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmQtAutoGeneratorRcc_h
+#define cmQtAutoGeneratorRcc_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmFilePathChecksum.h"
+#include "cmQtAutoGen.h"
+#include "cmQtAutoGenerator.h"
+
+#include <string>
+#include <vector>
+
+class cmMakefile;
+
+class cmQtAutoGeneratorRcc : public cmQtAutoGenerator
+{
+  CM_DISABLE_COPY(cmQtAutoGeneratorRcc)
+public:
+  cmQtAutoGeneratorRcc();
+
+private:
+  // -- Initialization & settings
+  bool InfoFileRead(cmMakefile* makefile);
+  void SettingsFileRead(cmMakefile* makefile);
+  bool SettingsFileWrite();
+  // -- Central processing
+  bool Process(cmMakefile* makefile) override;
+  bool RccGenerate();
+
+  // -- Config settings
+  std::string ConfigSuffix;
+  cmQtAutoGen::MultiConfig MultiConfig;
+  // -- Settings
+  bool SettingsChanged;
+  std::string SettingsFile;
+  std::string SettingsString;
+  // -- Directories
+  std::string ProjectSourceDir;
+  std::string ProjectBinaryDir;
+  std::string CurrentSourceDir;
+  std::string CurrentBinaryDir;
+  std::string AutogenBuildDir;
+  cmFilePathChecksum FilePathChecksum;
+  // -- Qt environment
+  std::string RccExecutable;
+  std::vector<std::string> RccListOptions;
+  // -- Job
+  std::string QrcFile;
+  std::string RccFile;
+  std::vector<std::string> Options;
+  std::vector<std::string> Inputs;
+};
+
+#endif
diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx
index 07df488..aae0a9d 100644
--- a/Source/cmServerProtocol.cxx
+++ b/Source/cmServerProtocol.cxx
@@ -1118,11 +1118,24 @@
     const cmMakefile* mf = lg->GetMakefile();
     pObj[kMINIMUM_CMAKE_VERSION] =
       mf->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
-    pObj[kHAS_INSTALL_RULE] = mf->GetInstallGenerators().empty() == false;
     pObj[kSOURCE_DIRECTORY_KEY] = mf->GetCurrentSourceDirectory();
     pObj[kBUILD_DIRECTORY_KEY] = mf->GetCurrentBinaryDirectory();
     pObj[kTARGETS_KEY] = DumpTargetsList(projectIt.second, config);
 
+    // For a project-level install rule it might be defined in any of its
+    // associated generators.
+    bool hasInstallRule = false;
+    for (const auto generator : projectIt.second) {
+      hasInstallRule =
+        generator->GetMakefile()->GetInstallGenerators().empty() == false;
+
+      if (hasInstallRule) {
+        break;
+      }
+    }
+
+    pObj[kHAS_INSTALL_RULE] = hasInstallRule;
+
     result.append(pObj);
   }
 
diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx
index 4f337f2..6add7b3 100644
--- a/Source/cmSourceFileLocation.cxx
+++ b/Source/cmSourceFileLocation.cxx
@@ -8,9 +8,7 @@
 #include "cmSystemTools.h"
 #include "cmake.h"
 
-#include <algorithm>
 #include <assert.h>
-#include <vector>
 
 cmSourceFileLocation::cmSourceFileLocation()
   : Makefile(nullptr)
@@ -86,13 +84,9 @@
   // The global generator checks extensions of enabled languages.
   cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
   cmMakefile const* mf = this->Makefile;
-  const std::vector<std::string>& srcExts =
-    mf->GetCMakeInstance()->GetSourceExtensions();
-  const std::vector<std::string>& hdrExts =
-    mf->GetCMakeInstance()->GetHeaderExtensions();
+  auto cm = mf->GetCMakeInstance();
   if (!gg->GetLanguageFromExtension(ext.c_str()).empty() ||
-      std::find(srcExts.begin(), srcExts.end(), ext) != srcExts.end() ||
-      std::find(hdrExts.begin(), hdrExts.end(), ext) != hdrExts.end()) {
+      cm->IsSourceExtension(ext) || cm->IsHeaderExtension(ext)) {
     // This is a known extension.  Use the given filename with extension.
     this->Name = cmSystemTools::GetFilenameName(name);
     this->AmbiguousExtension = false;
@@ -149,14 +143,8 @@
   // disk.  One of these must match if loc refers to this source file.
   std::string const& ext = this->Name.substr(loc.Name.size() + 1);
   cmMakefile const* mf = this->Makefile;
-  const std::vector<std::string>& srcExts =
-    mf->GetCMakeInstance()->GetSourceExtensions();
-  if (std::find(srcExts.begin(), srcExts.end(), ext) != srcExts.end()) {
-    return true;
-  }
-  std::vector<std::string> hdrExts =
-    mf->GetCMakeInstance()->GetHeaderExtensions();
-  return std::find(hdrExts.begin(), hdrExts.end(), ext) != hdrExts.end();
+  auto cm = mf->GetCMakeInstance();
+  return cm->IsSourceExtension(ext) || cm->IsHeaderExtension(ext);
 }
 
 bool cmSourceFileLocation::Matches(cmSourceFileLocation const& loc)
diff --git a/Source/cmSourceGroup.cxx b/Source/cmSourceGroup.cxx
index fba4c31..18bcb49 100644
--- a/Source/cmSourceGroup.cxx
+++ b/Source/cmSourceGroup.cxx
@@ -60,14 +60,14 @@
   this->GroupFiles.insert(name);
 }
 
-const char* cmSourceGroup::GetName() const
+std::string const& cmSourceGroup::GetName() const
 {
-  return this->Name.c_str();
+  return this->Name;
 }
 
-const char* cmSourceGroup::GetFullName() const
+std::string const& cmSourceGroup::GetFullName() const
 {
-  return this->FullName.c_str();
+  return this->FullName;
 }
 
 bool cmSourceGroup::MatchesRegex(const char* name)
@@ -105,7 +105,7 @@
 
   // st
   for (; iter != end; ++iter) {
-    std::string sgName = iter->GetName();
+    std::string const& sgName = iter->GetName();
 
     // look if descenened is the one were looking for
     if (sgName == name) {
diff --git a/Source/cmSourceGroup.h b/Source/cmSourceGroup.h
index e8bd697..7c7c35f 100644
--- a/Source/cmSourceGroup.h
+++ b/Source/cmSourceGroup.h
@@ -55,12 +55,12 @@
   /**
    * Get the name of this group.
    */
-  const char* GetName() const;
+  std::string const& GetName() const;
 
   /**
    * Get the full path name for group.
    */
-  const char* GetFullName() const;
+  std::string const& GetFullName() const;
 
   /**
    * Check if the given name matches this group's regex.
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 9cf835c..bf36074 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -279,6 +279,7 @@
     this->SetPropertyDefault("CUDA_STANDARD_REQUIRED", nullptr);
     this->SetPropertyDefault("CUDA_EXTENSIONS", nullptr);
     this->SetPropertyDefault("CUDA_COMPILER_LAUNCHER", nullptr);
+    this->SetPropertyDefault("CUDA_SEPARABLE_COMPILATION", nullptr);
     this->SetPropertyDefault("LINK_SEARCH_START_STATIC", nullptr);
     this->SetPropertyDefault("LINK_SEARCH_END_STATIC", nullptr);
   }
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 6486c8b..caeeeb9 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -1469,11 +1469,14 @@
   }
 
   this->WriteString("<ItemGroup>\n", 1);
-  for (std::set<cmSourceGroup*>::iterator g = groupsUsed.begin();
-       g != groupsUsed.end(); ++g) {
-    cmSourceGroup* sg = *g;
-    const char* name = sg->GetFullName();
-    if (strlen(name) != 0) {
+  std::vector<cmSourceGroup*> groupsVec(groupsUsed.begin(), groupsUsed.end());
+  std::sort(groupsVec.begin(), groupsVec.end(),
+            [](cmSourceGroup* l, cmSourceGroup* r) {
+              return l->GetFullName() < r->GetFullName();
+            });
+  for (cmSourceGroup* sg : groupsVec) {
+    std::string const& name = sg->GetFullName();
+    if (!name.empty()) {
       this->WriteString("<Filter Include=\"", 2);
       (*this->BuildFileStream) << name << "\">\n";
       std::string guidName = "SG_Filter_";
@@ -1558,12 +1561,12 @@
     std::string const& source = sf->GetFullPath();
     cmSourceGroup* sourceGroup =
       this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
-    const char* filter = sourceGroup->GetFullName();
+    std::string const& filter = sourceGroup->GetFullName();
     this->WriteString("<", 2);
     std::string path = this->ConvertPath(source, s->RelativePath);
     this->ConvertToWindowsSlash(path);
     (*this->BuildFileStream) << name << " Include=\"" << cmVS10EscapeXML(path);
-    if (strlen(filter)) {
+    if (!filter.empty()) {
       (*this->BuildFileStream) << "\">\n";
       this->WriteString("<Filter>", 3);
       (*this->BuildFileStream) << filter << "</Filter>\n";
diff --git a/Source/cmXMLWriter.h b/Source/cmXMLWriter.h
index 981255d..c890acf 100644
--- a/Source/cmXMLWriter.h
+++ b/Source/cmXMLWriter.h
@@ -7,6 +7,8 @@
 
 #include "cmXMLSafe.h"
 
+#include <chrono>
+#include <ctime>
 #include <ostream>
 #include <stack>
 #include <string>
@@ -99,6 +101,22 @@
     return cmXMLSafe(value).Quotes(false);
   }
 
+  /*
+   * Convert a std::chrono::system::time_point to the number of seconds since
+   * the UN*X epoch.
+   *
+   * It would be tempting to convert a time_point to number of seconds by
+   * using time_since_epoch(). Unfortunately the C++11 standard does not
+   * specify what the epoch of the system_clock must be.
+   * Therefore we must assume it is an arbitary point in time. Instead of this
+   * method, it is recommended to convert it by means of the to_time_t method.
+   */
+  static std::time_t SafeContent(
+    std::chrono::system_clock::time_point const& value)
+  {
+    return std::chrono::system_clock::to_time_t(value);
+  }
+
   template <typename T>
   static T SafeContent(T value)
   {
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index fde77a7..2a5bb6c 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -200,6 +200,11 @@
   this->SourceFileExtensions.push_back("M");
   this->SourceFileExtensions.push_back("mm");
 
+  std::copy(this->SourceFileExtensions.begin(),
+            this->SourceFileExtensions.end(),
+            std::inserter(this->SourceFileExtensionsSet,
+                          this->SourceFileExtensionsSet.end()));
+
   this->HeaderFileExtensions.push_back("h");
   this->HeaderFileExtensions.push_back("hh");
   this->HeaderFileExtensions.push_back("h++");
@@ -208,6 +213,11 @@
   this->HeaderFileExtensions.push_back("hxx");
   this->HeaderFileExtensions.push_back("in");
   this->HeaderFileExtensions.push_back("txx");
+
+  std::copy(this->HeaderFileExtensions.begin(),
+            this->HeaderFileExtensions.end(),
+            std::inserter(this->HeaderFileExtensionsSet,
+                          this->HeaderFileExtensionsSet.end()));
 }
 
 cmake::~cmake()
@@ -1647,6 +1657,21 @@
   this->UnwatchUnusedCli(key);
 }
 
+std::string cmake::StripExtension(const std::string& file) const
+{
+  auto dotpos = file.rfind('.');
+  if (dotpos != std::string::npos) {
+    auto ext = file.substr(dotpos + 1);
+#if defined(_WIN32) || defined(__APPLE__)
+    ext = cmSystemTools::LowerCase(ext);
+#endif
+    if (this->IsSourceExtension(ext) || this->IsHeaderExtension(ext)) {
+      return file.substr(0, dotpos);
+    }
+  }
+  return file;
+}
+
 const char* cmake::GetCacheDefinition(const std::string& name) const
 {
   return this->State->GetInitializedCacheValue(name);
diff --git a/Source/cmake.h b/Source/cmake.h
index 5c5a90d..02c6cdb 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -8,6 +8,7 @@
 #include <map>
 #include <set>
 #include <string>
+#include <unordered_set>
 #include <vector>
 
 #include "cmInstalledFile.h"
@@ -225,11 +226,27 @@
   {
     return this->SourceFileExtensions;
   }
+
+  bool IsSourceExtension(const std::string& ext) const
+  {
+    return this->SourceFileExtensionsSet.find(ext) !=
+      this->SourceFileExtensionsSet.end();
+  }
+
   const std::vector<std::string>& GetHeaderExtensions() const
   {
     return this->HeaderFileExtensions;
   }
 
+  bool IsHeaderExtension(const std::string& ext) const
+  {
+    return this->HeaderFileExtensionsSet.find(ext) !=
+      this->HeaderFileExtensionsSet.end();
+  }
+
+  // Strips the extension (if present and known) from a filename
+  std::string StripExtension(const std::string& file) const;
+
   /**
    * Given a variable name, return its value (as a string).
    */
@@ -486,7 +503,9 @@
   std::string CheckStampList;
   std::string VSSolutionFile;
   std::vector<std::string> SourceFileExtensions;
+  std::unordered_set<std::string> SourceFileExtensionsSet;
   std::vector<std::string> HeaderFileExtensions;
+  std::unordered_set<std::string> HeaderFileExtensionsSet;
   bool ClearBuildSystem;
   bool DebugTryCompile;
   cmFileTimeComparison* FileComparison;
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 449db9d..3d9f65a 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -6,7 +6,8 @@
 #include "cmGlobalGenerator.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
-#include "cmQtAutoGenerators.h"
+#include "cmQtAutoGeneratorMocUic.h"
+#include "cmQtAutoGeneratorRcc.h"
 #include "cmStateDirectory.h"
 #include "cmStateSnapshot.h"
 #include "cmSystemTools.h"
@@ -992,11 +993,20 @@
     }
 
 #ifdef CMAKE_BUILD_WITH_CMAKE
-    if (args[1] == "cmake_autogen" && args.size() >= 4) {
-      cmQtAutoGenerators autogen;
+    if ((args[1] == "cmake_autogen") && (args.size() >= 4)) {
+      cmQtAutoGeneratorMocUic autoGen;
+      std::string const& infoDir = args[2];
       std::string const& config = args[3];
-      bool autogenSuccess = autogen.Run(args[2], config);
-      return autogenSuccess ? 0 : 1;
+      return autoGen.Run(infoDir, config) ? 0 : 1;
+    }
+    if ((args[1] == "cmake_autorcc") && (args.size() >= 3)) {
+      cmQtAutoGeneratorRcc autoGen;
+      std::string const& infoFile = args[2];
+      std::string config;
+      if (args.size() > 3) {
+        config = args[3];
+      };
+      return autoGen.Run(infoFile, config) ? 0 : 1;
     }
 #endif
 
diff --git a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt
index 7ef626f..cfca823 100644
--- a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt
+++ b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt
@@ -13,7 +13,13 @@
 set(CMAKE_CXX_STANDARD 11)
 set(CMAKE_CUDA_STANDARD 11)
 
+set(CMAKE_CUDA_SEPARABLE_COMPILATION ON)
 add_library(CUDASeparateLibA STATIC file1.cu file2.cu file3.cu)
+get_property(sep_comp TARGET CUDASeparateLibA PROPERTY CUDA_SEPARABLE_COMPILATION)
+if(NOT sep_comp)
+  message(FATAL_ERROR "CUDA_SEPARABLE_COMPILATION not initialized")
+endif()
+unset(CMAKE_CUDA_SEPARABLE_COMPILATION)
 
 if(CMAKE_CUDA_SIMULATE_ID STREQUAL "MSVC")
   # Test adding a flag that is not in our CUDA flag table for VS.
diff --git a/Tests/FindOpenGL/Test/CMakeLists.txt b/Tests/FindOpenGL/Test/CMakeLists.txt
index 3b5ffee..9004a98 100644
--- a/Tests/FindOpenGL/Test/CMakeLists.txt
+++ b/Tests/FindOpenGL/Test/CMakeLists.txt
@@ -1,4 +1,5 @@
-cmake_minimum_required(VERSION 3.9)
+cmake_minimum_required(VERSION 3.10)
+cmake_policy(SET CMP0072 NEW)
 project(TestFindOpenGL C)
 include(CTest)
 
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 6b7b723..f306200 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -144,6 +144,7 @@
 add_RunCMake_test(FeatureSummary)
 add_RunCMake_test(FPHSA)
 add_RunCMake_test(FindBoost)
+add_RunCMake_test(FindOpenGL)
 if(NOT CMAKE_C_COMPILER_ID MATCHES "Watcom")
   add_RunCMake_test(GenerateExportHeader)
 endif()
diff --git a/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake b/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake
index 99d3155..948c6ab 100644
--- a/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake
+++ b/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake
@@ -45,13 +45,22 @@
     unset(prefix_)
   endif()
 
-  if(NOT DEFINED TEST_MAIN_INSTALL_PREFIX_PATH)
-    set(TEST_MAIN_INSTALL_PREFIX_PATH "/usr")
+  # add install prefix to expected paths
+  if(DEFINED EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX)
+    set(EXPECTED_FILE_PACKAGING_PREFIX
+      "${EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX}")
+  elseif(NOT DEFINED EXPECTED_FILE_PACKAGING_PREFIX)
+    # default CPack Archive packaging install prefix
+    set(EXPECTED_FILE_PACKAGING_PREFIX "/")
   endif()
+  set(prepared_ "${EXPECTED_FILE_PACKAGING_PREFIX}")
+  foreach(part_ IN LISTS ${CONTENT_VAR})
+    list(APPEND prepared_ "${EXPECTED_FILE_PACKAGING_PREFIX}${part_}")
+  endforeach()
 
   unset(filtered_)
-  foreach(part_ IN LISTS ${CONTENT_VAR})
-    string(REGEX REPLACE "^${TEST_MAIN_INSTALL_PREFIX_PATH}(/|$)" "" part_ "${part_}")
+  foreach(part_ IN LISTS prepared_)
+    string(REGEX REPLACE "^/" "" part_ "${part_}")
 
     if(part_)
       list(APPEND filtered_ "${prefix_}${part_}")
diff --git a/Tests/RunCMake/CPack/CPackTestHelpers.cmake b/Tests/RunCMake/CPack/CPackTestHelpers.cmake
index 5337b2c..447b08b 100644
--- a/Tests/RunCMake/CPack/CPackTestHelpers.cmake
+++ b/Tests/RunCMake/CPack/CPackTestHelpers.cmake
@@ -35,10 +35,27 @@
       "-DRunCMake_TEST_FILE_PREFIX=${TEST_NAME}"
       "-DRunCMake_SUBTEST_SUFFIX=${SUBTEST_SUFFIX}"
       "-DPACKAGING_TYPE=${PACKAGING_TYPE}")
+
+    foreach(o out err)
+      if(SUBTEST_SUFFIX AND EXISTS ${RunCMake_SOURCE_DIR}/tests/${TEST_NAME}/configure-${PACKAGING_TYPE}-${SUBTEST_SUFFIX}-std${o}.txt)
+        set(RunCMake-std${o}-file "tests/${TEST_NAME}/configure-${PACKAGING_TYPE}-${SUBTEST_SUFFIX}-std${o}.txt")
+      elseif(SUBTEST_SUFFIX AND EXISTS ${RunCMake_SOURCE_DIR}/tests/${TEST_NAME}/configure-${SUBTEST_SUFFIX}-std${o}.txt)
+        set(RunCMake-std${o}-file "tests/${TEST_NAME}/configure-${SUBTEST_SUFFIX}-std${o}.txt")
+      elseif(EXISTS ${RunCMake_SOURCE_DIR}/tests/${TEST_NAME}/configure-${PACKAGING_TYPE}-std${o}.txt)
+        set(RunCMake-std${o}-file "tests/${TEST_NAME}/configure-${PACKAGING_TYPE}-std${o}.txt")
+      elseif(EXISTS ${RunCMake_SOURCE_DIR}/tests/${TEST_NAME}/configure-std${o}.txt)
+        set(RunCMake-std${o}-file "tests/${TEST_NAME}/configure-std${o}.txt")
+      else()
+        unset(RunCMake-std${o}-file)
+      endif()
+    endforeach()
+
     run_cmake(${full_test_name_})
 
     # execute optional build step
     if(build)
+      unset(RunCMake-stdout-file)
+      unset(RunCMake-stderr-file)
       run_cmake_command(${full_test_name_}-Build "${CMAKE_COMMAND}" --build "${RunCMake_TEST_BINARY_DIR}")
     endif()
 
@@ -72,6 +89,8 @@
         set(RunCMake-std${o}-file "tests/${TEST_NAME}/${SUBTEST_SUFFIX}-std${o}.txt")
       elseif(EXISTS ${RunCMake_SOURCE_DIR}/${TEST_TYPE}/default_expected_std${o}.txt)
         set(RunCMake-std${o}-file "${TEST_TYPE}/default_expected_std${o}.txt")
+      else()
+        unset(RunCMake-std${o}-file)
       endif()
     endforeach()
 
diff --git a/Tests/RunCMake/CPack/DEB/Helpers.cmake b/Tests/RunCMake/CPack/DEB/Helpers.cmake
index 6d8e84a..f7c5c84 100644
--- a/Tests/RunCMake/CPack/DEB/Helpers.cmake
+++ b/Tests/RunCMake/CPack/DEB/Helpers.cmake
@@ -47,7 +47,20 @@
 endfunction()
 
 function(toExpectedContentList FILE_NO CONTENT_VAR)
-  # no need to do anything
+  # add install prefix to expected paths
+  if(DEFINED EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX)
+    set(EXPECTED_FILE_PACKAGING_PREFIX
+      "${EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX}")
+  elseif(NOT DEFINED EXPECTED_FILE_PACKAGING_PREFIX)
+    # default CPackDeb packaging install prefix
+    set(EXPECTED_FILE_PACKAGING_PREFIX "/usr")
+  endif()
+  set(prepared_ "${EXPECTED_FILE_PACKAGING_PREFIX}")
+  foreach(part_ IN LISTS ${CONTENT_VAR})
+    list(APPEND prepared_ "${EXPECTED_FILE_PACKAGING_PREFIX}${part_}")
+  endforeach()
+
+  set(${CONTENT_VAR} "${prepared_}" PARENT_SCOPE)
 endfunction()
 
 function(getMissingShlibsErrorExtra FILE RESULT_VAR)
diff --git a/Tests/RunCMake/CPack/README.txt b/Tests/RunCMake/CPack/README.txt
index 5877f97..2e2abdf 100644
--- a/Tests/RunCMake/CPack/README.txt
+++ b/Tests/RunCMake/CPack/README.txt
@@ -96,6 +96,14 @@
 a function run_after_include_cpack can be declared in test.cmake file and that
 function will run after the inclusion of CPack.cmake.
 
+NOTE: During CMake configure stage developer warnings may be expected. In such
+cases an expected output regular expression can be provided by creating
+'<test_name>/configure-stdout.txt' and/or '<test_name>/configure-stderr.txt'
+file. There are also more specialized versions of the file available:
+- configure-${PACKAGING_TYPE}-${SUBTEST_SUFFIX}-std${o}.txt
+- configure-${SUBTEST_SUFFIX}-std${o}.txt
+- configure-${PACKAGING_TYPE}-std${o}.txt
+
 build phase (optional and not available for source package tests)
 -----------------------------------------------------------------
 
@@ -153,13 +161,19 @@
         is later changed automatically depending on the generator so expected
         package content can be written only once per test for all generators.
 
+- EXPECTED_FILE_PACKAGING_PREFIX and
+  EXPECTED_FILE_<file_number_starting_with_1>_PACKAGING_PREFIX variables can be
+  set to explicitly specified CPACK_PACKAGING_PREFIX value. By default this
+  variable does not need to be set as it is implicitly set to package generator
+  specific prefix.
+
 Optional verification phase is generator specific and is optionaly executed.
 This phase is executed if '<test_name>/VerifyResult.cmake' script exists.
 
 VerifyResult.cmake script also automatically prints out standard output and
 standard error from CPack execution phase that is compared with
 '<test_name>/<generator_name>-stdout.txt' regular expression and
-and '<test_name>/<generator_name>-stderr.txt' regular expresson respectively.
+'<test_name>/<generator_name>-stderr.txt' regular expresson respectively.
 NOTE: For subtests generator name can also be suffixed with subtest name and/or
       packaging type (MONOLITHIC, COMPONENT, GROUP) and in such cases the
       preferences of which file will be used are as follows:
diff --git a/Tests/RunCMake/CPack/RPM/Helpers.cmake b/Tests/RunCMake/CPack/RPM/Helpers.cmake
index 88fc231..a29c020 100644
--- a/Tests/RunCMake/CPack/RPM/Helpers.cmake
+++ b/Tests/RunCMake/CPack/RPM/Helpers.cmake
@@ -47,14 +47,29 @@
 endfunction()
 
 function(toExpectedContentList FILE_NO CONTENT_VAR)
-  if(NOT DEFINED TEST_INSTALL_PREFIX_PATHS)
-    set(TEST_INSTALL_PREFIX_PATHS "/usr")
+  # add install prefix to expected paths
+  if(DEFINED EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX)
+    set(EXPECTED_FILE_PACKAGING_PREFIX
+      "${EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX}")
+  elseif(NOT DEFINED EXPECTED_FILE_PACKAGING_PREFIX)
+    # default CPackRPM packaging install prefix
+    set(EXPECTED_FILE_PACKAGING_PREFIX "/usr")
   endif()
-
-  unset(filtered_)
+  set(prepared_ "${EXPECTED_FILE_PACKAGING_PREFIX}")
   foreach(part_ IN LISTS ${CONTENT_VAR})
+    list(APPEND prepared_ "${EXPECTED_FILE_PACKAGING_PREFIX}${part_}")
+  endforeach()
+
+  # remove paths that are excluded from auto packaging
+  if(NOT DEFINED CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST)
+    set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST
+      /etc /etc/init.d /usr /usr/bin /usr/include /usr/lib
+      /usr/libx32 /usr/lib64 /usr/share /usr/share/aclocal /usr/share/doc)
+  endif()
+  unset(filtered_)
+  foreach(part_ IN LISTS prepared_)
     unset(dont_add_)
-    foreach(for_removal_ IN LISTS TEST_INSTALL_PREFIX_PATHS)
+    foreach(for_removal_ IN LISTS CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST)
       if(part_ STREQUAL for_removal_)
         set(dont_add_ TRUE)
         break()
diff --git a/Tests/RunCMake/CPack/STGZ/Helpers.cmake b/Tests/RunCMake/CPack/STGZ/Helpers.cmake
index 68b1eab..1756645 100644
--- a/Tests/RunCMake/CPack/STGZ/Helpers.cmake
+++ b/Tests/RunCMake/CPack/STGZ/Helpers.cmake
@@ -47,18 +47,29 @@
     string(SUBSTRING "${prefix_}" 0 ${pos_} prefix_)
   endif()
 
-  if(NOT DEFINED TEST_MAIN_INSTALL_PREFIX_PATH)
-    set(TEST_MAIN_INSTALL_PREFIX_PATH "/usr")
+    # add install prefix to expected paths
+  if(DEFINED EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX)
+    set(EXPECTED_FILE_PACKAGING_PREFIX
+      "${EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX}")
+  elseif(NOT DEFINED EXPECTED_FILE_PACKAGING_PREFIX)
+    # default CPack Archive packaging install prefix
+    set(EXPECTED_FILE_PACKAGING_PREFIX "/")
   endif()
 
-  set(filtered_ "${prefix_}")
-  foreach(part_ IN LISTS ${CONTENT_VAR})
-    string(REGEX REPLACE "^${TEST_MAIN_INSTALL_PREFIX_PATH}(/|$)" "" part_ "${part_}")
+  # remove trailing slash otherwise path concatenation will cause double slashes
+  string(REGEX REPLACE "/$" "" EXPECTED_FILE_PACKAGING_PREFIX
+    "${EXPECTED_FILE_PACKAGING_PREFIX}")
 
-    if(part_)
-      list(APPEND filtered_ "${prefix_}/${part_}")
-    endif()
+  if(EXPECTED_FILE_PACKAGING_PREFIX)
+    set(prepared_ "${prefix_}")
+  else()
+    unset(prepared_)
+  endif()
+
+  list(APPEND prepared_ "${prefix_}${EXPECTED_FILE_PACKAGING_PREFIX}")
+  foreach(part_ IN LISTS ${CONTENT_VAR})
+    list(APPEND prepared_ "${prefix_}${EXPECTED_FILE_PACKAGING_PREFIX}${part_}")
   endforeach()
 
-  set(${CONTENT_VAR} "${filtered_}" PARENT_SCOPE)
+  set(${CONTENT_VAR} "${prepared_}" PARENT_SCOPE)
 endfunction()
diff --git a/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/ExpectedFiles.cmake
index 5cb12c3..02a7821 100644
--- a/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/ExpectedFiles.cmake
@@ -1,3 +1,3 @@
 set(EXPECTED_FILES_COUNT "1")
 
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/abc.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/abc.txt")
diff --git a/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/ExpectedFiles.cmake
index 694dc00..6d895ec 100644
--- a/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/ExpectedFiles.cmake
@@ -1,9 +1,9 @@
 set(EXPECTED_FILES_COUNT "1")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
 
 if(PACKAGING_TYPE STREQUAL "COMPONENT")
   set(EXPECTED_FILES_COUNT "2")
   set(EXPECTED_FILE_1_COMPONENT "test")
   set(EXPECTED_FILE_2_COMPONENT "test2")
-  set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt")
+  set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt")
 endif()
diff --git a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake
index 5cb280c..07226df 100644
--- a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake
@@ -1,10 +1,10 @@
 set(EXPECTED_FILES_COUNT "3")
 set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE)
 set(EXPECTED_FILE_1_COMPONENT "pkg_1")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
 set(EXPECTED_FILE_2_NAME "second")
-set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
-set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_2_LIST "/foo;/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_3_LIST "/foo;/foo/CMakeLists.txt")
 
 if(GENERATOR_TYPE STREQUAL "DEB" OR GENERATOR_TYPE STREQUAL "RPM")
   string(TOLOWER "${GENERATOR_TYPE}" file_extension_)
diff --git a/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake
index 3d8de74..b26c6c7 100644
--- a/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake
@@ -5,11 +5,11 @@
 
 set(EXPECTED_FILE_1_NAME "Debuginfo")
 set(EXPECTED_FILE_1_COMPONENT "applications")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/test_prog")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog")
 set(EXPECTED_FILE_2 "TestDinfo-pkg*-headers.rpm")
-set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt")
 set(EXPECTED_FILE_3 "TestDinfo-pkg*-libs.rpm")
-set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/bas;/usr/bas/libtest_lib.so")
+set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/libtest_lib.so")
 
 set(EXPECTED_FILE_4_NAME "Debuginfo")
 set(EXPECTED_FILE_4_COMPONENT "applications-debuginfo")
diff --git a/Tests/RunCMake/CPack/tests/DEB_PACKAGE_VERSION_BACK_COMPATIBILITY/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/DEB_PACKAGE_VERSION_BACK_COMPATIBILITY/ExpectedFiles.cmake
index 6142eb3..d1a3a5f 100644
--- a/Tests/RunCMake/CPack/tests/DEB_PACKAGE_VERSION_BACK_COMPATIBILITY/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/DEB_PACKAGE_VERSION_BACK_COMPATIBILITY/ExpectedFiles.cmake
@@ -1,2 +1,2 @@
 set(EXPECTED_FILES_COUNT "1")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
diff --git a/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/ExpectedFiles.cmake
index 9b8205b..b6fcc17 100644
--- a/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/ExpectedFiles.cmake
@@ -2,5 +2,5 @@
   set(EXPECTED_FILES_COUNT "0")
 else()
   set(EXPECTED_FILES_COUNT "1")
-  set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+  set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
 endif()
diff --git a/Tests/RunCMake/CPack/tests/DEPENDENCIES/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/DEPENDENCIES/ExpectedFiles.cmake
index 3b280ba..be7ba07 100644
--- a/Tests/RunCMake/CPack/tests/DEPENDENCIES/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/DEPENDENCIES/ExpectedFiles.cmake
@@ -1,14 +1,14 @@
 set(EXPECTED_FILES_COUNT "5")
 set(EXPECTED_FILE_1_COMPONENT "applications")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/test_prog")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog")
 set(EXPECTED_FILE_2_COMPONENT "applications_auto")
-set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/foo_auto;/usr/foo_auto/test_prog")
+set(EXPECTED_FILE_CONTENT_2_LIST "/foo_auto;/foo_auto/test_prog")
 set(EXPECTED_FILE_3_COMPONENT "headers")
-set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_3_LIST "/bar;/bar/CMakeLists.txt")
 set(EXPECTED_FILE_4_COMPONENT "libs")
-set(EXPECTED_FILE_CONTENT_4_LIST "/usr/bas;/usr/bas/libtest_lib.so")
+set(EXPECTED_FILE_CONTENT_4_LIST "/bas;/bas/libtest_lib.so")
 set(EXPECTED_FILE_5_COMPONENT "libs_auto")
-set(EXPECTED_FILE_CONTENT_5_LIST "/usr;/usr/bas_auto;/usr/bas_auto/libtest_lib.so")
+set(EXPECTED_FILE_CONTENT_5_LIST "/bas_auto;/bas_auto/libtest_lib.so")
 
 if(GENERATOR_TYPE STREQUAL "DEB")
   set(whitespaces_ "[\t\n\r ]*")
diff --git a/Tests/RunCMake/CPack/tests/DIST/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/DIST/ExpectedFiles.cmake
index 6142eb3..d1a3a5f 100644
--- a/Tests/RunCMake/CPack/tests/DIST/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/DIST/ExpectedFiles.cmake
@@ -1,2 +1,2 @@
 set(EXPECTED_FILES_COUNT "1")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
diff --git a/Tests/RunCMake/CPack/tests/EMPTY_DIR/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/EMPTY_DIR/ExpectedFiles.cmake
index 650687c..8df6831 100644
--- a/Tests/RunCMake/CPack/tests/EMPTY_DIR/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/EMPTY_DIR/ExpectedFiles.cmake
@@ -1,6 +1,6 @@
 set(EXPECTED_FILES_COUNT "1")
 set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE)
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/empty")
+set(EXPECTED_FILE_CONTENT_1_LIST "/empty")
 
 if(PACKAGING_TYPE STREQUAL "COMPONENT")
   set(EXPECTED_FILE_1_COMPONENT "test")
diff --git a/Tests/RunCMake/CPack/tests/EXTRA/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/EXTRA/ExpectedFiles.cmake
index ded2923..407cbe6 100644
--- a/Tests/RunCMake/CPack/tests/EXTRA/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/EXTRA/ExpectedFiles.cmake
@@ -1,8 +1,8 @@
 set(EXPECTED_FILES_COUNT "3")
 set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE)
 set(EXPECTED_FILE_1_COMPONENT "foo")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
 set(EXPECTED_FILE_2_COMPONENT "bar")
-set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt")
 set(EXPECTED_FILE_3_COMPONENT "bas")
-set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/bas;/usr/bas/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/CMakeLists.txt")
diff --git a/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake
index a45b38d..974df22 100644
--- a/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake
@@ -2,6 +2,7 @@
 
 set(EXPECTED_FILES_COUNT "5")
 set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE)
+set(EXPECTED_FILE_PACKAGING_PREFIX "")
 
 set(EXPECTED_FILE_1_COMPONENT "applications")
 set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog")
diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake
index 44346ab..de38df9 100644
--- a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake
@@ -1,5 +1,5 @@
 set(EXPECTED_FILES_COUNT "2")
 set(EXPECTED_FILE_1_COMPONENT "foo")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
 set(EXPECTED_FILE_2_COMPONENT "bar")
-set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt")
diff --git a/Tests/RunCMake/CPack/tests/LONG_FILENAMES/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/LONG_FILENAMES/ExpectedFiles.cmake
index 631d957..4cb8dd0 100644
--- a/Tests/RunCMake/CPack/tests/LONG_FILENAMES/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/LONG_FILENAMES/ExpectedFiles.cmake
@@ -1,3 +1,3 @@
 set(EXPECTED_FILES_COUNT "1")
 set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE)
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/llllllllll_oooooooooo_nnnnnnnnnn_gggggggggg_ffffffffff_iiiiiiiiii_llllllllll_eeeeeeeeee_nnnnnnnnnn_aaaaaaaaaa_mmmmmmmmmm_eeeeeeeeee.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/llllllllll_oooooooooo_nnnnnnnnnn_gggggggggg_ffffffffff_iiiiiiiiii_llllllllll_eeeeeeeeee_nnnnnnnnnn_aaaaaaaaaa_mmmmmmmmmm_eeeeeeeeee.txt")
diff --git a/Tests/RunCMake/CPack/tests/MAIN_COMPONENT/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/MAIN_COMPONENT/ExpectedFiles.cmake
index 6bfb0c1..629be9e 100644
--- a/Tests/RunCMake/CPack/tests/MAIN_COMPONENT/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/MAIN_COMPONENT/ExpectedFiles.cmake
@@ -3,9 +3,9 @@
 if(NOT RunCMake_SUBTEST_SUFFIX STREQUAL "invalid")
   set(EXPECTED_FILES_COUNT "3")
   set(EXPECTED_FILE_1 "main_component-0.1.1-1.*.rpm")
-  set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+  set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
   set(EXPECTED_FILE_2_COMPONENT "headers")
-  set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt")
+  set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt")
   set(EXPECTED_FILE_3_COMPONENT "libs")
-  set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/bas;/usr/bas/CMakeLists.txt")
+  set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/CMakeLists.txt")
 endif()
diff --git a/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake
index 6142eb3..d1a3a5f 100644
--- a/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake
@@ -1,2 +1,2 @@
 set(EXPECTED_FILES_COUNT "1")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
diff --git a/Tests/RunCMake/CPack/tests/MINIMAL/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/MINIMAL/ExpectedFiles.cmake
index 6142eb3..d1a3a5f 100644
--- a/Tests/RunCMake/CPack/tests/MINIMAL/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/MINIMAL/ExpectedFiles.cmake
@@ -1,2 +1,2 @@
 set(EXPECTED_FILES_COUNT "1")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
diff --git a/Tests/RunCMake/CPack/tests/PACKAGE_CHECKSUM/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/PACKAGE_CHECKSUM/ExpectedFiles.cmake
index eed5b92..c375aca 100644
--- a/Tests/RunCMake/CPack/tests/PACKAGE_CHECKSUM/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/PACKAGE_CHECKSUM/ExpectedFiles.cmake
@@ -2,5 +2,5 @@
 
 if(NOT ${RunCMake_SUBTEST_SUFFIX} MATCHES "invalid")
   set(EXPECTED_FILES_COUNT "1")
-  set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+  set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
 endif()
diff --git a/Tests/RunCMake/CPack/tests/PARTIALLY_RELOCATABLE_WARNING/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/PARTIALLY_RELOCATABLE_WARNING/ExpectedFiles.cmake
index ae58c4b..137da47 100644
--- a/Tests/RunCMake/CPack/tests/PARTIALLY_RELOCATABLE_WARNING/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/PARTIALLY_RELOCATABLE_WARNING/ExpectedFiles.cmake
@@ -1,2 +1,4 @@
 set(EXPECTED_FILES_COUNT "1")
+# don't set the prefix here as we have absolute paths that should not be prefixed
+set(EXPECTED_FILE_PACKAGING_PREFIX "")
 set(EXPECTED_FILE_CONTENT_1_LIST "/not_relocatable;/not_relocatable/CMakeLists.txt;/opt")
diff --git a/Tests/RunCMake/CPack/tests/PER_COMPONENT_FIELDS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/PER_COMPONENT_FIELDS/ExpectedFiles.cmake
index 9bdb176..26fa1df 100644
--- a/Tests/RunCMake/CPack/tests/PER_COMPONENT_FIELDS/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/PER_COMPONENT_FIELDS/ExpectedFiles.cmake
@@ -1,8 +1,8 @@
 set(EXPECTED_FILES_COUNT "3")
 set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE)
 set(EXPECTED_FILE_1_COMPONENT "pkg_1")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
 set(EXPECTED_FILE_2_NAME "second")
-set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_2_LIST "/foo;/foo/CMakeLists.txt")
 set(EXPECTED_FILE_3_COMPONENT "pkg_3")
-set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_3_LIST "/foo;/foo/CMakeLists.txt")
diff --git a/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake
index ca866ea..8170d39 100644
--- a/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake
@@ -5,25 +5,25 @@
 if(RunCMake_SUBTEST_SUFFIX STREQUAL "valid" OR RunCMake_SUBTEST_SUFFIX STREQUAL "no_debuginfo")
   set(EXPECTED_FILES_COUNT "4")
   set(EXPECTED_FILE_1 "single_debuginfo-0.1.1-1.*.rpm")
-  set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/test_prog")
+  set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog")
   set(EXPECTED_FILE_2 "single_debuginfo*-headers.rpm")
-  set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt")
+  set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt")
   set(EXPECTED_FILE_3 "single_debuginfo*-libs.rpm")
-  set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/bas;/usr/bas/libtest_lib.so")
+  set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/libtest_lib.so")
 
   set(EXPECTED_FILE_4_COMPONENT "debuginfo")
   set(EXPECTED_FILE_CONTENT_4 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp${whitespaces_}/src/src_1/test_lib.cpp.*")
 elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "one_component" OR RunCMake_SUBTEST_SUFFIX STREQUAL "one_component_no_debuginfo")
   set(EXPECTED_FILES_COUNT "2")
   set(EXPECTED_FILE_1 "single_debuginfo-0*-applications.rpm")
-  set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/test_prog")
+  set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog")
 
   set(EXPECTED_FILE_2 "single_debuginfo-applications-debuginfo*.rpm")
   set(EXPECTED_FILE_CONTENT_2 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp.*")
 elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "one_component_main" OR RunCMake_SUBTEST_SUFFIX STREQUAL "no_components")
   set(EXPECTED_FILES_COUNT "2")
   set(EXPECTED_FILE_1 "single_debuginfo-0*.rpm")
-  set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/test_prog")
+  set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog")
 
   set(EXPECTED_FILE_2 "single_debuginfo-debuginfo*.rpm")
   set(EXPECTED_FILE_CONTENT_2 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp.*")
diff --git a/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/ExpectedFiles.cmake
index 0a3e426..d78f222 100644
--- a/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/ExpectedFiles.cmake
@@ -1,2 +1,3 @@
 set(EXPECTED_FILES_COUNT "1")
+set(EXPECTED_FILE_PACKAGING_PREFIX "")
 set(EXPECTED_FILE_CONTENT_1_LIST "source_package-0.1.1.tar.gz;source_package.spec")
diff --git a/Tests/RunCMake/CPack/tests/SUGGESTS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/SUGGESTS/ExpectedFiles.cmake
index 6142eb3..d1a3a5f 100644
--- a/Tests/RunCMake/CPack/tests/SUGGESTS/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/SUGGESTS/ExpectedFiles.cmake
@@ -1,2 +1,2 @@
 set(EXPECTED_FILES_COUNT "1")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
diff --git a/Tests/RunCMake/CPack/tests/SYMLINKS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/SYMLINKS/ExpectedFiles.cmake
index 05be748..e8281a8 100644
--- a/Tests/RunCMake/CPack/tests/SYMLINKS/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/SYMLINKS/ExpectedFiles.cmake
@@ -1,12 +1,11 @@
 set(EXPECTED_FILES_COUNT "1")
 
 set(EXPECTED_FILE_CONTENT_1_LIST
-  "/usr"
-  "/usr/empty_dir"
-  "/usr/non_empty_dir"
-  "/usr/non_empty_dir/CMakeLists.txt"
-  "/usr/symlink_to_empty_dir"
-  "/usr/symlink_to_non_empty_dir")
+  "/empty_dir"
+  "/non_empty_dir"
+  "/non_empty_dir/CMakeLists.txt"
+  "/symlink_to_empty_dir"
+  "/symlink_to_non_empty_dir")
 
 if(PACKAGING_TYPE STREQUAL "COMPONENT")
   set(EXPECTED_FILE_1_COMPONENT "links")
diff --git a/Tests/RunCMake/CPack/tests/USER_FILELIST/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/USER_FILELIST/ExpectedFiles.cmake
index aabe537..8420986 100644
--- a/Tests/RunCMake/CPack/tests/USER_FILELIST/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/USER_FILELIST/ExpectedFiles.cmake
@@ -1,2 +1,2 @@
 set(EXPECTED_FILES_COUNT "1")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr/one;/usr/one/foo.txt;/usr/one/two;/usr/one/two/bar.txt;/usr/three;/usr/three/baz.txt;/usr/three/qux.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/one;/one/foo.txt;/one/two;/one/two/bar.txt;/three;/three/baz.txt;/three/qux.txt")
diff --git a/Tests/RunCMake/CPack/tests/VERSION/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/VERSION/ExpectedFiles.cmake
index 85c571c..372f71b 100644
--- a/Tests/RunCMake/CPack/tests/VERSION/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/VERSION/ExpectedFiles.cmake
@@ -1,3 +1,3 @@
 set(EXPECTED_FILES_COUNT "1")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
 set(EXPECTED_FILE_1_REVISION "1")
diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-NEW-stdout.txt b/Tests/RunCMake/FindOpenGL/CMP0072-NEW-stdout.txt
new file mode 100644
index 0000000..f5ee220
--- /dev/null
+++ b/Tests/RunCMake/FindOpenGL/CMP0072-NEW-stdout.txt
@@ -0,0 +1,3 @@
+-- OpenGL_GL_PREFERENCE='GLVND'
+-- OPENGL_gl_LIBRARY=''
+-- OPENGL_LIBRARIES='OpenGL;GLX;GLU'
diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-NEW.cmake b/Tests/RunCMake/FindOpenGL/CMP0072-NEW.cmake
new file mode 100644
index 0000000..6cbbeec
--- /dev/null
+++ b/Tests/RunCMake/FindOpenGL/CMP0072-NEW.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0072 NEW)
+include(CMP0072-common.cmake)
diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-OLD-stdout.txt b/Tests/RunCMake/FindOpenGL/CMP0072-OLD-stdout.txt
new file mode 100644
index 0000000..22df1b1
--- /dev/null
+++ b/Tests/RunCMake/FindOpenGL/CMP0072-OLD-stdout.txt
@@ -0,0 +1,3 @@
+-- OpenGL_GL_PREFERENCE='LEGACY'
+-- OPENGL_gl_LIBRARY='GL'
+-- OPENGL_LIBRARIES='GL;GLU'
diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-OLD.cmake b/Tests/RunCMake/FindOpenGL/CMP0072-OLD.cmake
new file mode 100644
index 0000000..6d57004
--- /dev/null
+++ b/Tests/RunCMake/FindOpenGL/CMP0072-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0072 OLD)
+include(CMP0072-common.cmake)
diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-WARN-stderr.txt b/Tests/RunCMake/FindOpenGL/CMP0072-WARN-stderr.txt
new file mode 100644
index 0000000..f26f217
--- /dev/null
+++ b/Tests/RunCMake/FindOpenGL/CMP0072-WARN-stderr.txt
@@ -0,0 +1,21 @@
+^CMake Warning \(dev\) at .*/Modules/FindOpenGL.cmake:[0-9]+ \(message\):
+  Policy CMP0072 is not set: FindOpenGL prefers GLVND by default when
+  available.  Run "cmake --help-policy CMP0072" for policy details.  Use the
+  cmake_policy command to set the policy and suppress this warning.
+
+  FindOpenGL found both a legacy GL library:
+
+    OPENGL_gl_LIBRARY: GL
+
+  and GLVND libraries for OpenGL and GLX:
+
+    OPENGL_opengl_LIBRARY: OpenGL
+    OPENGL_glx_LIBRARY: GLX
+
+  OpenGL_GL_PREFERENCE has not been set to "GLVND" or "LEGACY", so for
+  compatibility with CMake 3.10 and below the legacy GL library will be used.
+Call Stack \(most recent call first\):
+  CMP0072-common.cmake:[0-9]+ \(find_package\)
+  CMP0072-WARN.cmake:[0-9]+ \(include\)
+  CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers.  Use -Wno-dev to suppress it.$
diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-WARN-stdout.txt b/Tests/RunCMake/FindOpenGL/CMP0072-WARN-stdout.txt
new file mode 100644
index 0000000..22df1b1
--- /dev/null
+++ b/Tests/RunCMake/FindOpenGL/CMP0072-WARN-stdout.txt
@@ -0,0 +1,3 @@
+-- OpenGL_GL_PREFERENCE='LEGACY'
+-- OPENGL_gl_LIBRARY='GL'
+-- OPENGL_LIBRARIES='GL;GLU'
diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-WARN.cmake b/Tests/RunCMake/FindOpenGL/CMP0072-WARN.cmake
new file mode 100644
index 0000000..459c458
--- /dev/null
+++ b/Tests/RunCMake/FindOpenGL/CMP0072-WARN.cmake
@@ -0,0 +1 @@
+include(CMP0072-common.cmake)
diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-common.cmake b/Tests/RunCMake/FindOpenGL/CMP0072-common.cmake
new file mode 100644
index 0000000..3fe8030
--- /dev/null
+++ b/Tests/RunCMake/FindOpenGL/CMP0072-common.cmake
@@ -0,0 +1,13 @@
+set(CYGWIN 0)
+set(WIN32 0)
+set(APPLE 0)
+set(OPENGL_INCLUDE_DIR GL/include)
+set(OPENGL_GLX_INCLUDE_DIR GLX/include)
+set(OPENGL_gl_LIBRARY GL)
+set(OPENGL_opengl_LIBRARY OpenGL)
+set(OPENGL_glx_LIBRARY GLX)
+set(OPENGL_glu_LIBRARY GLU)
+find_package(OpenGL)
+message(STATUS "OpenGL_GL_PREFERENCE='${OpenGL_GL_PREFERENCE}'")
+message(STATUS "OPENGL_gl_LIBRARY='${OPENGL_gl_LIBRARY}'")
+message(STATUS "OPENGL_LIBRARIES='${OPENGL_LIBRARIES}'")
diff --git a/Tests/RunCMake/FindOpenGL/CMakeLists.txt b/Tests/RunCMake/FindOpenGL/CMakeLists.txt
new file mode 100644
index 0000000..bf2ef15
--- /dev/null
+++ b/Tests/RunCMake/FindOpenGL/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.10)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/FindOpenGL/RunCMakeTest.cmake b/Tests/RunCMake/FindOpenGL/RunCMakeTest.cmake
new file mode 100644
index 0000000..fcc130f
--- /dev/null
+++ b/Tests/RunCMake/FindOpenGL/RunCMakeTest.cmake
@@ -0,0 +1,5 @@
+include(RunCMake)
+
+run_cmake(CMP0072-WARN)
+run_cmake(CMP0072-OLD)
+run_cmake(CMP0072-NEW)