[Cmake-commits] CMake branch, master, updated. v3.10.0-rc5-384-g08ce62b

Kitware Robot kwrobot at kitware.com
Mon Nov 20 10:15:07 EST 2017


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

The branch, master has been updated
       via  08ce62bee5bee6805fbb01c1821c438028e858dc (commit)
       via  66b37132b6c7d347a0fe83ee5082a751e8e0d9aa (commit)
       via  325f34d1507d391e5125d0a57e3575ecbe4e6f13 (commit)
       via  176281e131f244bfc987a696951a87ea9b909840 (commit)
       via  cf0c25995d6fd213727f578b35139a822fbaee77 (commit)
       via  2ff906b34e661cff80b7909bf2d4136b35c41fed (commit)
       via  4043463179d5e238cd1505f68fe0a4e75f4feba4 (commit)
       via  be11a85286ad538654dacce63a6be0af0c3c5bec (commit)
       via  ab9d5896ae43789872fca2e83d556912abb60254 (commit)
       via  2a85b5ac768cde4a9bbe98551528c8bae1e268a8 (commit)
       via  75819b8626abf0e64895ef19acd27dbd0fa9255b (commit)
       via  27ed3b3537676e6090a0845e4805bb4a65d05bae (commit)
       via  1cd285fe06088d6dad58a3b52c071579aa0ce8b8 (commit)
       via  a87f82e0258148f3047a3487c832a569dd841e09 (commit)
       via  b2a0b549bb9fea678517a52caf333eae009901dd (commit)
      from  345ae8d0e1133971e8acff93d6fcdf653c4d2e11 (commit)

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

- Log -----------------------------------------------------------------
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=08ce62bee5bee6805fbb01c1821c438028e858dc
commit 08ce62bee5bee6805fbb01c1821c438028e858dc
Merge: 66b3713 4043463
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Nov 20 15:12:56 2017 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Mon Nov 20 10:13:11 2017 -0500

    Merge topic 'autogen-rcc-custom-command'
    
    40434631 Autogen: Use integers instead of strings for the Qt version
    be11a852 Autogen: Use project relative paths in rcc custom command comment
    ab9d5896 Autogen: Detect rcc feature once during configuration
    2a85b5ac Autogen: Make cmQtAutoGeneratorInitializer an instantiable class
    75819b86 Autogen: Add and use cmQtAutoGenerator base class
    27ed3b35 Autogen: Rename cmQtAutoGenerators to cmQtAutoGeneratorMocUic
    1cd285fe Autogen: Remove rcc code from cmQtAutoGenerators
    a87f82e0 Autogen: Switch to use custom commands for RCC
    ...
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !1494


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=66b37132b6c7d347a0fe83ee5082a751e8e0d9aa
commit 66b37132b6c7d347a0fe83ee5082a751e8e0d9aa
Merge: 345ae8d 325f34d
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Nov 20 15:09:05 2017 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Mon Nov 20 10:09:14 2017 -0500

    Merge topic 'cpack-minor-cleanup-and-tests-extension'
    
    325f34d1 CPack tests: add possibility for expecting config developer warnings
    176281e1 CPack test: correctly handle CPACK_PACKAGING_INSTALL_PREFIX
    cf0c2599 CPack: set variable commands in lower case
    2ff906b3 CPack: documentation typo fix
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !1499


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=325f34d1507d391e5125d0a57e3575ecbe4e6f13
commit 325f34d1507d391e5125d0a57e3575ecbe4e6f13
Author:     Domen Vrankar <domen.vrankar at gmail.com>
AuthorDate: Sun Nov 19 14:22:17 2017 +0100
Commit:     Domen Vrankar <domen.vrankar at gmail.com>
CommitDate: Sun Nov 19 14:55:00 2017 +0100

    CPack tests: add possibility for expecting config developer warnings

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 @@ function(run_cpack_test_common_ TEST_NAME types build SUBTEST_SUFFIX source PACK
       "-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 @@ function(run_cpack_test_common_ TEST_NAME types build SUBTEST_SUFFIX source PACK
         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/README.txt b/Tests/RunCMake/CPack/README.txt
index 5ca1216..2e2abdf 100644
--- a/Tests/RunCMake/CPack/README.txt
+++ b/Tests/RunCMake/CPack/README.txt
@@ -96,6 +96,14 @@ the test has to run some functions after CPack.cmake is included. In such cases
 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)
 -----------------------------------------------------------------
 
@@ -165,7 +173,7 @@ 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:

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=176281e131f244bfc987a696951a87ea9b909840
commit 176281e131f244bfc987a696951a87ea9b909840
Author:     Domen Vrankar <domen.vrankar at gmail.com>
AuthorDate: Sun Nov 19 00:04:54 2017 +0100
Commit:     Domen Vrankar <domen.vrankar at gmail.com>
CommitDate: Sun Nov 19 14:55:00 2017 +0100

    CPack test: correctly handle CPACK_PACKAGING_INSTALL_PREFIX
    
    Every CPack generator sets default CPACK_PACKAGING_INSTALL_PREFIX
    variable value differently so test framework should support
    that correctly - previous version expected RPM/Deb /usr default and
    removed it for Archive packagers as the default there is /.

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 @@ function(toExpectedContentList FILE_NO CONTENT_VAR)
     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/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 @@ function(getPackageContentList FILE RESULT_VAR)
 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..5ca1216 100644
--- a/Tests/RunCMake/CPack/README.txt
+++ b/Tests/RunCMake/CPack/README.txt
@@ -153,6 +153,12 @@ this step and must contain
         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.
 
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 @@ function(getPackageContentList FILE RESULT_VAR)
 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()
+  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 ${CONTENT_VAR})
+  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 @@ function(toExpectedContentList FILE_NO CONTENT_VAR)
     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(EXPECTED_FILE_PACKAGING_PREFIX)
+    set(prepared_ "${prefix_}")
+  else()
+    unset(prepared_)
+  endif()
 
-    if(part_)
-      list(APPEND filtered_ "${prefix_}/${part_}")
-    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_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE)
 
 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 @@ if(${RunCMake_SUBTEST_SUFFIX} MATCHES "invalid_.*_var")
   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(whitespaces_ "[\t\n\r ]*")
 
 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 @@ set(EXPECTED_FILES_COUNT "0")
 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 @@ set(EXPECTED_FILES_COUNT "0")
 
 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 @@ set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE)
 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")

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cf0c25995d6fd213727f578b35139a822fbaee77
commit cf0c25995d6fd213727f578b35139a822fbaee77
Author:     Domen Vrankar <domen.vrankar at gmail.com>
AuthorDate: Sun Nov 12 22:31:19 2017 +0100
Commit:     Domen Vrankar <domen.vrankar at gmail.com>
CommitDate: Sun Nov 19 14:55:00 2017 +0100

    CPack: set variable commands in lower case

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 @@ function(cpack_encode_variables)
         set(value "${${var}}")
       endif()
 
-      string(APPEND commands "\nSET(${var} \"${value}\")")
+      string(APPEND commands "\nset(${var} \"${value}\")")
     endif()
   endforeach()
 

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2ff906b34e661cff80b7909bf2d4136b35c41fed
commit 2ff906b34e661cff80b7909bf2d4136b35c41fed
Author:     Domen Vrankar <domen.vrankar at gmail.com>
AuthorDate: Sun Nov 12 20:57:57 2017 +0100
Commit:     Domen Vrankar <domen.vrankar at gmail.com>
CommitDate: Sun Nov 19 14:55:00 2017 +0100

    CPack: documentation typo fix

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

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4043463179d5e238cd1505f68fe0a4e75f4feba4
commit 4043463179d5e238cd1505f68fe0a4e75f4feba4
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Sun Nov 19 12:44:21 2017 +0100
Commit:     Sebastian Holtermann <sebholt at xwmw.org>
CommitDate: Sun Nov 19 13:35:07 2017 +0100

    Autogen: Use integers instead of strings for the Qt version

diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in
index 8fa3684..9a4a06d 100644
--- a/Modules/AutogenInfo.cmake.in
+++ b/Modules/AutogenInfo.cmake.in
@@ -12,7 +12,6 @@ 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@)
 # MOC settings
diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx
index a2c9b42..d9a5a9a 100644
--- a/Source/cmQtAutoGeneratorInitializer.cxx
+++ b/Source/cmQtAutoGeneratorInitializer.cxx
@@ -899,10 +899,9 @@ void cmQtAutoGeneratorInitializer::SetupCustomTargets()
   AddDefinitionEscaped(makefile, "_multi_config",
                        cmQtAutoGen::MultiConfigName(this->MultiConfig));
   AddDefinitionEscaped(makefile, "_build_dir", this->DirBuild);
-  AddDefinitionEscaped(makefile, "_qt_version_major", this->QtVersionMajor);
-  AddDefinitionEscaped(makefile, "_qt_version_minor", this->QtVersionMinor);
 
   if (this->MocEnabled || this->UicEnabled) {
+    AddDefinitionEscaped(makefile, "_qt_version_major", this->QtVersionMajor);
     AddDefinitionEscaped(makefile, "_settings_file",
                          this->AutogenSettingsFile);
     AddDefinitionEscaped(makefile, "_sources", this->Sources);
diff --git a/Source/cmQtAutoGeneratorMocUic.cxx b/Source/cmQtAutoGeneratorMocUic.cxx
index 1956a89..0de02b5 100644
--- a/Source/cmQtAutoGeneratorMocUic.cxx
+++ b/Source/cmQtAutoGeneratorMocUic.cxx
@@ -49,6 +49,7 @@ static bool ListContains(std::vector<std::string> const& list,
 cmQtAutoGeneratorMocUic::cmQtAutoGeneratorMocUic()
   : MultiConfig(cmQtAutoGen::WRAP)
   , IncludeProjectDirsBefore(false)
+  , QtVersionMajor(4)
   , MocSettingsChanged(false)
   , MocPredefsChanged(false)
   , MocRelaxedMode(false)
@@ -163,19 +164,13 @@ bool cmQtAutoGeneratorMocUic::InitInfoFile(cmMakefile* makefile)
   }
 
   // - 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");
 
-  // Check Qt version
-  if ((this->QtMajorVersion != "4") && (this->QtMajorVersion != "5")) {
-    this->LogFileError(cmQtAutoGen::GEN, this->GetInfoFile(),
-                       "Unsupported Qt version: " +
-                         cmQtAutoGen::Quoted(this->QtMajorVersion));
-    return false;
-  }
-
   // - Moc
   if (this->MocEnabled()) {
     this->MocSkipList = InfoGetList("AM_MOC_SKIP");
@@ -203,7 +198,7 @@ bool cmQtAutoGeneratorMocUic::InitInfoFile(cmMakefile* makefile)
       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]*\"([^\"]+)\"");
@@ -1686,7 +1681,7 @@ bool cmQtAutoGeneratorMocUic::UicGenerateFile(const UicJob& uicJob)
         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());
       }
diff --git a/Source/cmQtAutoGeneratorMocUic.h b/Source/cmQtAutoGeneratorMocUic.h
index a03270b..d510939 100644
--- a/Source/cmQtAutoGeneratorMocUic.h
+++ b/Source/cmQtAutoGeneratorMocUic.h
@@ -154,8 +154,7 @@ private:
   std::string AutogenBuildDir;
   std::string AutogenIncludeDir;
   // -- Qt environment
-  std::string QtMajorVersion;
-  std::string QtMinorVersion;
+  unsigned long QtVersionMajor;
   std::string MocExecutable;
   std::string UicExecutable;
   // -- File lists

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=be11a85286ad538654dacce63a6be0af0c3c5bec
commit be11a85286ad538654dacce63a6be0af0c3c5bec
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Sun Nov 19 13:34:43 2017 +0100
Commit:     Sebastian Holtermann <sebholt at xwmw.org>
CommitDate: Sun Nov 19 13:35:07 2017 +0100

    Autogen: Use project relative paths in rcc custom command comment

diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx
index b265f28..a2c9b42 100644
--- a/Source/cmQtAutoGeneratorInitializer.cxx
+++ b/Source/cmQtAutoGeneratorInitializer.cxx
@@ -147,6 +147,26 @@ static void AddCleanFile(cmMakefile* makefile, std::string const& fileName)
                            false);
 }
 
+static std::string FileProjectRelativePath(cmMakefile* makefile,
+                                           std::string const& fileName)
+{
+  std::string res;
+  {
+    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;
+    }
+  }
+  return res;
+}
+
 /* @brief Tests if targetDepend is a STATIC_LIBRARY and if any of its
  * recursive STATIC_LIBRARY dependencies depends on targetOrigin
  * (STATIC_LIBRARY cycle).
@@ -646,7 +666,7 @@ void cmQtAutoGeneratorInitializer::InitCustomTargets()
         commandLines.push_back(std::move(currentLine));
       }
       std::string ccComment = "Automatic RCC for ";
-      ccComment += qrc.QrcFile;
+      ccComment += FileProjectRelativePath(makefile, qrc.QrcFile);
 
       if (qrc.Generated) {
         // Create custom rcc target

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ab9d5896ae43789872fca2e83d556912abb60254
commit ab9d5896ae43789872fca2e83d556912abb60254
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Sun Nov 19 12:22:49 2017 +0100
Commit:     Sebastian Holtermann <sebholt at xwmw.org>
CommitDate: Sun Nov 19 13:12:42 2017 +0100

    Autogen: Detect rcc feature once during configuration
    
    We used to detect the `rcc` features before every `rcc` list invocation
    wich resulted in `rcc` be called twice for every listing operation.
    
    Now we detect the `rcc` list capabilities once during configuration and
    pass it to the cmake_autorcc target in the info file.

diff --git a/Modules/AutoRccInfo.cmake.in b/Modules/AutoRccInfo.cmake.in
index 7b13b9e..5457a6f 100644
--- a/Modules/AutoRccInfo.cmake.in
+++ b/Modules/AutoRccInfo.cmake.in
@@ -7,5 +7,5 @@ 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_QT_VERSION_MAJOR @_qt_version_major@)
-set(ARCC_QT_RCC_EXECUTABLE @_qt_rcc_executable@)
+set(ARCC_RCC_EXECUTABLE @_qt_rcc_executable@)
+set(ARCC_RCC_LIST_OPTIONS @_qt_rcc_list_options@)
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 @@ void MergeOptions(std::vector<std::string>& baseOpts,
   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 @@ static bool RccListInputsQt4(std::string const& fileName,
       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 @@ static bool RccListInputsQt4(std::string const& fileName,
 /// @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 @@ static bool RccListInputsQt5(std::string const& rccCommand,
     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 @@ static bool RccListInputsQt5(std::string const& rccCommand,
   {
     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 @@ static bool RccListInputsQt5(std::string const& rccCommand,
   }
   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 @@ static bool RccListInputsQt5(std::string const& rccCommand,
     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 @@ void cmQtAutoGen::RccMergeOptions(std::vector<std::string>& baseOpts,
   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 @@ public:
 
   /// @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/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx
index 5edddaa..b265f28 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"
@@ -190,40 +191,6 @@ static bool StaticLibraryCycle(cmGeneratorTarget const* targetOrigin,
   return cycle;
 }
 
-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 += " (";
-    err += target->GetName();
-    err += ")";
-    cmSystemTools::Error(err.c_str());
-  }
-  return rccExec;
-}
-
 cmQtAutoGeneratorInitializer::cmQtAutoGeneratorInitializer(
   cmGeneratorTarget* target, bool mocEnabled, bool uicEnabled, bool rccEnabled,
   std::string const& qtVersionMajor)
@@ -368,6 +335,56 @@ void cmQtAutoGeneratorInitializer::InitCustomTargets()
     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;
@@ -548,8 +565,6 @@ void cmQtAutoGeneratorInitializer::InitCustomTargets()
   // Process qrc files
   if (!this->Qrcs.empty()) {
     const bool QtV5 = (this->QtVersionMajor == "5");
-    std::string const rcc =
-      RccGetExecutable(this->Target, this->QtVersionMajor);
     // Target rcc options
     std::vector<std::string> optionsTarget;
     cmSystemTools::ExpandListArgument(
@@ -673,9 +688,9 @@ void cmQtAutoGeneratorInitializer::InitCustomTargets()
           // Add the resource files to the dependencies
           {
             std::string error;
-            if (cmQtAutoGen::RccListInputs(this->QtVersionMajor, rcc,
-                                           qrc.QrcFile, qrc.Resources,
-                                           &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);
@@ -881,8 +896,9 @@ void cmQtAutoGeneratorInitializer::SetupCustomTargets()
     }
   }
   if (this->RccEnabled) {
-    AddDefinitionEscaped(makefile, "_qt_rcc_executable",
-                         RccGetExecutable(this->Target, this->QtVersionMajor));
+    AddDefinitionEscaped(makefile, "_qt_rcc_executable", this->RccExecutable);
+    AddDefinitionEscaped(makefile, "_qt_rcc_list_options",
+                         this->RccListOptions);
   }
 
   // Create info directory on demand
diff --git a/Source/cmQtAutoGeneratorInitializer.h b/Source/cmQtAutoGeneratorInitializer.h
index 9eebbd6..e06e1c4 100644
--- a/Source/cmQtAutoGeneratorInitializer.h
+++ b/Source/cmQtAutoGeneratorInitializer.h
@@ -65,8 +65,11 @@ private:
   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;
diff --git a/Source/cmQtAutoGeneratorRcc.cxx b/Source/cmQtAutoGeneratorRcc.cxx
index 573f04c..3c9f1a8 100644
--- a/Source/cmQtAutoGeneratorRcc.cxx
+++ b/Source/cmQtAutoGeneratorRcc.cxx
@@ -78,8 +78,8 @@ bool cmQtAutoGeneratorRcc::InfoFileRead(cmMakefile* makefile)
   this->AutogenBuildDir = InfoGet("ARCC_BUILD_DIR");
 
   // - Qt environment
-  this->QtMajorVersion = InfoGet("ARCC_QT_VERSION_MAJOR");
-  this->RccExecutable = InfoGet("ARCC_QT_RCC_EXECUTABLE");
+  this->RccExecutable = InfoGet("ARCC_RCC_EXECUTABLE");
+  this->RccListOptions = InfoGetList("ARCC_RCC_LIST_OPTIONS");
 
   // - Job
   this->QrcFile = InfoGet("ARCC_SOURCE");
@@ -135,6 +135,8 @@ void cmQtAutoGeneratorRcc::SettingsFileRead(cmMakefile* makefile)
       std::string str;
       str += this->RccExecutable;
       str += sep;
+      str += cmJoin(this->RccListOptions, ";");
+      str += sep;
       str += this->QrcFile;
       str += sep;
       str += this->RccFile;
@@ -307,7 +309,7 @@ bool cmQtAutoGeneratorRcc::RccGenerate()
     } else {
       // Read input file list from qrc file
       std::string error;
-      if (cmQtAutoGen::RccListInputs(this->QtMajorVersion, this->RccExecutable,
+      if (cmQtAutoGen::RccListInputs(this->RccExecutable, this->RccListOptions,
                                      this->QrcFile, readFiles, &error)) {
         files = &readFiles;
       } else {
diff --git a/Source/cmQtAutoGeneratorRcc.h b/Source/cmQtAutoGeneratorRcc.h
index 804d117..0e3f690 100644
--- a/Source/cmQtAutoGeneratorRcc.h
+++ b/Source/cmQtAutoGeneratorRcc.h
@@ -44,8 +44,8 @@ private:
   std::string AutogenBuildDir;
   cmFilePathChecksum FilePathChecksum;
   // -- Qt environment
-  std::string QtMajorVersion;
   std::string RccExecutable;
+  std::vector<std::string> RccListOptions;
   // -- Job
   std::string QrcFile;
   std::string RccFile;

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2a85b5ac768cde4a9bbe98551528c8bae1e268a8
commit 2a85b5ac768cde4a9bbe98551528c8bae1e268a8
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Sat Nov 18 15:08:08 2017 +0100
Commit:     Sebastian Holtermann <sebholt at xwmw.org>
CommitDate: Sun Nov 19 12:51:31 2017 +0100

    Autogen: Make cmQtAutoGeneratorInitializer an instantiable class
    
    Remove the cmQtAutoGenDigest classes and make
    cmQtAutoGeneratorInitializer instantiable instead.

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 6b086fa..6c60675 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -311,7 +311,6 @@ set(SRCS
   cmPropertyMap.h
   cmQtAutoGen.cxx
   cmQtAutoGen.h
-  cmQtAutoGenDigest.h
   cmQtAutoGenerator.cxx
   cmQtAutoGenerator.h
   cmQtAutoGeneratorInitializer.cxx
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 @@ bool cmGlobalGenerator::Compute()
 #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 @@ bool cmGlobalGenerator::Compute()
   }
 
 #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 @@ bool cmGlobalGenerator::ComputeTargetDepends()
   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 @@ cmQtAutoGenDigestUPV cmGlobalGenerator::CreateQtAutoGeneratorsTargets()
         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 cmLinkLineComputer;
 class cmLocalGenerator;
 class cmMakefile;
 class cmOutputConverter;
+class cmQtAutoGeneratorInitializer;
 class cmSourceFile;
 class cmStateDirectory;
 class cmake;
@@ -433,7 +433,8 @@ protected:
   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/cmQtAutoGenDigest.h b/Source/cmQtAutoGenDigest.h
deleted file mode 100644
index 9ee1117..0000000
--- a/Source/cmQtAutoGenDigest.h
+++ /dev/null
@@ -1,66 +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 InfoFile;
-  std::string SettingsFile;
-  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/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx
index 1d18bad..5edddaa 100644
--- a/Source/cmQtAutoGeneratorInitializer.cxx
+++ b/Source/cmQtAutoGeneratorInitializer.cxx
@@ -51,118 +51,6 @@ inline static std::string GetSafeProperty(cmSourceFile const* sf,
   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,50 +146,6 @@ static void AddCleanFile(cmMakefile* makefile, std::string const& fileName)
                            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)
-{
-  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));
-    }
-  }
-  {
-    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);
-    }
-  }
-
-  // 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;
-}
-
 /* @brief Tests if targetDepend is a STATIC_LIBRARY and if any of its
  * recursive STATIC_LIBRARY dependencies depends on targetOrigin
  * (STATIC_LIBRARY cycle).
@@ -346,371 +190,182 @@ static bool StaticLibraryCycle(cmGeneratorTarget const* targetOrigin,
   return cycle;
 }
 
-struct cmQtAutoGenSetup
+static std::string RccGetExecutable(cmGeneratorTarget const* target,
+                                    std::string const& qtMajorVersion)
 {
-  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::string rccExec;
+  std::string err;
 
-static void SetupAcquireSkipFiles(cmQtAutoGenDigest const& digest,
-                                  cmQtAutoGenSetup& setup)
-{
-  // Read skip files from makefile sources
-  {
-    const std::vector<cmSourceFile*>& allSources =
-      digest.Target->Makefile->GetSourceFiles();
-    for (cmSourceFile* sf : allSources) {
-      // sf->GetExtension() is only valid after sf->GetFullPath() ...
-      std::string const& fPath = sf->GetFullPath();
-      cmSystemTools::FileFormat const fileType =
-        cmSystemTools::GetFileFormat(sf->GetExtension().c_str());
-      if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) &&
-          !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
-        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"));
-      if (mocSkip || uicSkip) {
-        std::string const absFile = cmSystemTools::GetRealPath(fPath);
-        if (mocSkip) {
-          setup.MocSkip.insert(absFile);
-        }
-        if (uicSkip) {
-          setup.UicSkip.insert(absFile);
-        }
-      }
+  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 += " (";
+    err += target->GetName();
+    err += ")";
+    cmSystemTools::Error(err.c_str());
   }
+  return rccExec;
 }
 
-static void SetupAutoTargetMoc(cmQtAutoGenDigest const& digest,
-                               std::string const& configDefault,
-                               std::vector<std::string> const& configsList,
-                               cmQtAutoGenSetup& setup)
+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)
 {
-  cmGeneratorTarget const* target = digest.Target;
-  cmLocalGenerator* localGen = target->GetLocalGenerator();
-  cmMakefile* makefile = target->Target->GetMakefile();
+  this->QtVersionMinor = cmQtAutoGeneratorInitializer::GetQtMinorVersion(
+    target, this->QtVersionMajor);
+}
 
-  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"));
+void cmQtAutoGeneratorInitializer::InitCustomTargets()
+{
+  cmMakefile* makefile = this->Target->Target->GetMakefile();
+  cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
+  cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator();
 
-  // 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"));
-    }
+  // Configurations
+  this->ConfigDefault = makefile->GetConfigurations(this->ConfigsList);
+  if (this->ConfigsList.empty()) {
+    this->ConfigsList.push_back(this->ConfigDefault);
   }
-  // Moc includes and compile definitions
+
+  // Multi configuration
   {
-    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, ";");
-    };
+    if (!globalGen->IsMultiConfig()) {
+      this->MultiConfig = cmQtAutoGen::SINGLE;
+    }
 
-    // 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;
-        }
-      }
+    // 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;
     }
-    AddDefinitionEscaped(makefile, "_moc_include_dirs", includeDirs);
-    AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs);
+    cmSystemTools::ConvertToUnixSlashes(this->DirBuild);
+
+    // Working directory
+    this->DirWork = cbd;
+    cmSystemTools::ConvertToUnixSlashes(this->DirWork);
   }
 
-  // Moc executable
+  // Autogen files
   {
-    std::string mocExec;
-    std::string err;
+    this->AutogenInfoFile = this->DirInfo;
+    this->AutogenInfoFile += "/AutogenInfo.cmake";
 
-    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";
-    }
+    this->AutogenSettingsFile = this->DirInfo;
+    this->AutogenSettingsFile += "/AutogenOldSettings.cmake";
+  }
 
-    if (err.empty()) {
-      AddDefinitionEscaped(makefile, "_qt_moc_executable", mocExec);
-    } else {
-      err += " (" + target->GetName() + ")";
-      cmSystemTools::Error(err.c_str());
+  // 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;
     }
   }
-}
 
-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();
+  std::set<std::string> autogenDependFiles;
+  std::set<cmTarget*> autogenDependTargets;
+  std::vector<std::string> autogenProvides;
 
-  // Uic search paths
+  // Remove build directories on cleanup
+  AddCleanFile(makefile, this->DirBuild);
+  // Remove old settings on cleanup
   {
-    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;
-}
-
-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;
-
-  // Autogen target FOLDER property
-  std::string autogenFolder;
-  {
-    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(target->Target->GetProperty("FOLDER"));
-    }
-    if (folder != nullptr) {
-      autogenFolder = folder;
-    }
-  }
-
-  // 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);
+    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 (digest.MocEnabled) {
-    std::string const mocsComp = autogenBuildDir + "/mocs_compilation.cpp";
-    auto files = AddGeneratedSource(target, mocsComp, multiConfig, configsList,
-                                    cmQtAutoGen::MOC);
+  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 (digest.MocEnabled || digest.UicEnabled) {
-    std::string includeDir = autogenBuildDir + "/include";
-    if (multiConfig != cmQtAutoGen::SINGLE) {
+  if (this->MocEnabled || this->UicEnabled) {
+    std::string includeDir = this->DirBuild + "/include";
+    if (this->MultiConfig != cmQtAutoGen::SINGLE) {
       includeDir += "_$<CONFIG>";
     }
-    target->AddIncludeDirectory(includeDir, true);
+    this->Target->AddIncludeDirectory(includeDir, true);
   }
 
   // Extract relevant source files
@@ -719,7 +374,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
   {
     std::string const qrcExt = "qrc";
     std::vector<cmSourceFile*> srcFiles;
-    target->GetConfigCommonSourceFiles(srcFiles);
+    this->Target->GetConfigCommonSourceFiles(srcFiles);
     for (cmSourceFile* sf : srcFiles) {
       if (sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
         continue;
@@ -728,50 +383,50 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
       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) {
+      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 ((digest.MocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) ||
-              (digest.UicEnabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) {
+          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 {
-                digest.Headers.push_back(absPath);
+                this->Headers.push_back(absPath);
               }
             } else {
               if (generated) {
                 generatedSources.push_back(absPath);
               } else {
-                digest.Sources.push_back(absPath);
+                this->Sources.push_back(absPath);
               }
             }
           }
         }
       }
       // Register rcc enabled files
-      if (digest.RccEnabled && (ext == qrcExt) &&
+      if (this->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");
+          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, qrcDigest.Options);
+              cmSystemTools::ExpandListArgument(opts, qrc.Options);
             }
           }
-          digest.Qrcs.push_back(std::move(qrcDigest));
+          this->Qrcs.push_back(std::move(qrc));
         }
       }
     }
@@ -779,7 +434,35 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
     // 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();
+    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();
+      cmSystemTools::FileFormat const fileType =
+        cmSystemTools::GetFileFormat(sf->GetExtension().c_str());
+      if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) &&
+          !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
+        continue;
+      }
+      const bool skipAll = sf->GetPropertyAsBool("SKIP_AUTOGEN");
+      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) {
+          this->MocSkip.insert(absFile);
+        }
+        if (uicSkip) {
+          this->UicSkip.insert(absFile);
+        }
+      }
+    }
   }
 
   // Process GENERATED sources and headers
@@ -788,7 +471,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
     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;
@@ -807,11 +490,11 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
     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 {
@@ -821,13 +504,13 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
         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";
         }
@@ -852,27 +535,32 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
         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");
+    std::string const rcc =
+      RccGetExecutable(this->Target, this->QtVersionMajor);
     // 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;
         }
       }
@@ -880,41 +568,43 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
     // 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;
+          std::string rccFile = this->DirBuild + "/";
+          rccFile += qrc.PathChecksum;
           rccFile += "/qrc_";
-          rccFile += qrcDigest.QrcName;
+          rccFile += qrc.QrcName;
           rccFile += ".cpp";
-          qrcDigest.RccFile = std::move(rccFile);
+          qrc.RccFile = std::move(rccFile);
         }
         {
-          std::string base = autogenInfoDir;
+          std::string base = this->DirInfo;
           base += "/RCC";
-          base += qrcDigest.QrcName;
-          if (!qrcDigest.Unique) {
-            base += qrcDigest.PathChecksum;
+          base += qrc.QrcName;
+          if (!qrc.Unique) {
+            base += qrc.PathChecksum;
           }
-          qrcDigest.InfoFile = base + "Info.cmake";
-          qrcDigest.SettingsFile = base + "Settings.cmake";
+          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");
@@ -922,13 +612,13 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
         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 = AddGeneratedSource(
-        target, qrcDigest.RccFile, multiConfig, configsList, cmQtAutoGen::RCC);
+      std::vector<std::string> const ccOutput =
+        this->AddGeneratedSource(qrc.RccFile, cmQtAutoGen::RCC);
 
       cmCustomCommandLines commandLines;
       {
@@ -936,57 +626,57 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
         currentLine.push_back(cmSystemTools::GetCMakeCommand());
         currentLine.push_back("-E");
         currentLine.push_back("cmake_autorcc");
-        currentLine.push_back(qrcDigest.InfoFile);
+        currentLine.push_back(qrc.InfoFile);
         currentLine.push_back("$<CONFIGURATION>");
         commandLines.push_back(std::move(currentLine));
       }
       std::string ccComment = "Automatic RCC for ";
-      ccComment += qrcDigest.QrcFile;
+      ccComment += qrc.QrcFile;
 
-      if (qrcDigest.Generated) {
+      if (qrc.Generated) {
         // Create custom rcc target
         std::string ccName;
         {
-          ccName = target->GetName();
+          ccName = this->Target->GetName();
           ccName += "_arcc_";
-          ccName += qrcDigest.QrcName;
-          if (!qrcDigest.Unique) {
+          ccName += qrc.QrcName;
+          if (!qrc.Unique) {
             ccName += "_";
-            ccName += qrcDigest.PathChecksum;
+            ccName += qrc.PathChecksum;
           }
           std::vector<std::string> ccDepends;
           // Add the .qrc file to the custom target dependencies
-          ccDepends.push_back(qrcDigest.QrcFile);
+          ccDepends.push_back(qrc.QrcFile);
 
           cmTarget* autoRccTarget = makefile->AddUtilityCommand(
-            ccName, true, workingDirectory.c_str(), ccOutput, ccDepends,
+            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 (!autogenFolder.empty()) {
-            autoRccTarget->SetProperty("FOLDER", autogenFolder.c_str());
+          if (!this->AutogenFolder.empty()) {
+            autoRccTarget->SetProperty("FOLDER", this->AutogenFolder.c_str());
           }
         }
         // Add autogen target to the origin target dependencies
-        target->Target->AddUtility(ccName, makefile);
+        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(qrcDigest.QrcFile);
+          ccDepends.push_back(qrc.QrcFile);
 
           // Add the resource files to the dependencies
           {
             std::string error;
-            if (cmQtAutoGen::RccListInputs(digest.QtVersionMajor, rcc,
-                                           qrcDigest.QrcFile,
-                                           qrcDigest.Resources, &error)) {
-              for (std::string const& fileName : qrcDigest.Resources) {
+            if (cmQtAutoGen::RccListInputs(this->QtVersionMajor, rcc,
+                                           qrc.QrcFile, qrc.Resources,
+                                           &error)) {
+              for (std::string const& fileName : qrc.Resources) {
                 // Add resource file to the custom command dependencies
                 ccDepends.push_back(fileName);
               }
@@ -997,20 +687,20 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
           makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends,
                                              /*main_dependency*/ std::string(),
                                              commandLines, ccComment.c_str(),
-                                             workingDirectory.c_str());
+                                             this->DirWork.c_str());
         }
         // Reconfigure when .qrc file changes
-        makefile->AddCMakeDependFile(qrcDigest.QrcFile);
+        makefile->AddCMakeDependFile(qrc.QrcFile);
       }
     }
   }
 
   // Create _autogen target
-  if (digest.MocEnabled || digest.UicEnabled) {
+  if (this->MocEnabled || this->UicEnabled) {
     // Add user defined autogen target dependencies
     {
       std::string const deps =
-        GetSafeProperty(target, "AUTOGEN_TARGET_DEPENDS");
+        GetSafeProperty(this->Target, "AUTOGEN_TARGET_DEPENDS");
       if (!deps.empty()) {
         std::vector<std::string> extraDeps;
         cmSystemTools::ExpandListArgument(deps, extraDeps);
@@ -1029,29 +719,20 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
     // 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");
+      std::string tools;
+      if (this->MocEnabled) {
+        tools += "MOC";
       }
-      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());
+      if (this->UicEnabled) {
+        if (!tools.empty()) {
+          tools += " and ";
         }
-        tools += " and " + toolNames.front();
+        tools += "UIC";
       }
-      autogenComment =
-        "Automatic " + tools + " for target " + target->GetName();
+      autogenComment = "Automatic ";
+      autogenComment += tools;
+      autogenComment += " for target ";
+      autogenComment += this->Target->GetName();
     }
 
     // Compose command lines
@@ -1061,7 +742,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
       currentLine.push_back(cmSystemTools::GetCMakeCommand());
       currentLine.push_back("-E");
       currentLine.push_back("cmake_autogen");
-      currentLine.push_back(autogenInfoDir + "/AutogenInfo.cmake");
+      currentLine.push_back(this->AutogenInfoFile);
       currentLine.push_back("$<CONFIGURATION>");
       commandLines.push_back(std::move(currentLine));
     }
@@ -1086,7 +767,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
     if (usePRE_BUILD) {
       // Add additional autogen target dependencies to origin target
       for (cmTarget* depTarget : autogenDependTargets) {
-        target->Target->AddUtility(depTarget->GetName(), makefile);
+        this->Target->Target->AddUtility(depTarget->GetName(), makefile);
       }
 
       // Add the pre-build command directly to bypass the OBJECT_LIBRARY
@@ -1098,10 +779,10 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
       const std::vector<std::string> no_deps;
       cmCustomCommand cc(makefile, no_output, autogenProvides, no_deps,
                          commandLines, autogenComment.c_str(),
-                         workingDirectory.c_str());
+                         this->DirWork.c_str());
       cc.SetEscapeOldStyle(false);
       cc.SetEscapeAllowMakeVars(true);
-      target->Target->AddPreBuildCommand(cc);
+      this->Target->Target->AddPreBuildCommand(cc);
     } else {
 
       // Convert file dependencies std::set to std::vector
@@ -1110,22 +791,22 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
 
       // Add link library target dependencies to the autogen target
       // dependencies
-      for (std::string const& config : configsList) {
+      for (std::string const& config : this->ConfigsList) {
         cmLinkImplementationLibraries const* libs =
-          target->GetLinkImplementationLibraries(config);
+          this->Target->GetLinkImplementationLibraries(config);
         if (libs != nullptr) {
           for (cmLinkItem const& item : libs->Libraries) {
             cmGeneratorTarget const* libTarget = item.Target;
             if ((libTarget != nullptr) &&
-                !StaticLibraryCycle(target, libTarget, config)) {
+                !StaticLibraryCycle(this->Target, libTarget, config)) {
               std::string util;
-              if (configsList.size() > 1) {
+              if (this->ConfigsList.size() > 1) {
                 util += "$<$<CONFIG:";
                 util += config;
                 util += ">:";
               }
               util += libTarget->GetName();
-              if (configsList.size() > 1) {
+              if (this->ConfigsList.size() > 1) {
                 util += ">";
               }
               autogenDepends.push_back(util);
@@ -1136,7 +817,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
 
       // Create autogen target
       cmTarget* autogenTarget = makefile->AddUtilityCommand(
-        autogenTargetName, true, workingDirectory.c_str(),
+        this->AutogenTargetName, true, this->DirWork.c_str(),
         /*byproducts=*/autogenProvides, autogenDepends, commandLines, false,
         autogenComment.c_str());
       // Create autogen generator target
@@ -1144,7 +825,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
         new cmGeneratorTarget(autogenTarget, localGen));
 
       // Forward origin utilities to autogen target
-      for (std::string const& depName : target->Target->GetUtilities()) {
+      for (std::string const& depName : this->Target->Target->GetUtilities()) {
         autogenTarget->AddUtility(depName, makefile);
       }
       // Add additional autogen target dependencies to autogen target
@@ -1153,87 +834,66 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
       }
 
       // Set FOLDER property in autogen target
-      if (!autogenFolder.empty()) {
-        autogenTarget->SetProperty("FOLDER", autogenFolder.c_str());
+      if (!this->AutogenFolder.empty()) {
+        autogenTarget->SetProperty("FOLDER", this->AutogenFolder.c_str());
       }
 
       // Add autogen target to the origin target dependencies
-      target->Target->AddUtility(autogenTargetName, makefile);
+      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 : configsList) {
-    configSuffixes[cfg] = "_" + cfg;
+  for (std::string const& cfg : this->ConfigsList) {
+    std::string& suffix = configSuffixes[cfg];
+    suffix = "_";
+    suffix += cfg;
   }
 
-  // Configurations settings buffers
-  cmQtAutoGenSetup setup;
-
   // Basic setup
   AddDefinitionEscaped(makefile, "_multi_config",
-                       cmQtAutoGen::MultiConfigName(multiConfig));
-  AddDefinitionEscaped(makefile, "_build_dir",
-                       GetAutogenTargetBuildDir(target));
-  AddDefinitionEscaped(makefile, "_qt_version_major", digest.QtVersionMajor);
-  AddDefinitionEscaped(makefile, "_qt_version_minor", digest.QtVersionMinor);
-  {
-    if (digest.MocEnabled || digest.UicEnabled) {
-      {
-        std::string settingsFile = GetAutogenTargetFilesDir(target);
-        cmSystemTools::ConvertToUnixSlashes(settingsFile);
-        settingsFile += "/AutogenOldSettings.cmake";
-        AddDefinitionEscaped(makefile, "_settings_file", settingsFile);
-      }
-      AddDefinitionEscaped(makefile, "_sources", digest.Sources);
-      AddDefinitionEscaped(makefile, "_headers", digest.Headers);
-
-      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);
+  AddDefinitionEscaped(makefile, "_qt_version_major", this->QtVersionMajor);
+  AddDefinitionEscaped(makefile, "_qt_version_minor", this->QtVersionMinor);
+
+  if (this->MocEnabled || this->UicEnabled) {
+    AddDefinitionEscaped(makefile, "_settings_file",
+                         this->AutogenSettingsFile);
+    AddDefinitionEscaped(makefile, "_sources", this->Sources);
+    AddDefinitionEscaped(makefile, "_headers", this->Headers);
+
+    if (this->MocEnabled) {
+      this->SetupCustomTargetsMoc();
     }
-    if (digest.RccEnabled) {
-      AddDefinitionEscaped(
-        makefile, "_qt_rcc_executable",
-        RccGetExecutable(digest.Target, digest.QtVersionMajor));
+    if (this->UicEnabled) {
+      this->SetupCustomTargetsUic();
     }
   }
+  if (this->RccEnabled) {
+    AddDefinitionEscaped(makefile, "_qt_rcc_executable",
+                         RccGetExecutable(this->Target, this->QtVersionMajor));
+  }
 
   // Create info directory on demand
-  std::string const infoDir = GetAutogenTargetFilesDir(target);
-  if (!cmSystemTools::MakeDirectory(infoDir)) {
+  if (!cmSystemTools::MakeDirectory(this->DirInfo)) {
     std::string emsg = ("Could not create directory: ");
-    emsg += cmQtAutoGen::Quoted(infoDir);
+    emsg += cmQtAutoGen::Quoted(this->DirInfo);
     cmSystemTools::Error(emsg.c_str());
   }
 
-  auto AdjustFilePermissions = [](std::string const& fileName) {
+  auto ReOpenInfoFile = [](cmsys::ofstream& ofs,
+                           std::string const& fileName) -> bool {
     // Ensure we have write permission
     mode_t perm = 0;
 #if defined(_WIN32) && !defined(__CYGWIN__)
@@ -1245,27 +905,31 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
     if (!(perm & mode_write)) {
       cmSystemTools::SetPermissions(fileName, perm | mode_write);
     }
+
+    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
-  {
-    std::string const infoFile = infoDir + "/AutogenInfo.cmake";
+  if (this->MocEnabled || this->UicEnabled) {
     {
       std::string infoFileIn = cmSystemTools::GetCMakeRoot();
       infoFileIn += "/Modules/AutogenInfo.cmake.in";
-      makefile->ConfigureFile(infoFileIn.c_str(), infoFile.c_str(), false,
-                              true, false);
+      makefile->ConfigureFile(
+        infoFileIn.c_str(), this->AutogenInfoFile.c_str(), false, true, false);
     }
 
     // Append custom definitions to info file
     // --------------------------------------
-
-    // Ensure we have write permission in case .in was read-only.
-    AdjustFilePermissions(infoFile);
-
-    // Open and write file
-    cmsys::ofstream ofs(infoFile.c_str(), std::ios::app);
-    if (ofs) {
+    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) {
@@ -1275,36 +939,47 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
       };
       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 (cmQtAutoGenDigestQrc const& qrcDigest : digest.Qrcs) {
+    for (Qrc const& qrc : this->Qrcs) {
       // Configure info file
-      makefile->ConfigureFile(infoFileIn.c_str(), qrcDigest.InfoFile.c_str(),
-                              false, true, false);
+      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";
 
-      // Ensure we have write permission in case .in was read-only.
-      AdjustFilePermissions(qrcDigest.InfoFile);
-
-      // Open and write file
-      cmsys::ofstream ofs(qrcDigest.InfoFile.c_str(), std::ios::app);
-      if (ofs) {
+          };
+          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](
@@ -1315,27 +990,321 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
             }
           };
           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);
+          }
         }
-        {
-          ofs << "# Job\n";
-          auto OfsWrite = [&ofs](const char* key, std::string const& value) {
-            ofs << "set(" << key << " "
-                << cmOutputConverter::EscapeForCMake(value) << ")\n";
+      } else {
+        break;
+      }
+    }
+  }
+}
 
-          };
-          OfsWrite("ARCC_SETTINGS_FILE", qrcDigest.SettingsFile);
-          OfsWrite("ARCC_SOURCE", qrcDigest.QrcFile);
-          OfsWrite("ARCC_OUTPUT", qrcDigest.RccFile);
-          OfsWrite("ARCC_OPTIONS", cmJoin(qrcDigest.Options, ";"));
-          OfsWrite("ARCC_INPUTS", cmJoin(qrcDigest.Resources, ";"));
+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 {
-        // File open error
-        std::string error = "Internal CMake error when trying to open file: ";
-        error += cmQtAutoGen::Quoted(qrcDigest.InfoFile);
-        error += " for writing.";
-        cmSystemTools::Error(error.c_str());
+        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..9eebbd6 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,75 @@ public:
   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;
+  std::string QtVersionMajor;
+  std::string QtVersionMinor;
+  // 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/cmQtAutoGeneratorMocUic.cxx b/Source/cmQtAutoGeneratorMocUic.cxx
index ea99b1f..1956a89 100644
--- a/Source/cmQtAutoGeneratorMocUic.cxx
+++ b/Source/cmQtAutoGeneratorMocUic.cxx
@@ -142,14 +142,9 @@ bool cmQtAutoGeneratorMocUic::InitInfoFile(cmMakefile* makefile)
   }
 
   this->SettingsFile = InfoGetConfig("AM_SETTINGS_FILE");
-  if (!this->SettingsFile.empty()) {
-    if (this->MultiConfig != cmQtAutoGen::SINGLE) {
-      this->SettingsFile = cmQtAutoGen::AppendFilenameSuffix(
-        this->SettingsFile, this->ConfigSuffix);
-    }
-  } else {
+  if (this->SettingsFile.empty()) {
     this->LogFileError(cmQtAutoGen::GEN, this->GetInfoFile(),
-                       "Settings file is missing");
+                       "Settings file name missing");
     return false;
   }
 
diff --git a/Source/cmQtAutoGeneratorRcc.cxx b/Source/cmQtAutoGeneratorRcc.cxx
index 4348f2b..573f04c 100644
--- a/Source/cmQtAutoGeneratorRcc.cxx
+++ b/Source/cmQtAutoGeneratorRcc.cxx
@@ -69,12 +69,6 @@ bool cmQtAutoGeneratorRcc::InfoFileRead(cmMakefile* makefile)
   }
 
   this->SettingsFile = InfoGetConfig("ARCC_SETTINGS_FILE");
-  if (!this->SettingsFile.empty()) {
-    if (this->MultiConfig != cmQtAutoGen::SINGLE) {
-      this->SettingsFile = cmQtAutoGen::AppendFilenameSuffix(
-        this->SettingsFile, this->ConfigSuffix);
-    }
-  }
 
   // - Files and directories
   this->ProjectSourceDir = InfoGet("ARCC_CMAKE_SOURCE_DIR");

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=75819b8626abf0e64895ef19acd27dbd0fa9255b
commit 75819b8626abf0e64895ef19acd27dbd0fa9255b
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Sat Nov 18 11:29:26 2017 +0100
Commit:     Sebastian Holtermann <sebholt at xwmw.org>
CommitDate: Sun Nov 19 12:51:31 2017 +0100

    Autogen: Add and use cmQtAutoGenerator base class
    
    Adds the new base class `cmQtAutoGenerator` which contains common
    variables and methods used by `cmQtAutoGeneratorMocUic` and
    `cmQtAutoGeneratorRcc`.

diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in
index 7d1d6d8..8fa3684 100644
--- a/Modules/AutogenInfo.cmake.in
+++ b/Modules/AutogenInfo.cmake.in
@@ -9,6 +9,7 @@ set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJ
 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@)
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index cddef68..6b086fa 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -312,6 +312,8 @@ set(SRCS
   cmQtAutoGen.cxx
   cmQtAutoGen.h
   cmQtAutoGenDigest.h
+  cmQtAutoGenerator.cxx
+  cmQtAutoGenerator.h
   cmQtAutoGeneratorInitializer.cxx
   cmQtAutoGeneratorInitializer.h
   cmQtAutoGeneratorMocUic.cxx
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/cmQtAutoGeneratorRcc.h b/Source/cmQtAutoGenerator.h
similarity index 66%
copy from Source/cmQtAutoGeneratorRcc.h
copy to Source/cmQtAutoGenerator.h
index 4539461..285340d 100644
--- a/Source/cmQtAutoGeneratorRcc.h
+++ b/Source/cmQtAutoGenerator.h
@@ -1,11 +1,10 @@
 /* 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
+#ifndef cmQtAutoGenerator_h
+#define cmQtAutoGenerator_h
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include "cmFilePathChecksum.h"
 #include "cmQtAutoGen.h"
 
 #include <string>
@@ -13,21 +12,23 @@
 
 class cmMakefile;
 
-class cmQtAutoGeneratorRcc
+class cmQtAutoGenerator
 {
-  CM_DISABLE_COPY(cmQtAutoGeneratorRcc)
+  CM_DISABLE_COPY(cmQtAutoGenerator)
 public:
-  cmQtAutoGeneratorRcc();
+  cmQtAutoGenerator();
+  virtual ~cmQtAutoGenerator() = default;
   bool Run(std::string const& infoFile, std::string const& config);
 
-private:
-  // -- Initialization & settings
-  bool InfoFileRead(cmMakefile* makefile);
-  void SettingsFileRead(cmMakefile* makefile);
-  bool SettingsFileWrite();
+  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
-  bool Process(cmMakefile* makefile);
-  bool RccGenerate();
+  virtual bool Process(cmMakefile* makefile) = 0;
+
   // -- Log info
   void LogBold(std::string const& message) const;
   void LogInfo(cmQtAutoGen::Generator genType,
@@ -51,40 +52,25 @@ private:
   // -- Utility
   bool MakeParentDirectory(cmQtAutoGen::Generator genType,
                            std::string const& filename) const;
-  bool FileDiffers(std::string const& filename, std::string const& content);
+  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;
-  // -- Config settings
-  std::string ConfigSuffix;
-  cmQtAutoGen::MultiConfig MultiConfig;
   // -- Settings
   bool Verbose;
   bool ColorOutput;
-  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 QtMajorVersion;
-  std::string RccExecutable;
-  // -- Job
-  std::string QrcFile;
-  std::string RccFile;
-  std::vector<std::string> Options;
-  std::vector<std::string> Inputs;
 };
 
 #endif
diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx
index 9477bc3..1d18bad 100644
--- a/Source/cmQtAutoGeneratorInitializer.cxx
+++ b/Source/cmQtAutoGeneratorInitializer.cxx
@@ -1061,7 +1061,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
       currentLine.push_back(cmSystemTools::GetCMakeCommand());
       currentLine.push_back("-E");
       currentLine.push_back("cmake_autogen");
-      currentLine.push_back(autogenInfoDir);
+      currentLine.push_back(autogenInfoDir + "/AutogenInfo.cmake");
       currentLine.push_back("$<CONFIGURATION>");
       commandLines.push_back(std::move(currentLine));
     }
@@ -1197,12 +1197,19 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
                        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) {
+      {
+        std::string settingsFile = GetAutogenTargetFilesDir(target);
+        cmSystemTools::ConvertToUnixSlashes(settingsFile);
+        settingsFile += "/AutogenOldSettings.cmake";
+        AddDefinitionEscaped(makefile, "_settings_file", settingsFile);
+      }
+      AddDefinitionEscaped(makefile, "_sources", digest.Sources);
+      AddDefinitionEscaped(makefile, "_headers", digest.Headers);
+
       SetupAcquireSkipFiles(digest, setup);
       if (digest.MocEnabled) {
         SetupAutoTargetMoc(digest, configDefault, configsList, setup);
diff --git a/Source/cmQtAutoGeneratorMocUic.cxx b/Source/cmQtAutoGeneratorMocUic.cxx
index 36fc090..ea99b1f 100644
--- a/Source/cmQtAutoGeneratorMocUic.cxx
+++ b/Source/cmQtAutoGeneratorMocUic.cxx
@@ -3,8 +3,6 @@
 #include "cmQtAutoGen.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"
 
@@ -35,33 +29,6 @@ static const char* SettingsKeyUic = "AM_UIC_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));
@@ -71,56 +38,6 @@ static std::string SubDirPrefix(std::string const& fileName)
   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)
 {
@@ -132,21 +49,11 @@ static bool ListContains(std::vector<std::string> const& list,
 cmQtAutoGeneratorMocUic::cmQtAutoGeneratorMocUic()
   : MultiConfig(cmQtAutoGen::WRAP)
   , IncludeProjectDirsBefore(false)
-  , Verbose(cmSystemTools::HasEnv("VERBOSE"))
-  , ColorOutput(true)
   , MocSettingsChanged(false)
   , MocPredefsChanged(false)
   , MocRelaxedMode(false)
   , UicSettingsChanged(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]+"
@@ -155,39 +62,7 @@ cmQtAutoGeneratorMocUic::cmQtAutoGeneratorMocUic()
                                  "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
 }
 
-bool cmQtAutoGeneratorMocUic::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 cmQtAutoGeneratorMocUic::InitInfoFile(cmMakefile* makefile,
-                                           std::string const& targetDirectory,
-                                           std::string const& config)
+bool cmQtAutoGeneratorMocUic::InitInfoFile(cmMakefile* makefile)
 {
   // -- Meta
   this->HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions();
@@ -231,12 +106,12 @@ bool cmQtAutoGeneratorMocUic::InitInfoFile(cmMakefile* makefile,
     }
     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) {
@@ -252,11 +127,8 @@ bool cmQtAutoGeneratorMocUic::InitInfoFile(cmMakefile* makefile,
   };
 
   // -- 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;
   }
@@ -266,7 +138,19 @@ bool cmQtAutoGeneratorMocUic::InitInfoFile(cmMakefile* makefile,
   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()) {
+    if (this->MultiConfig != cmQtAutoGen::SINGLE) {
+      this->SettingsFile = cmQtAutoGen::AppendFilenameSuffix(
+        this->SettingsFile, this->ConfigSuffix);
+    }
+  } else {
+    this->LogFileError(cmQtAutoGen::GEN, this->GetInfoFile(),
+                       "Settings file is missing");
+    return false;
   }
 
   // - Files and directories
@@ -278,7 +162,7 @@ bool cmQtAutoGeneratorMocUic::InitInfoFile(cmMakefile* makefile,
     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;
   }
@@ -291,7 +175,7 @@ bool cmQtAutoGeneratorMocUic::InitInfoFile(cmMakefile* makefile,
 
   // Check Qt version
   if ((this->QtMajorVersion != "4") && (this->QtMajorVersion != "5")) {
-    this->LogFileError(cmQtAutoGen::GEN, this->InfoFile,
+    this->LogFileError(cmQtAutoGen::GEN, this->GetInfoFile(),
                        "Unsupported Qt version: " +
                          cmQtAutoGen::Quoted(this->QtMajorVersion));
     return false;
@@ -341,7 +225,7 @@ bool cmQtAutoGeneratorMocUic::InitInfoFile(cmMakefile* makefile,
         }
       } else {
         this->LogFileError(
-          cmQtAutoGen::MOC, this->InfoFile,
+          cmQtAutoGen::MOC, this->GetInfoFile(),
           "AUTOMOC_DEPEND_FILTERS list size is not a multiple of 2");
         return false;
       }
@@ -362,7 +246,7 @@ bool cmQtAutoGeneratorMocUic::InitInfoFile(cmMakefile* makefile,
         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();
@@ -535,17 +419,6 @@ bool cmQtAutoGeneratorMocUic::InitInfoFile(cmMakefile* makefile,
     }
   }
 
-  // - 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;
 }
 
@@ -614,7 +487,7 @@ 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));
     }
@@ -644,7 +517,7 @@ bool cmQtAutoGeneratorMocUic::SettingsFileWrite()
   return success;
 }
 
-bool cmQtAutoGeneratorMocUic::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
@@ -654,6 +527,12 @@ bool cmQtAutoGeneratorMocUic::Process()
   // 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(
@@ -690,6 +569,10 @@ bool cmQtAutoGeneratorMocUic::Process()
     return false;
   }
 
+  if (!this->SettingsFileWrite()) {
+    return false;
+  }
+
   return true;
 }
 
@@ -701,7 +584,7 @@ bool cmQtAutoGeneratorMocUic::ParseSourceFile(std::string const& absFilename,
 {
   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) {
@@ -729,7 +612,7 @@ bool cmQtAutoGeneratorMocUic::ParseHeaderFile(std::string const& absFilename,
 {
   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) {
@@ -760,7 +643,7 @@ bool cmQtAutoGeneratorMocUic::ParsePostprocess()
     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 {
@@ -968,7 +851,7 @@ void cmQtAutoGeneratorMocUic::MocFindDepends(std::string const& absFilename,
       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));
@@ -988,7 +871,7 @@ void cmQtAutoGeneratorMocUic::MocFindDepends(std::string const& absFilename,
 bool cmQtAutoGeneratorMocUic::MocParseSourceContent(
   std::string const& absFilename, std::string const& contentText)
 {
-  if (this->Verbose) {
+  if (this->GetVerbose()) {
     this->LogInfo(cmQtAutoGen::MOC, "Checking: " + absFilename);
   }
 
@@ -1227,7 +1110,7 @@ bool cmQtAutoGeneratorMocUic::MocParseSourceContent(
 void cmQtAutoGeneratorMocUic::MocParseHeaderContent(
   std::string const& absFilename, std::string const& contentText)
 {
-  if (this->Verbose) {
+  if (this->GetVerbose()) {
     this->LogInfo(cmQtAutoGen::MOC, "Checking: " + absFilename);
   }
 
@@ -1312,7 +1195,7 @@ bool cmQtAutoGeneratorMocUic::MocGenerateAll()
   if (!this->MocPredefsCmd.empty()) {
     if (this->MocSettingsChanged ||
         !cmSystemTools::FileExists(this->MocPredefsFileAbs)) {
-      if (this->Verbose) {
+      if (this->GetVerbose()) {
         this->LogBold("Generating MOC predefs " + this->MocPredefsFileRel);
       }
 
@@ -1347,7 +1230,7 @@ bool cmQtAutoGeneratorMocUic::MocGenerateAll()
         }
       } else {
         // Touch to update the time stamp
-        if (this->Verbose) {
+        if (this->GetVerbose()) {
           this->LogInfo(cmQtAutoGen::MOC,
                         "Touching moc_predefs " + this->MocPredefsFileRel);
         }
@@ -1398,7 +1281,7 @@ bool cmQtAutoGeneratorMocUic::MocGenerateAll()
 
     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)) {
@@ -1408,7 +1291,7 @@ bool cmQtAutoGeneratorMocUic::MocGenerateAll()
       }
     } else if (autoNameGenerated) {
       // Only touch mocs compilation file
-      if (this->Verbose) {
+      if (this->GetVerbose()) {
         this->LogInfo(cmQtAutoGen::MOC,
                       "Touching mocs compilation " + this->MocCompFileRel);
       }
@@ -1433,7 +1316,7 @@ bool cmQtAutoGeneratorMocUic::MocGenerateFile(const MocJobAuto& mocJob,
   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 ";
@@ -1443,7 +1326,7 @@ bool cmQtAutoGeneratorMocUic::MocGenerateFile(const MocJobAuto& mocJob,
     generate = true;
   }
   if (!generate && this->MocSettingsChanged) {
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       generateReason = "Generating ";
       generateReason += cmQtAutoGen::Quoted(mocFileAbs);
       generateReason += " from ";
@@ -1453,7 +1336,7 @@ bool cmQtAutoGeneratorMocUic::MocGenerateFile(const MocJobAuto& mocJob,
     generate = true;
   }
   if (!generate && this->MocPredefsChanged) {
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       generateReason = "Generating ";
       generateReason += cmQtAutoGen::Quoted(mocFileAbs);
       generateReason += " from ";
@@ -1465,7 +1348,7 @@ bool cmQtAutoGeneratorMocUic::MocGenerateFile(const MocJobAuto& mocJob,
   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 ";
@@ -1484,7 +1367,7 @@ bool cmQtAutoGeneratorMocUic::MocGenerateFile(const MocJobAuto& mocJob,
     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 ";
@@ -1505,7 +1388,7 @@ bool cmQtAutoGeneratorMocUic::MocGenerateFile(const MocJobAuto& mocJob,
 
   if (generate) {
     // Log
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       this->LogBold("Generating MOC source " + mocJob.BuildFileRel);
       this->LogInfo(cmQtAutoGen::MOC, generateReason);
     }
@@ -1569,7 +1452,7 @@ bool cmQtAutoGeneratorMocUic::UicSkip(std::string const& absFilename) const
 bool cmQtAutoGeneratorMocUic::UicParseContent(std::string const& absFilename,
                                               std::string const& contentText)
 {
-  if (this->Verbose) {
+  if (this->GetVerbose()) {
     this->LogInfo(cmQtAutoGen::UIC, "Checking: " + absFilename);
   }
 
@@ -1755,7 +1638,7 @@ bool cmQtAutoGeneratorMocUic::UicGenerateFile(const UicJob& uicJob)
   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 ";
@@ -1765,7 +1648,7 @@ bool cmQtAutoGeneratorMocUic::UicGenerateFile(const UicJob& uicJob)
     generate = true;
   }
   if (!generate && this->UicSettingsChanged) {
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       generateReason = "Generating ";
       generateReason += cmQtAutoGen::Quoted(uicFileAbs);
       generateReason += " from ";
@@ -1777,7 +1660,7 @@ bool cmQtAutoGeneratorMocUic::UicGenerateFile(const UicJob& uicJob)
   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 ";
@@ -1793,7 +1676,7 @@ bool cmQtAutoGeneratorMocUic::UicGenerateFile(const UicJob& uicJob)
   }
   if (generate) {
     // Log
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       this->LogBold("Generating UIC header " + uicJob.BuildFileRel);
       this->LogInfo(cmQtAutoGen::UIC, generateReason);
     }
@@ -1839,191 +1722,6 @@ bool cmQtAutoGeneratorMocUic::UicGenerateFile(const UicJob& uicJob)
   return success;
 }
 
-void cmQtAutoGeneratorMocUic::LogBold(std::string const& message) const
-{
-  cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue |
-                                     cmsysTerminal_Color_ForegroundBold,
-                                   message.c_str(), true, this->ColorOutput);
-}
-
-void cmQtAutoGeneratorMocUic::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 cmQtAutoGeneratorMocUic::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 cmQtAutoGeneratorMocUic::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 cmQtAutoGeneratorMocUic::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 cmQtAutoGeneratorMocUic::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 cmQtAutoGeneratorMocUic::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 cmQtAutoGeneratorMocUic::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 cmQtAutoGeneratorMocUic::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 cmQtAutoGeneratorMocUic::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 cmQtAutoGeneratorMocUic::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
diff --git a/Source/cmQtAutoGeneratorMocUic.h b/Source/cmQtAutoGeneratorMocUic.h
index 579b4f4..a03270b 100644
--- a/Source/cmQtAutoGeneratorMocUic.h
+++ b/Source/cmQtAutoGeneratorMocUic.h
@@ -7,6 +7,7 @@
 
 #include "cmFilePathChecksum.h"
 #include "cmQtAutoGen.h"
+#include "cmQtAutoGenerator.h"
 #include "cmsys/RegularExpression.hxx"
 
 #include <map>
@@ -17,12 +18,11 @@
 
 class cmMakefile;
 
-class cmQtAutoGeneratorMocUic
+class cmQtAutoGeneratorMocUic : public cmQtAutoGenerator
 {
   CM_DISABLE_COPY(cmQtAutoGeneratorMocUic)
 public:
   cmQtAutoGeneratorMocUic();
-  bool Run(std::string const& targetDirectory, std::string const& config);
 
 private:
   // -- Types
@@ -81,8 +81,7 @@ private:
   };
 
   // -- Initialization
-  bool InitInfoFile(cmMakefile* makefile, std::string const& targetDirectory,
-                    std::string const& config);
+  bool InitInfoFile(cmMakefile* makefile);
 
   // -- Settings file
   void SettingsFileRead(cmMakefile* makefile);
@@ -93,7 +92,7 @@ private:
   }
 
   // -- Central processing
-  bool Process();
+  bool Process(cmMakefile* makefile) override;
 
   // -- Source parsing
   bool ParseSourceFile(std::string const& absFilename, const SourceJob& job);
@@ -136,45 +135,14 @@ private:
   bool UicGenerateAll();
   bool UicGenerateFile(const UicJob& uicJob);
 
-  // -- 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;
diff --git a/Source/cmQtAutoGeneratorRcc.cxx b/Source/cmQtAutoGeneratorRcc.cxx
index e057937..4348f2b 100644
--- a/Source/cmQtAutoGeneratorRcc.cxx
+++ b/Source/cmQtAutoGeneratorRcc.cxx
@@ -3,146 +3,22 @@
 #include "cmQtAutoGen.h"
 #include "cmQtAutoGeneratorRcc.h"
 
-#include "cmsys/FStream.hxx"
-#include "cmsys/Terminal.h"
-
 #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"
-
-#if defined(__APPLE__)
-#include <unistd.h>
-#endif
 
 // -- Static variables
 
 static const char* SettingsKeyRcc = "ARCC_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 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;
-}
-
 // -- Class methods
 
 cmQtAutoGeneratorRcc::cmQtAutoGeneratorRcc()
   : MultiConfig(cmQtAutoGen::WRAP)
-  , Verbose(cmSystemTools::HasEnv("VERBOSE"))
-  , ColorOutput(true)
   , SettingsChanged(false)
 {
-  {
-    std::string colorEnv;
-    cmSystemTools::GetEnv("COLOR", colorEnv);
-    if (!colorEnv.empty()) {
-      this->ColorOutput = cmSystemTools::IsOn(colorEnv.c_str());
-    }
-  }
-}
-
-bool cmQtAutoGeneratorRcc::Run(std::string const& infoFile,
-                               std::string const& config)
-{
-  // Info settings
-  this->InfoFile = 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());
 }
 
 bool cmQtAutoGeneratorRcc::InfoFileRead(cmMakefile* makefile)
@@ -161,7 +37,7 @@ bool cmQtAutoGeneratorRcc::InfoFileRead(cmMakefile* makefile)
     {
       std::string keyConf = key;
       keyConf += '_';
-      keyConf += this->InfoConfig;
+      keyConf += this->GetInfoConfig();
       valueConf = makefile->GetDefinition(keyConf);
     }
     if (valueConf == nullptr) {
@@ -177,8 +53,8 @@ bool cmQtAutoGeneratorRcc::InfoFileRead(cmMakefile* makefile)
   };
 
   // -- Read info file
-  if (!makefile->ReadListFile(this->InfoFile.c_str())) {
-    this->LogFileError(cmQtAutoGen::RCC, this->InfoFile,
+  if (!makefile->ReadListFile(this->GetInfoFile().c_str())) {
+    this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
                        "File processing failed");
     return false;
   }
@@ -189,7 +65,7 @@ bool cmQtAutoGeneratorRcc::InfoFileRead(cmMakefile* makefile)
   this->ConfigSuffix = InfoGetConfig("ARCC_CONFIG_SUFFIX");
   if (this->ConfigSuffix.empty()) {
     this->ConfigSuffix = "_";
-    this->ConfigSuffix += this->InfoConfig;
+    this->ConfigSuffix += this->GetInfoConfig();
   }
 
   this->SettingsFile = InfoGetConfig("ARCC_SETTINGS_FILE");
@@ -219,27 +95,27 @@ bool cmQtAutoGeneratorRcc::InfoFileRead(cmMakefile* makefile)
 
   // - Validity checks
   if (this->SettingsFile.empty()) {
-    this->LogFileError(cmQtAutoGen::RCC, this->InfoFile,
+    this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
                        "Settings file name missing");
     return false;
   }
   if (this->AutogenBuildDir.empty()) {
-    this->LogFileError(cmQtAutoGen::RCC, this->InfoFile,
+    this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
                        "Autogen build directory missing");
     return false;
   }
   if (this->RccExecutable.empty()) {
-    this->LogFileError(cmQtAutoGen::RCC, this->InfoFile,
+    this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
                        "rcc executable missing");
     return false;
   }
   if (this->QrcFile.empty()) {
-    this->LogFileError(cmQtAutoGen::RCC, this->InfoFile,
+    this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
                        "rcc input file missing");
     return false;
   }
   if (this->RccFile.empty()) {
-    this->LogFileError(cmQtAutoGen::RCC, this->InfoFile,
+    this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
                        "rcc output file missing");
     return false;
   }
@@ -304,7 +180,7 @@ bool cmQtAutoGeneratorRcc::SettingsFileWrite()
   bool success = true;
   // Only write if any setting changed
   if (this->SettingsChanged) {
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       this->LogInfo(cmQtAutoGen::RCC, "Writing settings file " +
                       cmQtAutoGen::Quoted(this->SettingsFile));
     }
@@ -392,7 +268,7 @@ bool cmQtAutoGeneratorRcc::RccGenerate()
     success = false;
   }
   if (success && !generate && !cmSystemTools::FileExists(rccFileAbs.c_str())) {
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       generateReason = "Generating ";
       generateReason += cmQtAutoGen::Quoted(rccFileAbs);
       generateReason += " from its source file ";
@@ -402,7 +278,7 @@ bool cmQtAutoGeneratorRcc::RccGenerate()
     generate = true;
   }
   if (success && !generate && this->SettingsChanged) {
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       generateReason = "Generating ";
       generateReason += cmQtAutoGen::Quoted(rccFileAbs);
       generateReason += " from ";
@@ -414,7 +290,7 @@ bool cmQtAutoGeneratorRcc::RccGenerate()
   if (success && !generate) {
     std::string error;
     if (FileIsOlderThan(rccFileAbs, this->QrcFile, &error)) {
-      if (this->Verbose) {
+      if (this->GetVerbose()) {
         generateReason = "Generating ";
         generateReason += cmQtAutoGen::Quoted(rccFileAbs);
         generateReason += " because it is older than ";
@@ -457,7 +333,7 @@ bool cmQtAutoGeneratorRcc::RccGenerate()
           break;
         }
         if (FileIsOlderThan(rccFileAbs, resFile, &error)) {
-          if (this->Verbose) {
+          if (this->GetVerbose()) {
             generateReason = "Generating ";
             generateReason += cmQtAutoGen::Quoted(rccFileAbs);
             generateReason += " from ";
@@ -482,7 +358,7 @@ bool cmQtAutoGeneratorRcc::RccGenerate()
   // Regenerate on demand
   if (generate) {
     // Log
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       this->LogBold("Generating RCC source " + rccFileRel);
       this->LogInfo(cmQtAutoGen::RCC, generateReason);
     }
@@ -531,7 +407,7 @@ bool cmQtAutoGeneratorRcc::RccGenerate()
     // Write content to file
     if (this->FileDiffers(wrapperFileAbs, content)) {
       // Write new wrapper file
-      if (this->Verbose) {
+      if (this->GetVerbose()) {
         this->LogBold("Generating RCC wrapper " + wrapperFileRel);
       }
       if (!this->FileWrite(cmQtAutoGen::RCC, wrapperFileAbs, content)) {
@@ -541,7 +417,7 @@ bool cmQtAutoGeneratorRcc::RccGenerate()
       }
     } else if (rccGenerated) {
       // Just touch the wrapper file
-      if (this->Verbose) {
+      if (this->GetVerbose()) {
         this->LogInfo(cmQtAutoGen::RCC,
                       "Touching RCC wrapper " + wrapperFileRel);
       }
@@ -551,188 +427,3 @@ bool cmQtAutoGeneratorRcc::RccGenerate()
 
   return success;
 }
-
-void cmQtAutoGeneratorRcc::LogBold(std::string const& message) const
-{
-  cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue |
-                                     cmsysTerminal_Color_ForegroundBold,
-                                   message.c_str(), true, this->ColorOutput);
-}
-
-void cmQtAutoGeneratorRcc::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 cmQtAutoGeneratorRcc::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 cmQtAutoGeneratorRcc::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 cmQtAutoGeneratorRcc::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 cmQtAutoGeneratorRcc::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 cmQtAutoGeneratorRcc::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 cmQtAutoGeneratorRcc::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 cmQtAutoGeneratorRcc::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 cmQtAutoGeneratorRcc::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 cmQtAutoGeneratorRcc::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/cmQtAutoGeneratorRcc.h b/Source/cmQtAutoGeneratorRcc.h
index 4539461..804d117 100644
--- a/Source/cmQtAutoGeneratorRcc.h
+++ b/Source/cmQtAutoGeneratorRcc.h
@@ -7,18 +7,18 @@
 
 #include "cmFilePathChecksum.h"
 #include "cmQtAutoGen.h"
+#include "cmQtAutoGenerator.h"
 
 #include <string>
 #include <vector>
 
 class cmMakefile;
 
-class cmQtAutoGeneratorRcc
+class cmQtAutoGeneratorRcc : public cmQtAutoGenerator
 {
   CM_DISABLE_COPY(cmQtAutoGeneratorRcc)
 public:
   cmQtAutoGeneratorRcc();
-  bool Run(std::string const& infoFile, std::string const& config);
 
 private:
   // -- Initialization & settings
@@ -26,47 +26,13 @@ private:
   void SettingsFileRead(cmMakefile* makefile);
   bool SettingsFileWrite();
   // -- Central processing
-  bool Process(cmMakefile* makefile);
+  bool Process(cmMakefile* makefile) override;
   bool RccGenerate();
-  // -- 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 RunCommand(std::vector<std::string> const& command,
-                  std::string& output) const;
 
-  // -- Info settings
-  std::string InfoFile;
-  std::string InfoDir;
-  std::string InfoConfig;
   // -- Config settings
   std::string ConfigSuffix;
   cmQtAutoGen::MultiConfig MultiConfig;
   // -- Settings
-  bool Verbose;
-  bool ColorOutput;
   bool SettingsChanged;
   std::string SettingsFile;
   std::string SettingsString;

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=27ed3b3537676e6090a0845e4805bb4a65d05bae
commit 27ed3b3537676e6090a0845e4805bb4a65d05bae
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Fri Nov 17 13:04:26 2017 +0100
Commit:     Sebastian Holtermann <sebholt at xwmw.org>
CommitDate: Sun Nov 19 12:51:30 2017 +0100

    Autogen: Rename cmQtAutoGenerators to cmQtAutoGeneratorMocUic

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index fd02196..cddef68 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -314,8 +314,8 @@ set(SRCS
   cmQtAutoGenDigest.h
   cmQtAutoGeneratorInitializer.cxx
   cmQtAutoGeneratorInitializer.h
-  cmQtAutoGenerators.cxx
-  cmQtAutoGenerators.h
+  cmQtAutoGeneratorMocUic.cxx
+  cmQtAutoGeneratorMocUic.h
   cmQtAutoGeneratorRcc.cxx
   cmQtAutoGeneratorRcc.h
   cmRST.cxx
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGeneratorMocUic.cxx
similarity index 93%
rename from Source/cmQtAutoGenerators.cxx
rename to Source/cmQtAutoGeneratorMocUic.cxx
index bc6a28e..36fc090 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGeneratorMocUic.cxx
@@ -1,7 +1,7 @@
 /* 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"
@@ -129,7 +129,7 @@ static bool ListContains(std::vector<std::string> const& list,
 
 // -- Class methods
 
-cmQtAutoGenerators::cmQtAutoGenerators()
+cmQtAutoGeneratorMocUic::cmQtAutoGeneratorMocUic()
   : MultiConfig(cmQtAutoGen::WRAP)
   , IncludeProjectDirsBefore(false)
   , Verbose(cmSystemTools::HasEnv("VERBOSE"))
@@ -155,8 +155,8 @@ cmQtAutoGenerators::cmQtAutoGenerators()
                                  "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
 }
 
-bool cmQtAutoGenerators::Run(std::string const& targetDirectory,
-                             std::string const& config)
+bool cmQtAutoGeneratorMocUic::Run(std::string const& targetDirectory,
+                                  std::string const& config)
 {
   cmake cm(cmake::RoleScript);
   cm.SetHomeOutputDirectory(targetDirectory);
@@ -185,9 +185,9 @@ bool cmQtAutoGenerators::Run(std::string const& targetDirectory,
   return success;
 }
 
-bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile,
-                                      std::string const& targetDirectory,
-                                      std::string const& config)
+bool cmQtAutoGeneratorMocUic::InitInfoFile(cmMakefile* makefile,
+                                           std::string const& targetDirectory,
+                                           std::string const& config)
 {
   // -- Meta
   this->HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions();
@@ -549,7 +549,7 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile,
   return true;
 }
 
-void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile)
+void cmQtAutoGeneratorMocUic::SettingsFileRead(cmMakefile* makefile)
 {
   // Compose current settings strings
   {
@@ -609,7 +609,7 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile)
   }
 }
 
-bool cmQtAutoGenerators::SettingsFileWrite()
+bool cmQtAutoGeneratorMocUic::SettingsFileWrite()
 {
   bool success = true;
   // Only write if any setting changed
@@ -644,7 +644,7 @@ bool cmQtAutoGenerators::SettingsFileWrite()
   return success;
 }
 
-bool cmQtAutoGenerators::Process()
+bool cmQtAutoGeneratorMocUic::Process()
 {
   // 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
@@ -696,8 +696,8 @@ bool cmQtAutoGenerators::Process()
 /**
  * @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;
@@ -724,8 +724,8 @@ bool cmQtAutoGenerators::ParseSourceFile(std::string const& absFilename,
 /**
  * @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;
@@ -752,7 +752,7 @@ bool cmQtAutoGenerators::ParseHeaderFile(std::string const& absFilename,
 /**
  * @return True on success
  */
-bool cmQtAutoGenerators::ParsePostprocess()
+bool cmQtAutoGeneratorMocUic::ParsePostprocess()
 {
   bool success = true;
   // Read missing dependencies
@@ -783,7 +783,7 @@ bool cmQtAutoGenerators::ParsePostprocess()
  * @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
@@ -798,8 +798,8 @@ bool cmQtAutoGenerators::MocSkip(std::string const& absFilename) const
  * @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
@@ -817,7 +817,7 @@ bool cmQtAutoGenerators::MocRequired(std::string const& contentText,
   return false;
 }
 
-std::string cmQtAutoGenerators::MocStringMacros() const
+std::string cmQtAutoGeneratorMocUic::MocStringMacros() const
 {
   std::string res;
   const auto itB = this->MocMacroFilters.cbegin();
@@ -839,7 +839,7 @@ std::string cmQtAutoGenerators::MocStringMacros() const
   return res;
 }
 
-std::string cmQtAutoGenerators::MocStringHeaders(
+std::string cmQtAutoGeneratorMocUic::MocStringHeaders(
   std::string const& fileBase) const
 {
   std::string res = fileBase;
@@ -849,7 +849,7 @@ std::string cmQtAutoGenerators::MocStringHeaders(
   return res;
 }
 
-std::string cmQtAutoGenerators::MocFindIncludedHeader(
+std::string cmQtAutoGeneratorMocUic::MocFindIncludedHeader(
   std::string const& sourcePath, std::string const& includeBase) const
 {
   std::string header;
@@ -872,7 +872,7 @@ std::string cmQtAutoGenerators::MocFindIncludedHeader(
   return header;
 }
 
-bool cmQtAutoGenerators::MocFindIncludedFile(
+bool cmQtAutoGeneratorMocUic::MocFindIncludedFile(
   std::string& absFile, std::string const& sourcePath,
   std::string const& includeString) const
 {
@@ -902,8 +902,8 @@ bool cmQtAutoGenerators::MocFindIncludedFile(
   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()) {
@@ -937,9 +937,9 @@ bool cmQtAutoGenerators::MocDependFilterPush(std::string const& key,
   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;
@@ -985,8 +985,8 @@ void cmQtAutoGenerators::MocFindDepends(std::string const& absFilename,
 /**
  * @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) {
     this->LogInfo(cmQtAutoGen::MOC, "Checking: " + absFilename);
@@ -1224,8 +1224,8 @@ bool cmQtAutoGenerators::MocParseSourceContent(std::string const& absFilename,
   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) {
     this->LogInfo(cmQtAutoGen::MOC, "Checking: " + absFilename);
@@ -1257,7 +1257,7 @@ void cmQtAutoGenerators::MocParseHeaderContent(std::string const& absFilename,
   }
 }
 
-bool cmQtAutoGenerators::MocGenerateAll()
+bool cmQtAutoGeneratorMocUic::MocGenerateAll()
 {
   if (!this->MocEnabled()) {
     return true;
@@ -1422,8 +1422,8 @@ bool cmQtAutoGenerators::MocGenerateAll()
 /**
  * @return True on success
  */
-bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob,
-                                         bool* generated)
+bool cmQtAutoGeneratorMocUic::MocGenerateFile(const MocJobAuto& mocJob,
+                                              bool* generated)
 {
   bool success = true;
 
@@ -1555,7 +1555,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob,
 /**
  * @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
@@ -1566,8 +1566,8 @@ bool cmQtAutoGenerators::UicSkip(std::string const& absFilename) const
   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) {
     this->LogInfo(cmQtAutoGen::UIC, "Checking: " + absFilename);
@@ -1617,9 +1617,9 @@ bool cmQtAutoGenerators::UicParseContent(std::string const& absFilename,
   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 =
@@ -1681,7 +1681,7 @@ bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile,
   return success;
 }
 
-bool cmQtAutoGenerators::UicGenerateAll()
+bool cmQtAutoGeneratorMocUic::UicGenerateAll()
 {
   if (!this->UicEnabled()) {
     return true;
@@ -1745,7 +1745,7 @@ bool cmQtAutoGenerators::UicGenerateAll()
 /**
  * @return True on success
  */
-bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob)
+bool cmQtAutoGeneratorMocUic::UicGenerateFile(const UicJob& uicJob)
 {
   bool success = true;
 
@@ -1839,15 +1839,15 @@ bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob)
   return success;
 }
 
-void cmQtAutoGenerators::LogBold(std::string const& message) const
+void cmQtAutoGeneratorMocUic::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
+void cmQtAutoGeneratorMocUic::LogInfo(cmQtAutoGen::Generator genType,
+                                      std::string const& message) const
 {
   std::string msg = cmQtAutoGen::GeneratorName(genType);
   msg += ": ";
@@ -1858,8 +1858,8 @@ void cmQtAutoGenerators::LogInfo(cmQtAutoGen::Generator genType,
   cmSystemTools::Stdout(msg.c_str(), msg.size());
 }
 
-void cmQtAutoGenerators::LogWarning(cmQtAutoGen::Generator genType,
-                                    std::string const& message) const
+void cmQtAutoGeneratorMocUic::LogWarning(cmQtAutoGen::Generator genType,
+                                         std::string const& message) const
 {
   std::string msg = cmQtAutoGen::GeneratorName(genType);
   msg += " warning:";
@@ -1879,9 +1879,9 @@ void cmQtAutoGenerators::LogWarning(cmQtAutoGen::Generator genType,
   cmSystemTools::Stdout(msg.c_str(), msg.size());
 }
 
-void cmQtAutoGenerators::LogFileWarning(cmQtAutoGen::Generator genType,
-                                        std::string const& filename,
-                                        std::string const& message) const
+void cmQtAutoGeneratorMocUic::LogFileWarning(cmQtAutoGen::Generator genType,
+                                             std::string const& filename,
+                                             std::string const& message) const
 {
   std::string msg = "  ";
   msg += cmQtAutoGen::Quoted(filename);
@@ -1891,8 +1891,8 @@ void cmQtAutoGenerators::LogFileWarning(cmQtAutoGen::Generator genType,
   this->LogWarning(genType, msg);
 }
 
-void cmQtAutoGenerators::LogError(cmQtAutoGen::Generator genType,
-                                  std::string const& message) const
+void cmQtAutoGeneratorMocUic::LogError(cmQtAutoGen::Generator genType,
+                                       std::string const& message) const
 {
   std::string msg;
   msg.push_back('\n');
@@ -1906,9 +1906,9 @@ void cmQtAutoGenerators::LogError(cmQtAutoGen::Generator genType,
   cmSystemTools::Stderr(msg.c_str(), msg.size());
 }
 
-void cmQtAutoGenerators::LogFileError(cmQtAutoGen::Generator genType,
-                                      std::string const& filename,
-                                      std::string const& message) const
+void cmQtAutoGeneratorMocUic::LogFileError(cmQtAutoGen::Generator genType,
+                                           std::string const& filename,
+                                           std::string const& message) const
 {
   std::string emsg = "  ";
   emsg += cmQtAutoGen::Quoted(filename);
@@ -1918,7 +1918,7 @@ void cmQtAutoGenerators::LogFileError(cmQtAutoGen::Generator genType,
   this->LogError(genType, emsg);
 }
 
-void cmQtAutoGenerators::LogCommandError(
+void cmQtAutoGeneratorMocUic::LogCommandError(
   cmQtAutoGen::Generator genType, std::string const& message,
   std::vector<std::string> const& command, std::string const& output) const
 {
@@ -1949,8 +1949,8 @@ void cmQtAutoGenerators::LogCommandError(
  * @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 cmQtAutoGeneratorMocUic::MakeParentDirectory(
+  cmQtAutoGen::Generator genType, std::string const& filename) const
 {
   bool success = true;
   std::string const dirName = cmSystemTools::GetFilenamePath(filename);
@@ -1964,8 +1964,8 @@ bool cmQtAutoGenerators::MakeParentDirectory(cmQtAutoGen::Generator genType,
   return success;
 }
 
-bool cmQtAutoGenerators::FileDiffers(std::string const& filename,
-                                     std::string const& content)
+bool cmQtAutoGeneratorMocUic::FileDiffers(std::string const& filename,
+                                          std::string const& content)
 {
   bool differs = true;
   {
@@ -1977,9 +1977,9 @@ bool cmQtAutoGenerators::FileDiffers(std::string const& filename,
   return differs;
 }
 
-bool cmQtAutoGenerators::FileWrite(cmQtAutoGen::Generator genType,
-                                   std::string const& filename,
-                                   std::string const& content)
+bool cmQtAutoGeneratorMocUic::FileWrite(cmQtAutoGen::Generator genType,
+                                        std::string const& filename,
+                                        std::string const& content)
 {
   std::string error;
   // Make sure the parent directory exists
@@ -2008,8 +2008,8 @@ bool cmQtAutoGenerators::FileWrite(cmQtAutoGen::Generator genType,
  * @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
+bool cmQtAutoGeneratorMocUic::RunCommand(
+  std::vector<std::string> const& command, std::string& output) const
 {
   // Log command
   if (this->Verbose) {
@@ -2029,8 +2029,8 @@ bool cmQtAutoGenerators::RunCommand(std::vector<std::string> const& command,
  * 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 97%
rename from Source/cmQtAutoGenerators.h
rename to Source/cmQtAutoGeneratorMocUic.h
index b6e28b3..579b4f4 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGeneratorMocUic.h
@@ -1,7 +1,7 @@
 /* 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
 
@@ -17,11 +17,11 @@
 
 class cmMakefile;
 
-class cmQtAutoGenerators
+class cmQtAutoGeneratorMocUic
 {
-  CM_DISABLE_COPY(cmQtAutoGenerators)
+  CM_DISABLE_COPY(cmQtAutoGeneratorMocUic)
 public:
-  cmQtAutoGenerators();
+  cmQtAutoGeneratorMocUic();
   bool Run(std::string const& targetDirectory, std::string const& config);
 
 private:
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index a37bc3c..3d9f65a 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -6,8 +6,8 @@
 #include "cmGlobalGenerator.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
+#include "cmQtAutoGeneratorMocUic.h"
 #include "cmQtAutoGeneratorRcc.h"
-#include "cmQtAutoGenerators.h"
 #include "cmStateDirectory.h"
 #include "cmStateSnapshot.h"
 #include "cmSystemTools.h"
@@ -994,7 +994,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
 
 #ifdef CMAKE_BUILD_WITH_CMAKE
     if ((args[1] == "cmake_autogen") && (args.size() >= 4)) {
-      cmQtAutoGenerators autoGen;
+      cmQtAutoGeneratorMocUic autoGen;
       std::string const& infoDir = args[2];
       std::string const& config = args[3];
       return autoGen.Run(infoDir, config) ? 0 : 1;

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1cd285fe06088d6dad58a3b52c071579aa0ce8b8
commit 1cd285fe06088d6dad58a3b52c071579aa0ce8b8
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Fri Nov 17 12:53:20 2017 +0100
Commit:     Sebastian Holtermann <sebholt at xwmw.org>
CommitDate: Sun Nov 19 12:51:30 2017 +0100

    Autogen: Remove rcc code from cmQtAutoGenerators

diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in
index 7f4b398..7d1d6d8 100644
--- a/Modules/AutogenInfo.cmake.in
+++ b/Modules/AutogenInfo.cmake.in
@@ -14,7 +14,6 @@ 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_TARGET_OPTIONS @_uic_target_options@)
 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/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index 28a8df1..bc6a28e 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -32,7 +32,6 @@
 
 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
 
@@ -139,7 +138,6 @@ cmQtAutoGenerators::cmQtAutoGenerators()
   , MocPredefsChanged(false)
   , MocRelaxedMode(false)
   , UicSettingsChanged(false)
-  , RccSettingsChanged(false)
 {
   {
     std::string colorEnv;
@@ -290,7 +288,6 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile,
   this->QtMinorVersion = InfoGet("AM_QT_VERSION_MINOR");
   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")) {
@@ -379,53 +376,6 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile,
     }
   }
 
-  // - 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
@@ -631,20 +581,6 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile)
       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 +595,6 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile)
       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,7 +606,6 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile)
     // If the file could not be read re-generate everythiung.
     this->MocSettingsChanged = true;
     this->UicSettingsChanged = true;
-    this->RccSettingsChanged = true;
   }
 }
 
@@ -699,7 +631,6 @@ bool cmQtAutoGenerators::SettingsFileWrite()
       };
       SettingAppend(SettingsKeyMoc, this->SettingsStringMoc);
       SettingAppend(SettingsKeyUic, this->SettingsStringUic);
-      SettingAppend(SettingsKeyRcc, this->SettingsStringRcc);
     }
     // Write settings file
     if (!this->FileWrite(cmQtAutoGen::GEN, this->SettingsFile, settings)) {
@@ -758,9 +689,6 @@ bool cmQtAutoGenerators::Process()
   if (!this->UicGenerateAll()) {
     return false;
   }
-  if (!this->RccGenerateAll()) {
-    return false;
-  }
 
   return true;
 }
@@ -1911,221 +1839,6 @@ bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob)
   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 |
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
index a7bb538..b6e28b3 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGenerators.h
@@ -80,15 +80,6 @@ private:
     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);
@@ -98,8 +89,7 @@ private:
   bool SettingsFileWrite();
   bool SettingsChanged() const
   {
-    return (this->MocSettingsChanged || this->RccSettingsChanged ||
-            this->UicSettingsChanged);
+    return (this->MocSettingsChanged || this->UicSettingsChanged);
   }
 
   // -- Central processing
@@ -146,11 +136,6 @@ private:
   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,
@@ -193,7 +178,6 @@ private:
   std::string SettingsFile;
   std::string SettingsStringMoc;
   std::string SettingsStringUic;
-  std::string SettingsStringRcc;
   // -- Directories
   std::string ProjectSourceDir;
   std::string ProjectBinaryDir;
@@ -206,7 +190,6 @@ private:
   std::string QtMinorVersion;
   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 +223,6 @@ private:
   std::vector<std::string> UicSearchPaths;
   cmsys::RegularExpression UicRegExpInclude;
   std::vector<std::unique_ptr<UicJob>> UicJobs;
-  // -- Rcc
-  bool RccSettingsChanged;
-  std::vector<RccJob> RccJobs;
 };
 
 #endif

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a87f82e0258148f3047a3487c832a569dd841e09
commit a87f82e0258148f3047a3487c832a569dd841e09
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Thu Nov 16 15:17:14 2017 +0100
Commit:     Sebastian Holtermann <sebholt at xwmw.org>
CommitDate: Sun Nov 19 12:51:30 2017 +0100

    Autogen: Switch to use custom commands for RCC
    
    Instead of processing all `rcc` invocation requests in the
    _autogen target that calls `cmake -E cmake_autogen ...` once,
    use a dedicated custom command that calls
    `cmake -E cmake_autorcc ...` for each `.qrc` file.
    This allows parallel `.qrc` file processing and reduces the
    workload (and complexity) in the _autogen target.
    If only `AUTORCC` is enabled, the _autogen target won't be created
    at all since it is now used for `AUTOMOC` and `AUTOUIC` only.
    
    For `.qrc` files that are GENERATED a custom target is used
    instead of a custom command.
    
    Closes #17161

diff --git a/Modules/AutoRccInfo.cmake.in b/Modules/AutoRccInfo.cmake.in
new file mode 100644
index 0000000..7b13b9e
--- /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_QT_VERSION_MAJOR @_qt_version_major@)
+set(ARCC_QT_RCC_EXECUTABLE @_qt_rcc_executable@)
diff --git a/Source/cmQtAutoGenDigest.h b/Source/cmQtAutoGenDigest.h
index 677c397..9ee1117 100644
--- a/Source/cmQtAutoGenDigest.h
+++ b/Source/cmQtAutoGenDigest.h
@@ -24,6 +24,8 @@ public:
   std::string QrcFile;
   std::string QrcName;
   std::string PathChecksum;
+  std::string InfoFile;
+  std::string SettingsFile;
   std::string RccFile;
   bool Generated;
   bool Unique;
diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx
index c7550e6..9477bc3 100644
--- a/Source/cmQtAutoGeneratorInitializer.cxx
+++ b/Source/cmQtAutoGeneratorInitializer.cxx
@@ -635,29 +635,6 @@ static std::string RccGetExecutable(cmGeneratorTarget const* target,
   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)
 {
@@ -681,6 +658,24 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
   std::set<cmTarget*> autogenDependTargets;
   std::vector<std::string> autogenProvides;
 
+  // Autogen target FOLDER property
+  std::string autogenFolder;
+  {
+    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(target->Target->GetProperty("FOLDER"));
+    }
+    if (folder != nullptr) {
+      autogenFolder = folder;
+    }
+  }
+
   // Remove build directories on cleanup
   AddCleanFile(makefile, autogenBuildDir);
   // Remove old settings on cleanup
@@ -699,45 +694,6 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
     }
   }
 
-  // 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";
@@ -921,18 +877,30 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
         }
       }
     }
-    // Path checksum
+    // Path checksum and file names
     {
       cmFilePathChecksum const fpathCheckSum(makefile);
       for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
         qrcDigest.PathChecksum = fpathCheckSum.getPart(qrcDigest.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 = autogenBuildDir + "/";
+          rccFile += qrcDigest.PathChecksum;
+          rccFile += "/qrc_";
+          rccFile += qrcDigest.QrcName;
+          rccFile += ".cpp";
+          qrcDigest.RccFile = std::move(rccFile);
+        }
+        {
+          std::string base = autogenInfoDir;
+          base += "/RCC";
+          base += qrcDigest.QrcName;
+          if (!qrcDigest.Unique) {
+            base += qrcDigest.PathChecksum;
+          }
+          qrcDigest.InfoFile = base + "Info.cmake";
+          qrcDigest.SettingsFile = base + "Settings.cmake";
+        }
       }
     }
     // RCC options
@@ -959,159 +927,239 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
     }
     for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
       // Register file at target
+      std::vector<std::string> const ccOutput = AddGeneratedSource(
+        target, qrcDigest.RccFile, multiConfig, configsList, 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(qrcDigest.InfoFile);
+        currentLine.push_back("$<CONFIGURATION>");
+        commandLines.push_back(std::move(currentLine));
       }
-      // Dependencies
+      std::string ccComment = "Automatic RCC for ";
+      ccComment += qrcDigest.QrcFile;
+
       if (qrcDigest.Generated) {
-        // Add the GENERATED .qrc file to the dependencies
-        autogenDependFiles.insert(qrcDigest.QrcFile);
+        // Create custom rcc target
+        std::string ccName;
+        {
+          ccName = target->GetName();
+          ccName += "_arcc_";
+          ccName += qrcDigest.QrcName;
+          if (!qrcDigest.Unique) {
+            ccName += "_";
+            ccName += qrcDigest.PathChecksum;
+          }
+          std::vector<std::string> ccDepends;
+          // Add the .qrc file to the custom target dependencies
+          ccDepends.push_back(qrcDigest.QrcFile);
+
+          cmTarget* autoRccTarget = makefile->AddUtilityCommand(
+            ccName, true, workingDirectory.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 (!autogenFolder.empty()) {
+            autoRccTarget->SetProperty("FOLDER", autogenFolder.c_str());
+          }
+        }
+        // Add autogen target to the origin target dependencies
+        target->Target->AddUtility(ccName, makefile);
       } else {
-        // Add the resource files to the dependencies
+        // Create custom rcc command
         {
-          std::string error;
-          if (cmQtAutoGen::RccListInputs(digest.QtVersionMajor, rcc,
-                                         qrcDigest.QrcFile,
-                                         qrcDigest.Resources, &error)) {
-            for (std::string const& fileName : qrcDigest.Resources) {
-              autogenDependFiles.insert(fileName);
+          std::vector<std::string> ccByproducts;
+          std::vector<std::string> ccDepends;
+          // Add the .qrc file to the custom command dependencies
+          ccDepends.push_back(qrcDigest.QrcFile);
+
+          // Add the resource files to the dependencies
+          {
+            std::string error;
+            if (cmQtAutoGen::RccListInputs(digest.QtVersionMajor, rcc,
+                                           qrcDigest.QrcFile,
+                                           qrcDigest.Resources, &error)) {
+              for (std::string const& fileName : qrcDigest.Resources) {
+                // Add resource file to the custom command dependencies
+                ccDepends.push_back(fileName);
+              }
+            } else {
+              cmSystemTools::Error(error.c_str());
             }
-          } else {
-            cmSystemTools::Error(error.c_str());
           }
+          makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends,
+                                             /*main_dependency*/ std::string(),
+                                             commandLines, ccComment.c_str(),
+                                             workingDirectory.c_str());
         }
-        // Run cmake again when .qrc file changes
+        // Reconfigure when .qrc file changes
         makefile->AddCMakeDependFile(qrcDigest.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);
+  // Create _autogen target
+  if (digest.MocEnabled || digest.UicEnabled) {
+    // 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;
+    // 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();
     }
-  }
-  // 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);
+
+    // 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(std::move(currentLine));
     }
 
-    // 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 {
+    // 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);
+      }
 
-    // Convert file dependencies std::set to std::vector
-    std::vector<std::string> autogenDepends(autogenDependFiles.begin(),
-                                            autogenDependFiles.end());
+      // 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 {
 
-    // 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 += ">:";
-            }
-            util += libTarget->GetName();
-            if (configsList.size() > 1) {
-              util += ">";
+      // 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 += ">:";
+              }
+              util += libTarget->GetName();
+              if (configsList.size() > 1) {
+                util += ">";
+              }
+              autogenDepends.push_back(util);
             }
-            autogenDepends.push_back(util);
           }
         }
       }
-    }
 
-    // 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
-    {
-      const char* autogenFolder =
-        makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER");
-      if (autogenFolder == nullptr) {
-        autogenFolder =
-          makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER");
+      // 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);
       }
-      // Inherit FOLDER property from target (#13688)
-      if (autogenFolder == nullptr) {
-        autogenFolder = SafeString(target->Target->GetProperty("FOLDER"));
+      // Add additional autogen target dependencies to autogen target
+      for (cmTarget* depTarget : autogenDependTargets) {
+        autogenTarget->AddUtility(depTarget->GetName(), makefile);
       }
-      if ((autogenFolder != nullptr) && (*autogenFolder != '\0')) {
-        autogenTarget->SetProperty("FOLDER", autogenFolder);
+
+      // Set FOLDER property in autogen target
+      if (!autogenFolder.empty()) {
+        autogenTarget->SetProperty("FOLDER", autogenFolder.c_str());
       }
-    }
 
-    // Add autogen target to the origin target dependencies
-    target->Target->AddUtility(autogenTargetName, makefile);
+      // Add autogen target to the origin target dependencies
+      target->Target->AddUtility(autogenTargetName, makefile);
+    }
   }
 }
 
@@ -1164,18 +1212,36 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
       }
     }
     if (digest.RccEnabled) {
-      SetupAutoTargetRcc(digest);
+      AddDefinitionEscaped(
+        makefile, "_qt_rcc_executable",
+        RccGetExecutable(digest.Target, digest.QtVersionMajor));
     }
   }
 
-  // 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());
+  // Create info directory on demand
+  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());
+  }
+
+  auto AdjustFilePermissions = [](std::string const& fileName) {
+    // 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(fileName, perm);
+    if (!(perm & mode_write)) {
+      cmSystemTools::SetPermissions(fileName, perm | mode_write);
     }
+  };
+
+  // Generate autogen target info file
+  {
     std::string const infoFile = infoDir + "/AutogenInfo.cmake";
     {
       std::string infoFileIn = cmSystemTools::GetCMakeRoot();
@@ -1188,16 +1254,7 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
     // --------------------------------------
 
     // Ensure we have write permission in case .in was read-only.
-    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);
-    if (!(perm & mode_write)) {
-      cmSystemTools::SetPermissions(infoFile, perm | mode_write);
-    }
+    AdjustFilePermissions(infoFile);
 
     // Open and write file
     cmsys::ofstream ofs(infoFile.c_str(), std::ios::app);
@@ -1222,4 +1279,56 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
       cmSystemTools::Error(error.c_str());
     }
   }
+
+  // Generate auto RCC info files
+  {
+    std::string infoFileIn = cmSystemTools::GetCMakeRoot();
+    infoFileIn += "/Modules/AutoRccInfo.cmake.in";
+    for (cmQtAutoGenDigestQrc const& qrcDigest : digest.Qrcs) {
+      // Configure info file
+      makefile->ConfigureFile(infoFileIn.c_str(), qrcDigest.InfoFile.c_str(),
+                              false, true, false);
+
+      // Append custom definitions to info file
+      // --------------------------------------
+
+      // Ensure we have write permission in case .in was read-only.
+      AdjustFilePermissions(qrcDigest.InfoFile);
+
+      // Open and write file
+      cmsys::ofstream ofs(qrcDigest.InfoFile.c_str(), std::ios::app);
+      if (ofs) {
+        {
+          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);
+        }
+        {
+          ofs << "# Job\n";
+          auto OfsWrite = [&ofs](const char* key, std::string const& value) {
+            ofs << "set(" << key << " "
+                << cmOutputConverter::EscapeForCMake(value) << ")\n";
+
+          };
+          OfsWrite("ARCC_SETTINGS_FILE", qrcDigest.SettingsFile);
+          OfsWrite("ARCC_SOURCE", qrcDigest.QrcFile);
+          OfsWrite("ARCC_OUTPUT", qrcDigest.RccFile);
+          OfsWrite("ARCC_OPTIONS", cmJoin(qrcDigest.Options, ";"));
+          OfsWrite("ARCC_INPUTS", cmJoin(qrcDigest.Resources, ";"));
+        }
+      } else {
+        // File open error
+        std::string error = "Internal CMake error when trying to open file: ";
+        error += cmQtAutoGen::Quoted(qrcDigest.InfoFile);
+        error += " for writing.";
+        cmSystemTools::Error(error.c_str());
+      }
+    }
+  }
 }

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b2a0b549bb9fea678517a52caf333eae009901dd
commit b2a0b549bb9fea678517a52caf333eae009901dd
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Thu Nov 16 09:59:03 2017 +0100
Commit:     Sebastian Holtermann <sebholt at xwmw.org>
CommitDate: Sun Nov 19 12:51:30 2017 +0100

    Autogen: Introduce standalone RCC generator class
    
    Introduces the standalone RCC generator class `cmQtAutoGeneratorRcc`.
    
    Every instance of `cmQtAutoGeneratorRcc` class handles the
    `rcc` invocation for a single `.qrc` file.
    The class will be used in the future to allow parallel `.qrc` file
    processing by calling `cmake -E cmake_autorcc <INFO_FILE> <CONFIG>`.

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 54e5063..fd02196 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -316,6 +316,8 @@ set(SRCS
   cmQtAutoGeneratorInitializer.h
   cmQtAutoGenerators.cxx
   cmQtAutoGenerators.h
+  cmQtAutoGeneratorRcc.cxx
+  cmQtAutoGeneratorRcc.h
   cmRST.cxx
   cmRST.h
   cmScriptGenerator.h
diff --git a/Source/cmQtAutoGeneratorRcc.cxx b/Source/cmQtAutoGeneratorRcc.cxx
new file mode 100644
index 0000000..e057937
--- /dev/null
+++ b/Source/cmQtAutoGeneratorRcc.cxx
@@ -0,0 +1,738 @@
+/* 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 "cmsys/FStream.hxx"
+#include "cmsys/Terminal.h"
+
+#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"
+
+#if defined(__APPLE__)
+#include <unistd.h>
+#endif
+
+// -- Static variables
+
+static const char* SettingsKeyRcc = "ARCC_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 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;
+}
+
+// -- Class methods
+
+cmQtAutoGeneratorRcc::cmQtAutoGeneratorRcc()
+  : MultiConfig(cmQtAutoGen::WRAP)
+  , Verbose(cmSystemTools::HasEnv("VERBOSE"))
+  , ColorOutput(true)
+  , SettingsChanged(false)
+{
+  {
+    std::string colorEnv;
+    cmSystemTools::GetEnv("COLOR", colorEnv);
+    if (!colorEnv.empty()) {
+      this->ColorOutput = cmSystemTools::IsOn(colorEnv.c_str());
+    }
+  }
+}
+
+bool cmQtAutoGeneratorRcc::Run(std::string const& infoFile,
+                               std::string const& config)
+{
+  // Info settings
+  this->InfoFile = 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());
+}
+
+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->InfoConfig;
+      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->InfoFile.c_str())) {
+    this->LogFileError(cmQtAutoGen::RCC, this->InfoFile,
+                       "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->InfoConfig;
+  }
+
+  this->SettingsFile = InfoGetConfig("ARCC_SETTINGS_FILE");
+  if (!this->SettingsFile.empty()) {
+    if (this->MultiConfig != cmQtAutoGen::SINGLE) {
+      this->SettingsFile = cmQtAutoGen::AppendFilenameSuffix(
+        this->SettingsFile, this->ConfigSuffix);
+    }
+  }
+
+  // - 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->QtMajorVersion = InfoGet("ARCC_QT_VERSION_MAJOR");
+  this->RccExecutable = InfoGet("ARCC_QT_RCC_EXECUTABLE");
+
+  // - 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->InfoFile,
+                       "Settings file name missing");
+    return false;
+  }
+  if (this->AutogenBuildDir.empty()) {
+    this->LogFileError(cmQtAutoGen::RCC, this->InfoFile,
+                       "Autogen build directory missing");
+    return false;
+  }
+  if (this->RccExecutable.empty()) {
+    this->LogFileError(cmQtAutoGen::RCC, this->InfoFile,
+                       "rcc executable missing");
+    return false;
+  }
+  if (this->QrcFile.empty()) {
+    this->LogFileError(cmQtAutoGen::RCC, this->InfoFile,
+                       "rcc input file missing");
+    return false;
+  }
+  if (this->RccFile.empty()) {
+    this->LogFileError(cmQtAutoGen::RCC, this->InfoFile,
+                       "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 += 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->Verbose) {
+      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->Verbose) {
+      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->Verbose) {
+      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->Verbose) {
+        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->QtMajorVersion, this->RccExecutable,
+                                     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->Verbose) {
+            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->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(), 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->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 cmQtAutoGeneratorRcc::LogBold(std::string const& message) const
+{
+  cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue |
+                                     cmsysTerminal_Color_ForegroundBold,
+                                   message.c_str(), true, this->ColorOutput);
+}
+
+void cmQtAutoGeneratorRcc::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 cmQtAutoGeneratorRcc::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 cmQtAutoGeneratorRcc::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 cmQtAutoGeneratorRcc::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 cmQtAutoGeneratorRcc::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 cmQtAutoGeneratorRcc::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 cmQtAutoGeneratorRcc::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 cmQtAutoGeneratorRcc::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 cmQtAutoGeneratorRcc::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 cmQtAutoGeneratorRcc::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/cmQtAutoGeneratorRcc.h b/Source/cmQtAutoGeneratorRcc.h
new file mode 100644
index 0000000..4539461
--- /dev/null
+++ b/Source/cmQtAutoGeneratorRcc.h
@@ -0,0 +1,90 @@
+/* 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 <string>
+#include <vector>
+
+class cmMakefile;
+
+class cmQtAutoGeneratorRcc
+{
+  CM_DISABLE_COPY(cmQtAutoGeneratorRcc)
+public:
+  cmQtAutoGeneratorRcc();
+  bool Run(std::string const& infoFile, std::string const& config);
+
+private:
+  // -- Initialization & settings
+  bool InfoFileRead(cmMakefile* makefile);
+  void SettingsFileRead(cmMakefile* makefile);
+  bool SettingsFileWrite();
+  // -- Central processing
+  bool Process(cmMakefile* makefile);
+  bool RccGenerate();
+  // -- 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 RunCommand(std::vector<std::string> const& command,
+                  std::string& output) const;
+
+  // -- Info settings
+  std::string InfoFile;
+  std::string InfoDir;
+  std::string InfoConfig;
+  // -- Config settings
+  std::string ConfigSuffix;
+  cmQtAutoGen::MultiConfig MultiConfig;
+  // -- Settings
+  bool Verbose;
+  bool ColorOutput;
+  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 QtMajorVersion;
+  std::string RccExecutable;
+  // -- Job
+  std::string QrcFile;
+  std::string RccFile;
+  std::vector<std::string> Options;
+  std::vector<std::string> Inputs;
+};
+
+#endif
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 449db9d..a37bc3c 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -6,6 +6,7 @@
 #include "cmGlobalGenerator.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
+#include "cmQtAutoGeneratorRcc.h"
 #include "cmQtAutoGenerators.h"
 #include "cmStateDirectory.h"
 #include "cmStateSnapshot.h"
@@ -992,11 +993,20 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
     }
 
 #ifdef CMAKE_BUILD_WITH_CMAKE
-    if (args[1] == "cmake_autogen" && args.size() >= 4) {
-      cmQtAutoGenerators autogen;
+    if ((args[1] == "cmake_autogen") && (args.size() >= 4)) {
+      cmQtAutoGenerators 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
 

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

Summary of changes:
 Modules/AutoRccInfo.cmake.in                       |   11 +
 Modules/AutogenInfo.cmake.in                       |    8 +-
 Modules/CPack.cmake                                |    2 +-
 Modules/CPackComponent.cmake                       |    2 +-
 Source/CMakeLists.txt                              |    9 +-
 Source/cmGlobalGenerator.cxx                       |   36 +-
 Source/cmGlobalGenerator.h                         |    5 +-
 Source/cmQtAutoGen.cxx                             |   91 +-
 Source/cmQtAutoGen.h                               |    6 +-
 Source/cmQtAutoGenDigest.h                         |   64 -
 Source/cmQtAutoGenerator.cxx                       |  320 ++++
 Source/cmQtAutoGenerator.h                         |   76 +
 Source/cmQtAutoGeneratorInitializer.cxx            | 1654 +++++++++++---------
 Source/cmQtAutoGeneratorInitializer.h              |   79 +-
 ...oGenerators.cxx => cmQtAutoGeneratorMocUic.cxx} |  783 ++-------
 ...tAutoGenerators.h => cmQtAutoGeneratorMocUic.h} |   73 +-
 Source/cmQtAutoGeneratorRcc.cxx                    |  425 +++++
 Source/cmQtAutoGeneratorRcc.h                      |   56 +
 Source/cmcmd.cxx                                   |   20 +-
 .../CPack/ArchiveCommon/common_helpers.cmake       |   17 +-
 Tests/RunCMake/CPack/CPackTestHelpers.cmake        |   19 +
 Tests/RunCMake/CPack/DEB/Helpers.cmake             |   15 +-
 Tests/RunCMake/CPack/README.txt                    |   16 +-
 Tests/RunCMake/CPack/RPM/Helpers.cmake             |   23 +-
 Tests/RunCMake/CPack/STGZ/Helpers.cmake            |   29 +-
 .../tests/CPACK_INSTALL_SCRIPT/ExpectedFiles.cmake |    2 +-
 .../CUSTOM_BINARY_SPEC_FILE/ExpectedFiles.cmake    |    4 +-
 .../CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake   |    6 +-
 .../CPack/tests/DEBUGINFO/ExpectedFiles.cmake      |    6 +-
 .../ExpectedFiles.cmake                            |    2 +-
 .../tests/DEFAULT_PERMISSIONS/ExpectedFiles.cmake  |    2 +-
 .../CPack/tests/DEPENDENCIES/ExpectedFiles.cmake   |   10 +-
 .../RunCMake/CPack/tests/DIST/ExpectedFiles.cmake  |    2 +-
 .../CPack/tests/EMPTY_DIR/ExpectedFiles.cmake      |    2 +-
 .../RunCMake/CPack/tests/EXTRA/ExpectedFiles.cmake |    6 +-
 .../tests/EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake  |    1 +
 .../tests/INSTALL_SCRIPTS/ExpectedFiles.cmake      |    4 +-
 .../CPack/tests/LONG_FILENAMES/ExpectedFiles.cmake |    2 +-
 .../CPack/tests/MAIN_COMPONENT/ExpectedFiles.cmake |    6 +-
 .../CPack/tests/MD5SUMS/ExpectedFiles.cmake        |    2 +-
 .../CPack/tests/MINIMAL/ExpectedFiles.cmake        |    2 +-
 .../tests/PACKAGE_CHECKSUM/ExpectedFiles.cmake     |    2 +-
 .../ExpectedFiles.cmake                            |    2 +
 .../tests/PER_COMPONENT_FIELDS/ExpectedFiles.cmake |    6 +-
 .../tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake     |   10 +-
 .../CPack/tests/SOURCE_PACKAGE/ExpectedFiles.cmake |    1 +
 .../CPack/tests/SUGGESTS/ExpectedFiles.cmake       |    2 +-
 .../CPack/tests/SYMLINKS/ExpectedFiles.cmake       |   11 +-
 .../CPack/tests/USER_FILELIST/ExpectedFiles.cmake  |    2 +-
 .../CPack/tests/VERSION/ExpectedFiles.cmake        |    2 +-
 50 files changed, 2185 insertions(+), 1751 deletions(-)
 create mode 100644 Modules/AutoRccInfo.cmake.in
 delete mode 100644 Source/cmQtAutoGenDigest.h
 create mode 100644 Source/cmQtAutoGenerator.cxx
 create mode 100644 Source/cmQtAutoGenerator.h
 rename Source/{cmQtAutoGenerators.cxx => cmQtAutoGeneratorMocUic.cxx} (69%)
 rename Source/{cmQtAutoGenerators.h => cmQtAutoGeneratorMocUic.h} (69%)
 create mode 100644 Source/cmQtAutoGeneratorRcc.cxx
 create mode 100644 Source/cmQtAutoGeneratorRcc.h


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list