Merge topic 'fix-cmake-server-bad-buffering'

01c42155 server: Fix regression in partial message handling

Acked-by: Kitware Robot <kwrobot@kitware.com>
Reviewed-by: jdavidberger <j.david.berger@gmail.com>
Merge-request: !1498
diff --git a/Auxiliary/bash-completion/cmake b/Auxiliary/bash-completion/cmake
index 0a862fa..5d67b0b 100644
--- a/Auxiliary/bash-completion/cmake
+++ b/Auxiliary/bash-completion/cmake
@@ -96,7 +96,7 @@
             _filedir
             return
             ;;
-        --build)
+        --build|--open)
             _filedir -d
             return
             ;;
diff --git a/Auxiliary/vim/cmake.vim.in b/Auxiliary/vim/cmake.vim.in
index 2461e0b..d7eff3e 100644
--- a/Auxiliary/vim/cmake.vim.in
+++ b/Auxiliary/vim/cmake.vim.in
@@ -1,4 +1,3 @@
-" vim: set nowrap:
 " Vim syntax file
 " Program:      CMake - Cross-Platform Makefile Generator
 " Version:      @VERSION@
@@ -8,6 +7,7 @@
 "               Patrick Boettcher <patrick.boettcher@posteo.de>
 " Maintainer:   Dimitri Merejkowsky <d.merej@gmail.com>
 " Former Maintainer: Karthik Krishnan <karthik.krishnan@kitware.com>
+" Last Change:  @DATE@
 "
 " Licence:      The CMake license applies to this file. See
 "               https://cmake.org/licensing
@@ -100,4 +100,4 @@
 let &cpo = s:keepcpo
 unlet s:keepcpo
 
-"EOF"
+" vim: set nowrap:
diff --git a/Auxiliary/vim/extract-upper-case.pl b/Auxiliary/vim/extract-upper-case.pl
index 9e3c439..6dbb678 100755
--- a/Auxiliary/vim/extract-upper-case.pl
+++ b/Auxiliary/vim/extract-upper-case.pl
@@ -2,6 +2,7 @@
 
 use strict;
 use warnings;
+use POSIX qw(strftime);
 
 #my $cmake = "/home/pboettch/devel/upstream/cmake/build/bin/cmake";
 my $cmake = "cmake";
@@ -129,6 +130,10 @@
 		} elsif ($1 eq "VERSION") {
 			$_ =~ s/\@VERSION\@/$version/;
 			print OUT $_;
+		} elsif ($1 eq "DATE") {
+			my $date = strftime "%Y %b %d", localtime;
+			$_ =~ s/\@DATE\@/$date/;
+			print OUT $_;
 		} else {
 			print "ERROR do not know how to replace $1\n";
 		}
diff --git a/Auxiliary/vim/indent/cmake.vim b/Auxiliary/vim/indent/cmake.vim
index 76aff64..33e583d 100644
--- a/Auxiliary/vim/indent/cmake.vim
+++ b/Auxiliary/vim/indent/cmake.vim
@@ -1,9 +1,9 @@
 " Vim indent file
 " Language:     CMake (ft=cmake)
 " Author:       Andy Cedilnik <andy.cedilnik@kitware.com>
-" Maintainer:   Karthik Krishnan <karthik.krishnan@kitware.com>
-" Last Change:  $Date$
-" Version:      $Revision$
+" Maintainer:   Dimitri Merejkowsky <d.merej@gmail.com>
+" Former Maintainer: Karthik Krishnan <karthik.krishnan@kitware.com>
+" Last Change:  2017 Aug 30
 "
 " Licence:      The CMake license applies to this file. See
 "               https://cmake.org/licensing
@@ -14,6 +14,9 @@
 endif
 let b:did_indent = 1
 
+let s:keepcpo= &cpo
+set cpo&vim
+
 setlocal indentexpr=CMakeGetIndent(v:lnum)
 setlocal indentkeys+==ENDIF(,ENDFOREACH(,ENDMACRO(,ELSE(,ELSEIF(,ENDWHILE(
 
@@ -64,20 +67,23 @@
     let ind = ind
   else
     if previous_line =~? cmake_indent_begin_regex
-      let ind = ind + &sw
+      let ind = ind + shiftwidth()
     endif
     if previous_line =~? cmake_indent_open_regex
-      let ind = ind + &sw
+      let ind = ind + shiftwidth()
     endif
   endif
 
   " Subtract
   if this_line =~? cmake_indent_end_regex
-    let ind = ind - &sw
+    let ind = ind - shiftwidth()
   endif
   if previous_line =~? cmake_indent_close_regex
-    let ind = ind - &sw
+    let ind = ind - shiftwidth()
   endif
 
   return ind
 endfun
+
+let &cpo = s:keepcpo
+unlet s:keepcpo
diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim
index 5f9af05..98d6ef1 100644
--- a/Auxiliary/vim/syntax/cmake.vim
+++ b/Auxiliary/vim/syntax/cmake.vim
@@ -1,13 +1,13 @@
-" vim: set nowrap:
 " Vim syntax file
 " Program:      CMake - Cross-Platform Makefile Generator
-" Version:      cmake version 3.9.20170830-ge0713
+" Version:      cmake version 3.10.20171031-gfd2e6
 " Language:     CMake
 " Author:       Andy Cedilnik <andy.cedilnik@kitware.com>,
 "               Nicholas Hutchinson <nshutchinson@gmail.com>,
 "               Patrick Boettcher <patrick.boettcher@posteo.de>
 " Maintainer:   Dimitri Merejkowsky <d.merej@gmail.com>
 " Former Maintainer: Karthik Krishnan <karthik.krishnan@kitware.com>
+" Last Change:  2017 Oct 31
 "
 " Licence:      The CMake license applies to this file. See
 "               https://cmake.org/licensing
@@ -38,16 +38,16 @@
 syn case match
 
 syn keyword cmakeProperty contained
-            \ ABSTRACT ADDITIONAL_MAKE_CLEAN_FILES ADVANCED ALIASED_TARGET ALLOW_DUPLICATE_CUSTOM_TARGETS ANDROID_ANT_ADDITIONAL_OPTIONS ANDROID_API ANDROID_API_MIN ANDROID_ARCH ANDROID_ASSETS_DIRECTORIES ANDROID_GUI ANDROID_JAR_DEPENDENCIES ANDROID_JAR_DIRECTORIES ANDROID_JAVA_SOURCE_DIR ANDROID_NATIVE_LIB_DEPENDENCIES ANDROID_NATIVE_LIB_DIRECTORIES ANDROID_PROCESS_MAX ANDROID_PROGUARD ANDROID_PROGUARD_CONFIG_PATH ANDROID_SECURE_PROPS_PATH ANDROID_SKIP_ANT_STEP ANDROID_STL_TYPE ARCHIVE_OUTPUT_DIRECTORY ARCHIVE_OUTPUT_NAME ATTACHED_FILES ATTACHED_FILES_ON_FAIL AUTOGEN_BUILD_DIR AUTOGEN_SOURCE_GROUP AUTOGEN_TARGETS_FOLDER AUTOGEN_TARGET_DEPENDS AUTOMOC AUTOMOC_DEPEND_FILTERS AUTOMOC_MACRO_NAMES AUTOMOC_MOC_OPTIONS AUTOMOC_SOURCE_GROUP AUTOMOC_TARGETS_FOLDER AUTORCC AUTORCC_OPTIONS AUTORCC_SOURCE_GROUP AUTOUIC AUTOUIC_OPTIONS AUTOUIC_SEARCH_PATHS BINARY_DIR BUILDSYSTEM_TARGETS BUILD_RPATH BUILD_WITH_INSTALL_NAME_DIR BUILD_WITH_INSTALL_RPATH BUNDLE BUNDLE_EXTENSION CACHE_VARIABLES CLEAN_NO_CUSTOM CMAKE_CONFIGURE_DEPENDS CMAKE_CXX_KNOWN_FEATURES CMAKE_C_KNOWN_FEATURES COMPATIBLE_INTERFACE_BOOL COMPATIBLE_INTERFACE_NUMBER_MAX COMPATIBLE_INTERFACE_NUMBER_MIN COMPATIBLE_INTERFACE_STRING COMPILE_DEFINITIONS COMPILE_FEATURES COMPILE_FLAGS COMPILE_OPTIONS COMPILE_PDB_NAME COMPILE_PDB_OUTPUT_DIRECTORY COST CPACK_DESKTOP_SHORTCUTS CPACK_NEVER_OVERWRITE CPACK_PERMANENT CPACK_STARTUP_SHORTCUTS CPACK_START_MENU_SHORTCUTS CPACK_WIX_ACL CROSSCOMPILING_EMULATOR CUDA_EXTENSIONS CUDA_PTX_COMPILATION CUDA_RESOLVE_DEVICE_SYMBOLS CUDA_SEPARABLE_COMPILATION CUDA_STANDARD CUDA_STANDARD_REQUIRED CXX_EXTENSIONS CXX_STANDARD CXX_STANDARD_REQUIRED C_EXTENSIONS C_STANDARD C_STANDARD_REQUIRED DEBUG_CONFIGURATIONS DEBUG_POSTFIX DEFINE_SYMBOL DEFINITIONS DEPENDS DEPLOYMENT_REMOTE_DIRECTORY DISABLED DISABLED_FEATURES ECLIPSE_EXTRA_NATURES ENABLED_FEATURES ENABLED_LANGUAGES ENABLE_EXPORTS ENVIRONMENT EXCLUDE_FROM_ALL EXCLUDE_FROM_DEFAULT_BUILD EXPORT_NAME EXTERNAL_OBJECT EchoString FAIL_REGULAR_EXPRESSION FIND_LIBRARY_USE_LIB32_PATHS FIND_LIBRARY_USE_LIB64_PATHS FIND_LIBRARY_USE_LIBX32_PATHS FIND_LIBRARY_USE_OPENBSD_VERSIONING FIXTURES_CLEANUP FIXTURES_REQUIRED FIXTURES_SETUP FOLDER FRAMEWORK FRAMEWORK_VERSION Fortran_FORMAT Fortran_MODULE_DIRECTORY GENERATED GENERATOR_FILE_NAME GENERATOR_IS_MULTI_CONFIG GLOBAL_DEPENDS_DEBUG_MODE GLOBAL_DEPENDS_NO_CYCLES GNUtoMS HAS_CXX HEADER_FILE_ONLY HELPSTRING IMPLICIT_DEPENDS_INCLUDE_TRANSFORM IMPORTED IMPORTED_CONFIGURATIONS IMPORTED_IMPLIB IMPORTED_LIBNAME IMPORTED_LINK_DEPENDENT_LIBRARIES IMPORTED_LINK_INTERFACE_LANGUAGES IMPORTED_LINK_INTERFACE_LIBRARIES IMPORTED_LINK_INTERFACE_MULTIPLICITY IMPORTED_LOCATION IMPORTED_NO_SONAME IMPORTED_OBJECTS IMPORTED_SONAME IMPORT_PREFIX IMPORT_SUFFIX INCLUDE_DIRECTORIES INCLUDE_REGULAR_EXPRESSION INSTALL_NAME_DIR INSTALL_RPATH INSTALL_RPATH_USE_LINK_PATH INTERFACE_AUTOUIC_OPTIONS INTERFACE_COMPILE_DEFINITIONS INTERFACE_COMPILE_FEATURES INTERFACE_COMPILE_OPTIONS INTERFACE_INCLUDE_DIRECTORIES INTERFACE_LINK_LIBRARIES INTERFACE_POSITION_INDEPENDENT_CODE INTERFACE_SOURCES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES INTERPROCEDURAL_OPTIMIZATION IN_TRY_COMPILE IOS_INSTALL_COMBINED JOB_POOLS JOB_POOL_COMPILE JOB_POOL_LINK KEEP_EXTENSION LABELS LANGUAGE LIBRARY_OUTPUT_DIRECTORY LIBRARY_OUTPUT_NAME LINKER_LANGUAGE LINK_DEPENDS LINK_DEPENDS_NO_SHARED LINK_DIRECTORIES LINK_FLAGS LINK_INTERFACE_LIBRARIES LINK_INTERFACE_MULTIPLICITY LINK_LIBRARIES LINK_SEARCH_END_STATIC LINK_SEARCH_START_STATIC LINK_WHAT_YOU_USE LISTFILE_STACK LOCATION MACOSX_BUNDLE MACOSX_BUNDLE_INFO_PLIST MACOSX_FRAMEWORK_INFO_PLIST MACOSX_PACKAGE_LOCATION MACOSX_RPATH MACROS MANUALLY_ADDED_DEPENDENCIES MEASUREMENT MODIFIED NAME NO_SONAME NO_SYSTEM_FROM_IMPORTED OBJECT_DEPENDS OBJECT_OUTPUTS OSX_ARCHITECTURES OUTPUT_NAME PACKAGES_FOUND PACKAGES_NOT_FOUND PARENT_DIRECTORY PASS_REGULAR_EXPRESSION PDB_NAME PDB_OUTPUT_DIRECTORY POSITION_INDEPENDENT_CODE POST_INSTALL_SCRIPT PREDEFINED_TARGETS_FOLDER PREFIX PRE_INSTALL_SCRIPT PRIVATE_HEADER PROCESSORS PROJECT_LABEL PUBLIC_HEADER REPORT_UNDEFINED_PROPERTIES REQUIRED_FILES RESOURCE RESOURCE_LOCK RULE_LAUNCH_COMPILE RULE_LAUNCH_CUSTOM RULE_LAUNCH_LINK RULE_MESSAGES RUNTIME_OUTPUT_DIRECTORY RUNTIME_OUTPUT_NAME RUN_SERIAL SKIP_AUTOGEN SKIP_AUTOMOC SKIP_AUTORCC SKIP_AUTOUIC SKIP_BUILD_RPATH SKIP_RETURN_CODE SOURCES SOURCE_DIR SOVERSION STATIC_LIBRARY_FLAGS STRINGS SUBDIRECTORIES SUFFIX SYMBOLIC TARGET_ARCHIVES_MAY_BE_SHARED_LIBS TARGET_MESSAGES TARGET_SUPPORTS_SHARED_LIBS TEST_INCLUDE_FILE TEST_INCLUDE_FILES TIMEOUT TIMEOUT_AFTER_MATCH TYPE USE_FOLDERS VALUE VARIABLES VERSION VISIBILITY_INLINES_HIDDEN VS_CONFIGURATION_TYPE VS_COPY_TO_OUT_DIR VS_DEBUGGER_WORKING_DIRECTORY VS_DEPLOYMENT_CONTENT VS_DEPLOYMENT_LOCATION VS_DESKTOP_EXTENSIONS_VERSION VS_DOTNET_REFERENCES VS_DOTNET_REFERENCES_COPY_LOCAL VS_DOTNET_TARGET_FRAMEWORK_VERSION VS_GLOBAL_KEYWORD VS_GLOBAL_PROJECT_TYPES VS_GLOBAL_ROOTNAMESPACE VS_INCLUDE_IN_VSIX VS_IOT_EXTENSIONS_VERSION VS_IOT_STARTUP_TASK VS_KEYWORD VS_MOBILE_EXTENSIONS_VERSION VS_RESOURCE_GENERATOR VS_SCC_AUXPATH VS_SCC_LOCALPATH VS_SCC_PROJECTNAME VS_SCC_PROVIDER VS_SDK_REFERENCES VS_SHADER_ENTRYPOINT VS_SHADER_FLAGS VS_SHADER_MODEL VS_SHADER_TYPE VS_SHADER_OUTPUT_HEADER_FILE VS_SHADER_VARIABLE_NAME VS_STARTUP_PROJECT VS_TOOL_OVERRIDE VS_USER_PROPS VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION VS_WINRT_COMPONENT VS_WINRT_EXTENSIONS VS_WINRT_REFERENCES VS_XAML_TYPE WILL_FAIL WIN32_EXECUTABLE WINDOWS_EXPORT_ALL_SYMBOLS WORKING_DIRECTORY WRAP_EXCLUDE XCODE_EMIT_EFFECTIVE_PLATFORM_NAME XCODE_EXPLICIT_FILE_TYPE XCODE_FILE_ATTRIBUTES XCODE_LAST_KNOWN_FILE_TYPE XCODE_PRODUCT_TYPE XCTEST
+            \ ABSTRACT ADDITIONAL_MAKE_CLEAN_FILES ADVANCED ALIASED_TARGET ALLOW_DUPLICATE_CUSTOM_TARGETS ANDROID_ANT_ADDITIONAL_OPTIONS ANDROID_API ANDROID_API_MIN ANDROID_ARCH ANDROID_ASSETS_DIRECTORIES ANDROID_GUI ANDROID_JAR_DEPENDENCIES ANDROID_JAR_DIRECTORIES ANDROID_JAVA_SOURCE_DIR ANDROID_NATIVE_LIB_DEPENDENCIES ANDROID_NATIVE_LIB_DIRECTORIES ANDROID_PROCESS_MAX ANDROID_PROGUARD ANDROID_PROGUARD_CONFIG_PATH ANDROID_SECURE_PROPS_PATH ANDROID_SKIP_ANT_STEP ANDROID_STL_TYPE ARCHIVE_OUTPUT_DIRECTORY ARCHIVE_OUTPUT_NAME ATTACHED_FILES ATTACHED_FILES_ON_FAIL AUTOGEN_BUILD_DIR AUTOGEN_SOURCE_GROUP AUTOGEN_TARGETS_FOLDER AUTOGEN_TARGET_DEPENDS AUTOMOC AUTOMOC_COMPILER_PREDEFINES AUTOMOC_DEPEND_FILTERS AUTOMOC_MACRO_NAMES AUTOMOC_MOC_OPTIONS AUTOMOC_SOURCE_GROUP AUTOMOC_TARGETS_FOLDER AUTORCC AUTORCC_OPTIONS AUTORCC_SOURCE_GROUP AUTOUIC AUTOUIC_OPTIONS AUTOUIC_SEARCH_PATHS BINARY_DIR BUILDSYSTEM_TARGETS BUILD_RPATH BUILD_WITH_INSTALL_NAME_DIR BUILD_WITH_INSTALL_RPATH BUNDLE BUNDLE_EXTENSION CACHE_VARIABLES CLEAN_NO_CUSTOM CMAKE_CONFIGURE_DEPENDS CMAKE_CXX_KNOWN_FEATURES CMAKE_C_KNOWN_FEATURES COMPATIBLE_INTERFACE_BOOL COMPATIBLE_INTERFACE_NUMBER_MAX COMPATIBLE_INTERFACE_NUMBER_MIN COMPATIBLE_INTERFACE_STRING COMPILE_DEFINITIONS COMPILE_FEATURES COMPILE_FLAGS COMPILE_OPTIONS COMPILE_PDB_NAME COMPILE_PDB_OUTPUT_DIRECTORY COST CPACK_DESKTOP_SHORTCUTS CPACK_NEVER_OVERWRITE CPACK_PERMANENT CPACK_STARTUP_SHORTCUTS CPACK_START_MENU_SHORTCUTS CPACK_WIX_ACL CROSSCOMPILING_EMULATOR CUDA_EXTENSIONS CUDA_PTX_COMPILATION CUDA_RESOLVE_DEVICE_SYMBOLS CUDA_SEPARABLE_COMPILATION CUDA_STANDARD CUDA_STANDARD_REQUIRED CXX_EXTENSIONS CXX_STANDARD CXX_STANDARD_REQUIRED C_EXTENSIONS C_STANDARD C_STANDARD_REQUIRED DEBUG_CONFIGURATIONS DEBUG_POSTFIX DEFINE_SYMBOL DEFINITIONS DEPENDS DEPLOYMENT_REMOTE_DIRECTORY DISABLED DISABLED_FEATURES ECLIPSE_EXTRA_NATURES ENABLED_FEATURES ENABLED_LANGUAGES ENABLE_EXPORTS ENVIRONMENT EXCLUDE_FROM_ALL EXCLUDE_FROM_DEFAULT_BUILD EXPORT_NAME EXTERNAL_OBJECT EchoString FAIL_REGULAR_EXPRESSION FIND_LIBRARY_USE_LIB32_PATHS FIND_LIBRARY_USE_LIB64_PATHS FIND_LIBRARY_USE_LIBX32_PATHS FIND_LIBRARY_USE_OPENBSD_VERSIONING FIXTURES_CLEANUP FIXTURES_REQUIRED FIXTURES_SETUP FOLDER FRAMEWORK FRAMEWORK_VERSION Fortran_FORMAT Fortran_MODULE_DIRECTORY GENERATED GENERATOR_FILE_NAME GENERATOR_IS_MULTI_CONFIG GLOBAL_DEPENDS_DEBUG_MODE GLOBAL_DEPENDS_NO_CYCLES GNUtoMS HAS_CXX HEADER_FILE_ONLY HELPSTRING IMPLICIT_DEPENDS_INCLUDE_TRANSFORM IMPORTED IMPORTED_CONFIGURATIONS IMPORTED_IMPLIB IMPORTED_LIBNAME IMPORTED_LINK_DEPENDENT_LIBRARIES IMPORTED_LINK_INTERFACE_LANGUAGES IMPORTED_LINK_INTERFACE_LIBRARIES IMPORTED_LINK_INTERFACE_MULTIPLICITY IMPORTED_LOCATION IMPORTED_NO_SONAME IMPORTED_OBJECTS IMPORTED_SONAME IMPORT_PREFIX IMPORT_SUFFIX INCLUDE_DIRECTORIES INCLUDE_REGULAR_EXPRESSION INSTALL_NAME_DIR INSTALL_RPATH INSTALL_RPATH_USE_LINK_PATH INTERFACE_AUTOUIC_OPTIONS INTERFACE_COMPILE_DEFINITIONS INTERFACE_COMPILE_FEATURES INTERFACE_COMPILE_OPTIONS INTERFACE_INCLUDE_DIRECTORIES INTERFACE_LINK_LIBRARIES INTERFACE_POSITION_INDEPENDENT_CODE INTERFACE_SOURCES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES INTERPROCEDURAL_OPTIMIZATION IN_TRY_COMPILE IOS_INSTALL_COMBINED JOB_POOLS JOB_POOL_COMPILE JOB_POOL_LINK KEEP_EXTENSION LABELS LANGUAGE LIBRARY_OUTPUT_DIRECTORY LIBRARY_OUTPUT_NAME LINKER_LANGUAGE LINK_DEPENDS LINK_DEPENDS_NO_SHARED LINK_DIRECTORIES LINK_FLAGS LINK_INTERFACE_LIBRARIES LINK_INTERFACE_MULTIPLICITY LINK_LIBRARIES LINK_SEARCH_END_STATIC LINK_SEARCH_START_STATIC LINK_WHAT_YOU_USE LISTFILE_STACK LOCATION MACOSX_BUNDLE MACOSX_BUNDLE_INFO_PLIST MACOSX_FRAMEWORK_INFO_PLIST MACOSX_PACKAGE_LOCATION MACOSX_RPATH MACROS MANUALLY_ADDED_DEPENDENCIES MEASUREMENT MODIFIED NAME NO_SONAME NO_SYSTEM_FROM_IMPORTED OBJECT_DEPENDS OBJECT_OUTPUTS OSX_ARCHITECTURES OUTPUT_NAME PACKAGES_FOUND PACKAGES_NOT_FOUND PARENT_DIRECTORY PASS_REGULAR_EXPRESSION PDB_NAME PDB_OUTPUT_DIRECTORY POSITION_INDEPENDENT_CODE POST_INSTALL_SCRIPT PREDEFINED_TARGETS_FOLDER PREFIX PRE_INSTALL_SCRIPT PRIVATE_HEADER PROCESSORS PROJECT_LABEL PUBLIC_HEADER REPORT_UNDEFINED_PROPERTIES REQUIRED_FILES RESOURCE RESOURCE_LOCK RULE_LAUNCH_COMPILE RULE_LAUNCH_CUSTOM RULE_LAUNCH_LINK RULE_MESSAGES RUNTIME_OUTPUT_DIRECTORY RUNTIME_OUTPUT_NAME RUN_SERIAL SKIP_AUTOGEN SKIP_AUTOMOC SKIP_AUTORCC SKIP_AUTOUIC SKIP_BUILD_RPATH SKIP_RETURN_CODE SOURCES SOURCE_DIR SOVERSION STATIC_LIBRARY_FLAGS STRINGS SUBDIRECTORIES SUFFIX SYMBOLIC TARGET_ARCHIVES_MAY_BE_SHARED_LIBS TARGET_MESSAGES TARGET_SUPPORTS_SHARED_LIBS TEST_INCLUDE_FILE TEST_INCLUDE_FILES TIMEOUT TIMEOUT_AFTER_MATCH TYPE USE_FOLDERS VALUE VARIABLES VERSION VISIBILITY_INLINES_HIDDEN VS_CONFIGURATION_TYPE VS_COPY_TO_OUT_DIR VS_DEBUGGER_WORKING_DIRECTORY VS_DEPLOYMENT_CONTENT VS_DEPLOYMENT_LOCATION VS_DESKTOP_EXTENSIONS_VERSION VS_DOTNET_REFERENCES VS_DOTNET_REFERENCES_COPY_LOCAL VS_DOTNET_TARGET_FRAMEWORK_VERSION VS_GLOBAL_KEYWORD VS_GLOBAL_PROJECT_TYPES VS_GLOBAL_ROOTNAMESPACE VS_INCLUDE_IN_VSIX VS_IOT_EXTENSIONS_VERSION VS_IOT_STARTUP_TASK VS_KEYWORD VS_MOBILE_EXTENSIONS_VERSION VS_RESOURCE_GENERATOR VS_SCC_AUXPATH VS_SCC_LOCALPATH VS_SCC_PROJECTNAME VS_SCC_PROVIDER VS_SDK_REFERENCES VS_SHADER_ENTRYPOINT VS_SHADER_FLAGS VS_SHADER_MODEL VS_SHADER_OUTPUT_HEADER_FILE VS_SHADER_TYPE VS_SHADER_VARIABLE_NAME VS_STARTUP_PROJECT VS_TOOL_OVERRIDE VS_USER_PROPS VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION VS_WINRT_COMPONENT VS_WINRT_EXTENSIONS VS_WINRT_REFERENCES VS_XAML_TYPE WILL_FAIL WIN32_EXECUTABLE WINDOWS_EXPORT_ALL_SYMBOLS WORKING_DIRECTORY WRAP_EXCLUDE XCODE_EMIT_EFFECTIVE_PLATFORM_NAME XCODE_EXPLICIT_FILE_TYPE XCODE_FILE_ATTRIBUTES XCODE_LAST_KNOWN_FILE_TYPE XCODE_PRODUCT_TYPE XCTEST
 
 syn keyword cmakeVariable contained
-            \ ANDROID APPLE BORLAND BUILD_SHARED_LIBS CMAKE_ABSOLUTE_DESTINATION_FILES CMAKE_ANDROID_ANT_ADDITIONAL_OPTIONS CMAKE_ANDROID_API CMAKE_ANDROID_API_MIN CMAKE_ANDROID_ARCH CMAKE_ANDROID_ARCH_ABI CMAKE_ANDROID_ARM_MODE CMAKE_ANDROID_ARM_NEON CMAKE_ANDROID_ASSETS_DIRECTORIES CMAKE_ANDROID_GUI CMAKE_ANDROID_JAR_DEPENDENCIES CMAKE_ANDROID_JAR_DIRECTORIES CMAKE_ANDROID_JAVA_SOURCE_DIR CMAKE_ANDROID_NATIVE_LIB_DEPENDENCIES CMAKE_ANDROID_NATIVE_LIB_DIRECTORIES CMAKE_ANDROID_NDK CMAKE_ANDROID_NDK_DEPRECATED_HEADERS CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION CMAKE_ANDROID_PROCESS_MAX CMAKE_ANDROID_PROGUARD CMAKE_ANDROID_PROGUARD_CONFIG_PATH CMAKE_ANDROID_SECURE_PROPS_PATH CMAKE_ANDROID_SKIP_ANT_STEP CMAKE_ANDROID_STANDALONE_TOOLCHAIN CMAKE_ANDROID_STL_TYPE CMAKE_APPBUNDLE_PATH CMAKE_AR CMAKE_ARCHIVE_OUTPUT_DIRECTORY CMAKE_ARGC CMAKE_ARGV0 CMAKE_AUTOMOC CMAKE_AUTOMOC_DEPEND_FILTERS CMAKE_AUTOMOC_MACRO_NAMES CMAKE_AUTOMOC_MOC_OPTIONS CMAKE_AUTOMOC_RELAXED_MODE CMAKE_AUTORCC CMAKE_AUTORCC_OPTIONS CMAKE_AUTOUIC CMAKE_AUTOUIC_OPTIONS CMAKE_AUTOUIC_SEARCH_PATHS CMAKE_BACKWARDS_COMPATIBILITY CMAKE_BINARY_DIR CMAKE_BUILD_RPATH CMAKE_BUILD_TOOL CMAKE_BUILD_TYPE CMAKE_BUILD_WITH_INSTALL_NAME_DIR CMAKE_BUILD_WITH_INSTALL_RPATH CMAKE_CACHEFILE_DIR CMAKE_CACHE_MAJOR_VERSION CMAKE_CACHE_MINOR_VERSION CMAKE_CACHE_PATCH_VERSION CMAKE_CFG_INTDIR CMAKE_CL_64 CMAKE_CODELITE_USE_TARGETS CMAKE_COLOR_MAKEFILE CMAKE_COMMAND CMAKE_COMPILER_2005 CMAKE_COMPILER_IS_GNUCC CMAKE_COMPILER_IS_GNUCXX CMAKE_COMPILER_IS_GNUG77 CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY CMAKE_CONFIGURATION_TYPES CMAKE_CROSSCOMPILING CMAKE_CROSSCOMPILING_EMULATOR CMAKE_CTEST_COMMAND CMAKE_CUDA_EXTENSIONS CMAKE_CUDA_STANDARD CMAKE_CUDA_STANDARD_REQUIRED CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES CMAKE_CURRENT_BINARY_DIR CMAKE_CURRENT_LIST_DIR CMAKE_CURRENT_LIST_FILE CMAKE_CURRENT_LIST_LINE CMAKE_CURRENT_SOURCE_DIR CMAKE_CXX_COMPILE_FEATURES CMAKE_CXX_EXTENSIONS CMAKE_CXX_STANDARD CMAKE_CXX_STANDARD_REQUIRED CMAKE_C_COMPILE_FEATURES CMAKE_C_EXTENSIONS CMAKE_C_STANDARD CMAKE_C_STANDARD_REQUIRED CMAKE_DEBUG_POSTFIX CMAKE_DEBUG_TARGET_PROPERTIES CMAKE_DEPENDS_IN_PROJECT_ONLY CMAKE_DIRECTORY_LABELS CMAKE_DL_LIBS CMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT CMAKE_ECLIPSE_MAKE_ARGUMENTS CMAKE_ECLIPSE_VERSION CMAKE_EDIT_COMMAND CMAKE_ENABLE_EXPORTS CMAKE_ERROR_DEPRECATED CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION CMAKE_EXECUTABLE_SUFFIX CMAKE_EXE_LINKER_FLAGS CMAKE_EXE_LINKER_FLAGS_INIT CMAKE_EXPORT_COMPILE_COMMANDS CMAKE_EXPORT_NO_PACKAGE_REGISTRY CMAKE_EXTRA_GENERATOR CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES CMAKE_FIND_APPBUNDLE CMAKE_FIND_FRAMEWORK CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX CMAKE_FIND_LIBRARY_PREFIXES CMAKE_FIND_LIBRARY_SUFFIXES CMAKE_FIND_NO_INSTALL_PREFIX CMAKE_FIND_PACKAGE_NAME CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY CMAKE_FIND_PACKAGE_SORT_DIRECTION CMAKE_FIND_PACKAGE_SORT_ORDER CMAKE_FIND_PACKAGE_WARN_NO_MODULE CMAKE_FIND_ROOT_PATH CMAKE_FIND_ROOT_PATH_MODE_INCLUDE CMAKE_FIND_ROOT_PATH_MODE_LIBRARY CMAKE_FIND_ROOT_PATH_MODE_PACKAGE CMAKE_FIND_ROOT_PATH_MODE_PROGRAM CMAKE_FRAMEWORK_PATH CMAKE_Fortran_FORMAT CMAKE_Fortran_MODDIR_DEFAULT CMAKE_Fortran_MODDIR_FLAG CMAKE_Fortran_MODOUT_FLAG CMAKE_Fortran_MODULE_DIRECTORY CMAKE_GENERATOR CMAKE_GENERATOR_PLATFORM CMAKE_GENERATOR_TOOLSET CMAKE_GNUtoMS CMAKE_HOME_DIRECTORY CMAKE_HOST_APPLE CMAKE_HOST_SOLARIS CMAKE_HOST_SYSTEM CMAKE_HOST_SYSTEM_NAME CMAKE_HOST_SYSTEM_PROCESSOR CMAKE_HOST_SYSTEM_VERSION CMAKE_HOST_UNIX CMAKE_HOST_WIN32 CMAKE_IGNORE_PATH CMAKE_IMPORT_LIBRARY_PREFIX CMAKE_IMPORT_LIBRARY_SUFFIX CMAKE_INCLUDE_CURRENT_DIR CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE CMAKE_INCLUDE_DIRECTORIES_BEFORE CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE CMAKE_INCLUDE_PATH CMAKE_INSTALL_DEFAULT_COMPONENT_NAME CMAKE_INSTALL_MESSAGE CMAKE_INSTALL_NAME_DIR CMAKE_INSTALL_PREFIX CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT CMAKE_INSTALL_RPATH CMAKE_INSTALL_RPATH_USE_LINK_PATH CMAKE_INTERNAL_PLATFORM_ABI CMAKE_INTERPROCEDURAL_OPTIMIZATION CMAKE_IOS_INSTALL_COMBINED CMAKE_JOB_POOL_COMPILE CMAKE_JOB_POOL_LINK CMAKE_LIBRARY_ARCHITECTURE CMAKE_LIBRARY_ARCHITECTURE_REGEX CMAKE_LIBRARY_OUTPUT_DIRECTORY CMAKE_LIBRARY_PATH CMAKE_LIBRARY_PATH_FLAG CMAKE_LINK_DEF_FILE_FLAG CMAKE_LINK_DEPENDS_NO_SHARED CMAKE_LINK_INTERFACE_LIBRARIES CMAKE_LINK_LIBRARY_FILE_FLAG CMAKE_LINK_LIBRARY_FLAG CMAKE_LINK_LIBRARY_SUFFIX CMAKE_LINK_SEARCH_END_STATIC CMAKE_LINK_SEARCH_START_STATIC CMAKE_LINK_WHAT_YOU_USE CMAKE_MACOSX_BUNDLE CMAKE_MACOSX_RPATH CMAKE_MAJOR_VERSION CMAKE_MAKE_PROGRAM CMAKE_MATCH_COUNT CMAKE_MFC_FLAG CMAKE_MINIMUM_REQUIRED_VERSION CMAKE_MINOR_VERSION CMAKE_MODULE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS_INIT CMAKE_MODULE_PATH CMAKE_MSVCIDE_RUN_PATH CMAKE_NINJA_OUTPUT_PATH_PREFIX CMAKE_NOT_USING_CONFIG_FLAGS CMAKE_NO_BUILTIN_CHRPATH CMAKE_NO_SYSTEM_FROM_IMPORTED CMAKE_OBJECT_PATH_MAX CMAKE_OSX_ARCHITECTURES CMAKE_OSX_DEPLOYMENT_TARGET CMAKE_OSX_SYSROOT CMAKE_PARENT_LIST_FILE CMAKE_PATCH_VERSION CMAKE_PDB_OUTPUT_DIRECTORY CMAKE_POSITION_INDEPENDENT_CODE CMAKE_PREFIX_PATH CMAKE_PROGRAM_PATH CMAKE_PROJECT_DESCRIPTION CMAKE_PROJECT_NAME CMAKE_RANLIB CMAKE_ROOT CMAKE_RUNTIME_OUTPUT_DIRECTORY CMAKE_SCRIPT_MODE_FILE CMAKE_SHARED_LIBRARY_PREFIX CMAKE_SHARED_LIBRARY_SUFFIX CMAKE_SHARED_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS_INIT CMAKE_SHARED_MODULE_PREFIX CMAKE_SHARED_MODULE_SUFFIX CMAKE_SIZEOF_VOID_P CMAKE_SKIP_BUILD_RPATH CMAKE_SKIP_INSTALL_ALL_DEPENDENCY CMAKE_SKIP_INSTALL_RPATH CMAKE_SKIP_INSTALL_RULES CMAKE_SKIP_RPATH CMAKE_SOURCE_DIR CMAKE_STAGING_PREFIX CMAKE_STATIC_LIBRARY_PREFIX CMAKE_STATIC_LIBRARY_SUFFIX CMAKE_STATIC_LINKER_FLAGS CMAKE_STATIC_LINKER_FLAGS_INIT CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE CMAKE_SYSROOT CMAKE_SYSROOT_COMPILE CMAKE_SYSROOT_LINK CMAKE_SYSTEM CMAKE_SYSTEM_APPBUNDLE_PATH CMAKE_SYSTEM_FRAMEWORK_PATH CMAKE_SYSTEM_IGNORE_PATH CMAKE_SYSTEM_INCLUDE_PATH CMAKE_SYSTEM_LIBRARY_PATH CMAKE_SYSTEM_NAME CMAKE_SYSTEM_PREFIX_PATH CMAKE_SYSTEM_PROCESSOR CMAKE_SYSTEM_PROGRAM_PATH CMAKE_SYSTEM_VERSION CMAKE_Swift_LANGUAGE_VERSION CMAKE_TOOLCHAIN_FILE CMAKE_TRY_COMPILE_CONFIGURATION CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_TRY_COMPILE_TARGET_TYPE CMAKE_TWEAK_VERSION CMAKE_USER_MAKE_RULES_OVERRIDE CMAKE_USE_RELATIVE_PATHS CMAKE_VERBOSE_MAKEFILE CMAKE_VERSION CMAKE_VISIBILITY_INLINES_HIDDEN CMAKE_VS_DEVENV_COMMAND CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD CMAKE_VS_INTEL_Fortran_PROJECT_VERSION CMAKE_VS_MSBUILD_COMMAND CMAKE_VS_NsightTegra_VERSION CMAKE_VS_PLATFORM_NAME CMAKE_VS_PLATFORM_TOOLSET CMAKE_VS_PLATFORM_TOOLSET_CUDA CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION CMAKE_WARN_DEPRECATED CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION CMAKE_WIN32_EXECUTABLE CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS CMAKE_XCODE_GENERATE_SCHEME CMAKE_XCODE_PLATFORM_TOOLSET CPACK_ABSOLUTE_DESTINATION_FILES CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION CPACK_INCLUDE_TOPLEVEL_DIRECTORY CPACK_INSTALL_SCRIPT CPACK_PACKAGING_INSTALL_PREFIX CPACK_SET_DESTDIR CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION CTEST_BINARY_DIRECTORY CTEST_BUILD_COMMAND CTEST_BUILD_NAME CTEST_BZR_COMMAND CTEST_BZR_UPDATE_OPTIONS CTEST_CHANGE_ID CTEST_CHECKOUT_COMMAND CTEST_CONFIGURATION_TYPE CTEST_CONFIGURE_COMMAND CTEST_COVERAGE_COMMAND CTEST_COVERAGE_EXTRA_FLAGS CTEST_CURL_OPTIONS CTEST_CUSTOM_COVERAGE_EXCLUDE CTEST_CUSTOM_ERROR_EXCEPTION CTEST_CUSTOM_ERROR_MATCH CTEST_CUSTOM_ERROR_POST_CONTEXT CTEST_CUSTOM_ERROR_PRE_CONTEXT CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE CTEST_CUSTOM_MEMCHECK_IGNORE CTEST_CUSTOM_POST_MEMCHECK CTEST_CUSTOM_POST_TEST CTEST_CUSTOM_PRE_MEMCHECK CTEST_CUSTOM_PRE_TEST CTEST_CUSTOM_TEST_IGNORE CTEST_CUSTOM_WARNING_EXCEPTION CTEST_CUSTOM_WARNING_MATCH CTEST_CVS_CHECKOUT CTEST_CVS_COMMAND CTEST_CVS_UPDATE_OPTIONS CTEST_DROP_LOCATION CTEST_DROP_METHOD CTEST_DROP_SITE CTEST_DROP_SITE_CDASH CTEST_DROP_SITE_PASSWORD CTEST_DROP_SITE_USER CTEST_EXTRA_COVERAGE_GLOB CTEST_GIT_COMMAND CTEST_GIT_INIT_SUBMODULES CTEST_GIT_UPDATE_CUSTOM CTEST_GIT_UPDATE_OPTIONS CTEST_HG_COMMAND CTEST_HG_UPDATE_OPTIONS CTEST_LABELS_FOR_SUBPROJECTS CTEST_MEMORYCHECK_COMMAND CTEST_MEMORYCHECK_COMMAND_OPTIONS CTEST_MEMORYCHECK_SANITIZER_OPTIONS CTEST_MEMORYCHECK_SUPPRESSIONS_FILE CTEST_MEMORYCHECK_TYPE CTEST_NIGHTLY_START_TIME CTEST_P4_CLIENT CTEST_P4_COMMAND CTEST_P4_OPTIONS CTEST_P4_UPDATE_OPTIONS CTEST_SCP_COMMAND CTEST_SITE CTEST_SOURCE_DIRECTORY CTEST_SVN_COMMAND CTEST_SVN_OPTIONS CTEST_SVN_UPDATE_OPTIONS CTEST_TEST_LOAD CTEST_TEST_TIMEOUT CTEST_TRIGGER_SITE CTEST_UPDATE_COMMAND CTEST_UPDATE_OPTIONS CTEST_UPDATE_VERSION_ONLY CTEST_USE_LAUNCHERS CYGWIN ENV EXECUTABLE_OUTPUT_PATH GHS-MULTI LIBRARY_OUTPUT_PATH MINGW MSVC MSVC10 MSVC11 MSVC12 MSVC14 MSVC60 MSVC70 MSVC71 MSVC80 MSVC90 MSVC_IDE MSVC_VERSION PROJECT_BINARY_DIR PROJECT_DESCRIPTION PROJECT_NAME PROJECT_SOURCE_DIR PROJECT_VERSION PROJECT_VERSION_MAJOR PROJECT_VERSION_MINOR PROJECT_VERSION_PATCH PROJECT_VERSION_TWEAK UNIX WIN32 WINCE WINDOWS_PHONE WINDOWS_STORE XCODE XCODE_VERSION
+            \ ANDROID APPLE BORLAND BUILD_SHARED_LIBS CMAKE_ABSOLUTE_DESTINATION_FILES CMAKE_ANDROID_ANT_ADDITIONAL_OPTIONS CMAKE_ANDROID_API CMAKE_ANDROID_API_MIN CMAKE_ANDROID_ARCH CMAKE_ANDROID_ARCH_ABI CMAKE_ANDROID_ARM_MODE CMAKE_ANDROID_ARM_NEON CMAKE_ANDROID_ASSETS_DIRECTORIES CMAKE_ANDROID_GUI CMAKE_ANDROID_JAR_DEPENDENCIES CMAKE_ANDROID_JAR_DIRECTORIES CMAKE_ANDROID_JAVA_SOURCE_DIR CMAKE_ANDROID_NATIVE_LIB_DEPENDENCIES CMAKE_ANDROID_NATIVE_LIB_DIRECTORIES CMAKE_ANDROID_NDK CMAKE_ANDROID_NDK_DEPRECATED_HEADERS CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION CMAKE_ANDROID_PROCESS_MAX CMAKE_ANDROID_PROGUARD CMAKE_ANDROID_PROGUARD_CONFIG_PATH CMAKE_ANDROID_SECURE_PROPS_PATH CMAKE_ANDROID_SKIP_ANT_STEP CMAKE_ANDROID_STANDALONE_TOOLCHAIN CMAKE_ANDROID_STL_TYPE CMAKE_APPBUNDLE_PATH CMAKE_AR CMAKE_ARCHIVE_OUTPUT_DIRECTORY CMAKE_ARGC CMAKE_ARGV0 CMAKE_AUTOMOC CMAKE_AUTOMOC_COMPILER_PREDEFINES CMAKE_AUTOMOC_DEPEND_FILTERS CMAKE_AUTOMOC_MACRO_NAMES CMAKE_AUTOMOC_MOC_OPTIONS CMAKE_AUTOMOC_RELAXED_MODE CMAKE_AUTORCC CMAKE_AUTORCC_OPTIONS CMAKE_AUTOUIC CMAKE_AUTOUIC_OPTIONS CMAKE_AUTOUIC_SEARCH_PATHS CMAKE_BACKWARDS_COMPATIBILITY CMAKE_BINARY_DIR CMAKE_BUILD_RPATH CMAKE_BUILD_TOOL CMAKE_BUILD_TYPE CMAKE_BUILD_WITH_INSTALL_NAME_DIR CMAKE_BUILD_WITH_INSTALL_RPATH CMAKE_CACHEFILE_DIR CMAKE_CACHE_MAJOR_VERSION CMAKE_CACHE_MINOR_VERSION CMAKE_CACHE_PATCH_VERSION CMAKE_CFG_INTDIR CMAKE_CL_64 CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES CMAKE_CODELITE_USE_TARGETS CMAKE_COLOR_MAKEFILE CMAKE_COMMAND CMAKE_COMPILER_2005 CMAKE_COMPILER_IS_GNUCC CMAKE_COMPILER_IS_GNUCXX CMAKE_COMPILER_IS_GNUG77 CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY CMAKE_CONFIGURATION_TYPES CMAKE_CROSSCOMPILING CMAKE_CROSSCOMPILING_EMULATOR CMAKE_CTEST_COMMAND CMAKE_CUDA_EXTENSIONS CMAKE_CUDA_HOST_COMPILER CMAKE_CUDA_STANDARD CMAKE_CUDA_STANDARD_REQUIRED CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES CMAKE_CURRENT_BINARY_DIR CMAKE_CURRENT_LIST_DIR CMAKE_CURRENT_LIST_FILE CMAKE_CURRENT_LIST_LINE CMAKE_CURRENT_SOURCE_DIR CMAKE_CXX_COMPILE_FEATURES CMAKE_CXX_EXTENSIONS CMAKE_CXX_STANDARD CMAKE_CXX_STANDARD_REQUIRED CMAKE_C_COMPILE_FEATURES CMAKE_C_EXTENSIONS CMAKE_C_STANDARD CMAKE_C_STANDARD_REQUIRED CMAKE_DEBUG_POSTFIX CMAKE_DEBUG_TARGET_PROPERTIES CMAKE_DEPENDS_IN_PROJECT_ONLY CMAKE_DIRECTORY_LABELS CMAKE_DL_LIBS CMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT CMAKE_ECLIPSE_MAKE_ARGUMENTS CMAKE_ECLIPSE_VERSION CMAKE_EDIT_COMMAND CMAKE_ENABLE_EXPORTS CMAKE_ERROR_DEPRECATED CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION CMAKE_EXECUTABLE_SUFFIX CMAKE_EXE_LINKER_FLAGS CMAKE_EXE_LINKER_FLAGS_INIT CMAKE_EXPORT_COMPILE_COMMANDS CMAKE_EXPORT_NO_PACKAGE_REGISTRY CMAKE_EXTRA_GENERATOR CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES CMAKE_FIND_APPBUNDLE CMAKE_FIND_FRAMEWORK CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX CMAKE_FIND_LIBRARY_PREFIXES CMAKE_FIND_LIBRARY_SUFFIXES CMAKE_FIND_NO_INSTALL_PREFIX CMAKE_FIND_PACKAGE_NAME CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY CMAKE_FIND_PACKAGE_SORT_DIRECTION CMAKE_FIND_PACKAGE_SORT_ORDER CMAKE_FIND_PACKAGE_WARN_NO_MODULE CMAKE_FIND_ROOT_PATH CMAKE_FIND_ROOT_PATH_MODE_INCLUDE CMAKE_FIND_ROOT_PATH_MODE_LIBRARY CMAKE_FIND_ROOT_PATH_MODE_PACKAGE CMAKE_FIND_ROOT_PATH_MODE_PROGRAM CMAKE_FRAMEWORK_PATH CMAKE_Fortran_FORMAT CMAKE_Fortran_MODDIR_DEFAULT CMAKE_Fortran_MODDIR_FLAG CMAKE_Fortran_MODOUT_FLAG CMAKE_Fortran_MODULE_DIRECTORY CMAKE_GENERATOR CMAKE_GENERATOR_INSTANCE CMAKE_GENERATOR_PLATFORM CMAKE_GENERATOR_TOOLSET CMAKE_GNUtoMS CMAKE_HOME_DIRECTORY CMAKE_HOST_APPLE CMAKE_HOST_SOLARIS CMAKE_HOST_SYSTEM CMAKE_HOST_SYSTEM_NAME CMAKE_HOST_SYSTEM_PROCESSOR CMAKE_HOST_SYSTEM_VERSION CMAKE_HOST_UNIX CMAKE_HOST_WIN32 CMAKE_IGNORE_PATH CMAKE_IMPORT_LIBRARY_PREFIX CMAKE_IMPORT_LIBRARY_SUFFIX CMAKE_INCLUDE_CURRENT_DIR CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE CMAKE_INCLUDE_DIRECTORIES_BEFORE CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE CMAKE_INCLUDE_PATH CMAKE_INSTALL_DEFAULT_COMPONENT_NAME CMAKE_INSTALL_MESSAGE CMAKE_INSTALL_NAME_DIR CMAKE_INSTALL_PREFIX CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT CMAKE_INSTALL_RPATH CMAKE_INSTALL_RPATH_USE_LINK_PATH CMAKE_INTERNAL_PLATFORM_ABI CMAKE_INTERPROCEDURAL_OPTIMIZATION CMAKE_IOS_INSTALL_COMBINED CMAKE_JOB_POOL_COMPILE CMAKE_JOB_POOL_LINK CMAKE_LIBRARY_ARCHITECTURE CMAKE_LIBRARY_ARCHITECTURE_REGEX CMAKE_LIBRARY_OUTPUT_DIRECTORY CMAKE_LIBRARY_PATH CMAKE_LIBRARY_PATH_FLAG CMAKE_LINK_DEF_FILE_FLAG CMAKE_LINK_DEPENDS_NO_SHARED CMAKE_LINK_INTERFACE_LIBRARIES CMAKE_LINK_LIBRARY_FILE_FLAG CMAKE_LINK_LIBRARY_FLAG CMAKE_LINK_LIBRARY_SUFFIX CMAKE_LINK_SEARCH_END_STATIC CMAKE_LINK_SEARCH_START_STATIC CMAKE_LINK_WHAT_YOU_USE CMAKE_MACOSX_BUNDLE CMAKE_MACOSX_RPATH CMAKE_MAJOR_VERSION CMAKE_MAKE_PROGRAM CMAKE_MATCH_COUNT CMAKE_MFC_FLAG CMAKE_MINIMUM_REQUIRED_VERSION CMAKE_MINOR_VERSION CMAKE_MODULE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS_INIT CMAKE_MODULE_PATH CMAKE_MSVCIDE_RUN_PATH CMAKE_NETRC CMAKE_NETRC_FILE CMAKE_NINJA_OUTPUT_PATH_PREFIX CMAKE_NOT_USING_CONFIG_FLAGS CMAKE_NO_BUILTIN_CHRPATH CMAKE_NO_SYSTEM_FROM_IMPORTED CMAKE_OBJECT_PATH_MAX CMAKE_OSX_ARCHITECTURES CMAKE_OSX_DEPLOYMENT_TARGET CMAKE_OSX_SYSROOT CMAKE_PARENT_LIST_FILE CMAKE_PATCH_VERSION CMAKE_PDB_OUTPUT_DIRECTORY CMAKE_POSITION_INDEPENDENT_CODE CMAKE_PREFIX_PATH CMAKE_PROGRAM_PATH CMAKE_PROJECT_DESCRIPTION CMAKE_PROJECT_NAME CMAKE_RANLIB CMAKE_ROOT CMAKE_RUNTIME_OUTPUT_DIRECTORY CMAKE_SCRIPT_MODE_FILE CMAKE_SHARED_LIBRARY_PREFIX CMAKE_SHARED_LIBRARY_SUFFIX CMAKE_SHARED_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS_INIT CMAKE_SHARED_MODULE_PREFIX CMAKE_SHARED_MODULE_SUFFIX CMAKE_SIZEOF_VOID_P CMAKE_SKIP_BUILD_RPATH CMAKE_SKIP_INSTALL_ALL_DEPENDENCY CMAKE_SKIP_INSTALL_RPATH CMAKE_SKIP_INSTALL_RULES CMAKE_SKIP_RPATH CMAKE_SOURCE_DIR CMAKE_STAGING_PREFIX CMAKE_STATIC_LIBRARY_PREFIX CMAKE_STATIC_LIBRARY_SUFFIX CMAKE_STATIC_LINKER_FLAGS CMAKE_STATIC_LINKER_FLAGS_INIT CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE CMAKE_SYSROOT CMAKE_SYSROOT_COMPILE CMAKE_SYSROOT_LINK CMAKE_SYSTEM CMAKE_SYSTEM_APPBUNDLE_PATH CMAKE_SYSTEM_FRAMEWORK_PATH CMAKE_SYSTEM_IGNORE_PATH CMAKE_SYSTEM_INCLUDE_PATH CMAKE_SYSTEM_LIBRARY_PATH CMAKE_SYSTEM_NAME CMAKE_SYSTEM_PREFIX_PATH CMAKE_SYSTEM_PROCESSOR CMAKE_SYSTEM_PROGRAM_PATH CMAKE_SYSTEM_VERSION CMAKE_Swift_LANGUAGE_VERSION CMAKE_TOOLCHAIN_FILE CMAKE_TRY_COMPILE_CONFIGURATION CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_TRY_COMPILE_TARGET_TYPE CMAKE_TWEAK_VERSION CMAKE_USER_MAKE_RULES_OVERRIDE CMAKE_USE_RELATIVE_PATHS CMAKE_VERBOSE_MAKEFILE CMAKE_VERSION CMAKE_VISIBILITY_INLINES_HIDDEN CMAKE_VS_DEVENV_COMMAND CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD CMAKE_VS_INTEL_Fortran_PROJECT_VERSION CMAKE_VS_MSBUILD_COMMAND CMAKE_VS_NsightTegra_VERSION CMAKE_VS_PLATFORM_NAME CMAKE_VS_PLATFORM_TOOLSET CMAKE_VS_PLATFORM_TOOLSET_CUDA CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION CMAKE_WARN_DEPRECATED CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION CMAKE_WIN32_EXECUTABLE CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS CMAKE_XCODE_GENERATE_SCHEME CMAKE_XCODE_PLATFORM_TOOLSET CPACK_ABSOLUTE_DESTINATION_FILES CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION CPACK_INCLUDE_TOPLEVEL_DIRECTORY CPACK_INSTALL_SCRIPT CPACK_PACKAGING_INSTALL_PREFIX CPACK_SET_DESTDIR CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION CTEST_BINARY_DIRECTORY CTEST_BUILD_COMMAND CTEST_BUILD_NAME CTEST_BZR_COMMAND CTEST_BZR_UPDATE_OPTIONS CTEST_CHANGE_ID CTEST_CHECKOUT_COMMAND CTEST_CONFIGURATION_TYPE CTEST_CONFIGURE_COMMAND CTEST_COVERAGE_COMMAND CTEST_COVERAGE_EXTRA_FLAGS CTEST_CURL_OPTIONS CTEST_CUSTOM_COVERAGE_EXCLUDE CTEST_CUSTOM_ERROR_EXCEPTION CTEST_CUSTOM_ERROR_MATCH CTEST_CUSTOM_ERROR_POST_CONTEXT CTEST_CUSTOM_ERROR_PRE_CONTEXT CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE CTEST_CUSTOM_MEMCHECK_IGNORE CTEST_CUSTOM_POST_MEMCHECK CTEST_CUSTOM_POST_TEST CTEST_CUSTOM_PRE_MEMCHECK CTEST_CUSTOM_PRE_TEST CTEST_CUSTOM_TEST_IGNORE CTEST_CUSTOM_WARNING_EXCEPTION CTEST_CUSTOM_WARNING_MATCH CTEST_CVS_CHECKOUT CTEST_CVS_COMMAND CTEST_CVS_UPDATE_OPTIONS CTEST_DROP_LOCATION CTEST_DROP_METHOD CTEST_DROP_SITE CTEST_DROP_SITE_CDASH CTEST_DROP_SITE_PASSWORD CTEST_DROP_SITE_USER CTEST_EXTRA_COVERAGE_GLOB CTEST_GIT_COMMAND CTEST_GIT_INIT_SUBMODULES CTEST_GIT_UPDATE_CUSTOM CTEST_GIT_UPDATE_OPTIONS CTEST_HG_COMMAND CTEST_HG_UPDATE_OPTIONS CTEST_LABELS_FOR_SUBPROJECTS CTEST_MEMORYCHECK_COMMAND CTEST_MEMORYCHECK_COMMAND_OPTIONS CTEST_MEMORYCHECK_SANITIZER_OPTIONS CTEST_MEMORYCHECK_SUPPRESSIONS_FILE CTEST_MEMORYCHECK_TYPE CTEST_NIGHTLY_START_TIME CTEST_P4_CLIENT CTEST_P4_COMMAND CTEST_P4_OPTIONS CTEST_P4_UPDATE_OPTIONS CTEST_SCP_COMMAND CTEST_SITE CTEST_SOURCE_DIRECTORY CTEST_SVN_COMMAND CTEST_SVN_OPTIONS CTEST_SVN_UPDATE_OPTIONS CTEST_TEST_LOAD CTEST_TEST_TIMEOUT CTEST_TRIGGER_SITE CTEST_UPDATE_COMMAND CTEST_UPDATE_OPTIONS CTEST_UPDATE_VERSION_ONLY CTEST_USE_LAUNCHERS CYGWIN ENV EXECUTABLE_OUTPUT_PATH GHS-MULTI LIBRARY_OUTPUT_PATH MINGW MSVC MSVC10 MSVC11 MSVC12 MSVC14 MSVC60 MSVC70 MSVC71 MSVC80 MSVC90 MSVC_IDE MSVC_VERSION PROJECT_BINARY_DIR PROJECT_DESCRIPTION PROJECT_NAME PROJECT_SOURCE_DIR PROJECT_VERSION PROJECT_VERSION_MAJOR PROJECT_VERSION_MINOR PROJECT_VERSION_PATCH PROJECT_VERSION_TWEAK UNIX WIN32 WINCE WINDOWS_PHONE WINDOWS_STORE XCODE XCODE_VERSION
 
 syn keyword cmakeModule contained
             \ ExternalProject
 
 syn keyword cmakeKWExternalProject contained
-            \ ALGO AWS BINARY_DIR BUILD_ALWAYS BUILD_BYPRODUCTS BUILD_COMMAND BUILD_IN_SOURCE CMAKE_ARGS CMAKE_CACHE_ARGS CMAKE_CACHE_DEFAULT_ARGS CMAKE_TLS_CAINFO CMAKE_TLS_VERIFY COMMENT CONFIGURE_COMMAND CVS CVSROOT CVS_MODULE CVS_REPOSITORY CVS_TAG DEPENDEES DEPENDERS DEPENDS DOWNLOADED_FILE DOWNLOAD_COMMAND DOWNLOAD_DIR DOWNLOAD_NAME DOWNLOAD_NO_EXTRACT DOWNLOAD_NO_PROGRESS EP_BASE EP_INDEPENDENT_STEP_TARGETS EP_PREFIX EP_STEP_TARGETS EP_UPDATE_DISCONNECTED EXCLUDE_FROM_ALL FORCE GIT_CONFIG GIT_PROGRESS GIT_REMOTE_NAME GIT_REPOSITORY GIT_SHALLOW GIT_SUBMODULES GIT_TAG HG_REPOSITORY HG_TAG HTTP_HEADER HTTP_PASSWORD HTTP_USERNAME INDEPENDENT_STEP_TARGETS INSTALL_COMMAND INSTALL_DIR JOB_POOLS LIST_SEPARATOR LOG_ LOG_BUILD LOG_CONFIGURE LOG_DOWNLOAD LOG_INSTALL LOG_TEST LOG_UPDATE MAKE_EXE NAMES NOTE NO_DEPENDS PATCH_COMMAND PREFIX PROPERTY SOURCE_DIR SOURCE_SUBDIR STAMP_DIR STEP_TARGETS STRING SVN_PASSWORD SVN_REPOSITORY SVN_REVISION SVN_TRUST_CERT SVN_USERNAME TEST_AFTER_INSTALL TEST_BEFORE_INSTALL TEST_COMMAND TEST_EXCLUDE_FROM_MAIN TIMEOUT TLS_CAINFO TLS_VERIFY TMP_DIR TRUE UPDATE_COMMAND UPDATE_DISCONNECTED URL URL_HASH USES_TERMINAL_BUILD USES_TERMINAL_CONFIGURE USES_TERMINAL_DOWNLOAD USES_TERMINAL_INSTALL USES_TERMINAL_TEST USES_TERMINAL_UPDATE WORKING_DIRECTORY
+            \ ALGO AWS BINARY_DIR BUILD_ALWAYS BUILD_BYPRODUCTS BUILD_COMMAND BUILD_IN_SOURCE CMAKE_ARGS CMAKE_CACHE_ARGS CMAKE_CACHE_DEFAULT_ARGS CMAKE_TLS_CAINFO CMAKE_TLS_VERIFY COMMENT CONFIGURE_COMMAND CVS CVSROOT CVS_MODULE CVS_REPOSITORY CVS_TAG DEPENDEES DEPENDERS DEPENDS DOWNLOADED_FILE DOWNLOAD_COMMAND DOWNLOAD_DIR DOWNLOAD_NAME DOWNLOAD_NO_EXTRACT DOWNLOAD_NO_PROGRESS EP_BASE EP_INDEPENDENT_STEP_TARGETS EP_PREFIX EP_STEP_TARGETS EP_UPDATE_DISCONNECTED EXCLUDE_FROM_ALL FORCE GIT_CONFIG GIT_PROGRESS GIT_REMOTE_NAME GIT_REPOSITORY GIT_SHALLOW GIT_SUBMODULES GIT_TAG HG_REPOSITORY HG_TAG HTTP_HEADER HTTP_PASSWORD HTTP_USERNAME IGNORED INDEPENDENT_STEP_TARGETS INSTALL_COMMAND INSTALL_DIR JOB_POOLS LIST_SEPARATOR LOG_ LOG_BUILD LOG_CONFIGURE LOG_DOWNLOAD LOG_INSTALL LOG_TEST LOG_UPDATE MAKE_EXE NAMES NETRC NETRC_FILE NOTE NO_DEPENDS OPTIONAL PATCH_COMMAND PREFIX PROPERTY REQUIRED SOURCE_DIR SOURCE_SUBDIR STAMP_DIR STEP_TARGETS STRING SVN_PASSWORD SVN_REPOSITORY SVN_REVISION SVN_TRUST_CERT SVN_USERNAME TEST_AFTER_INSTALL TEST_BEFORE_INSTALL TEST_COMMAND TEST_EXCLUDE_FROM_MAIN TIMEOUT TLS_CAINFO TLS_VERIFY TMP_DIR TRUE UPDATE_COMMAND UPDATE_DISCONNECTED URL URL_HASH USES_TERMINAL_BUILD USES_TERMINAL_CONFIGURE USES_TERMINAL_DOWNLOAD USES_TERMINAL_INSTALL USES_TERMINAL_TEST USES_TERMINAL_UPDATE WORKING_DIRECTORY
 
 syn keyword cmakeKWadd_compile_options contained
             \ COMPILE_OPTIONS
@@ -89,7 +89,7 @@
             \ FATAL_ERROR VERSION
 
 syn keyword cmakeKWcmake_parse_arguments contained
-            \ ARGN CONFIGURATIONS DESTINATION FALSE FAST FILES MY_INSTALL MY_INSTALL_CONFIGURATIONS MY_INSTALL_DESTINATION MY_INSTALL_FAST MY_INSTALL_OPTIONAL MY_INSTALL_RENAME MY_INSTALL_TARGETS MY_INSTALL_UNPARSED_ARGUMENTS OPTIONAL PARSE_ARGV RENAME TARGETS TRUE _UNPARSED_ARGUMENTS
+            \ ARGN CONFIGURATIONS DESTINATION FALSE FAST FILES MY_INSTALL MY_INSTALL_CONFIGURATIONS MY_INSTALL_DESTINATION MY_INSTALL_FAST MY_INSTALL_OPTIONAL MY_INSTALL_RENAME MY_INSTALL_TARGETS MY_INSTALL_UNPARSED_ARGUMENTS OPTIONAL PARSE_ARGV RENAME TARGETS TRUE UNDEFINED _UNPARSED_ARGUMENTS
 
 syn keyword cmakeKWcmake_policy contained
             \ CMAKE_POLICY_DEFAULT_CMP CMP GET NNNN NO_POLICY_SCOPE OLD POP PUSH SET VERSION
@@ -149,7 +149,7 @@
             \ APPEND EXPORT INCLUDE LINK_INTERFACE_LIBRARIES SET
 
 syn keyword cmakeKWfile contained
-            \ ALGO APPEND ASCII CMAKE_TLS_CAINFO CMAKE_TLS_VERIFY CONDITION CONFIG CONTENT COPY CR DESTINATION DIRECTORY_PERMISSIONS DOWNLOAD ENCODING EXCLUDE EXPECTED_HASH FILES_MATCHING FILE_PERMISSIONS FOLLOW_SYMLINKS FUNCTION GENERATE GLOB GLOB_RECURSE GUARD HASH HEX HTTPHEADER INACTIVITY_TIMEOUT INSTALL LENGTH_MAXIMUM LENGTH_MINIMUM LF LIMIT LIMIT_COUNT LIMIT_INPUT LIMIT_OUTPUT LIST_DIRECTORIES LOCK LOG MAKE_DIRECTORY NEWLINE_CONSUME NO_HEX_CONVERSION NO_SOURCE_PERMISSIONS OFFSET OLD PATTERN PROCESS READ REGEX RELATIVE RELATIVE_PATH RELEASE REMOVE REMOVE_RECURSE RENAME RESULT_VARIABLE SHOW_PROGRESS SSL STATUS STRINGS TIMESTAMP TLS_CAINFO TLS_VERIFY TO_CMAKE_PATH TO_NATIVE_PATH UPLOAD USERPWD USE_SOURCE_PERMISSIONS UTC UTF WRITE
+            \ ALGO APPEND ASCII CMAKE_TLS_CAINFO CMAKE_TLS_VERIFY CONDITION CONFIG CONTENT COPY CR DESTINATION DIRECTORY_PERMISSIONS DOWNLOAD ENCODING EXCLUDE EXPECTED_HASH FILES_MATCHING FILE_PERMISSIONS FOLLOW_SYMLINKS FUNCTION GENERATE GLOB GLOB_RECURSE GUARD HASH HEX HTTPHEADER IGNORED INACTIVITY_TIMEOUT INSTALL LENGTH_MAXIMUM LENGTH_MINIMUM LF LIMIT LIMIT_COUNT LIMIT_INPUT LIMIT_OUTPUT LIST_DIRECTORIES LOCK LOG MAKE_DIRECTORY NETRC NETRC_FILE NEWLINE_CONSUME NO_HEX_CONVERSION NO_SOURCE_PERMISSIONS OFFSET OLD OPTIONAL PATTERN PROCESS READ REGEX RELATIVE RELATIVE_PATH RELEASE REMOVE REMOVE_RECURSE RENAME REQUIRED RESULT_VARIABLE SHOW_PROGRESS SSL STATUS STRINGS TIMESTAMP TLS_CAINFO TLS_VERIFY TO_CMAKE_PATH TO_NATIVE_PATH UPLOAD URL USERPWD USE_SOURCE_PERMISSIONS UTC UTF WRITE
 
 syn keyword cmakeKWfind_file contained
             \ CMAKE_FIND_ROOT_PATH_BOTH DOC DVAR HINTS INCLUDE NAMES NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OS PATHS PATH_SUFFIXES VAR
@@ -287,22 +287,22 @@
             \ EXCLUDE_FROM_ALL PREORDER
 
 syn keyword cmakeKWtarget_compile_definitions contained
-            \ COMPILE_DEFINITIONS INTERFACE INTERFACE_COMPILE_DEFINITIONS PRIVATE PUBLIC
+            \ ALIAS COMPILE_DEFINITIONS IMPORTED INTERFACE INTERFACE_COMPILE_DEFINITIONS PRIVATE PUBLIC
 
 syn keyword cmakeKWtarget_compile_features contained
-            \ COMPILE_FEATURES IMPORTED INTERFACE INTERFACE_COMPILE_FEATURES PRIVATE PUBLIC
+            \ ALIAS COMPILE_FEATURES IMPORTED INTERFACE INTERFACE_COMPILE_FEATURES PRIVATE PUBLIC
 
 syn keyword cmakeKWtarget_compile_options contained
-            \ BEFORE COMPILE_OPTIONS IMPORTED INTERFACE INTERFACE_COMPILE_OPTIONS PRIVATE PUBLIC
+            \ ALIAS BEFORE COMPILE_OPTIONS IMPORTED INTERFACE INTERFACE_COMPILE_OPTIONS PRIVATE PUBLIC
 
 syn keyword cmakeKWtarget_include_directories contained
-            \ BEFORE BUILD_INTERFACE IMPORTED INCLUDE_DIRECTORIES INSTALL_INTERFACE INTERFACE INTERFACE_INCLUDE_DIRECTORIES INTERFACE_LINK_LIBRARIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES PRIVATE PUBLIC SYSTEM
+            \ ALIAS BEFORE BUILD_INTERFACE IMPORTED INCLUDE_DIRECTORIES INSTALL_INTERFACE INTERFACE INTERFACE_INCLUDE_DIRECTORIES INTERFACE_LINK_LIBRARIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES PRIVATE PUBLIC SYSTEM
 
 syn keyword cmakeKWtarget_link_libraries contained
             \ ALIAS DAG DEBUG_CONFIGURATIONS IMPORTED IMPORTED_NO_SONAME INTERFACE INTERFACE_LINK_LIBRARIES LINK_FLAGS LINK_INTERFACE_LIBRARIES LINK_INTERFACE_LIBRARIES_DEBUG LINK_INTERFACE_MULTIPLICITY LINK_PRIVATE LINK_PUBLIC OLD OSX PRIVATE PUBLIC STATIC
 
 syn keyword cmakeKWtarget_sources contained
-            \ IMPORTED INTERFACE INTERFACE_SOURCES PRIVATE PUBLIC SOURCES
+            \ ALIAS IMPORTED INTERFACE INTERFACE_SOURCES PRIVATE PUBLIC SOURCES
 
 syn keyword cmakeKWtry_compile contained
             \ ALL_BUILD CMAKE_FLAGS COMPILE_DEFINITIONS COPY_FILE COPY_FILE_ERROR CUDA_EXTENSIONS CUDA_STANDARD CUDA_STANDARD_REQUIRED CXX_EXTENSIONS CXX_STANDARD CXX_STANDARD_REQUIRED C_EXTENSIONS C_STANDARD C_STANDARD_REQUIRED DEFINED DLINK_LIBRARIES DVAR FALSE INCLUDE_DIRECTORIES LANG LINK_DIRECTORIES LINK_LIBRARIES NOT OUTPUT_VARIABLE RESULT_VAR SOURCES TRUE TYPE VALUE _EXTENSIONS _STANDARD _STANDARD_REQUIRED
@@ -474,4 +474,4 @@
 let &cpo = s:keepcpo
 unlet s:keepcpo
 
-"EOF"
+" vim: set nowrap:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f14f62f..bf0c4d1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -267,7 +267,7 @@
     message(FATAL_ERROR "CMake_RUN_IWYU is ON but include-what-you-use is not found!")
   endif()
   set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE
-    "${IWYU_COMMAND};-Xiwyu;--mapping_file=${CMake_SOURCE_DIR}/Utilities/IWYU/mapping.imp")
+    "${IWYU_COMMAND};-Xiwyu;--mapping_file=${CMake_SOURCE_DIR}/Utilities/IWYU/mapping.imp;-w")
 endif()
 
 
diff --git a/Help/command/add_executable.rst b/Help/command/add_executable.rst
index c088796..c7a30d7 100644
--- a/Help/command/add_executable.rst
+++ b/Help/command/add_executable.rst
@@ -7,14 +7,15 @@
 
   add_executable(<name> [WIN32] [MACOSX_BUNDLE]
                  [EXCLUDE_FROM_ALL]
-                 source1 [source2 ...])
+                 [source1] [source2 ...])
 
 Adds an executable target called ``<name>`` to be built from the source
-files listed in the command invocation.  The ``<name>`` corresponds to the
-logical target name and must be globally unique within a project.  The
-actual file name of the executable built is constructed based on
-conventions of the native platform (such as ``<name>.exe`` or just
-``<name>``).
+files listed in the command invocation.  (The source files can be omitted
+here if they are added later using :command:`target_sources`.)  The
+``<name>`` corresponds to the logical target name and must be globally
+unique within a project.  The actual file name of the executable built is
+constructed based on conventions of the native platform (such as
+``<name>.exe`` or just ``<name>``).
 
 By default the executable file will be created in the build tree
 directory corresponding to the source tree directory in which the
@@ -73,8 +74,9 @@
 Creates an :ref:`Alias Target <Alias Targets>`, such that ``<name>`` can
 be used to refer to ``<target>`` in subsequent commands.  The ``<name>``
 does not appear in the generated buildsystem as a make target.  The
-``<target>`` may not be an :ref:`Imported Target <Imported Targets>` or an
-``ALIAS``.  ``ALIAS`` targets can be used as targets to read properties
+``<target>`` may not be a non-``GLOBAL``
+:ref:`Imported Target <Imported Targets>` or an ``ALIAS``.
+``ALIAS`` targets can be used as targets to read properties
 from, executables for custom commands and custom targets.  They can also be
 tested for existence with the regular :command:`if(TARGET)` subcommand.
 The ``<name>`` may not be used to modify properties of ``<target>``, that
diff --git a/Help/command/add_library.rst b/Help/command/add_library.rst
index de5335e..4e85d8c 100644
--- a/Help/command/add_library.rst
+++ b/Help/command/add_library.rst
@@ -14,13 +14,14 @@
 
   add_library(<name> [STATIC | SHARED | MODULE]
               [EXCLUDE_FROM_ALL]
-              source1 [source2 ...])
+              [source1] [source2 ...])
 
 Adds a library target called ``<name>`` to be built from the source files
-listed in the command invocation.  The ``<name>`` corresponds to the
-logical target name and must be globally unique within a project.  The
-actual file name of the library built is constructed based on
-conventions of the native platform (such as ``lib<name>.a`` or
+listed in the command invocation.  (The source files can be omitted here
+if they are added later using :command:`target_sources`.)  The ``<name>``
+corresponds to the logical target name and must be globally unique within
+a project.  The actual file name of the library built is constructed based
+on conventions of the native platform (such as ``lib<name>.a`` or
 ``<name>.lib``).
 
 ``STATIC``, ``SHARED``, or ``MODULE`` may be given to specify the type of
@@ -124,7 +125,8 @@
 Creates an :ref:`Alias Target <Alias Targets>`, such that ``<name>`` can be
 used to refer to ``<target>`` in subsequent commands.  The ``<name>`` does
 not appear in the generated buildsystem as a make target.  The ``<target>``
-may not be an :ref:`Imported Target <Imported Targets>` or an ``ALIAS``.
+may not be a non-``GLOBAL`` :ref:`Imported Target <Imported Targets>` or an
+``ALIAS``.
 ``ALIAS`` targets can be used as linkable targets and as targets to
 read properties from.  They can also be tested for existence with the
 regular :command:`if(TARGET)` subcommand.  The ``<name>`` may not be used
diff --git a/Help/command/add_subdirectory.rst b/Help/command/add_subdirectory.rst
index e979253..012ded4 100644
--- a/Help/command/add_subdirectory.rst
+++ b/Help/command/add_subdirectory.rst
@@ -30,7 +30,7 @@
 Typically the subdirectory should contain its own :command:`project`
 command invocation so that a full build system will be generated in the
 subdirectory (such as a VS IDE solution file).  Note that inter-target
-dependencies supercede this exclusion.  If a target built by the
+dependencies supersede this exclusion.  If a target built by the
 parent project depends on a target in the subdirectory, the dependee
 target will be included in the parent project build system to satisfy
 the dependency.
diff --git a/Help/command/enable_language.rst b/Help/command/enable_language.rst
index 4445561..871ac4e 100644
--- a/Help/command/enable_language.rst
+++ b/Help/command/enable_language.rst
@@ -19,4 +19,5 @@
 needed languages in the top-level directory of a project.
 
 The ``OPTIONAL`` keyword is a placeholder for future implementation and
-does not currently work.
+does not currently work. Instead you can use the :module:`CheckLanguage`
+module to verify support before enabling.
diff --git a/Help/command/file.rst b/Help/command/file.rst
index edccac5..5ce86e5 100644
--- a/Help/command/file.rst
+++ b/Help/command/file.rst
@@ -110,7 +110,7 @@
 specified, the results will be returned as relative paths to the given
 path.  The results will be ordered lexicographically.
 
-By default ``GLOB`` lists directories - directories are omited in result if
+By default ``GLOB`` lists directories - directories are omitted in result if
 ``LIST_DIRECTORIES`` is set to false.
 
 .. note::
@@ -232,6 +232,31 @@
 ``HTTPHEADER <HTTP-header>``
   HTTP header for operation. Suboption can be repeated several times.
 
+``NETRC <level>``
+  Specify whether the .netrc file is to be used for operation.  If this
+  option is not specified, the value of the ``CMAKE_NETRC`` variable
+  will be used instead.
+  Valid levels are:
+
+  ``IGNORED``
+    The .netrc file is ignored.
+    This is the default.
+  ``OPTIONAL``
+    The .netrc file is optional, and information in the URL is preferred.
+    The file will be scanned to find which ever information is not specified
+    in the URL.
+  ``REQUIRED``
+    The .netrc file is required, and information in the URL is ignored.
+
+``NETRC_FILE <file>``
+  Specify an alternative .netrc file to the one in your home directory,
+  if the ``NETRC`` level is ``OPTIONAL`` or ``REQUIRED``. If this option
+  is not specified, the value of the ``CMAKE_NETRC_FILE`` variable will
+  be used instead.
+
+If neither ``NETRC`` option is given CMake will check variables
+``CMAKE_NETRC`` and ``CMAKE_NETRC_FILE``, respectively.
+
 Additional options to ``DOWNLOAD`` are:
 
 ``EXPECTED_HASH ALGO=<value>``
diff --git a/Help/command/install.rst b/Help/command/install.rst
index 58438b7..9f9ee13 100644
--- a/Help/command/install.rst
+++ b/Help/command/install.rst
@@ -346,7 +346,7 @@
 included in the export but a target to which it links is not included
 the behavior is unspecified.
 
-In additon to cmake language files, the ``EXPORT_ANDROID_MK`` option maybe
+In addition to cmake language files, the ``EXPORT_ANDROID_MK`` option maybe
 used to specifiy an export to the android ndk build system.  The Android
 NDK supports the use of prebuilt libraries, both static and shared. This
 allows cmake to build the libraries of a project and make them available
diff --git a/Help/command/target_compile_definitions.rst b/Help/command/target_compile_definitions.rst
index 8bd3233..3709e7a 100644
--- a/Help/command/target_compile_definitions.rst
+++ b/Help/command/target_compile_definitions.rst
@@ -12,14 +12,15 @@
 Specify compile definitions to use when compiling a given ``<target>``.  The
 named ``<target>`` must have been created by a command such as
 :command:`add_executable` or :command:`add_library` and must not be an
-:ref:`Imported Target <Imported Targets>`.
+:ref:`ALIAS target <Alias Targets>`.
 
 The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
 specify the scope of the following arguments.  ``PRIVATE`` and ``PUBLIC``
 items will populate the :prop_tgt:`COMPILE_DEFINITIONS` property of
 ``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the
-:prop_tgt:`INTERFACE_COMPILE_DEFINITIONS` property of ``<target>``.  The
-following arguments specify compile definitions.  Repeated calls for the
+:prop_tgt:`INTERFACE_COMPILE_DEFINITIONS` property of ``<target>``.
+(:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items.)
+The following arguments specify compile definitions.  Repeated calls for the
 same ``<target>`` append items in the order called.
 
 Arguments to ``target_compile_definitions`` may use "generator expressions"
diff --git a/Help/command/target_compile_features.rst b/Help/command/target_compile_features.rst
index b66a4ec..bf413bf 100644
--- a/Help/command/target_compile_features.rst
+++ b/Help/command/target_compile_features.rst
@@ -18,12 +18,13 @@
 specify the scope of the features.  ``PRIVATE`` and ``PUBLIC`` items will
 populate the :prop_tgt:`COMPILE_FEATURES` property of ``<target>``.
 ``PUBLIC`` and ``INTERFACE`` items will populate the
-:prop_tgt:`INTERFACE_COMPILE_FEATURES` property of ``<target>``.  Repeated
-calls for the same ``<target>`` append items.
+:prop_tgt:`INTERFACE_COMPILE_FEATURES` property of ``<target>``.
+(:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items.)
+Repeated calls for the same ``<target>`` append items.
 
 The named ``<target>`` must have been created by a command such as
-:command:`add_executable` or :command:`add_library` and must not be
-an ``IMPORTED`` target.
+:command:`add_executable` or :command:`add_library` and must not be an
+:ref:`ALIAS target <Alias Targets>`.
 
 Arguments to ``target_compile_features`` may use "generator expressions"
 with the syntax ``$<...>``.
diff --git a/Help/command/target_compile_options.rst b/Help/command/target_compile_options.rst
index 73e01e7..3e7dc47 100644
--- a/Help/command/target_compile_options.rst
+++ b/Help/command/target_compile_options.rst
@@ -12,8 +12,10 @@
 Specify compile options to use when compiling a given target.  The
 named ``<target>`` must have been created by a command such as
 :command:`add_executable` or :command:`add_library` and must not be an
-:ref:`IMPORTED Target <Imported Targets>`.  If ``BEFORE`` is specified,
-the content will be prepended to the property instead of being appended.
+:ref:`ALIAS target <Alias Targets>`.
+
+If ``BEFORE`` is specified, the content will be prepended to the property
+instead of being appended.
 
 This command can be used to add any options, but
 alternative commands exist to add preprocessor definitions
@@ -27,8 +29,9 @@
 specify the scope of the following arguments.  ``PRIVATE`` and ``PUBLIC``
 items will populate the :prop_tgt:`COMPILE_OPTIONS` property of
 ``<target>``.  ``PUBLIC`` and ``INTERFACE`` items will populate the
-:prop_tgt:`INTERFACE_COMPILE_OPTIONS` property of ``<target>``.  The
-following arguments specify compile options.  Repeated calls for the same
+:prop_tgt:`INTERFACE_COMPILE_OPTIONS` property of ``<target>``.
+(:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items.)
+The following arguments specify compile options.  Repeated calls for the same
 ``<target>`` append items in the order called.
 
 Arguments to ``target_compile_options`` may use "generator expressions"
diff --git a/Help/command/target_include_directories.rst b/Help/command/target_include_directories.rst
index 30ec2cb..e71be64 100644
--- a/Help/command/target_include_directories.rst
+++ b/Help/command/target_include_directories.rst
@@ -12,7 +12,7 @@
 Specify include directories to use when compiling a given target.
 The named ``<target>`` must have been created by a command such
 as :command:`add_executable` or :command:`add_library` and must not be an
-:prop_tgt:`IMPORTED` target.
+:ref:`ALIAS target <Alias Targets>`.
 
 If ``BEFORE`` is specified, the content will be prepended to the property
 instead of being appended.
@@ -21,9 +21,9 @@
 the scope of the following arguments.  ``PRIVATE`` and ``PUBLIC`` items will
 populate the :prop_tgt:`INCLUDE_DIRECTORIES` property of ``<target>``.
 ``PUBLIC`` and ``INTERFACE`` items will populate the
-:prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES`
-property of ``<target>``.  The following arguments specify include
-directories.
+:prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` property of ``<target>``.
+(:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items.)
+The following arguments specify include directories.
 
 Specified include directories may be absolute paths or relative paths.
 Repeated calls for the same <target> append items in the order called.  If
diff --git a/Help/command/target_link_libraries.rst b/Help/command/target_link_libraries.rst
index 30d69f2..2ec8744 100644
--- a/Help/command/target_link_libraries.rst
+++ b/Help/command/target_link_libraries.rst
@@ -19,7 +19,8 @@
   target_link_libraries(<target> ... <item>... ...)
 
 The named ``<target>`` must have been created in the current directory by
-a command such as :command:`add_executable` or :command:`add_library`.
+a command such as :command:`add_executable` or :command:`add_library` and
+must not be an :ref:`ALIAS target <Alias Targets>`.
 Repeated calls for the same ``<target>`` append items in the order called.
 Each ``<item>`` may be:
 
diff --git a/Help/command/target_sources.rst b/Help/command/target_sources.rst
index d6f148d..a4f5196 100644
--- a/Help/command/target_sources.rst
+++ b/Help/command/target_sources.rst
@@ -12,14 +12,15 @@
 Specify sources to use when compiling a given target.  The
 named ``<target>`` must have been created by a command such as
 :command:`add_executable` or :command:`add_library` and must not be an
-:ref:`IMPORTED Target <Imported Targets>`.
+:ref:`ALIAS target <Alias Targets>`.
 
 The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
 specify the scope of the following arguments.  ``PRIVATE`` and ``PUBLIC``
 items will populate the :prop_tgt:`SOURCES` property of
 ``<target>``.  ``PUBLIC`` and ``INTERFACE`` items will populate the
-:prop_tgt:`INTERFACE_SOURCES` property of ``<target>``.  The
-following arguments specify sources.  Repeated calls for the same
+:prop_tgt:`INTERFACE_SOURCES` property of ``<target>``.
+(:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items.)
+The following arguments specify sources.  Repeated calls for the same
 ``<target>`` append items in the order called.
 
 Arguments to ``target_sources`` may use "generator expressions"
diff --git a/Help/dev/testing.rst b/Help/dev/testing.rst
index 731930c..1b29acf 100644
--- a/Help/dev/testing.rst
+++ b/Help/dev/testing.rst
@@ -16,7 +16,7 @@
 platforms working.
 
 The `CMake Dashboard Scripts Repository`_ provides CTest scripts to drive
-nightly, continous, and experimental testing of CMake.  Use the following
+nightly, continuous, and experimental testing of CMake.  Use the following
 commands to set up a new integration testing client:
 
 .. code-block:: console
diff --git a/Help/generator/Visual Studio 15 2017.rst b/Help/generator/Visual Studio 15 2017.rst
index 2ac0449..2cf1aa0 100644
--- a/Help/generator/Visual Studio 15 2017.rst
+++ b/Help/generator/Visual Studio 15 2017.rst
@@ -19,13 +19,17 @@
 ^^^^^^^^^^^^^^^^^^
 
 VS 2017 supports multiple installations on the same machine.
-CMake queries the Visual Studio Installer to locate VS instances.
-If more than one instance is installed we do not define which one
-is chosen by default.  If the ``VS150COMNTOOLS`` environment variable
-is set and points to the ``Common7/Tools`` directory within one of
-the instances, that instance will be used.  The environment variable
-must remain consistently set whenever CMake is re-run within a given
-build tree.
+The :variable:`CMAKE_GENERATOR_INSTANCE` variable may be set as a
+cache entry containing the absolute path to a Visual Studio instance.
+If the value is not specified explicitly by the user or a toolchain file,
+CMake queries the Visual Studio Installer to locate VS instances, chooses
+one, and sets the variable as a cache entry to hold the value persistently.
+
+When CMake first chooses an instance, if the ``VS150COMNTOOLS`` environment
+variable is set and points to the ``Common7/Tools`` directory within
+one of the instances, that instance will be used.  Otherwise, if more
+than one instance is installed we do not define which one is chosen
+by default.
 
 Toolset Selection
 ^^^^^^^^^^^^^^^^^
diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst
index 8f4b252..9fd92ec 100644
--- a/Help/manual/cmake-modules.7.rst
+++ b/Help/manual/cmake-modules.7.rst
@@ -80,6 +80,7 @@
    /module/ExternalData
    /module/ExternalProject
    /module/FeatureSummary
+   /module/FetchContent
    /module/FindALSA
    /module/FindArmadillo
    /module/FindASPELL
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index c81ba59..96d5c7d 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -51,6 +51,14 @@
 to determine whether to report an error on use of deprecated macros or
 functions.
 
+Policies Introduced by CMake 3.11
+=================================
+
+.. toctree::
+   :maxdepth: 1
+
+   CMP0072: FindOpenGL prefers GLVND by default when available. </policy/CMP0072>
+
 Policies Introduced by CMake 3.10
 =================================
 
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index dd59a00..2c63c4b 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -184,6 +184,7 @@
    /prop_tgt/HAS_CXX
    /prop_tgt/IMPLICIT_DEPENDS_INCLUDE_TRANSFORM
    /prop_tgt/IMPORTED_CONFIGURATIONS
+   /prop_tgt/IMPORTED_GLOBAL
    /prop_tgt/IMPORTED_IMPLIB_CONFIG
    /prop_tgt/IMPORTED_IMPLIB
    /prop_tgt/IMPORTED_LIBNAME_CONFIG
@@ -390,6 +391,8 @@
    /prop_sf/VS_DEPLOYMENT_LOCATION
    /prop_sf/VS_INCLUDE_IN_VSIX
    /prop_sf/VS_RESOURCE_GENERATOR
+   /prop_sf/VS_SHADER_DISABLE_OPTIMIZATIONS
+   /prop_sf/VS_SHADER_ENABLE_DEBUG
    /prop_sf/VS_SHADER_ENTRYPOINT
    /prop_sf/VS_SHADER_FLAGS
    /prop_sf/VS_SHADER_MODEL
diff --git a/Help/manual/cmake-server.7.rst b/Help/manual/cmake-server.7.rst
index c56e5a7..ee8fada 100644
--- a/Help/manual/cmake-server.7.rst
+++ b/Help/manual/cmake-server.7.rst
@@ -458,6 +458,11 @@
 
 "name"
   contains the (sub-)projects name.
+"minimumCMakeVersion"
+  contains the minimum cmake version allowed for this project, null if the
+  project doesn't specify one.
+"hasInstallRule"
+  true if the project contains any install rules, false otherwise.
 "sourceDirectory"
   contains the current source directory
 "buildDirectory"
@@ -481,6 +486,10 @@
   contains the current source directory.
 "buildDirectory"
   contains the current build directory.
+"hasInstallRule"
+  true if the target contains any install rules, false otherwise.
+"installPaths"
+  full path to the destination directories defined by target install rules.
 "artifacts"
   with a list of build artifacts. The list is sorted with the most
   important artifacts first (e.g. a .DLL file is listed before a
@@ -622,6 +631,79 @@
   ]== "CMake Server" ==]
 
 
+Type "ctestInfo"
+^^^^^^^^^^^^^^^^
+
+The "ctestInfo" request can be used after a project was "compute"d successfully.
+
+It will list the complete project test structure as it is known to cmake.
+
+The reply will contain a key "configurations", which will contain a list of
+configuration objects. Configuration objects are used to destinquish between
+different configurations the build directory might have enabled. While most
+generators only support one configuration, others might support several.
+
+Each configuration object can have the following keys:
+
+"name"
+  contains the name of the configuration. The name may be empty.
+"projects"
+  contains a list of project objects, one for each build project.
+
+Project objects define one (sub-)project defined in the cmake build system.
+
+Each project object can have the following keys:
+
+"name"
+  contains the (sub-)projects name.
+"targets"
+  contains a list of build system target objects.
+
+Target objects define individual build targets for a certain configuration.
+
+Each target object can have the following keys:
+
+"name"
+  contains the name of the target.
+"type"
+  defines the type of build of the target. Possible values are
+  "STATIC_LIBRARY", "MODULE_LIBRARY", "SHARED_LIBRARY", "OBJECT_LIBRARY",
+  "EXECUTABLE", "UTILITY" and "INTERFACE_LIBRARY".
+"fullName"
+  contains the full name of the build result (incl. extensions, etc.).
+"hasEnabledTests"
+  true if testing is enabled for this target.
+"ctestInfo"
+  contains a list of test objects for this target.
+
+Each test object can have the following keys:
+
+"ctestName"
+  contains the name of the test.
+"ctestCommand"
+  contains the test command.
+"properties"
+  contains a list of test property objects.
+"backtrace"
+  contains a list of backtrace objects that specify where the test was defined.
+
+Each backtrace object can have the following keys:
+
+"path"
+  contains the full path to the file containing the statement.
+"line"
+  contains the line number in the file where the statement was defined.
+"name"
+  contains the name of the statement that added the test.
+
+Each test property object can have the following keys:
+
+"key"
+  contains the test property key.
+"value"
+  contains the test property value.
+
+
 Type "cmakeInputs"
 ^^^^^^^^^^^^^^^^^^
 
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index 2e369e3..0451466 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -42,6 +42,7 @@
    /variable/CMAKE_FIND_PACKAGE_SORT_DIRECTION
    /variable/CMAKE_FIND_PACKAGE_SORT_ORDER
    /variable/CMAKE_GENERATOR
+   /variable/CMAKE_GENERATOR_INSTANCE
    /variable/CMAKE_GENERATOR_PLATFORM
    /variable/CMAKE_GENERATOR_TOOLSET
    /variable/CMAKE_HOME_DIRECTORY
@@ -60,6 +61,8 @@
    /variable/CMAKE_MATCH_n
    /variable/CMAKE_MINIMUM_REQUIRED_VERSION
    /variable/CMAKE_MINOR_VERSION
+   /variable/CMAKE_NETRC
+   /variable/CMAKE_NETRC_FILE
    /variable/CMAKE_PARENT_LIST_FILE
    /variable/CMAKE_PATCH_VERSION
    /variable/CMAKE_PROJECT_DESCRIPTION
@@ -156,6 +159,7 @@
    /variable/CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE
    /variable/CMAKE_INCLUDE_PATH
    /variable/CMAKE_INSTALL_DEFAULT_COMPONENT_NAME
+   /variable/CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
    /variable/CMAKE_INSTALL_MESSAGE
    /variable/CMAKE_INSTALL_PREFIX
    /variable/CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT
@@ -185,6 +189,7 @@
    /variable/CMAKE_USER_MAKE_RULES_OVERRIDE
    /variable/CMAKE_WARN_DEPRECATED
    /variable/CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION
+   /variable/CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY
 
 Variables that Describe the System
 ==================================
@@ -285,6 +290,7 @@
    /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY
    /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG
    /variable/CMAKE_CONFIG_POSTFIX
+   /variable/CMAKE_CUDA_SEPARABLE_COMPILATION
    /variable/CMAKE_DEBUG_POSTFIX
    /variable/CMAKE_ENABLE_EXPORTS
    /variable/CMAKE_EXE_LINKER_FLAGS
@@ -525,6 +531,7 @@
    /variable/CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY
    /variable/CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION
    /variable/CPACK_INCLUDE_TOPLEVEL_DIRECTORY
+   /variable/CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
    /variable/CPACK_INSTALL_SCRIPT
    /variable/CPACK_PACKAGING_INSTALL_PREFIX
    /variable/CPACK_SET_DESTDIR
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index 6a21683..ff8c6c7 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -11,6 +11,7 @@
  cmake [<options>] (<path-to-source> | <path-to-existing-build>)
  cmake [(-D <var>=<value>)...] -P <cmake-script-file>
  cmake --build <dir> [<options>...] [-- <build-tool-options>...]
+ cmake --open <dir>
  cmake -E <command> [<options>...]
  cmake --find-package <options>...
 
@@ -51,6 +52,10 @@
 ``--build <dir>``
  See `Build Tool Mode`_.
 
+``--open <dir>``
+ Open the generated project in the associated application.  This is
+ only supported by some generators.
+
 ``-N``
  View mode only.
 
diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst
index 423f1ca..d9af3bc 100644
--- a/Help/manual/ctest.1.rst
+++ b/Help/manual/ctest.1.rst
@@ -3,12 +3,18 @@
 ctest(1)
 ********
 
+.. contents::
+
 Synopsis
 ========
 
 .. parsed-literal::
 
  ctest [<options>]
+ ctest <path-to-source> <path-to-build> --build-generator <generator>
+       [<options>...] [-- <build-options>...] [--test-command <test>]
+ ctest (-D <dashboard> | -M <model> -T <action> | -S <script> | -SP <script>)
+       [-- <dashboard-options>...]
 
 Description
 ===========
@@ -55,17 +61,21 @@
 ``-F``
  Enable failover.
 
- This option allows ctest to resume a test set execution that was
+ This option allows CTest to resume a test set execution that was
  previously interrupted.  If no interruption occurred, the ``-F`` option
  will have no effect.
 
 ``-j <jobs>, --parallel <jobs>``
  Run the tests in parallel using the given number of jobs.
 
- This option tells ctest to run the tests in parallel using given
- number of jobs.  This option can also be set by setting the
+ This option tells CTest to run the tests in parallel using given
+ number of jobs. This option can also be set by setting the
  environment variable ``CTEST_PARALLEL_LEVEL``.
 
+ This option can be used with the :prop_test:`PROCESSORS` test property.
+
+ See `Label and Subproject Summary`_.
+
 ``--test-load <level>``
  While running tests in parallel (e.g. with ``-j``), try not to start
  tests when they may cause the CPU load to pass above a given threshold.
@@ -74,7 +84,7 @@
  ``TestLoad`` option of the `CTest Test Step`_.
 
 ``-Q,--quiet``
- Make ctest quiet.
+ Make CTest quiet.
 
  This option will suppress all the output.  The output log file will
  still be generated if the ``--output-log`` is specified.  Options such
@@ -84,37 +94,37 @@
 ``-O <file>, --output-log <file>``
  Output to log file.
 
- This option tells ctest to write all its output to a log file.
+ This option tells CTest to write all its output to a log file.
 
 ``-N,--show-only``
  Disable actual execution of tests.
 
- This option tells ctest to list the tests that would be run but not
+ This option tells CTest to list the tests that would be run but not
  actually run them.  Useful in conjunction with the ``-R`` and ``-E``
  options.
 
 ``-L <regex>, --label-regex <regex>``
  Run tests with labels matching regular expression.
 
- This option tells ctest to run only the tests whose labels match the
+ This option tells CTest to run only the tests whose labels match the
  given regular expression.
 
 ``-R <regex>, --tests-regex <regex>``
  Run tests matching regular expression.
 
- This option tells ctest to run only the tests whose names match the
+ This option tells CTest to run only the tests whose names match the
  given regular expression.
 
 ``-E <regex>, --exclude-regex <regex>``
  Exclude tests matching regular expression.
 
- This option tells ctest to NOT run the tests whose names match the
+ This option tells CTest to NOT run the tests whose names match the
  given regular expression.
 
 ``-LE <regex>, --label-exclude <regex>``
  Exclude tests with labels matching regular expression.
 
- This option tells ctest to NOT run the tests whose labels match the
+ This option tells CTest to NOT run the tests whose labels match the
  given regular expression.
 
 ``-FA <regex>, --fixture-exclude-any <regex>``
@@ -137,11 +147,13 @@
 ``-D <dashboard>, --dashboard <dashboard>``
  Execute dashboard test.
 
- This option tells ctest to act as a CDash client and perform a
+ This option tells CTest to act as a CDash client and perform a
  dashboard test.  All tests are <Mode><Test>, where Mode can be
  Experimental, Nightly, and Continuous, and Test can be Start,
  Update, Configure, Build, Test, Coverage, and Submit.
 
+ See `Dashboard Client`_.
+
 ``-D <var>:<type>=<value>``
  Define a variable for script mode.
 
@@ -153,35 +165,33 @@
 ``-M <model>, --test-model <model>``
  Sets the model for a dashboard.
 
- This option tells ctest to act as a CDash client where the ``<model>``
+ This option tells CTest to act as a CDash client where the ``<model>``
  can be ``Experimental``, ``Nightly``, and ``Continuous``.
  Combining ``-M`` and ``-T`` is similar to ``-D``.
 
+ See `Dashboard Client`_.
+
 ``-T <action>, --test-action <action>``
  Sets the dashboard action to perform.
 
- This option tells ctest to act as a CDash client and perform some
+ This option tells CTest to act as a CDash client and perform some
  action such as ``start``, ``build``, ``test`` etc. See
  `Dashboard Client Steps`_ for the full list of actions.
  Combining ``-M`` and ``-T`` is similar to ``-D``.
 
-``--track <track>``
- Specify the track to submit dashboard to
-
- Submit dashboard to specified track instead of default one.  By
- default, the dashboard is submitted to Nightly, Experimental, or
- Continuous track, but by specifying this option, the track can be
- arbitrary.
+ See `Dashboard Client`_.
 
 ``-S <script>, --script <script>``
  Execute a dashboard for a configuration.
 
- This option tells ctest to load in a configuration script which sets
+ This option tells CTest to load in a configuration script which sets
  a number of parameters such as the binary and source directories.
- Then ctest will do what is required to create and run a dashboard.
+ Then CTest will do what is required to create and run a dashboard.
  This option basically sets up a dashboard and then runs ``ctest -D``
  with the appropriate options.
 
+ See `Dashboard Client`_.
+
 ``-SP <script>, --script-new-process <script>``
  Execute a dashboard for a configuration.
 
@@ -190,16 +200,12 @@
  script may modify the environment and you do not want the modified
  environment to impact other ``-S`` scripts.
 
-``-A <file>, --add-notes <file>``
- Add a notes file with submission.
-
- This option tells ctest to include a notes file when submitting
- dashboard.
+ See `Dashboard Client`_.
 
 ``-I [Start,End,Stride,test#,test#|Test file], --tests-information``
  Run a specific number of tests by number.
 
- This option causes ctest to run tests starting at number Start,
+ This option causes CTest to run tests starting at number Start,
  ending at number End, and incrementing by Stride.  Any additional
  numbers after Stride are considered individual test numbers.  Start,
  End,or stride can be empty.  Optionally a file can be given that
@@ -214,11 +220,11 @@
 ``--rerun-failed``
  Run only the tests that failed previously.
 
- This option tells ctest to perform only the tests that failed during
- its previous run.  When this option is specified, ctest ignores all
+ This option tells CTest to perform only the tests that failed during
+ its previous run.  When this option is specified, CTest ignores all
  other options intended to modify the list of tests to run (``-L``, ``-R``,
  ``-E``, ``-LE``, ``-I``, etc).  In the event that CTest runs and no tests
- fail, subsequent calls to ctest with the ``--rerun-failed`` option will run
+ fail, subsequent calls to CTest with the ``--rerun-failed`` option will run
  the set of tests that most recently failed (if any).
 
 ``--repeat-until-fail <n>``
@@ -236,7 +242,7 @@
 ``--interactive-debug-mode [0|1]``
  Set the interactive mode to 0 or 1.
 
- This option causes ctest to run tests in either an interactive mode
+ This option causes CTest to run tests in either an interactive mode
  or a non-interactive mode.  On Windows this means that in
  non-interactive mode, all system debug pop up windows are blocked.
  In dashboard mode (Experimental, Nightly, Continuous), the default
@@ -246,36 +252,111 @@
 ``--no-label-summary``
  Disable timing summary information for labels.
 
- This option tells ctest not to print summary information for each
+ This option tells CTest not to print summary information for each
  label associated with the tests run.  If there are no labels on the
  tests, nothing extra is printed.
 
- ``--no-subproject-summary``
+ See `Label and Subproject Summary`_.
+
+``--no-subproject-summary``
  Disable timing summary information for subprojects.
 
- This option tells ctest not to print summary information for each
+ This option tells CTest not to print summary information for each
  subproject associated with the tests run.  If there are no subprojects on the
  tests, nothing extra is printed.
 
-``--build-and-test <path-to-source> <path-to-build>``
- Configure, build and run a test.
+ See `Label and Subproject Summary`_.
 
- This option tells ctest to configure (i.e.  run cmake on), build,
- and or execute a test.  The configure and test steps are optional.
- The arguments to this command line are the source and binary
- directories.
- The ``--build-generator`` option *must* be provided to use
- ``--build-and-test``.  If ``--test-command`` is specified then that will be
- run after the build is complete.  Other options that affect this
- mode are ``--build-target``, ``--build-nocmake``, ``--build-run-dir``,
- ``--build-two-config``, ``--build-exe-dir``,
- ``--build-project``, ``--build-noclean`` and ``--build-options``.
+``--build-and-test``
+See `Build and Test Mode`_.
+
+``--test-output-size-passed <size>``
+ Limit the output for passed tests to ``<size>`` bytes.
+
+``--test-output-size-failed <size>``
+ Limit the output for failed tests to ``<size>`` bytes.
+
+``--overwrite``
+ Overwrite CTest configuration option.
+
+ By default CTest uses configuration options from configuration file.
+ This option will overwrite the configuration option.
+
+``--force-new-ctest-process``
+ Run child CTest instances as new processes.
+
+ By default CTest will run child CTest instances within the same
+ process.  If this behavior is not desired, this argument will
+ enforce new processes for child CTest processes.
+
+``--schedule-random``
+ Use a random order for scheduling tests.
+
+ This option will run the tests in a random order.  It is commonly
+ used to detect implicit dependencies in a test suite.
+
+``--submit-index``
+ Legacy option for old Dart2 dashboard server feature.
+ Do not use.
+
+``--timeout <seconds>``
+ Set a global timeout on all tests.
+
+ This option will set a global timeout on all tests that do not
+ already have a timeout set on them.
+
+``--stop-time <time>``
+ Set a time at which all tests should stop running.
+
+ Set a real time of day at which all tests should timeout.  Example:
+ ``7:00:00 -0400``.  Any time format understood by the curl date parser
+ is accepted.  Local time is assumed if no timezone is specified.
+
+``--print-labels``
+ Print all available test labels.
+
+ This option will not run any tests, it will simply print the list of
+ all labels associated with the test set.
+
+.. include:: OPTIONS_HELP.txt
+
+.. _`Label and Subproject Summary`:
+
+Label and Subproject Summary
+============================
+
+CTest prints timing summary information for each label and subproject
+associated with the tests run. The label time summary will not include labels
+that are mapped to subprojects.
+
+When the :prop_test:`PROCESSORS` test property is set, CTest will display a
+weighted test timing result in label and subproject summaries. The wall clock
+time for the test run will be multiplied by this property to give a better
+idea of how much cpu resource CTest allocated for the test. The time is
+reported with `sec*proc` instead of just `sec`.
+
+.. _`Build and Test Mode`:
+
+Build and Test Mode
+===================
+
+CTest provides a command-line signature to to configure (i.e.  run cmake on),
+build, and or execute a test::
+
+  ctest --build-and-test <path-to-source> <path-to-build>
+        --build-generator <generator> [<options>...] [-- <build-options>...]
+        [--test-command <test>]
+
+The configure and test steps are optional. The arguments to this command line
+are the source and binary directories. The ``--build-generator`` option *must*
+be provided to use ``--build-and-test``.  If ``--test-command`` is specified
+then that will be run after the build is complete.  Other options that affect
+this mode include:
 
 ``--build-target``
  Specify a specific target to build.
 
- This option goes with the ``--build-and-test`` option, if left out the
- ``all`` target is built.
+ If left out the ``all`` target is built.
 
 ``--build-nocmake``
  Run the build without running cmake first.
@@ -324,68 +405,48 @@
 ``--test-command``
  The test to run with the ``--build-and-test`` option.
 
-``--test-output-size-passed <size>``
- Limit the output for passed tests to ``<size>`` bytes.
-
-``--test-output-size-failed <size>``
- Limit the output for failed tests to ``<size>`` bytes.
-
 ``--test-timeout``
- The time limit in seconds, internal use only.
+ The time limit in seconds
+
+.. _`Dashboard Client`:
+
+Dashboard Client
+================
+
+CTest can operate as a client for the `CDash`_ software quality dashboard
+application.  As a dashboard client, CTest performs a sequence of steps
+to configure, build, and test software, and then submits the results to
+a `CDash`_ server. The command-line signature used to submit to `CDash`_ is::
+
+  ctest (-D <dashboard> | -M <model> -T <action> | -S <script> | -SP <script>)
+        [-- <dashboard-options>...]
+
+Options for Dashboard Client include:
+
+``--track <track>``
+ Specify the track to submit dashboard to
+
+ Submit dashboard to specified track instead of default one.  By
+ default, the dashboard is submitted to Nightly, Experimental, or
+ Continuous track, but by specifying this option, the track can be
+ arbitrary.
+
+``-A <file>, --add-notes <file>``
+ Add a notes file with submission.
+
+ This option tells CTest to include a notes file when submitting
+ dashboard.
 
 ``--tomorrow-tag``
  Nightly or experimental starts with next day tag.
 
  This is useful if the build will not finish in one day.
 
-``--ctest-config``
- The configuration file used to initialize CTest state when submitting dashboards.
-
- This option tells CTest to use different initialization file instead
- of CTestConfiguration.tcl.  This way multiple initialization files
- can be used for example to submit to multiple dashboards.
-
-``--overwrite``
- Overwrite CTest configuration option.
-
- By default ctest uses configuration options from configuration file.
- This option will overwrite the configuration option.
-
 ``--extra-submit <file>[;<file>]``
  Submit extra files to the dashboard.
 
  This option will submit extra files to the dashboard.
 
-``--force-new-ctest-process``
- Run child CTest instances as new processes.
-
- By default CTest will run child CTest instances within the same
- process.  If this behavior is not desired, this argument will
- enforce new processes for child CTest processes.
-
-``--schedule-random``
- Use a random order for scheduling tests.
-
- This option will run the tests in a random order.  It is commonly
- used to detect implicit dependencies in a test suite.
-
-``--submit-index``
- Legacy option for old Dart2 dashboard server feature.
- Do not use.
-
-``--timeout <seconds>``
- Set a global timeout on all tests.
-
- This option will set a global timeout on all tests that do not
- already have a timeout set on them.
-
-``--stop-time <time>``
- Set a time at which all tests should stop running.
-
- Set a real time of day at which all tests should timeout.  Example:
- ``7:00:00 -0400``.  Any time format understood by the curl date parser
- is accepted.  Local time is assumed if no timezone is specified.
-
 ``--http1.0``
  Submit using HTTP 1.0.
 
@@ -399,26 +460,6 @@
  this to maintain compatibility with an older version of CDash which
  doesn't support compressed test output.
 
-``--print-labels``
- Print all available test labels.
-
- This option will not run any tests, it will simply print the list of
- all labels associated with the test set.
-
-.. include:: OPTIONS_HELP.txt
-
-.. _`Dashboard Client`:
-
-Dashboard Client
-================
-
-CTest can operate as a client for the `CDash`_ software quality dashboard
-application.  As a dashboard client, CTest performs a sequence of steps
-to configure, build, and test software, and then submits the results to
-a `CDash`_ server.
-
-.. _`CDash`: http://cdash.org/
-
 Dashboard Client Steps
 ----------------------
 
@@ -731,7 +772,6 @@
   * `CTest Script`_ variable: :variable:`CTEST_UPDATE_VERSION_ONLY`
 
 
-
 Additional configuration settings include:
 
 ``NightlyStartTime``
@@ -773,6 +813,7 @@
   * `CTest Script`_ variable: :variable:`CTEST_LABELS_FOR_SUBPROJECTS`
   * :module:`CTest` module variable: ``CTEST_LABELS_FOR_SUBPROJECTS``
 
+  See `Label and Subproject Summary`_.
 
 .. _`CTest Build Step`:
 
@@ -804,6 +845,8 @@
   * `CTest Script`_ variable: :variable:`CTEST_LABELS_FOR_SUBPROJECTS`
   * :module:`CTest` module variable: ``CTEST_LABELS_FOR_SUBPROJECTS``
 
+  See `Label and Subproject Summary`_.
+
 ``MakeCommand``
   Command-line to launch the software build process.
   It will be executed in the location specified by the
@@ -847,6 +890,7 @@
   * `CTest Script`_ variable: :variable:`CTEST_LABELS_FOR_SUBPROJECTS`
   * :module:`CTest` module variable: ``CTEST_LABELS_FOR_SUBPROJECTS``
 
+  See `Label and Subproject Summary`_.
 
 ``TestLoad``
   While running tests in parallel (e.g. with ``-j``), try not to start
@@ -1082,3 +1126,5 @@
 ========
 
 .. include:: LINKS.txt
+
+.. _`CDash`: http://cdash.org/
diff --git a/Help/module/FetchContent.rst b/Help/module/FetchContent.rst
new file mode 100644
index 0000000..c130a6d
--- /dev/null
+++ b/Help/module/FetchContent.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/FetchContent.cmake
diff --git a/Help/policy/CMP0037.rst b/Help/policy/CMP0037.rst
index 9f8457c..8041960 100644
--- a/Help/policy/CMP0037.rst
+++ b/Help/policy/CMP0037.rst
@@ -14,7 +14,12 @@
 targets and IMPORTED targets may contain two consequtive colons.
 
 Target names reserved by one or more CMake generators are not allowed.
-Among others these include "all", "help" and "test".
+Among others these include "all", "clean", "help", and "install".
+
+Target names associated with optional features, such as "test" and "package",
+may also be reserved.  CMake 3.10 and below always reserve them.  CMake 3.11
+and above reserve them only when the corresponding feature is enabled
+(e.g. by including the :module:`CTest` or :module:`CPack` modules).
 
 The OLD behavior for this policy is to allow creating targets with
 reserved names or which do not match the validity pattern.
diff --git a/Help/policy/CMP0072.rst b/Help/policy/CMP0072.rst
new file mode 100644
index 0000000..3abbad7
--- /dev/null
+++ b/Help/policy/CMP0072.rst
@@ -0,0 +1,26 @@
+CMP0072
+-------
+
+:module:`FindOpenGL` prefers GLVND by default when available.
+
+The :module:`FindOpenGL` module provides an ``OpenGL::GL`` target and an
+``OPENGL_LIBRARIES`` variable for projects to use for legacy GL interfaces.
+When both a legacy GL library (e.g. ``libGL.so``) and GLVND libraries
+for OpenGL and GLX (e.g. ``libOpenGL.so`` and ``libGLX.so``) are available,
+the module must choose between them.  It documents an ``OpenGL_GL_PREFERENCE``
+variable that can be used to specify an explicit preference.  When no such
+preference is set, the module must choose a default preference.
+
+CMake 3.11 and above prefer to choose GLVND libraries.  This policy provides
+compatibility with projects that expect the legacy GL library to be used.
+
+The ``OLD`` behavior for this policy is to set ``OpenGL_GL_PREFERENCE`` to
+``LEGACY``.  The ``NEW`` behavior for this policy is to set
+``OpenGL_GL_PREFERENCE`` to ``GLVND``.
+
+This policy was introduced in CMake version 3.11.  CMake version
+|release| warns when the policy is not set and uses ``OLD`` behavior.
+Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW``
+explicitly.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/prop_sf/VS_SHADER_DISABLE_OPTIMIZATIONS.rst b/Help/prop_sf/VS_SHADER_DISABLE_OPTIMIZATIONS.rst
new file mode 100644
index 0000000..446dd26
--- /dev/null
+++ b/Help/prop_sf/VS_SHADER_DISABLE_OPTIMIZATIONS.rst
@@ -0,0 +1,6 @@
+VS_SHADER_DISABLE_OPTIMIZATIONS
+-------------------------------
+
+Disable compiler optimizations for an ``.hlsl`` source file.  This adds the
+``-Od`` flag to the command line for the FxCompiler tool.  Specify the value
+``true`` for this property to disable compiler optimizations.
diff --git a/Help/prop_sf/VS_SHADER_ENABLE_DEBUG.rst b/Help/prop_sf/VS_SHADER_ENABLE_DEBUG.rst
new file mode 100644
index 0000000..c0e60a3
--- /dev/null
+++ b/Help/prop_sf/VS_SHADER_ENABLE_DEBUG.rst
@@ -0,0 +1,6 @@
+VS_SHADER_ENABLE_DEBUG
+----------------------
+
+Enable debugging information for an ``.hlsl`` source file.  This adds the
+``-Zi`` flag to the command line for the FxCompiler tool.  Specify the value
+``true`` to generate debugging information for the compiled shader.
diff --git a/Help/prop_tgt/COMPILE_FLAGS.rst b/Help/prop_tgt/COMPILE_FLAGS.rst
index 1a5389e..8fe651b 100644
--- a/Help/prop_tgt/COMPILE_FLAGS.rst
+++ b/Help/prop_tgt/COMPILE_FLAGS.rst
@@ -8,4 +8,4 @@
 to pass additional preprocessor definitions.
 
 This property is deprecated.  Use the :prop_tgt:`COMPILE_OPTIONS`
-property or the command:`target_compile_options` command instead.
+property or the :command:`target_compile_options` command instead.
diff --git a/Help/prop_tgt/CUDA_SEPARABLE_COMPILATION.rst b/Help/prop_tgt/CUDA_SEPARABLE_COMPILATION.rst
index 1c7dd80..d306d7f 100644
--- a/Help/prop_tgt/CUDA_SEPARABLE_COMPILATION.rst
+++ b/Help/prop_tgt/CUDA_SEPARABLE_COMPILATION.rst
@@ -11,3 +11,7 @@
 .. code-block:: cmake
 
   set_property(TARGET myexe PROPERTY CUDA_SEPARABLE_COMPILATION ON)
+
+This property is initialized by the value of the
+:variable:`CMAKE_CUDA_SEPARABLE_COMPILATION` variable if it is set when a
+target is created.
diff --git a/Help/prop_tgt/IMPORTED_GLOBAL.rst b/Help/prop_tgt/IMPORTED_GLOBAL.rst
new file mode 100644
index 0000000..1feca04
--- /dev/null
+++ b/Help/prop_tgt/IMPORTED_GLOBAL.rst
@@ -0,0 +1,22 @@
+IMPORTED_GLOBAL
+---------------
+
+Indication of whether an :ref:`IMPORTED target <Imported Targets>` is
+globally visible.
+
+The boolean value of this property is True for targets created with the
+``IMPORTED`` ``GLOBAL`` options to :command:`add_executable()` or
+:command:`add_library()`. It is always False for targets built within the
+project.
+
+For targets created with the ``IMPORTED`` option to
+:command:`add_executable()` or :command:`add_library()` but without the
+additional option ``GLOBAL`` this is False, too. However, setting this
+property for such a locally ``IMPORTED`` target to True promotes that
+target to global scope. This promotion can only be done in the same
+directory where that ``IMPORTED`` target was created in the first place.
+
+Once an imported target has been made global, it cannot be changed back to
+non-global. Therefore, if a project sets this property, it may only
+provide a value of True. CMake will issue an error if the project tries to
+set the property to a non-True value, even if the value was already False.
diff --git a/Help/release/3.4.rst b/Help/release/3.4.rst
index 89c5561..468627e 100644
--- a/Help/release/3.4.rst
+++ b/Help/release/3.4.rst
@@ -66,7 +66,7 @@
 Properties
 ----------
 
-* :ref:`Visual Studio Generators` learned to support additonal
+* :ref:`Visual Studio Generators` learned to support additional
   target properties to customize projects for NVIDIA Nsight
   Tegra Visual Studio Edition:
 
diff --git a/Help/release/3.6.rst b/Help/release/3.6.rst
index 144537d..a542b77 100644
--- a/Help/release/3.6.rst
+++ b/Help/release/3.6.rst
@@ -111,7 +111,7 @@
 
 * The :module:`ExternalProject` module learned to initialize Git submodules
   recursively and also to initialize new submodules on updates.  Use the
-  ``GIT_SUBMODULES`` option to restrict which submodules are initalized and
+  ``GIT_SUBMODULES`` option to restrict which submodules are initialized and
   updated.
 
 * The :module:`ExternalProject` module leared the ``DOWNLOAD_NO_EXTRACT 1``
diff --git a/Help/release/3.7.rst b/Help/release/3.7.rst
index 4c51af4..d4d374b 100644
--- a/Help/release/3.7.rst
+++ b/Help/release/3.7.rst
@@ -237,7 +237,7 @@
 
 * The :module:`CPackIFW` module :command:`cpack_ifw_configure_component` and
   :command:`cpack_ifw_configure_component_group` commands gained a new
-  ``USER_INTERFACES`` option to add a list of additonal pages to the IFW
+  ``USER_INTERFACES`` option to add a list of additional pages to the IFW
   installer.
 
 * The :module:`CPackRPM` module learned to generate debuginfo
diff --git a/Help/release/dev/0-sample-topic.rst b/Help/release/dev/0-sample-topic.rst
new file mode 100644
index 0000000..e4cc01e
--- /dev/null
+++ b/Help/release/dev/0-sample-topic.rst
@@ -0,0 +1,7 @@
+0-sample-topic
+--------------
+
+* This is a sample release note for the change in a topic.
+  Developers should add similar notes for each topic branch
+  making a noteworthy change.  Each document should be named
+  and titled to match the topic name to avoid merge conflicts.
diff --git a/Help/release/dev/FetchContent.rst b/Help/release/dev/FetchContent.rst
new file mode 100644
index 0000000..3b12977
--- /dev/null
+++ b/Help/release/dev/FetchContent.rst
@@ -0,0 +1,11 @@
+FetchContent
+------------
+
+* A new :module:`FetchContent` module was added which supports populating
+  content at configure time using any of the download/update methods
+  supported by :command:`ExternalProject_Add`.  This allows the content
+  to be used immediately during the configure stage, such as with
+  :command:`add_subdirectory`, etc.  Hierarchical project structures are
+  well supported, allowing parent projects to override the content details
+  of child projects and ensuring content is not populated multiple times
+  throughout the whole project tree.
diff --git a/Help/release/dev/FindOpenGL-glvnd-policy.rst b/Help/release/dev/FindOpenGL-glvnd-policy.rst
new file mode 100644
index 0000000..3348acf
--- /dev/null
+++ b/Help/release/dev/FindOpenGL-glvnd-policy.rst
@@ -0,0 +1,5 @@
+FindOpenGL-glvnd-policy
+-----------------------
+
+* The :module:`FindOpenGL` module now prefers GLVND libraries if available.
+  See policy :policy:`CMP0072`.
diff --git a/Help/release/dev/blas-lapack-flame.rst b/Help/release/dev/blas-lapack-flame.rst
new file mode 100644
index 0000000..fdc3a69
--- /dev/null
+++ b/Help/release/dev/blas-lapack-flame.rst
@@ -0,0 +1,5 @@
+blas-lapack-flame
+-----------------
+
+* The :module:`FindBLAS` and :module:`FindLAPACK` modules learned to support
+  `FLAME <https://github.com/flame>`__ ``blis`` and ``libflame``.
diff --git a/Help/release/dev/cmake-default-dir-install-permissions.rst b/Help/release/dev/cmake-default-dir-install-permissions.rst
new file mode 100644
index 0000000..8325fda
--- /dev/null
+++ b/Help/release/dev/cmake-default-dir-install-permissions.rst
@@ -0,0 +1,12 @@
+cmake-default-dir-install-permissions
+-------------------------------------
+
+* The :variable:`CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS` variable was added
+  to enable setting of default permissions for directories created implicitly
+  during installation of files by :command:`install` and
+  :command:`file(INSTALL)`.
+
+* The :variable:`CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS` variable was added
+  which serves the same purpose during packaging as the
+  :variable:`CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS` variable serves during
+  installation (e.g. ``make install``).
diff --git a/Help/release/dev/cmake-open.rst b/Help/release/dev/cmake-open.rst
new file mode 100644
index 0000000..a8f77ae
--- /dev/null
+++ b/Help/release/dev/cmake-open.rst
@@ -0,0 +1,6 @@
+cmake-open
+----------
+
+* The :manual:`cmake(1)` ``--open <dir>`` command line option can now
+  be used to open generated IDE projects like Visual Studio solutions
+  or Xcode projects.
diff --git a/Help/release/dev/cuda-sep-comp-var.rst b/Help/release/dev/cuda-sep-comp-var.rst
new file mode 100644
index 0000000..23536ef
--- /dev/null
+++ b/Help/release/dev/cuda-sep-comp-var.rst
@@ -0,0 +1,6 @@
+cuda-sep-comp-var
+-----------------
+
+* A :variable:`CMAKE_CUDA_SEPARABLE_COMPILATION` variable was added to
+  initialize the :prop_tgt:`CUDA_SEPARABLE_COMPILATION` target property
+  on targets when they are created.
diff --git a/Help/release/dev/curl_netrc_options.rst b/Help/release/dev/curl_netrc_options.rst
new file mode 100644
index 0000000..850c9ce
--- /dev/null
+++ b/Help/release/dev/curl_netrc_options.rst
@@ -0,0 +1,14 @@
+curl_netrc_options
+------------------
+
+* The :command:`file(DOWNLOAD)` and :command:`file(UPLOAD)` commands
+  gained ``NETRC`` and ``NETRC_FILE`` options to specify use of a
+  ``.netrc`` file.
+
+* The :module:`ExternalProject` module gained ``NETRC`` and ``NETRC_FILE``
+  options to specify use of a ``.netrc`` file.
+
+* The :variable:`CMAKE_NETRC` and :variable:`CMAKE_NETRC_FILE` variables
+  were added to specify use of a ``.netrc`` file by the
+  :command:`file(DOWNLOAD)` and :command:`file(UPLOAD)` commands and
+  the :module:`ExternalProject` module.
diff --git a/Help/release/dev/defer-target-source-check.rst b/Help/release/dev/defer-target-source-check.rst
new file mode 100644
index 0000000..65f5488
--- /dev/null
+++ b/Help/release/dev/defer-target-source-check.rst
@@ -0,0 +1,6 @@
+defer-target-source-check
+-------------------------
+
+* :command:`add_library` and :command:`add_executable` commands can now be
+  called without any sources and will not complain as long as sources will
+  be added later via :command:`target_sources`.
diff --git a/Help/release/dev/deprecate-policy-old.rst b/Help/release/dev/deprecate-policy-old.rst
new file mode 100644
index 0000000..bcfa70a
--- /dev/null
+++ b/Help/release/dev/deprecate-policy-old.rst
@@ -0,0 +1,8 @@
+deprecate-policy-old
+--------------------
+
+* An explicit deprecation diagnostic was added for policies ``CMP0037``
+  through ``CMP0054`` (``CMP0036`` and below were already deprecated).
+  The :manual:`cmake-policies(7)` manual explains that the OLD behaviors
+  of all policies are deprecated and that projects should port to the
+  NEW behaviors.
diff --git a/Help/release/dev/generalize-importedtargets-behavior.rst b/Help/release/dev/generalize-importedtargets-behavior.rst
new file mode 100644
index 0000000..c6f4523
--- /dev/null
+++ b/Help/release/dev/generalize-importedtargets-behavior.rst
@@ -0,0 +1,25 @@
+generalize-importedtargets-behavior
+-----------------------------------
+
+* The :command:`target_compile_definitions` command learned to set the
+  :prop_tgt:`INTERFACE_COMPILE_DEFINITIONS` property on
+  :ref:`Imported Targets`.
+
+* The :command:`target_compile_features` command learned to set the
+  :prop_tgt:`INTERFACE_COMPILE_FEATURES` property on :ref:`Imported Targets`.
+
+* The :command:`target_compile_options` command learned to set the
+  :prop_tgt:`INTERFACE_COMPILE_OPTIONS` property on :ref:`Imported Targets`.
+
+* The :command:`target_include_directories` command learned to set the
+  :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` property on
+  :ref:`Imported Targets`.
+
+* The :command:`target_sources` command learned to set the
+  :prop_tgt:`INTERFACE_SOURCES` property on :ref:`Imported Targets`.
+
+* The :command:`target_link_libraries` command learned to set the
+  :prop_tgt:`INTERFACE_LINK_LIBRARIES` property on :ref:`Imported Targets`.
+
+* :ref:`Alias Targets` may now alias :ref:`Imported Targets` that are
+  created with the ``GLOBAL`` option to :command:`add_library`.
diff --git a/Help/release/dev/generator-instance.rst b/Help/release/dev/generator-instance.rst
new file mode 100644
index 0000000..a3ff658
--- /dev/null
+++ b/Help/release/dev/generator-instance.rst
@@ -0,0 +1,8 @@
+generator-instance
+------------------
+
+* A :variable:`CMAKE_GENERATOR_INSTANCE` variable was introduced
+  to hold the selected instance of the generator's corresponding
+  native tools if multiple are available.  This is used by the
+  :generator:`Visual Studio 15 2017` generator to hold the
+  selected instance of Visual Studio persistently.
diff --git a/Help/release/dev/imported-promotion.rst b/Help/release/dev/imported-promotion.rst
new file mode 100644
index 0000000..d184178
--- /dev/null
+++ b/Help/release/dev/imported-promotion.rst
@@ -0,0 +1,15 @@
+imported-promotion
+------------------
+
+* Added new target-property :prop_tgt:`IMPORTED_GLOBAL` which
+  indicates if an :ref:`IMPORTED target <Imported Targets>` is
+  globally visible.
+  It will be set automatically if such an imported target is
+  created with the ``GLOBAL`` flag.
+
+* Additionally, it is now also possible to promote a local imported
+  target to become globally visible by setting its
+  :prop_tgt:`IMPORTED_GLOBAL` property to `TRUE`. (However, this
+  promotion can only succeed if it is done from within the same
+  directory where the imported target was created in the first
+  place.) Setting it to `FALSE` is not supported!
diff --git a/Help/release/dev/ti-compiler-depfile-support.rst b/Help/release/dev/ti-compiler-depfile-support.rst
new file mode 100644
index 0000000..f870afd
--- /dev/null
+++ b/Help/release/dev/ti-compiler-depfile-support.rst
@@ -0,0 +1,4 @@
+ti-compiler-depfile-support
+---------------------------
+
+* TI C/C++ compilers are now supported by the :generator:`Ninja` generator.
diff --git a/Help/release/dev/vs-hlsl-opt-dbg.rst b/Help/release/dev/vs-hlsl-opt-dbg.rst
new file mode 100644
index 0000000..8f398ae
--- /dev/null
+++ b/Help/release/dev/vs-hlsl-opt-dbg.rst
@@ -0,0 +1,6 @@
+vs-hlsl-opt-dbg
+---------------
+
+* Source file properties :prop_sf:`VS_SHADER_DISABLE_OPTIMIZATIONS` and
+  :prop_sf:`VS_SHADER_ENABLE_DEBUG` have been added to specify more
+  details of ``.hlsl`` sources with :ref:`Visual Studio Generators`.
diff --git a/Help/release/dev/write-single-xcodeproj.rst b/Help/release/dev/write-single-xcodeproj.rst
new file mode 100644
index 0000000..d5e9fef
--- /dev/null
+++ b/Help/release/dev/write-single-xcodeproj.rst
@@ -0,0 +1,8 @@
+write-single-xcodeproj
+----------------------
+
+* The :generator:`Xcode` generator behavior of generating one project
+  file per :command:`project()` command could now be controlled with the
+  :variable:`CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY` variable.
+  This could be useful to speed up the CMake generation step for
+  large projects and to work-around a bug in the ``ZERO_CHECK`` logic.
diff --git a/Help/release/index.rst b/Help/release/index.rst
index 0c7572f..6472b51 100644
--- a/Help/release/index.rst
+++ b/Help/release/index.rst
@@ -7,6 +7,8 @@
   This file should include the adjacent "dev.txt" file
   in development versions but not in release versions.
 
+.. include:: dev.txt
+
 Releases
 ========
 
diff --git a/Help/variable/CMAKE_CUDA_SEPARABLE_COMPILATION.rst b/Help/variable/CMAKE_CUDA_SEPARABLE_COMPILATION.rst
new file mode 100644
index 0000000..eef92fb
--- /dev/null
+++ b/Help/variable/CMAKE_CUDA_SEPARABLE_COMPILATION.rst
@@ -0,0 +1,6 @@
+CMAKE_CUDA_SEPARABLE_COMPILATION
+--------------------------------
+
+Default value for :prop_tgt:`CUDA_SEPARABLE_COMPILATION` target property.
+This variable is used to initialize the property on each target as it is
+created.
diff --git a/Help/variable/CMAKE_GENERATOR_INSTANCE.rst b/Help/variable/CMAKE_GENERATOR_INSTANCE.rst
new file mode 100644
index 0000000..78c81b1
--- /dev/null
+++ b/Help/variable/CMAKE_GENERATOR_INSTANCE.rst
@@ -0,0 +1,24 @@
+CMAKE_GENERATOR_INSTANCE
+------------------------
+
+Generator-specific instance specification provided by user.
+
+Some CMake generators support selection of an instance of the native build
+system when multiple instances are available.  If the user specifies an
+instance (e.g. by setting this cache entry), or after a default instance is
+chosen when a build tree is first configured, the value will be available in
+this variable.
+
+The value of this variable should never be modified by project code.
+A toolchain file specified by the :variable:`CMAKE_TOOLCHAIN_FILE`
+variable may initialize ``CMAKE_GENERATOR_INSTANCE`` as a cache entry.
+Once a given build tree has been initialized with a particular value
+for this variable, changing the value has undefined behavior.
+
+Instance specification is supported only on specific generators:
+
+* For the :generator:`Visual Studio 15 2017` generator (and above)
+  this specifies the absolute path to the VS installation directory
+  of the selected VS instance.
+
+See native build system documentation for allowed instance values.
diff --git a/Help/variable/CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS.rst b/Help/variable/CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS.rst
new file mode 100644
index 0000000..f994fbe
--- /dev/null
+++ b/Help/variable/CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS.rst
@@ -0,0 +1,29 @@
+CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
+-------------------------------------------
+
+Default permissions for directories created implicitly during installation
+of files by :command:`install` and :command:`file(INSTALL)`.
+
+If ``make install`` is invoked and directories are implicitly created they
+get permissions set by :variable:`CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS`
+variable or platform specific default permissions if the variable is not set.
+
+Implicitly created directories are created if they are not explicitly installed
+by :command:`install` command but are needed to install a file on a certain
+path. Example of such locations are directories created due to the setting of
+:variable:`CMAKE_INSTALL_PREFIX`.
+
+Expected content of the :variable:`CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS`
+variable is a list of permissions that can be used by :command:`install` command
+`PERMISSIONS` section.
+
+Example usage:
+
+::
+
+ set(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
+      OWNER_READ
+      OWNER_WRITE
+      OWNER_EXECUTE
+      GROUP_READ
+    )
diff --git a/Help/variable/CMAKE_NETRC.rst b/Help/variable/CMAKE_NETRC.rst
new file mode 100644
index 0000000..52f857e
--- /dev/null
+++ b/Help/variable/CMAKE_NETRC.rst
@@ -0,0 +1,9 @@
+CMAKE_NETRC
+-----------
+
+This variable is used to initialize the ``NETRC`` option for
+:command:`file(DOWNLOAD)` and :command:`file(DOWNLOAD)` commands and the
+module :module:`ExternalProject`. See those commands for additional
+information.
+
+The local option takes precedence over this variable.
diff --git a/Help/variable/CMAKE_NETRC_FILE.rst b/Help/variable/CMAKE_NETRC_FILE.rst
new file mode 100644
index 0000000..1508f1e
--- /dev/null
+++ b/Help/variable/CMAKE_NETRC_FILE.rst
@@ -0,0 +1,9 @@
+CMAKE_NETRC_FILE
+----------------
+
+This variable is used to initialize the ``NETRC_FILE`` option for
+:command:`file(DOWNLOAD)` and :command:`file(DOWNLOAD)` commands and the
+module :module:`ExternalProject`. See those commands for additional
+information.
+
+The local option takes precedence over this variable.
diff --git a/Help/variable/CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY.rst b/Help/variable/CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY.rst
new file mode 100644
index 0000000..ea3e240
--- /dev/null
+++ b/Help/variable/CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY.rst
@@ -0,0 +1,9 @@
+CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY
+-------------------------------------------
+
+If enabled, the :generator:`Xcode` generator will generate only a
+single Xcode project file for the topmost :command:`project()` command
+instead of generating one for every ``project()`` command.
+
+This could be useful to speed up the CMake generation step for
+large projects and to work-around a bug in the ``ZERO_CHECK`` logic.
diff --git a/Help/variable/CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS.rst b/Help/variable/CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS.rst
new file mode 100644
index 0000000..83d5ce7
--- /dev/null
+++ b/Help/variable/CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS.rst
@@ -0,0 +1,11 @@
+CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
+-------------------------------------------
+
+Default permissions for implicitly created directories during packaging.
+
+This variable serves the same purpose during packaging as the
+:variable:`CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS` variable
+serves during installation (e.g. ``make install``).
+
+If `include(CPack)` is used then by default this variable is set to the content
+of :variable:`CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS`.
diff --git a/Help/variable/LIBRARY_OUTPUT_PATH.rst b/Help/variable/LIBRARY_OUTPUT_PATH.rst
index ba02911..bb4328f 100644
--- a/Help/variable/LIBRARY_OUTPUT_PATH.rst
+++ b/Help/variable/LIBRARY_OUTPUT_PATH.rst
@@ -5,5 +5,5 @@
 
 The target properties :prop_tgt:`ARCHIVE_OUTPUT_DIRECTORY`,
 :prop_tgt:`LIBRARY_OUTPUT_DIRECTORY`, and :prop_tgt:`RUNTIME_OUTPUT_DIRECTORY`
-supercede this variable for a target if they are set.  Library targets are
+supersede this variable for a target if they are set.  Library targets are
 otherwise placed in this directory.
diff --git a/Modules/AndroidTestUtilities/PushToAndroidDevice.cmake b/Modules/AndroidTestUtilities/PushToAndroidDevice.cmake
index 04529b1..fccff67 100644
--- a/Modules/AndroidTestUtilities/PushToAndroidDevice.cmake
+++ b/Modules/AndroidTestUtilities/PushToAndroidDevice.cmake
@@ -31,7 +31,7 @@
     set(out_var ${out_var} PARENT_SCOPE)
     if(res_var)
       string(REGEX REPLACE ";" " " com "${ARGN}")
-      message(FATAL_ERROR "Error occured during adb command: adb ${com}\nError: ${err_var}.")
+      message(FATAL_ERROR "Error occurred during adb command: adb ${com}\nError: ${err_var}.")
     endif()
   endfunction()
 
diff --git a/Modules/AutoRccInfo.cmake.in b/Modules/AutoRccInfo.cmake.in
new file mode 100644
index 0000000..5457a6f
--- /dev/null
+++ b/Modules/AutoRccInfo.cmake.in
@@ -0,0 +1,11 @@
+# Meta
+set(ARCC_MULTI_CONFIG @_multi_config@)
+# Directories and files
+set(ARCC_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/")
+set(ARCC_CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@/")
+set(ARCC_CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@/")
+set(ARCC_CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/")
+set(ARCC_BUILD_DIR @_build_dir@)
+# Qt environment
+set(ARCC_RCC_EXECUTABLE @_qt_rcc_executable@)
+set(ARCC_RCC_LIST_OPTIONS @_qt_rcc_list_options@)
diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in
index 7f4b398..9a4a06d 100644
--- a/Modules/AutogenInfo.cmake.in
+++ b/Modules/AutogenInfo.cmake.in
@@ -9,12 +9,11 @@
 set(AM_BUILD_DIR @_build_dir@)
 set(AM_SOURCES @_sources@)
 set(AM_HEADERS @_headers@)
+set(AM_SETTINGS_FILE @_settings_file@)
 # Qt environment
 set(AM_QT_VERSION_MAJOR @_qt_version_major@)
-set(AM_QT_VERSION_MINOR @_qt_version_minor@)
 set(AM_QT_MOC_EXECUTABLE @_qt_moc_executable@)
 set(AM_QT_UIC_EXECUTABLE @_qt_uic_executable@)
-set(AM_QT_RCC_EXECUTABLE @_qt_rcc_executable@)
 # MOC settings
 set(AM_MOC_SKIP @_moc_skip@)
 set(AM_MOC_DEFINITIONS @_moc_compile_defs@)
@@ -30,8 +29,3 @@
 set(AM_UIC_OPTIONS_FILES @_qt_uic_options_files@)
 set(AM_UIC_OPTIONS_OPTIONS @_qt_uic_options_options@)
 set(AM_UIC_SEARCH_PATHS @_uic_search_paths@)
-# RCC settings
-set(AM_RCC_SOURCES @_rcc_files@)
-set(AM_RCC_BUILDS @_rcc_builds@)
-set(AM_RCC_OPTIONS @_rcc_options@)
-set(AM_RCC_INPUTS @_rcc_inputs@)
diff --git a/Modules/CMakeFindSublimeText2.cmake b/Modules/CMakeFindSublimeText2.cmake
new file mode 100644
index 0000000..022d010
--- /dev/null
+++ b/Modules/CMakeFindSublimeText2.cmake
@@ -0,0 +1,23 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+
+# This file is included in CMakeSystemSpecificInformation.cmake if
+# the Sublime Text 2 extra generator has been selected.
+
+find_program(CMAKE_SUBLIMETEXT_EXECUTABLE
+    NAMES subl3 subl sublime_text
+    PATHS
+        "/Applications/Sublime Text.app/Contents/SharedSupport/bin"
+        "/Applications/Sublime Text 3.app/Contents/SharedSupport/bin"
+        "/Applications/Sublime Text 2.app/Contents/SharedSupport/bin"
+        "$ENV{HOME}/Applications/Sublime Text.app/Contents/SharedSupport/bin"
+        "$ENV{HOME}/Applications/Sublime Text 3.app/Contents/SharedSupport/bin"
+        "$ENV{HOME}/Applications/Sublime Text 2.app/Contents/SharedSupport/bin"
+        "/opt/sublime_text"
+        "/opt/sublime_text_3"
+    DOC "The Sublime Text executable")
+
+if(CMAKE_SUBLIMETEXT_EXECUTABLE)
+   set(CMAKE_OPEN_PROJECT_COMMAND "${CMAKE_SUBLIMETEXT_EXECUTABLE} --project <PROJECT_FILE>" )
+endif()
diff --git a/Modules/CMakeFortranCompilerId.F.in b/Modules/CMakeFortranCompilerId.F.in
index 49789f1..da3d953 100644
--- a/Modules/CMakeFortranCompilerId.F.in
+++ b/Modules/CMakeFortranCompilerId.F.in
@@ -2,6 +2,26 @@
 #if 0
 ! Identify the compiler
 #endif
+#if defined(_MSC_VER)
+       PRINT *, 'INFO:simulate[MSVC]'
+# if _MSC_VER >= 1900
+       PRINT *, 'INFO:simulate_version[019.00]'
+# elif _MSC_VER >= 1800
+       PRINT *, 'INFO:simulate_version[018.00]'
+# elif _MSC_VER >= 1700
+       PRINT *, 'INFO:simulate_version[017.00]'
+# elif _MSC_VER >= 1600
+       PRINT *, 'INFO:simulate_version[016.00]'
+# elif _MSC_VER >= 1500
+       PRINT *, 'INFO:simulate_version[015.00]'
+# elif _MSC_VER >= 1400
+       PRINT *, 'INFO:simulate_version[014.00]'
+# elif _MSC_VER >= 1310
+       PRINT *, 'INFO:simulate_version[013.01]'
+# else
+       PRINT *, 'INFO:simulate_version[013.00]'
+# endif
+#endif
 #if defined(__INTEL_COMPILER) || defined(__ICC)
         PRINT *, 'INFO:compiler[Intel]'
 # define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100)
@@ -14,27 +34,6 @@
 # if defined(__INTEL_COMPILER_BUILD_DATE)
 #  define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE)
 # endif
-
-# if defined(_MSC_VER)
-        PRINT *, 'INFO:simulate[MSVC]'
-#  if _MSC_VER >= 1900
-        PRINT *, 'INFO:simulate_version[019.00]'
-#  elif _MSC_VER >= 1800
-        PRINT *, 'INFO:simulate_version[018.00]'
-#  elif _MSC_VER >= 1700
-        PRINT *, 'INFO:simulate_version[017.00]'
-#  elif _MSC_VER >= 1600
-        PRINT *, 'INFO:simulate_version[016.00]'
-#  elif _MSC_VER >= 1500
-        PRINT *, 'INFO:simulate_version[015.00]'
-#  elif _MSC_VER >= 1400
-        PRINT *, 'INFO:simulate_version[014.00]'
-#  elif _MSC_VER >= 1310
-        PRINT *, 'INFO:simulate_version[013.01]'
-#  else
-        PRINT *, 'INFO:simulate_version[013.00]'
-#  endif
-# endif
 #elif defined(__SUNPRO_F95)
         PRINT *, 'INFO:compiler[SunPro]'
 # define COMPILER_VERSION_MAJOR HEX(__SUNPRO_F95>>8)
diff --git a/Modules/CMakeFortranInformation.cmake b/Modules/CMakeFortranInformation.cmake
index 8005da6..b315d33 100644
--- a/Modules/CMakeFortranInformation.cmake
+++ b/Modules/CMakeFortranInformation.cmake
@@ -169,7 +169,7 @@
 endforeach()
 
 set (CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS_INIT}" CACHE STRING
-     "Flags for Fortran compiler.")
+     "Flags used by the compiler during all build types.")
 
 include(CMakeCommonLanguageInclude)
 
diff --git a/Modules/CMakePackageConfigHelpers.cmake b/Modules/CMakePackageConfigHelpers.cmake
index 90c2a57..f5a8e59 100644
--- a/Modules/CMakePackageConfigHelpers.cmake
+++ b/Modules/CMakePackageConfigHelpers.cmake
@@ -154,7 +154,7 @@
 # macro.
 #
 # Internally, this macro executes :command:`configure_file()` to create the
-# resulting version file.  Depending on the ``COMPATIBLITY``, either the file
+# resulting version file.  Depending on the ``COMPATIBILITY``, either the file
 # ``BasicConfigVersion-SameMajorVersion.cmake.in`` or
 # ``BasicConfigVersion-AnyNewerVersion.cmake.in`` is used.  Please note that
 # these two files are internal to CMake and you should not call
diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake
index 3915943..812917f 100644
--- a/Modules/CPack.cmake
+++ b/Modules/CPack.cmake
@@ -338,7 +338,7 @@
         set(value "${${var}}")
       endif()
 
-      string(APPEND commands "\nSET(${var} \"${value}\")")
+      string(APPEND commands "\nset(${var} \"${value}\")")
     endif()
   endforeach()
 
@@ -384,6 +384,12 @@
 
 _cpack_set_default(CPACK_MODULE_PATH "${CMAKE_MODULE_PATH}")
 
+# Set default directory creation permissions mode
+if(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS)
+  _cpack_set_default(CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
+    "${CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS}")
+endif()
+
 if(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL)
   set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
 endif()
diff --git a/Modules/CPackComponent.cmake b/Modules/CPackComponent.cmake
index 2374fbd..6c122e5 100644
--- a/Modules/CPackComponent.cmake
+++ b/Modules/CPackComponent.cmake
@@ -66,7 +66,7 @@
 #  the component differently depending on the value of this variable:
 #
 #  * ONE_PER_GROUP (default): creates one package file per component group
-#  * ALL_COMPONENTS_IN_ONE : creates a single package with all (requested) component
+#  * ALL_COMPONENTS_IN_ONE : creates a single package with all (requested) components
 #  * IGNORE : creates one package per component, i.e. IGNORE component group
 #
 #  One can specify different grouping for different CPack generator by
diff --git a/Modules/CPackDeb.cmake b/Modules/CPackDeb.cmake
index 1879827..91bf2f2 100644
--- a/Modules/CPackDeb.cmake
+++ b/Modules/CPackDeb.cmake
@@ -987,7 +987,7 @@
     if(READELF_EXECUTABLE)
       foreach(_FILE IN LISTS CPACK_DEB_SHARED_OBJECT_FILES)
         extract_so_info("${_FILE}" libname soversion)
-        if(libname AND soversion)
+        if(libname AND DEFINED soversion)
           list(APPEND CPACK_DEBIAN_PACKAGE_SHLIBS_LIST
                "${libname} ${soversion} ${CPACK_DEBIAN_PACKAGE_NAME} (${CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS_POLICY} ${CPACK_DEBIAN_PACKAGE_VERSION})")
         else()
diff --git a/Modules/CPackIFW.cmake b/Modules/CPackIFW.cmake
index 8d8b070..05a54a0 100644
--- a/Modules/CPackIFW.cmake
+++ b/Modules/CPackIFW.cmake
@@ -817,7 +817,7 @@
       endif()
     endif()
   endforeach()
-  # Finaly try to get version from executable path
+  # Finally try to get version from executable path
   if(NOT CPACK_IFW_FRAMEWORK_VERSION)
     string(REGEX MATCH "[0-9]+(\\.[0-9]+)*"
       CPACK_IFW_FRAMEWORK_VERSION "${CPACK_IFW_INSTALLERBASE_EXECUTABLE}")
@@ -864,7 +864,7 @@
   endif()
 endmacro()
 
-# Resolve full path to lisense file
+# Resolve full path to license file
 macro(_cpack_ifw_resolve_lisenses _variable)
   if(${_variable})
     set(_ifw_license_file FALSE)
diff --git a/Modules/CPackRPM.cmake b/Modules/CPackRPM.cmake
index 9f77ec3..c5a27f9 100644
--- a/Modules/CPackRPM.cmake
+++ b/Modules/CPackRPM.cmake
@@ -545,7 +545,7 @@
 #                /usr/share/doc
 #
 #  May be used to exclude path (directories or files) from the auto-generated
-#  list of paths discovered by CPack RPM. The defaut value contains a
+#  list of paths discovered by CPack RPM. The default value contains a
 #  reasonable set of values if the variable is not defined by the user. If the
 #  variable is defined by the user then CPackRPM will NOT any of the default
 #  path. If you want to add some path to the default list then you can use
@@ -782,7 +782,7 @@
 #
 # .. note::
 #
-#  Each source path prefix is additionaly suffixed by ``src_<index>`` where
+#  Each source path prefix is additionally suffixed by ``src_<index>`` where
 #  index is index of the path used from :variable:`CPACK_BUILD_SOURCE_DIRS`
 #  variable. This produces ``<CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX>/src_<index>``
 #  replacement path.
@@ -1985,13 +1985,13 @@
   # CPACK_RPM_POST_INSTALL_SCRIPT_FILE (or CPACK_RPM_<COMPONENT>_POST_INSTALL_SCRIPT_FILE)
   # CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE (or CPACK_RPM_<COMPONENT>_POST_UNINSTALL_SCRIPT_FILE)
   # May be used to embed a post (un)installation script in the spec file.
-  # The refered script file(s) will be read and directly
+  # The referred script file(s) will be read and directly
   # put after the %post or %postun section
   # ----------------------------------------------------------------
   # CPACK_RPM_PRE_INSTALL_SCRIPT_FILE (or CPACK_RPM_<COMPONENT>_PRE_INSTALL_SCRIPT_FILE)
   # CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE (or CPACK_RPM_<COMPONENT>_PRE_UNINSTALL_SCRIPT_FILE)
   # May be used to embed a pre (un)installation script in the spec file.
-  # The refered script file(s) will be read and directly
+  # The referred script file(s) will be read and directly
   # put after the %pre or %preun section
   foreach(RPM_SCRIPT_FILE_TYPE_ "INSTALL" "UNINSTALL")
     foreach(RPM_SCRIPT_FILE_TIME_ "PRE" "POST")
@@ -2022,7 +2022,7 @@
 
   # CPACK_RPM_CHANGELOG_FILE
   # May be used to embed a changelog in the spec file.
-  # The refered file will be read and directly put after the %changelog section
+  # The referred file will be read and directly put after the %changelog section
   if(CPACK_RPM_CHANGELOG_FILE)
     if(EXISTS ${CPACK_RPM_CHANGELOG_FILE})
       file(READ ${CPACK_RPM_CHANGELOG_FILE} CPACK_RPM_SPEC_CHANGELOG)
@@ -2152,7 +2152,7 @@
     string(STRIP "${CPACK_RPM_INSTALL_FILES}" CPACK_RPM_INSTALL_FILES_LIST)
     # Transform endline separated - string into CMake List
     string(REPLACE "\n" ";" CPACK_RPM_INSTALL_FILES_LIST "${CPACK_RPM_INSTALL_FILES_LIST}")
-    # Remove unecessary quotes
+    # Remove unnecessary quotes
     string(REPLACE "\"" "" CPACK_RPM_INSTALL_FILES_LIST "${CPACK_RPM_INSTALL_FILES_LIST}")
     # Remove ABSOLUTE install file from INSTALL FILE LIST
     list(REMOVE_ITEM CPACK_RPM_INSTALL_FILES_LIST ${CPACK_ABSOLUTE_DESTINATION_FILES_INTERNAL})
@@ -2413,7 +2413,7 @@
     endif()
 
     # Disable debuginfo packages - srpm generates invalid packages due to
-    # releasing controll to cpack to generate binary packages.
+    # releasing control to cpack to generate binary packages.
     # Note however that this doesn't prevent cpack to generate debuginfo
     # packages when run from srpm with --rebuild.
     set(TMP_RPM_DISABLE_DEBUGINFO "%define debug_package %{nil}")
diff --git a/Modules/CPackWIX.cmake b/Modules/CPackWIX.cmake
index 1dc37d4..c723e72 100644
--- a/Modules/CPackWIX.cmake
+++ b/Modules/CPackWIX.cmake
@@ -289,7 +289,7 @@
 #
 
 if(NOT CPACK_WIX_ROOT)
-  file(TO_CMAKE_PATH "$ENV{WIX}" CPACK_WIX_ROOT)
+  string(REPLACE "\\" "/" CPACK_WIX_ROOT "$ENV{WIX}")
 endif()
 
 find_program(CPACK_WIX_CANDLE_EXECUTABLE candle
diff --git a/Modules/CTest.cmake b/Modules/CTest.cmake
index 9370596..a08282e 100644
--- a/Modules/CTest.cmake
+++ b/Modules/CTest.cmake
@@ -65,7 +65,7 @@
 include(CTestUseLaunchers)
 
 if(BUILD_TESTING)
-  # Setup some auxilary macros
+  # Setup some auxiliary macros
   macro(SET_IF_NOT_SET var val)
     if(NOT DEFINED "${var}")
       set("${var}" "${val}")
diff --git a/Modules/CheckLanguage.cmake b/Modules/CheckLanguage.cmake
index 1ea91d2..70c14d7 100644
--- a/Modules/CheckLanguage.cmake
+++ b/Modules/CheckLanguage.cmake
@@ -43,11 +43,17 @@
   \"set(CMAKE_${lang}_COMPILER \\\"\${CMAKE_${lang}_COMPILER}\\\")\\n\"
   )
 ")
+    if(CMAKE_GENERATOR_INSTANCE)
+      set(_D_CMAKE_GENERATOR_INSTANCE "-DCMAKE_GENERATOR_INSTANCE:INTERNAL=${CMAKE_GENERATOR_INSTANCE}")
+    else()
+      set(_D_CMAKE_GENERATOR_INSTANCE "")
+    endif()
     execute_process(
       WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang}
       COMMAND ${CMAKE_COMMAND} . -G ${CMAKE_GENERATOR}
                                  -A "${CMAKE_GENERATOR_PLATFORM}"
                                  -T "${CMAKE_GENERATOR_TOOLSET}"
+                                 ${_D_CMAKE_GENERATOR_INSTANCE}
       OUTPUT_VARIABLE output
       ERROR_VARIABLE output
       RESULT_VARIABLE result
diff --git a/Modules/Compiler/Clang.cmake b/Modules/Compiler/Clang.cmake
index 9f5e921..7ce1adb 100644
--- a/Modules/Compiler/Clang.cmake
+++ b/Modules/Compiler/Clang.cmake
@@ -11,7 +11,8 @@
 include(Compiler/CMakeCommonCompilerMacros)
 
 if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC"
-    OR "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
+    OR "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC"
+    OR "x${CMAKE_Fortran_SIMULATE_ID}" STREQUAL "xMSVC")
   macro(__compiler_clang lang)
   endmacro()
 else()
diff --git a/Modules/Compiler/IAR-FindBinUtils.cmake b/Modules/Compiler/IAR-FindBinUtils.cmake
index 2b04795..b29ee81 100644
--- a/Modules/Compiler/IAR-FindBinUtils.cmake
+++ b/Modules/Compiler/IAR-FindBinUtils.cmake
@@ -17,7 +17,7 @@
   find_program(CMAKE_IAR_ARCHIVE iarchive.exe HINTS ${__iar_hints}
       DOC "The IAR archiver")
 
-  # find auxillary tools
+  # find auxiliary tools
   find_program(CMAKE_IAR_ELFTOOL ielftool.exe HINTS ${__iar_hints}
       DOC "The IAR ELF Tool")
     find_program(CMAKE_IAR_ELFDUMP ielfdumparm.exe HINTS ${__iar_hints}
diff --git a/Modules/Compiler/IAR.cmake b/Modules/Compiler/IAR.cmake
index 52ebaf2..43243b9 100644
--- a/Modules/Compiler/IAR.cmake
+++ b/Modules/Compiler/IAR.cmake
@@ -29,7 +29,7 @@
 # "Silent" Operation
 #
 # this really is different to most programs I know.
-# nothing meaningfull from the operation is lost, just some redundant
+# nothing meaningful from the operation is lost, just some redundant
 # code and data size printouts (that can be inspected with common tools).
 
 # This module is shared by multiple languages; use include blocker.
diff --git a/Modules/Compiler/TI-C.cmake b/Modules/Compiler/TI-C.cmake
index ebc79f4..e149237 100644
--- a/Modules/Compiler/TI-C.cmake
+++ b/Modules/Compiler/TI-C.cmake
@@ -2,6 +2,8 @@
 set(CMAKE_LINK_LIBRARY_FLAG "--library=")
 set(CMAKE_INCLUDE_FLAG_C "--include_path=")
 
+set(CMAKE_DEPFILE_FLAGS_C "--preproc_with_compile --preproc_dependency=<DEPFILE>")
+
 set(CMAKE_C_CREATE_ASSEMBLY_SOURCE "<CMAKE_C_COMPILER> --compile_only --skip_assembler --c_file=<SOURCE> <DEFINES> <INCLUDES> <FLAGS> --output_file=<ASSEMBLY_SOURCE>")
 set(CMAKE_C_CREATE_PREPROCESSED_SOURCE "<CMAKE_C_COMPILER> --preproc_only --c_file=<SOURCE> <DEFINES> <INCLUDES> <FLAGS> --output_file=<PREPROCESSED_SOURCE>")
 
diff --git a/Modules/Compiler/TI-CXX.cmake b/Modules/Compiler/TI-CXX.cmake
index 4104c3b..8b0069b 100644
--- a/Modules/Compiler/TI-CXX.cmake
+++ b/Modules/Compiler/TI-CXX.cmake
@@ -2,6 +2,8 @@
 set(CMAKE_LINK_LIBRARY_FLAG "--library=")
 set(CMAKE_INCLUDE_FLAG_CXX "--include_path=")
 
+set(CMAKE_DEPFILE_FLAGS_CCX "--preproc_with_compile --preproc_dependency=<DEPFILE>")
+
 set(CMAKE_CXX_CREATE_ASSEMBLY_SOURCE "<CMAKE_CXX_COMPILER> --compile_only --skip_assembler --cpp_file=<SOURCE> <DEFINES> <INCLUDES> <FLAGS> --output_file=<ASSEMBLY_SOURCE>")
 set(CMAKE_CXX_CREATE_PREPROCESSED_SOURCE "<CMAKE_CXX_COMPILER> --preproc_only --cpp_file=<SOURCE> <DEFINES> <INCLUDES> <FLAGS> --output_file=<PREPROCESSED_SOURCE>")
 
diff --git a/Modules/Documentation.cmake b/Modules/Documentation.cmake
index fc398e6..6e21249 100644
--- a/Modules/Documentation.cmake
+++ b/Modules/Documentation.cmake
@@ -40,7 +40,7 @@
     )
 
   #
-  # The documentation process is controled by a batch file.
+  # The documentation process is controlled by a batch file.
   # We will probably need bash to create the custom target
   #
 
diff --git a/Modules/ExternalProject-download.cmake.in b/Modules/ExternalProject-download.cmake.in
index 7f92596..99fb917 100644
--- a/Modules/ExternalProject-download.cmake.in
+++ b/Modules/ExternalProject-download.cmake.in
@@ -116,6 +116,8 @@
 
     @TLS_VERIFY_CODE@
     @TLS_CAINFO_CODE@
+    @NETRC_CODE@
+    @NETRC_FILE_CODE@
 
     file(
         DOWNLOAD
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index 419c9d6..67aac4f 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -193,6 +193,28 @@
         ``CMAKE_TLS_CAINFO`` variable will be used instead (see
         :command:`file(DOWNLOAD)`)
 
+      ``NETRC <level>``
+        Specify whether the .netrc file is to be used for operation. If this
+        option is not specified, the value of the ``CMAKE_NETRC`` variable
+        will be used instead (see :command:`file(DOWNLOAD)`)
+        Valid levels are:
+
+        ``IGNORED``
+          The .netrc file is ignored.
+          This is the default.
+        ``OPTIONAL``
+          The .netrc file is optional, and information in the URL is preferred.
+          The file will be scanned to find which ever information is not specified
+          in the URL.
+        ``REQUIRED``
+          The .netrc file is required, and information in the URL is ignored.
+
+      ``NETRC_FILE <file>``
+        Specify an alternative .netrc file to the one in your home directory
+        if the ``NETRC`` level is ``OPTIONAL`` or ``REQUIRED``. If this option
+        is not specified, the value of the ``CMAKE_NETRC_FILE`` variable will
+        be used instead (see :command:`file(DOWNLOAD)`)
+
     *Git*
       NOTE: A git version of 1.6.5 or later is required if this download method
       is used.
@@ -359,6 +381,11 @@
       :variable:`CMAKE_GENERATOR_TOOLSET`). It is an error to provide this
       option without the ``CMAKE_GENERATOR`` option.
 
+    ``CMAKE_GENERATOR_INSTANCE <instance>``
+      Pass a generator-specific instance selection to the CMake command (see
+      :variable:`CMAKE_GENERATOR_INSTANCE`). It is an error to provide this
+      option without the ``CMAKE_GENERATOR`` option.
+
     ``CMAKE_ARGS <arg>...``
       The specified arguments are passed to the ``cmake`` command line. They
       can be any argument the ``cmake`` command understands, not just cache
@@ -1346,7 +1373,7 @@
 
 endfunction(_ep_write_gitupdate_script)
 
-function(_ep_write_downloadfile_script script_filename REMOTE LOCAL timeout no_progress hash tls_verify tls_cainfo userpwd http_headers)
+function(_ep_write_downloadfile_script script_filename REMOTE LOCAL timeout no_progress hash tls_verify tls_cainfo userpwd http_headers netrc netrc_file)
   if(timeout)
     set(TIMEOUT_ARGS TIMEOUT ${timeout})
     set(TIMEOUT_MSG "${timeout} seconds")
@@ -1371,6 +1398,8 @@
 
   set(TLS_VERIFY_CODE "")
   set(TLS_CAINFO_CODE "")
+  set(NETRC_CODE "")
+  set(NETRC_FILE_CODE "")
 
   # check for curl globals in the project
   if(DEFINED CMAKE_TLS_VERIFY)
@@ -1379,6 +1408,12 @@
   if(DEFINED CMAKE_TLS_CAINFO)
     set(TLS_CAINFO_CODE "set(CMAKE_TLS_CAINFO \"${CMAKE_TLS_CAINFO}\")")
   endif()
+  if(DEFINED CMAKE_NETRC)
+    set(NETRC_CODE "set(CMAKE_NETRC \"${CMAKE_NETRC}\")")
+  endif()
+  if(DEFINED CMAKE_NETRC_FILE)
+    set(NETRC_FILE_CODE "set(CMAKE_NETRC_FILE \"${CMAKE_NETRC_FILE}\")")
+  endif()
 
   # now check for curl locals so that the local values
   # will override the globals
@@ -1393,6 +1428,16 @@
   if(tls_cainfo_len GREATER 0)
     set(TLS_CAINFO_CODE "set(CMAKE_TLS_CAINFO \"${tls_cainfo}\")")
   endif()
+  # check for netrc argument
+  string(LENGTH "${netrc}" netrc_len)
+  if(netrc_len GREATER 0)
+    set(NETRC_CODE "set(CMAKE_NETRC \"${netrc}\")")
+  endif()
+  # check for netrc_file argument
+  string(LENGTH "${netrc_file}" netrc_file_len)
+  if(netrc_file_len GREATER 0)
+    set(NETRC_FILE_CODE "set(CMAKE_NETRC_FILE \"${netrc_file}\")")
+  endif()
 
   if(userpwd STREQUAL ":")
     set(USERPWD_ARGS)
@@ -2436,11 +2481,13 @@
         get_property(no_progress TARGET ${name} PROPERTY _EP_DOWNLOAD_NO_PROGRESS)
         get_property(tls_verify TARGET ${name} PROPERTY _EP_TLS_VERIFY)
         get_property(tls_cainfo TARGET ${name} PROPERTY _EP_TLS_CAINFO)
+        get_property(netrc TARGET ${name} PROPERTY _EP_NETRC)
+        get_property(netrc_file TARGET ${name} PROPERTY _EP_NETRC_FILE)
         get_property(http_username TARGET ${name} PROPERTY _EP_HTTP_USERNAME)
         get_property(http_password TARGET ${name} PROPERTY _EP_HTTP_PASSWORD)
         get_property(http_headers TARGET ${name} PROPERTY _EP_HTTP_HEADER)
         set(download_script "${stamp_dir}/download-${name}.cmake")
-        _ep_write_downloadfile_script("${download_script}" "${url}" "${file}" "${timeout}" "${no_progress}" "${hash}" "${tls_verify}" "${tls_cainfo}" "${http_username}:${http_password}" "${http_headers}")
+        _ep_write_downloadfile_script("${download_script}" "${url}" "${file}" "${timeout}" "${no_progress}" "${hash}" "${tls_verify}" "${tls_cainfo}" "${http_username}:${http_password}" "${http_headers}" "${netrc}" "${netrc_file}")
         set(cmd ${CMAKE_COMMAND} -P "${download_script}"
           COMMAND)
         if (no_extract)
@@ -2712,6 +2759,7 @@
     endif()
 
     get_target_property(cmake_generator ${name} _EP_CMAKE_GENERATOR)
+    get_target_property(cmake_generator_instance ${name} _EP_CMAKE_GENERATOR_INSTANCE)
     get_target_property(cmake_generator_platform ${name} _EP_CMAKE_GENERATOR_PLATFORM)
     get_target_property(cmake_generator_toolset ${name} _EP_CMAKE_GENERATOR_TOOLSET)
     if(cmake_generator)
@@ -2722,6 +2770,9 @@
       if(cmake_generator_toolset)
         list(APPEND cmd "-T${cmake_generator_toolset}")
       endif()
+      if(cmake_generator_instance)
+        list(APPEND cmd "-DCMAKE_GENERATOR_INSTANCE:INTERNAL=${cmake_generator_instance}")
+      endif()
     else()
       if(CMAKE_EXTRA_GENERATOR)
         list(APPEND cmd "-G${CMAKE_EXTRA_GENERATOR} - ${CMAKE_GENERATOR}")
@@ -2740,6 +2791,12 @@
       if(CMAKE_GENERATOR_TOOLSET)
         list(APPEND cmd "-T${CMAKE_GENERATOR_TOOLSET}")
       endif()
+      if(cmake_generator_instance)
+        message(FATAL_ERROR "Option CMAKE_GENERATOR_INSTANCE not allowed without CMAKE_GENERATOR.")
+      endif()
+      if(CMAKE_GENERATOR_INSTANCE)
+        list(APPEND cmd "-DCMAKE_GENERATOR_INSTANCE:INTERNAL=${CMAKE_GENERATOR_INSTANCE}")
+      endif()
     endif()
 
     list(APPEND cmd "<SOURCE_DIR><SOURCE_SUBDIR>")
diff --git a/Modules/FeatureSummary.cmake b/Modules/FeatureSummary.cmake
index 1b93304..fbce235 100644
--- a/Modules/FeatureSummary.cmake
+++ b/Modules/FeatureSummary.cmake
@@ -493,7 +493,7 @@
     by the project when available at buildtime, but it also work without.
     ``RECOMMENDED`` is similar to ``OPTIONAL``, i.e.  the project will build if
     the package is not present, but the functionality of the resulting
-    binaries will be severly limited.  If a ``REQUIRED`` package is not
+    binaries will be severely limited.  If a ``REQUIRED`` package is not
     available at buildtime, the project may not even build.  This can be
     combined with the ``FATAL_ON_MISSING_REQUIRED_PACKAGES`` argument for
     ``feature_summary()``.  Last, a ``RUNTIME`` package is a package which is
diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake
new file mode 100644
index 0000000..98cdf6c
--- /dev/null
+++ b/Modules/FetchContent.cmake
@@ -0,0 +1,916 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+FetchContent
+------------------
+
+.. only:: html
+
+  .. contents::
+
+Overview
+^^^^^^^^
+
+This module enables populating content at configure time via any method
+supported by the :module:`ExternalProject` module.  Whereas
+:command:`ExternalProject_Add` downloads at build time, the
+``FetchContent`` module makes content available immediately, allowing the
+configure step to use the content in commands like :command:`add_subdirectory`,
+:command:`include` or :command:`file` operations.
+
+Content population details would normally be defined separately from the
+command that performs the actual population.  Projects should also
+check whether the content has already been populated somewhere else in the
+project hierarchy.  Typical usage would look something like this:
+
+.. code-block:: cmake
+
+  FetchContent_Declare(
+    googletest
+    GIT_REPOSITORY https://github.com/google/googletest.git
+    GIT_TAG        release-1.8.0
+  )
+
+  FetchContent_GetProperties(googletest)
+  if(NOT googletest_POPULATED)
+    FetchContent_Populate(googletest)
+    add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR})
+  endif()
+
+When using the above pattern with a hierarchical project arrangement,
+projects at higher levels in the hierarchy are able to define or override
+the population details of content specified anywhere lower in the project
+hierarchy.  The ability to detect whether content has already been
+populated ensures that even if multiple child projects want certain content
+to be available, the first one to populate it wins.  The other child project
+can simply make use of the already available content instead of repeating
+the population for itself.  See the
+:ref:`Examples <fetch-content-examples>` section which demonstrates
+this scenario.
+
+The ``FetchContent`` module also supports defining and populating
+content in a single call, with no check for whether the content has been
+populated elsewhere in the project already.  This is a more low level
+operation and would not normally be the way the module is used, but it is
+sometimes useful as part of implementing some higher level feature or to
+populate some content in CMake's script mode.
+
+
+Declaring Content Details
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. command:: FetchContent_Declare
+
+  .. code-block:: cmake
+
+    FetchContent_Declare(<name> <contentOptions>...)
+
+  The ``FetchContent_Declare()`` function records the options that describe
+  how to populate the specified content, but if such details have already
+  been recorded earlier in this project (regardless of where in the project
+  hierarchy), this and all later calls for the same content ``<name>`` are
+  ignored.  This "first to record, wins" approach is what allows hierarchical
+  projects to have parent projects override content details of child projects.
+
+  The content ``<name>`` can be any string without spaces, but good practice
+  would be to use only letters, numbers and underscores.  The name will be
+  treated case-insensitively and it should be obvious for the content it
+  represents, often being the name of the child project or the value given
+  to its top level :command:`project` command (if it is a CMake project).
+  For well-known public projects, the name should generally be the official
+  name of the project.  Choosing an unusual name makes it unlikely that other
+  projects needing that same content will use the same name, leading to
+  the content being populated multiple times.
+
+  The ``<contentOptions>`` can be any of the download or update/patch options
+  that the :command:`ExternalProject_Add` command understands.  The configure,
+  build, install and test steps are explicitly disabled and therefore options
+  related to them will be ignored.  In most cases, ``<contentOptions>`` will
+  just be a couple of options defining the download method and method-specific
+  details like a commit tag or archive hash.  For example:
+
+  .. code-block:: cmake
+
+    FetchContent_Declare(
+      googletest
+      GIT_REPOSITORY https://github.com/google/googletest.git
+      GIT_TAG        release-1.8.0
+    )
+
+    FetchContent_Declare(
+      myCompanyIcons
+      URL      https://intranet.mycompany.com/assets/iconset_1.12.tar.gz
+      URL_HASH 5588a7b18261c20068beabfb4f530b87
+    )
+
+    FetchContent_Declare(
+      myCompanyCertificates
+      SVN_REPOSITORY svn+ssh://svn.mycompany.com/srv/svn/trunk/certs
+      SVN_REVISION   -r12345
+    )
+
+Populating The Content
+^^^^^^^^^^^^^^^^^^^^^^
+
+.. command:: FetchContent_Populate
+
+  .. code-block:: cmake
+
+    FetchContent_Populate( <name> )
+
+  In most cases, the only argument given to ``FetchContent_Populate()`` is the
+  ``<name>``.  When used this way, the command assumes the content details have
+  been recorded by an earlier call to :command:`FetchContent_Declare`.  The
+  details are stored in a global property, so they are unaffected by things
+  like variable or directory scope.  Therefore, it doesn't matter where in the
+  project the details were previously declared, as long as they have been
+  declared before the call to ``FetchContent_Populate()``.  Those saved details
+  are then used to construct a call to :command:`ExternalProject_Add` in a
+  private sub-build to perform the content population immediately.  The
+  implementation of ``ExternalProject_Add()`` ensures that if the content has
+  already been populated in a previous CMake run, that content will be reused
+  rather than repopulating them again.  For the common case where population
+  involves downloading content, the cost of the download is only paid once.
+
+  An internal global property records when a particular content population
+  request has been processed.  If ``FetchContent_Populate()`` is called more
+  than once for the same content name within a configure run, the second call
+  will halt with an error.  Projects can and should check whether content
+  population has already been processed with the
+  :command:`FetchContent_GetProperties` command before calling
+  ``FetchContent_Populate()``.
+
+  ``FetchContent_Populate()`` will set three variables in the scope of the
+  caller; ``<lcName>_POPULATED``, ``<lcName>_SOURCE_DIR`` and
+  ``<lcName>_BINARY_DIR``, where ``<lcName>`` is the lowercased ``<name>``.
+  ``<lcName>_POPULATED`` will always be set to ``True`` by the call.
+  ``<lcName>_SOURCE_DIR`` is the location where the
+  content can be found upon return (it will have already been populated), while
+  ``<lcName>_BINARY_DIR`` is a directory intended for use as a corresponding
+  build directory.  The main use case for the two directory variables is to
+  call :command:`add_subdirectory` immediately after population, i.e.:
+
+  .. code-block:: cmake
+
+    FetchContent_Populate(FooBar ...)
+    add_subdirectory(${foobar_SOURCE_DIR} ${foobar_BINARY_DIR})
+
+  The values of the three variables can also be retrieved from anywhere in the
+  project hierarchy using the :command:`FetchContent_GetProperties` command.
+
+  A number of cache variables influence the behavior of all content population
+  performed using details saved from a :command:`FetchContent_Declare` call:
+
+  ``FETCHCONTENT_BASE_DIR``
+    In most cases, the saved details do not specify any options relating to the
+    directories to use for the internal sub-build, final source and build areas.
+    It is generally best to leave these decisions up to the ``FetchContent``
+    module to handle on the project's behalf.  The ``FETCHCONTENT_BASE_DIR``
+    cache variable controls the point under which all content population
+    directories are collected, but in most cases developers would not need to
+    change this.  The default location is ``${CMAKE_BINARY_DIR}/_deps``, but if
+    developers change this value, they should aim to keep the path short and
+    just below the top level of the build tree to avoid running into path
+    length problems on Windows.
+
+  ``FETCHCONTENT_QUIET``
+    The logging output during population can be quite verbose, making the
+    configure stage quite noisy.  This cache option (``ON`` by default) hides
+    all population output unless an error is encountered.  If experiencing
+    problems with hung downloads, temporarily switching this option off may
+    help diagnose which content population is causing the issue.
+
+  ``FETCHCONTENT_FULLY_DISCONNECTED``
+    When this option is enabled, no attempt is made to download or update
+    any content.  It is assumed that all content has already been populated in
+    a previous run or the source directories have been pointed at existing
+    contents the developer has provided manually (using options described
+    further below).  When the developer knows that no changes have been made to
+    any content details, turning this option ``ON`` can significantly speed up
+    the configure stage.  It is ``OFF`` by default.
+
+  ``FETCHCONTENT_UPDATES_DISCONNECTED``
+    This is a less severe download/update control compared to
+    ``FETCHCONTENT_FULLY_DISCONNECTED``.  Instead of bypassing all download and
+    update logic, the ``FETCHCONTENT_UPDATES_DISCONNECTED`` only disables the
+    update stage.  Therefore, if content has not been downloaded previously,
+    it will still be downloaded when this option is enabled.  This can speed up
+    the configure stage, but not as much as
+    ``FETCHCONTENT_FULLY_DISCONNECTED``.  It is ``OFF`` by default.
+
+  In addition to the above cache variables, the following cache variables are
+  also defined for each content name (``<ucName>`` is the uppercased value of
+  ``<name>``):
+
+  ``FETCHCONTENT_SOURCE_DIR_<ucName>``
+    If this is set, no download or update steps are performed for the specified
+    content and the ``<lcName>_SOURCE_DIR`` variable returned to the caller is
+    pointed at this location.  This gives developers a way to have a separate
+    checkout of the content that they can modify freely without interference
+    from the build.  The build simply uses that existing source, but it still
+    defines ``<lcName>_BINARY_DIR`` to point inside its own build area.
+    Developers are strongly encouraged to use this mechanism rather than
+    editing the sources populated in the default location, as changes to
+    sources in the default location can be lost when content population details
+    are changed by the project.
+
+  ``FETCHCONTENT_UPDATES_DISCONNECTED_<ucName>``
+    This is the per-content equivalent of
+    ``FETCHCONTENT_UPDATES_DISCONNECTED``. If the global option or this option
+    is ``ON``, then updates will be disabled for the named content.
+    Disabling updates for individual content can be useful for content whose
+    details rarely change, while still leaving other frequently changing
+    content with updates enabled.
+
+
+  The ``FetchContent_Populate()`` command also supports a syntax allowing the
+  content details to be specified directly rather than using any saved
+  details.  This is more low-level and use of this form is generally to be
+  avoided in favour of using saved content details as outlined above.
+  Nevertheless, in certain situations it can be useful to invoke the content
+  population as an isolated operation (typically as part of implementing some
+  other higher level feature or when using CMake in script mode):
+
+  .. code-block:: cmake
+
+    FetchContent_Populate( <name>
+      [QUIET]
+      [SUBBUILD_DIR <subBuildDir>]
+      [SOURCE_DIR <srcDir>]
+      [BINARY_DIR <binDir>]
+      ...
+    )
+
+  This form has a number of key differences to that where only ``<name>`` is
+  provided:
+
+  - All required population details are assumed to have been provided directly
+    in the call to ``FetchContent_Populate()``. Any saved details for
+    ``<name>`` are ignored.
+  - No check is made for whether content for ``<name>`` has already been
+    populated.
+  - No global property is set to record that the population has occurred.
+  - No global properties record the source or binary directories used for the
+    populated content.
+  - The ``FETCHCONTENT_FULLY_DISCONNECTED`` and
+    ``FETCHCONTENT_UPDATES_DISCONNECTED`` cache variables are ignored.
+
+  The ``<lcName>_SOURCE_DIR`` and ``<lcName>_BINARY_DIR`` variables are still
+  returned to the caller, but since these locations are not stored as global
+  properties when this form is used, they are only available to the calling
+  scope and below rather than the entire project hierarchy.  No
+  ``<lcName>_POPULATED`` variable is set in the caller's scope with this form.
+
+  The supported options for ``FetchContent_Populate()`` are the same as those
+  for :command:`FetchContent_Declare()`.  Those few options shown just
+  above are either specific to ``FetchContent_Populate()`` or their behavior is
+  slightly modified from how :command:`ExternalProject_Add` treats them.
+
+  ``QUIET``
+    The ``QUIET`` option can be given to hide the output associated with
+    populating the specified content.  If the population fails, the output will
+    be shown regardless of whether this option was given or not so that the
+    cause of the failure can be diagnosed.  The global ``FETCHCONTENT_QUIET``
+    cache variable has no effect on ``FetchContent_Populate()`` calls where the
+    content details are provided directly.
+
+  ``SUBBUILD_DIR``
+    The ``SUBBUILD_DIR`` argument can be provided to change the location of the
+    sub-build created to perform the population.  The default value is
+    ``${CMAKE_CURRENT_BINARY_DIR}/<lcName>-subbuild`` and it would be unusual
+    to need to override this default.  If a relative path is specified, it will
+    be interpreted as relative to :variable:`CMAKE_CURRENT_BINARY_DIR`.
+
+  ``SOURCE_DIR``, ``BINARY_DIR``
+    The ``SOURCE_DIR`` and ``BINARY_DIR`` arguments are supported by
+    :command:`ExternalProject_Add`, but different default values are used by
+    ``FetchContent_Populate()``.  ``SOURCE_DIR`` defaults to
+    ``${CMAKE_CURRENT_BINARY_DIR}/<lcName>-src`` and ``BINARY_DIR`` defaults to
+    ``${CMAKE_CURRENT_BINARY_DIR}/<lcName>-build``.  If a relative path is
+    specified, it will be interpreted as relative to
+    :variable:`CMAKE_CURRENT_BINARY_DIR`.
+
+  In addition to the above explicit options, any other unrecognized options are
+  passed through unmodified to :command:`ExternalProject_Add` to perform the
+  download, patch and update steps.  The following options are explicitly
+  prohibited (they are disabled by the ``FetchContent_Populate()`` command):
+
+  - ``CONFIGURE_COMMAND``
+  - ``BUILD_COMMAND``
+  - ``INSTALL_COMMAND``
+  - ``TEST_COMMAND``
+
+  If using ``FetchContent_Populate()`` within CMake's script mode, be aware
+  that the implementation sets up a sub-build which therefore requires a CMake
+  generator and build tool to be available. If these cannot be found by
+  default, then the :variable:`CMAKE_GENERATOR` and/or
+  :variable:`CMAKE_MAKE_PROGRAM` variables will need to be set appropriately
+  on the command line invoking the script.
+
+
+Retrieve Population Properties
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. command:: FetchContent_GetProperties
+
+  When using saved content details, a call to :command:`FetchContent_Populate`
+  records information in global properties which can be queried at any time.
+  This information includes the source and binary directories associated with
+  the content and also whether or not the content population has been processed
+  during the current configure run.
+
+  .. code-block:: cmake
+
+    FetchContent_GetProperties( <name>
+      [SOURCE_DIR <srcDirVar>]
+      [BINARY_DIR <binDirVar>]
+      [POPULATED <doneVar>]
+    )
+
+  The ``SOURCE_DIR``, ``BINARY_DIR`` and ``POPULATED`` options can be used to
+  specify which properties should be retrieved.  Each option accepts a value
+  which is the name of the variable in which to store that property.  Most of
+  the time though, only ``<name>`` is given, in which case the call will then
+  set the same variables as a call to
+  :command:`FetchContent_Populate(name) <FetchContent_Populate>`.  This allows
+  the following canonical pattern to be used, which ensures that the relevant
+  variables will always be defined regardless of whether or not the population
+  has been performed elsewhere in the project already:
+
+  .. code-block:: cmake
+
+    FetchContent_GetProperties(foobar)
+    if(NOT foobar_POPULATED)
+      FetchContent_Populate(foobar)
+
+      # Set any custom variables, etc. here, then
+      # populate the content as part of this build
+
+      add_subdirectory(${foobar_SOURCE_DIR} ${foobar_BINARY_DIR})
+    endif()
+
+  The above pattern allows other parts of the overall project hierarchy to
+  re-use the same content and ensure that it is only populated once.
+
+
+.. _`fetch-content-examples`:
+
+Examples
+^^^^^^^^
+
+Consider a project hierarchy where ``projA`` is the top level project and it
+depends on projects ``projB`` and ``projC``. Both ``projB`` and ``projC``
+can be built standalone and they also both depend on another project
+``projD``.  For simplicity, this example will assume that all four projects
+are available on a company git server.  The ``CMakeLists.txt`` of each project
+might have sections like the following:
+
+*projA*:
+
+.. code-block:: cmake
+
+  include(FetchContent)
+  FetchContent_Declare(
+    projB
+    GIT_REPOSITORY git@mycompany.com/git/projB.git
+    GIT_TAG        4a89dc7e24ff212a7b5167bef7ab079d
+  )
+  FetchContent_Declare(
+    projC
+    GIT_REPOSITORY git@mycompany.com/git/projC.git
+    GIT_TAG        4ad4016bd1d8d5412d135cf8ceea1bb9
+  )
+  FetchContent_Declare(
+    projD
+    GIT_REPOSITORY git@mycompany.com/git/projD.git
+    GIT_TAG        origin/integrationBranch
+  )
+
+  FetchContent_GetProperties(projB)
+  if(NOT projb_POPULATED)
+    FetchContent_Populate(projB)
+    add_subdirectory(${projb_SOURCE_DIR} ${projb_BINARY_DIR})
+  endif()
+
+  FetchContent_GetProperties(projC)
+  if(NOT projc_POPULATED)
+    FetchContent_Populate(projC)
+    add_subdirectory(${projc_SOURCE_DIR} ${projc_BINARY_DIR})
+  endif()
+
+*projB*:
+
+.. code-block:: cmake
+
+  include(FetchContent)
+  FetchContent_Declare(
+    projD
+    GIT_REPOSITORY git@mycompany.com/git/projD.git
+    GIT_TAG        20b415f9034bbd2a2e8216e9a5c9e632
+  )
+
+  FetchContent_GetProperties(projD)
+  if(NOT projd_POPULATED)
+    FetchContent_Populate(projD)
+    add_subdirectory(${projd_SOURCE_DIR} ${projd_BINARY_DIR})
+  endif()
+
+
+*projC*:
+
+.. code-block:: cmake
+
+  include(FetchContent)
+  FetchContent_Declare(
+    projD
+    GIT_REPOSITORY git@mycompany.com/git/projD.git
+    GIT_TAG        7d9a17ad2c962aa13e2fbb8043fb6b8a
+  )
+
+  FetchContent_GetProperties(projD)
+  if(NOT projd_POPULATED)
+    FetchContent_Populate(projD)
+    add_subdirectory(${projd_SOURCE_DIR} ${projd_BINARY_DIR})
+  endif()
+
+A few key points should be noted in the above:
+
+- ``projB`` and ``projC`` define different content details for ``projD``,
+  but ``projA`` also defines a set of content details for ``projD`` and
+  because ``projA`` will define them first, the details from ``projB`` and
+  ``projC`` will not be used.  The override details defined by ``projA``
+  are not required to match either of those from ``projB`` or ``projC``, but
+  it is up to the higher level project to ensure that the details it does
+  define still make sense for the child projects.
+- While ``projA`` defined content details for ``projD``, it did not need
+  to explicitly call ``FetchContent_Populate(projD)`` itself.  Instead, it
+  leaves that to a child project to do (in this case it will be ``projB``
+  since it is added to the build ahead of ``projC``).  If ``projA`` needed to
+  customize how the ``projD`` content was brought into the build as well
+  (e.g. define some CMake variables before calling
+  :command:`add_subdirectory` after populating), it would do the call to
+  ``FetchContent_Populate()``, etc. just as it did for the ``projB`` and
+  ``projC`` content.  For higher level projects, it is usually enough to
+  just define the override content details and leave the actual population
+  to the child projects.  This saves repeating the same thing at each level
+  of the project hierarchy unnecessarily.
+- Even though ``projA`` is the top level project in this example, it still
+  checks whether ``projB`` and ``projC`` have already been populated before
+  going ahead to do those populations.  This makes ``projA`` able to be more
+  easily incorporated as a child of some other higher level project in the
+  future if required.  Always protect a call to
+  :command:`FetchContent_Populate` with a check to
+  :command:`FetchContent_GetProperties`, even in what may be considered a top
+  level project at the time.
+
+
+The following example demonstrates how one might download and unpack a
+firmware tarball using CMake's :manual:`script mode <cmake(1)>`.  The call to
+:command:`FetchContent_Populate` specifies all the content details and the
+unpacked firmware will be placed in a ``firmware`` directory below the
+current working directory.
+
+*getFirmware.cmake*:
+
+.. code-block:: cmake
+
+  # NOTE: Intended to be run in script mode with cmake -P
+  include(FetchContent)
+  FetchContent_Populate(
+    firmware
+    URL        https://mycompany.com/assets/firmware-1.23-arm.tar.gz
+    URL_HASH   MD5=68247684da89b608d466253762b0ff11
+    SOURCE_DIR firmware
+  )
+
+#]=======================================================================]
+
+
+set(__FetchContent_privateDir "${CMAKE_CURRENT_LIST_DIR}/FetchContent")
+
+#=======================================================================
+# Recording and retrieving content details for later population
+#=======================================================================
+
+# Internal use, projects must not call this directly. It is
+# intended for use by FetchContent_Declare() only.
+#
+# Sets a content-specific global property (not meant for use
+# outside of functions defined here in this file) which can later
+# be retrieved using __FetchContent_getSavedDetails() with just the
+# same content name. If there is already a value stored in the
+# property, it is left unchanged and this call has no effect.
+# This allows parent projects to define the content details,
+# overriding anything a child project may try to set (properties
+# are not cached between runs, so the first thing to set it in a
+# build will be in control).
+function(__FetchContent_declareDetails contentName)
+
+  string(TOLOWER ${contentName} contentNameLower)
+  set(propertyName "_FetchContent_${contentNameLower}_savedDetails")
+  get_property(alreadyDefined GLOBAL PROPERTY ${propertyName} DEFINED)
+  if(NOT alreadyDefined)
+    define_property(GLOBAL PROPERTY ${propertyName}
+      BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()"
+      FULL_DOCS  "Details used by FetchContent_Populate() for ${contentName}"
+    )
+    set_property(GLOBAL PROPERTY ${propertyName} ${ARGN})
+  endif()
+
+endfunction()
+
+
+# Internal use, projects must not call this directly. It is
+# intended for use by the FetchContent_Declare() function.
+#
+# Retrieves details saved for the specified content in an
+# earlier call to __FetchContent_declareDetails().
+function(__FetchContent_getSavedDetails contentName outVar)
+
+  string(TOLOWER ${contentName} contentNameLower)
+  set(propertyName "_FetchContent_${contentNameLower}_savedDetails")
+  get_property(alreadyDefined GLOBAL PROPERTY ${propertyName} DEFINED)
+  if(NOT alreadyDefined)
+    message(FATAL_ERROR "No content details recorded for ${contentName}")
+  endif()
+  get_property(propertyValue GLOBAL PROPERTY ${propertyName})
+  set(${outVar} "${propertyValue}" PARENT_SCOPE)
+
+endfunction()
+
+
+# Saves population details of the content, sets defaults for the
+# SOURCE_DIR and BUILD_DIR.
+function(FetchContent_Declare contentName)
+
+  set(options "")
+  set(oneValueArgs SVN_REPOSITORY)
+  set(multiValueArgs "")
+
+  cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+  unset(srcDirSuffix)
+  unset(svnRepoArgs)
+  if(ARG_SVN_REPOSITORY)
+    # Add a hash of the svn repository URL to the source dir. This works
+    # around the problem where if the URL changes, the download would
+    # fail because it tries to checkout/update rather than switch the
+    # old URL to the new one. We limit the hash to the first 7 characters
+    # so that the source path doesn't get overly long (which can be a
+    # problem on windows due to path length limits).
+    string(SHA1 urlSHA ${ARG_SVN_REPOSITORY})
+    string(SUBSTRING ${urlSHA} 0 7 urlSHA)
+    set(srcDirSuffix "-${urlSHA}")
+    set(svnRepoArgs  SVN_REPOSITORY ${ARG_SVN_REPOSITORY})
+  endif()
+
+  string(TOLOWER ${contentName} contentNameLower)
+  __FetchContent_declareDetails(
+    ${contentNameLower}
+    SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src${srcDirSuffix}"
+    BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build"
+    ${svnRepoArgs}
+    # List these last so they can override things we set above
+    ${ARG_UNPARSED_ARGUMENTS}
+  )
+
+endfunction()
+
+
+#=======================================================================
+# Set/get whether the specified content has been populated yet.
+# The setter also records the source and binary dirs used.
+#=======================================================================
+
+# Internal use, projects must not call this directly. It is
+# intended for use by the FetchContent_Populate() function to
+# record when FetchContent_Populate() is called for a particular
+# content name.
+function(__FetchContent_setPopulated contentName sourceDir binaryDir)
+
+  string(TOLOWER ${contentName} contentNameLower)
+  set(prefix "_FetchContent_${contentNameLower}")
+
+  set(propertyName "${prefix}_sourceDir")
+  define_property(GLOBAL PROPERTY ${propertyName}
+    BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()"
+    FULL_DOCS  "Details used by FetchContent_Populate() for ${contentName}"
+  )
+  set_property(GLOBAL PROPERTY ${propertyName} ${sourceDir})
+
+  set(propertyName "${prefix}_binaryDir")
+  define_property(GLOBAL PROPERTY ${propertyName}
+    BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()"
+    FULL_DOCS  "Details used by FetchContent_Populate() for ${contentName}"
+  )
+  set_property(GLOBAL PROPERTY ${propertyName} ${binaryDir})
+
+  set(propertyName "${prefix}_populated")
+  define_property(GLOBAL PROPERTY ${propertyName}
+    BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()"
+    FULL_DOCS  "Details used by FetchContent_Populate() for ${contentName}"
+  )
+  set_property(GLOBAL PROPERTY ${propertyName} True)
+
+endfunction()
+
+
+# Set variables in the calling scope for any of the retrievable
+# properties. If no specific properties are requested, variables
+# will be set for all retrievable properties.
+#
+# This function is intended to also be used by projects as the canonical
+# way to detect whether they should call FetchContent_Populate()
+# and pull the populated source into the build with add_subdirectory(),
+# if they are using the populated content in that way.
+function(FetchContent_GetProperties contentName)
+
+  string(TOLOWER ${contentName} contentNameLower)
+
+  set(options "")
+  set(oneValueArgs SOURCE_DIR BINARY_DIR POPULATED)
+  set(multiValueArgs "")
+
+  cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+  if(NOT ARG_SOURCE_DIR AND
+     NOT ARG_BINARY_DIR AND
+     NOT ARG_POPULATED)
+    # No specific properties requested, provide them all
+    set(ARG_SOURCE_DIR ${contentNameLower}_SOURCE_DIR)
+    set(ARG_BINARY_DIR ${contentNameLower}_BINARY_DIR)
+    set(ARG_POPULATED  ${contentNameLower}_POPULATED)
+  endif()
+
+  set(prefix "_FetchContent_${contentNameLower}")
+
+  if(ARG_SOURCE_DIR)
+    set(propertyName "${prefix}_sourceDir")
+    get_property(value GLOBAL PROPERTY ${propertyName})
+    if(value)
+      set(${ARG_SOURCE_DIR} ${value} PARENT_SCOPE)
+    endif()
+  endif()
+
+  if(ARG_BINARY_DIR)
+    set(propertyName "${prefix}_binaryDir")
+    get_property(value GLOBAL PROPERTY ${propertyName})
+    if(value)
+      set(${ARG_BINARY_DIR} ${value} PARENT_SCOPE)
+    endif()
+  endif()
+
+  if(ARG_POPULATED)
+    set(propertyName "${prefix}_populated")
+    get_property(value GLOBAL PROPERTY ${propertyName} DEFINED)
+    set(${ARG_POPULATED} ${value} PARENT_SCOPE)
+  endif()
+
+endfunction()
+
+
+#=======================================================================
+# Performing the population
+#=======================================================================
+
+# The value of contentName will always have been lowercased by the caller.
+# All other arguments are assumed to be options that are understood by
+# ExternalProject_Add(), except for QUIET and SUBBUILD_DIR.
+function(__FetchContent_directPopulate contentName)
+
+  set(options
+      QUIET
+  )
+  set(oneValueArgs
+      SUBBUILD_DIR
+      SOURCE_DIR
+      BINARY_DIR
+      # Prevent the following from being passed through
+      CONFIGURE_COMMAND
+      BUILD_COMMAND
+      INSTALL_COMMAND
+      TEST_COMMAND
+  )
+  set(multiValueArgs "")
+
+  cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+  if(NOT ARG_SUBBUILD_DIR)
+    message(FATAL_ERROR "Internal error: SUBBUILD_DIR not set")
+  elseif(NOT IS_ABSOLUTE "${ARG_SUBBUILD_DIR}")
+    set(ARG_SUBBUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/${ARG_SUBBUILD_DIR}")
+  endif()
+
+  if(NOT ARG_SOURCE_DIR)
+    message(FATAL_ERROR "Internal error: SOURCE_DIR not set")
+  elseif(NOT IS_ABSOLUTE "${ARG_SOURCE_DIR}")
+    set(ARG_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/${ARG_SOURCE_DIR}")
+  endif()
+
+  if(NOT ARG_BINARY_DIR)
+    message(FATAL_ERROR "Internal error: BINARY_DIR not set")
+  elseif(NOT IS_ABSOLUTE "${ARG_BINARY_DIR}")
+    set(ARG_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/${ARG_BINARY_DIR}")
+  endif()
+
+  # Ensure the caller can know where to find the source and build directories
+  # with some convenient variables. Doing this here ensures the caller sees
+  # the correct result in the case where the default values are overridden by
+  # the content details set by the project.
+  set(${contentName}_SOURCE_DIR "${ARG_SOURCE_DIR}" PARENT_SCOPE)
+  set(${contentName}_BINARY_DIR "${ARG_BINARY_DIR}" PARENT_SCOPE)
+
+  # The unparsed arguments may contain spaces, so build up ARG_EXTRA
+  # in such a way that it correctly substitutes into the generated
+  # CMakeLists.txt file with each argument quoted.
+  unset(ARG_EXTRA)
+  foreach(arg IN LISTS ARG_UNPARSED_ARGUMENTS)
+    set(ARG_EXTRA "${ARG_EXTRA} \"${arg}\"")
+  endforeach()
+
+  # Hide output if requested, but save it to a variable in case there's an
+  # error so we can show the output upon failure. When not quiet, don't
+  # capture the output to a variable because the user may want to see the
+  # output as it happens (e.g. progress during long downloads). Combine both
+  # stdout and stderr in the one capture variable so the output stays in order.
+  if (ARG_QUIET)
+    set(outputOptions
+        OUTPUT_VARIABLE capturedOutput
+        ERROR_VARIABLE  capturedOutput
+    )
+  else()
+    set(capturedOutput)
+    set(outputOptions)
+    message(STATUS "Populating ${contentName}")
+  endif()
+
+  if(CMAKE_GENERATOR)
+    set(generatorOpts "-G${CMAKE_GENERATOR}")
+    if(CMAKE_GENERATOR_PLATFORM)
+      list(APPEND generatorOpts "-A${CMAKE_GENERATOR_PLATFORM}")
+    endif()
+    if(CMAKE_GENERATOR_TOOLSET)
+      list(APPEND generatorOpts "-T${CMAKE_GENERATOR_TOOLSET}")
+    endif()
+
+    if(CMAKE_MAKE_PROGRAM)
+      list(APPEND generatorOpts "-DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}")
+    endif()
+
+  else()
+    # Likely we've been invoked via CMake's script mode where no
+    # generator is set (and hence CMAKE_MAKE_PROGRAM could not be
+    # trusted even if provided). We will have to rely on being
+    # able to find the default generator and build tool.
+    unset(generatorOpts)
+  endif()
+
+  # Create and build a separate CMake project to carry out the population.
+  # If we've already previously done these steps, they will not cause
+  # anything to be updated, so extra rebuilds of the project won't occur.
+  # Make sure to pass through CMAKE_MAKE_PROGRAM in case the main project
+  # has this set to something not findable on the PATH.
+  configure_file("${__FetchContent_privateDir}/CMakeLists.cmake.in"
+                 "${ARG_SUBBUILD_DIR}/CMakeLists.txt")
+  execute_process(
+    COMMAND ${CMAKE_COMMAND} ${generatorOpts} .
+    RESULT_VARIABLE result
+    ${outputOptions}
+    WORKING_DIRECTORY "${ARG_SUBBUILD_DIR}"
+  )
+  if(result)
+    if(capturedOutput)
+      message("${capturedOutput}")
+    endif()
+    message(FATAL_ERROR "CMake step for ${contentName} failed: ${result}")
+  endif()
+  execute_process(
+    COMMAND ${CMAKE_COMMAND} --build .
+    RESULT_VARIABLE result
+    ${outputOptions}
+    WORKING_DIRECTORY "${ARG_SUBBUILD_DIR}"
+  )
+  if(result)
+    if(capturedOutput)
+      message("${capturedOutput}")
+    endif()
+    message(FATAL_ERROR "Build step for ${contentName} failed: ${result}")
+  endif()
+
+endfunction()
+
+
+option(FETCHCONTENT_FULLY_DISCONNECTED   "Disables all attempts to download or update content and assumes source dirs already exist")
+option(FETCHCONTENT_UPDATES_DISCONNECTED "Enables UPDATE_DISCONNECTED behavior for all content population")
+option(FETCHCONTENT_QUIET                "Enables QUIET option for all content population" ON)
+set(FETCHCONTENT_BASE_DIR "${CMAKE_BINARY_DIR}/_deps" CACHE PATH "Directory under which to collect all populated content")
+
+# Populate the specified content using details stored from
+# an earlier call to FetchContent_Declare().
+function(FetchContent_Populate contentName)
+
+  if(NOT contentName)
+    message(FATAL_ERROR "Empty contentName not allowed for FetchContent_Populate()")
+  endif()
+
+  string(TOLOWER ${contentName} contentNameLower)
+
+  if(ARGN)
+    # This is the direct population form with details fully specified
+    # as part of the call, so we already have everything we need
+    __FetchContent_directPopulate(
+      ${contentNameLower}
+      SUBBUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/${contentNameLower}-subbuild"
+      SOURCE_DIR   "${CMAKE_CURRENT_BINARY_DIR}/${contentNameLower}-src"
+      BINARY_DIR   "${CMAKE_CURRENT_BINARY_DIR}/${contentNameLower}-build"
+      ${ARGN}  # Could override any of the above ..._DIR variables
+    )
+
+    # Pass source and binary dir variables back to the caller
+    set(${contentNameLower}_SOURCE_DIR "${${contentNameLower}_SOURCE_DIR}" PARENT_SCOPE)
+    set(${contentNameLower}_BINARY_DIR "${${contentNameLower}_BINARY_DIR}" PARENT_SCOPE)
+
+    # Don't set global properties, or record that we did this population, since
+    # this was a direct call outside of the normal declared details form.
+    # We only want to save values in the global properties for content that
+    # honours the hierarchical details mechanism so that projects are not
+    # robbed of the ability to override details set in nested projects.
+    return()
+  endif()
+
+  # No details provided, so assume they were saved from an earlier call
+  # to FetchContent_Declare(). Do a check that we haven't already
+  # populated this content before in case the caller forgot to check.
+  FetchContent_GetProperties(${contentName})
+  if(${contentNameLower}_POPULATED)
+    message(FATAL_ERROR "Content ${contentName} already populated in ${${contentNameLower}_SOURCE_DIR}")
+  endif()
+
+  string(TOUPPER ${contentName} contentNameUpper)
+  set(FETCHCONTENT_SOURCE_DIR_${contentNameUpper}
+      "${FETCHCONTENT_SOURCE_DIR_${contentNameUpper}}"
+      CACHE PATH "When not empty, overrides where to find pre-populated content for ${contentName}")
+
+  if(FETCHCONTENT_SOURCE_DIR_${contentNameUpper})
+    # The source directory has been explicitly provided in the cache,
+    # so no population is required
+    set(${contentNameLower}_SOURCE_DIR "${FETCHCONTENT_SOURCE_DIR_${contentNameUpper}}")
+    set(${contentNameLower}_BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build")
+
+  elseif(FETCHCONTENT_FULLY_DISCONNECTED)
+    # Bypass population and assume source is already there from a previous run
+    set(${contentNameLower}_SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src")
+    set(${contentNameLower}_BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build")
+
+  else()
+    # Support both a global "disconnect all updates" and a per-content
+    # update test (either one being set disables updates for this content).
+    option(FETCHCONTENT_UPDATES_DISCONNECTED_${contentNameUpper}
+           "Enables UPDATE_DISCONNECTED behavior just for population of ${contentName}")
+    if(FETCHCONTENT_UPDATES_DISCONNECTED OR
+       FETCHCONTENT_UPDATES_DISCONNECTED_${contentNameUpper})
+      set(disconnectUpdates True)
+    else()
+      set(disconnectUpdates False)
+    endif()
+
+    if(FETCHCONTENT_QUIET)
+      set(quietFlag QUIET)
+    else()
+      unset(quietFlag)
+    endif()
+
+    __FetchContent_getSavedDetails(${contentName} contentDetails)
+    if("${contentDetails}" STREQUAL "")
+      message(FATAL_ERROR "No details have been set for content: ${contentName}")
+    endif()
+
+    __FetchContent_directPopulate(
+      ${contentNameLower}
+      ${quietFlag}
+      UPDATE_DISCONNECTED ${disconnectUpdates}
+      SUBBUILD_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-subbuild"
+      SOURCE_DIR   "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src"
+      BINARY_DIR   "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build"
+      # Put the saved details last so they can override any of the
+      # the options we set above (this can include SOURCE_DIR or
+      # BUILD_DIR)
+      ${contentDetails}
+    )
+  endif()
+
+  __FetchContent_setPopulated(
+    ${contentName}
+    ${${contentNameLower}_SOURCE_DIR}
+    ${${contentNameLower}_BINARY_DIR}
+  )
+
+  # Pass variables back to the caller. The variables passed back here
+  # must match what FetchContent_GetProperties() sets when it is called
+  # with just the content name.
+  set(${contentNameLower}_SOURCE_DIR "${${contentNameLower}_SOURCE_DIR}" PARENT_SCOPE)
+  set(${contentNameLower}_BINARY_DIR "${${contentNameLower}_BINARY_DIR}" PARENT_SCOPE)
+  set(${contentNameLower}_POPULATED  True PARENT_SCOPE)
+
+endfunction()
diff --git a/Modules/FetchContent/CMakeLists.cmake.in b/Modules/FetchContent/CMakeLists.cmake.in
new file mode 100644
index 0000000..9a7a771
--- /dev/null
+++ b/Modules/FetchContent/CMakeLists.cmake.in
@@ -0,0 +1,21 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+cmake_minimum_required(VERSION ${CMAKE_VERSION})
+
+# We name the project and the target for the ExternalProject_Add() call
+# to something that will highlight to the user what we are working on if
+# something goes wrong and an error message is produced.
+
+project(${contentName}-populate NONE)
+
+include(ExternalProject)
+ExternalProject_Add(${contentName}-populate
+                    ${ARG_EXTRA}
+                    SOURCE_DIR          "${ARG_SOURCE_DIR}"
+                    BINARY_DIR          "${ARG_BINARY_DIR}"
+                    CONFIGURE_COMMAND   ""
+                    BUILD_COMMAND       ""
+                    INSTALL_COMMAND     ""
+                    TEST_COMMAND        ""
+)
diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake
index 2684617..bb8b308 100644
--- a/Modules/FindBLAS.cmake
+++ b/Modules/FindBLAS.cmake
@@ -36,6 +36,7 @@
 #
 # * Goto
 # * OpenBLAS
+# * FLAME
 # * ATLAS PhiPACK
 # * CXML
 # * DXML
@@ -190,6 +191,20 @@
  endif()
 endif ()
 
+if (BLA_VENDOR STREQUAL "FLAME" OR BLA_VENDOR STREQUAL "All")
+ if(NOT BLAS_LIBRARIES)
+  # FLAME's blis library (https://github.com/flame/blis)
+  check_fortran_libraries(
+  BLAS_LIBRARIES
+  BLAS
+  sgemm
+  ""
+  "blis"
+  ""
+  )
+ endif()
+endif ()
+
 if (BLA_VENDOR STREQUAL "ATLAS" OR BLA_VENDOR STREQUAL "All")
  if(NOT BLAS_LIBRARIES)
   # BLAS in ATLAS library? (http://math-atlas.sourceforge.net/)
diff --git a/Modules/FindBZip2.cmake b/Modules/FindBZip2.cmake
index d2307f1..0375b09 100644
--- a/Modules/FindBZip2.cmake
+++ b/Modules/FindBZip2.cmake
@@ -38,6 +38,8 @@
 
     include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
     SELECT_LIBRARY_CONFIGURATIONS(BZIP2)
+else ()
+    file(TO_CMAKE_PATH "${BZIP2_LIBRARIES}" BZIP2_LIBRARIES)
 endif ()
 
 if (BZIP2_INCLUDE_DIR AND EXISTS "${BZIP2_INCLUDE_DIR}/bzlib.h")
diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake
index 88d14ab..6f60eeb 100644
--- a/Modules/FindBoost.cmake
+++ b/Modules/FindBoost.cmake
@@ -391,13 +391,8 @@
 # version with a regex.
 #
 function(_Boost_COMPILER_DUMPVERSION _OUTPUT_VERSION)
-
-  exec_program(${CMAKE_CXX_COMPILER}
-    ARGS ${CMAKE_CXX_COMPILER_ARG1} -dumpversion
-    OUTPUT_VARIABLE _boost_COMPILER_VERSION
-  )
-  string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2"
-    _boost_COMPILER_VERSION ${_boost_COMPILER_VERSION})
+  string(REGEX REPLACE "([0-9]+)\\.([0-9]+)(\\.[0-9]+)?" "\\1\\2"
+    _boost_COMPILER_VERSION ${CMAKE_CXX_COMPILER_VERSION})
 
   set(${_OUTPUT_VERSION} ${_boost_COMPILER_VERSION} PARENT_SCOPE)
 endfunction()
diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake
index 1c8ac26..8708938 100644
--- a/Modules/FindCUDA.cmake
+++ b/Modules/FindCUDA.cmake
@@ -18,35 +18,36 @@
 #
 # Tools for building CUDA C files: libraries and build dependencies.
 #
-# This script locates the NVIDIA CUDA C tools.  It should work on linux,
-# windows, and mac and should be reasonably up to date with CUDA C
+# This script locates the NVIDIA CUDA C tools.  It should work on Linux,
+# Windows, and macOS and should be reasonably up to date with CUDA C
 # releases.
 #
-# This script makes use of the standard find_package arguments of
-# <VERSION>, REQUIRED and QUIET.  CUDA_FOUND will report if an
+# This script makes use of the standard :command:`find_package` arguments of
+# ``<VERSION>``, ``REQUIRED`` and ``QUIET``.  ``CUDA_FOUND`` will report if an
 # acceptable version of CUDA was found.
 #
-# The script will prompt the user to specify CUDA_TOOLKIT_ROOT_DIR if
+# The script will prompt the user to specify ``CUDA_TOOLKIT_ROOT_DIR`` if
 # the prefix cannot be determined by the location of nvcc in the system
-# path and REQUIRED is specified to find_package().  To use a different
-# installed version of the toolkit set the environment variable
-# CUDA_BIN_PATH before running cmake (e.g.
-# CUDA_BIN_PATH=/usr/local/cuda1.0 instead of the default
-# /usr/local/cuda) or set CUDA_TOOLKIT_ROOT_DIR after configuring.  If
-# you change the value of CUDA_TOOLKIT_ROOT_DIR, various components that
+# path and ``REQUIRED`` is specified to :command:`find_package`.  To use
+# a different installed version of the toolkit set the environment variable
+# ``CUDA_BIN_PATH`` before running cmake (e.g.
+# ``CUDA_BIN_PATH=/usr/local/cuda1.0`` instead of the default
+# ``/usr/local/cuda``) or set ``CUDA_TOOLKIT_ROOT_DIR`` after configuring.  If
+# you change the value of ``CUDA_TOOLKIT_ROOT_DIR``, various components that
 # depend on the path will be relocated.
 #
-# It might be necessary to set CUDA_TOOLKIT_ROOT_DIR manually on certain
-# platforms, or to use a cuda runtime not installed in the default
-# location.  In newer versions of the toolkit the cuda library is
-# included with the graphics driver- be sure that the driver version
-# matches what is needed by the cuda runtime version.
+# It might be necessary to set ``CUDA_TOOLKIT_ROOT_DIR`` manually on certain
+# platforms, or to use a CUDA runtime not installed in the default
+# location.  In newer versions of the toolkit the CUDA library is
+# included with the graphics driver -- be sure that the driver version
+# matches what is needed by the CUDA runtime version.
 #
 # The following variables affect the behavior of the macros in the
 # script (in alphebetical order).  Note that any of these flags can be
 # changed multiple times in the same directory before calling
-# CUDA_ADD_EXECUTABLE, CUDA_ADD_LIBRARY, CUDA_COMPILE, CUDA_COMPILE_PTX,
-# CUDA_COMPILE_FATBIN, CUDA_COMPILE_CUBIN or CUDA_WRAP_SRCS::
+# ``CUDA_ADD_EXECUTABLE``, ``CUDA_ADD_LIBRARY``, ``CUDA_COMPILE``,
+# ``CUDA_COMPILE_PTX``, ``CUDA_COMPILE_FATBIN``, ``CUDA_COMPILE_CUBIN``
+# or ``CUDA_WRAP_SRCS``::
 #
 #   CUDA_64_BIT_DEVICE_CODE (Default matches host bit size)
 #   -- Set to ON to compile for 64 bit device code, OFF for 32 bit device code.
@@ -580,7 +581,7 @@
 # Makefile and similar generators don't define CMAKE_CONFIGURATION_TYPES, so we
 # need to add another entry for the CMAKE_BUILD_TYPE.  We also need to add the
 # standerd set of 4 build types (Debug, MinSizeRel, Release, and RelWithDebInfo)
-# for completeness.  We need run this loop in order to accomodate the addition
+# for completeness.  We need run this loop in order to accommodate the addition
 # of extra configuration types.  Duplicate entries will be removed by
 # REMOVE_DUPLICATES.
 set(CUDA_configuration_types ${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE} Debug MinSizeRel Release RelWithDebInfo)
diff --git a/Modules/FindCUDA/run_nvcc.cmake b/Modules/FindCUDA/run_nvcc.cmake
index f78119d..86051cf 100644
--- a/Modules/FindCUDA/run_nvcc.cmake
+++ b/Modules/FindCUDA/run_nvcc.cmake
@@ -181,7 +181,7 @@
 set(depends_CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS}")
 set(CUDA_VERSION @CUDA_VERSION@)
 if(CUDA_VERSION VERSION_LESS "3.0")
-  # Note that this will remove all occurances of -G.
+  # Note that this will remove all occurrences of -G.
   list(REMOVE_ITEM depends_CUDA_NVCC_FLAGS "-G")
 endif()
 
diff --git a/Modules/FindCxxTest.cmake b/Modules/FindCxxTest.cmake
index 9ba1ff3..2aa5f6f 100644
--- a/Modules/FindCxxTest.cmake
+++ b/Modules/FindCxxTest.cmake
@@ -145,7 +145,7 @@
 #
 # Version 1.3 (8/19/10) (CMake 2.8.3)
 #     Included patch by Simone Rossetto to check if either Python or Perl
-#     are present in the system.  Whichever intepreter that is detected
+#     are present in the system.  Whichever interpreter that is detected
 #     is now used to run the test generator program.  If both interpreters
 #     are detected, the CXXTEST_USE_PYTHON variable is obeyed.
 #
diff --git a/Modules/FindDCMTK.cmake b/Modules/FindDCMTK.cmake
index 0d86e8e..f348d3a 100644
--- a/Modules/FindDCMTK.cmake
+++ b/Modules/FindDCMTK.cmake
@@ -217,7 +217,7 @@
   if(NOT EXISTS ${EXTDCMTK_SOURCE_DIR})
     message(FATAL_ERROR
       "DCMTK build directory references
-nonexistant DCMTK source directory ${EXTDCMTK_SOURCE_DIR}")
+nonexistent DCMTK source directory ${EXTDCMTK_SOURCE_DIR}")
   endif()
 endif()
 
diff --git a/Modules/FindDevIL.cmake b/Modules/FindDevIL.cmake
index f6c8e3f..e904a30 100644
--- a/Modules/FindDevIL.cmake
+++ b/Modules/FindDevIL.cmake
@@ -70,5 +70,5 @@
 FIND_PACKAGE_HANDLE_STANDARD_ARGS(DevIL DEFAULT_MSG
                                   IL_LIBRARIES ILU_LIBRARIES
                                   IL_INCLUDE_DIR)
-# provide legacy variable for compatiblity
+# provide legacy variable for compatibility
 set(IL_FOUND ${DevIL_FOUND})
diff --git a/Modules/FindFLEX.cmake b/Modules/FindFLEX.cmake
index fef7fb4..3945b78 100644
--- a/Modules/FindFLEX.cmake
+++ b/Modules/FindFLEX.cmake
@@ -52,7 +52,7 @@
 #
 #
 #
-# Flex scanners oftenly use tokens defined by Bison: the code generated
+# Flex scanners often use tokens defined by Bison: the code generated
 # by Flex depends of the header generated by Bison.  This module also
 # defines a macro:
 #
diff --git a/Modules/FindFreetype.cmake b/Modules/FindFreetype.cmake
index 0e6d336..2acb4bc 100644
--- a/Modules/FindFreetype.cmake
+++ b/Modules/FindFreetype.cmake
@@ -115,6 +115,9 @@
   )
   include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
   select_library_configurations(FREETYPE)
+else()
+  # on Windows, ensure paths are in canonical format (forward slahes):
+  file(TO_CMAKE_PATH "${FREETYPE_LIBRARY}" FREETYPE_LIBRARY)
 endif()
 
 unset(FREETYPE_FIND_ARGS)
diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake
index 3279bf2..41b1002 100644
--- a/Modules/FindHDF5.cmake
+++ b/Modules/FindHDF5.cmake
@@ -479,7 +479,7 @@
             #if we detect that occurrence clear the suffix
             if(_suffix AND NOT TARGET ${HDF5_${_lang}_TARGET}${_suffix})
               if(NOT TARGET ${HDF5_${_lang}_TARGET})
-                #cant find this component with or without the suffix
+                #can't find this component with or without the suffix
                 #so bail out, and let the following locate HDF5
                 set(HDF5_FOUND FALSE)
                 break()
diff --git a/Modules/FindICU.cmake b/Modules/FindICU.cmake
index d9705d9..aa531d5 100644
--- a/Modules/FindICU.cmake
+++ b/Modules/FindICU.cmake
@@ -156,7 +156,7 @@
 
 
   # Find all ICU programs
-  list(APPEND icu_binary_suffixes "${_bin64}" "bin")
+  list(APPEND icu_binary_suffixes "${_bin64}" "bin" "sbin")
   foreach(program ${icu_programs})
     string(TOUPPER "${program}" program_upcase)
     set(cache_var "ICU_${program_upcase}_EXECUTABLE")
@@ -172,6 +172,11 @@
   # Find all ICU libraries
   list(APPEND icu_library_suffixes "${_lib64}" "lib")
   set(ICU_REQUIRED_LIBS_FOUND ON)
+  set(static_prefix )
+  # static icu libraries compiled with MSVC have the prefix 's'
+  if(MSVC)
+    set(static_prefix "s")
+  endif()
   foreach(component ${ICU_FIND_COMPONENTS})
     string(TOUPPER "${component}" component_upcase)
     set(component_cache "ICU_${component_upcase}_LIBRARY")
@@ -206,6 +211,20 @@
       list(APPEND component_debug_libnames "icui18nd")
     endif()
 
+    if(static_prefix)
+      unset(static_component_libnames)
+      unset(static_component_debug_libnames)
+      foreach(component_libname ${component_libnames})
+        list(APPEND static_component_libnames
+          ${static_prefix}${component_libname})
+      endforeach()
+      foreach(component_libname ${component_debug_libnames})
+        list(APPEND static_component_debug_libnames
+          ${static_prefix}${component_libname})
+      endforeach()
+      list(APPEND component_libnames ${static_component_libnames})
+      list(APPEND component_debug_libnames ${static_component_debug_libnames})
+    endif()
     find_library("${component_cache_release}" ${component_libnames}
       HINTS ${icu_roots}
       PATH_SUFFIXES ${icu_library_suffixes}
diff --git a/Modules/FindJNI.cmake b/Modules/FindJNI.cmake
index cebba10..96e3e21 100644
--- a/Modules/FindJNI.cmake
+++ b/Modules/FindJNI.cmake
@@ -25,7 +25,7 @@
 #   JAVA_INCLUDE_PATH2    = the include path to jni_md.h
 #   JAVA_AWT_INCLUDE_PATH = the include path to jawt.h
 
-# Expand {libarch} occurences to java_libarch subdirectory(-ies) and set ${_var}
+# Expand {libarch} occurrences to java_libarch subdirectory(-ies) and set ${_var}
 macro(java_append_library_directories _var)
     # Determine java arch-specific library subdir
     # Mostly based on openjdk/jdk/make/common/shared/Platform.gmk as of openjdk
@@ -46,7 +46,7 @@
         set(_java_libarch "arm" "aarch32")
     elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips")
         # mips* machines are bi-endian mostly so processor does not tell
-        # endianess of the underlying system.
+        # endianness of the underlying system.
         set(_java_libarch "${CMAKE_SYSTEM_PROCESSOR}" "mips" "mipsel" "mipseb" "mips64" "mips64el" "mipsn32" "mipsn32el")
     elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64le")
         set(_java_libarch "ppc64" "ppc64le")
diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake
index a451e6c..a3c87f8 100644
--- a/Modules/FindLAPACK.cmake
+++ b/Modules/FindLAPACK.cmake
@@ -37,6 +37,7 @@
 #
 # * Intel(mkl)
 # * OpenBLAS
+# * FLAME
 # * ACML
 # * Apple
 # * NAS
@@ -201,6 +202,20 @@
  endif()
 endif ()
 
+if (BLA_VENDOR STREQUAL "FLAME" OR BLA_VENDOR STREQUAL "All")
+ if(NOT LAPACK_LIBRARIES)
+  check_lapack_libraries(
+  LAPACK_LIBRARIES
+  LAPACK
+  cheev
+  ""
+  "flame"
+  "${BLAS_LIBRARIES}"
+  ""
+  )
+ endif()
+endif ()
+
 #acml lapack
  if (BLA_VENDOR MATCHES "ACML" OR BLA_VENDOR STREQUAL "All")
    if (BLAS_LIBRARIES MATCHES ".+acml.+")
diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake
index 7f4c44c..3320a07 100644
--- a/Modules/FindMPI.cmake
+++ b/Modules/FindMPI.cmake
@@ -346,7 +346,7 @@
   # library that has invalid or missing version information there would be warning
   # messages emitted by ld.so in the compiler output. In either case, we'll treat
   # the output as invalid.
-  if("${WRAPPER_OUTPUT}" MATCHES "undefined reference|unrecognized|need to set|no version information available")
+  if("${WRAPPER_OUTPUT}" MATCHES "undefined reference|unrecognized|need to set|no version information available|command not found")
     set(WRAPPER_RETURN 255)
   endif()
   # Ensure that no error output might be passed upwards.
diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake
index 7d4ed6a..06f7d96 100644
--- a/Modules/FindMatlab.cmake
+++ b/Modules/FindMatlab.cmake
@@ -356,7 +356,7 @@
   endif()
 
 
-  if(${win64} AND ${CMAKE_HOST_SYSTEM_PROCESSOR} MATCHES "64")
+  if(${win64} AND CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "64")
     set(APPEND_REG "/reg:64")
   else()
     set(APPEND_REG "/reg:32")
@@ -1198,7 +1198,7 @@
 
 
   # At this point, we have no other choice than trying to find it from PATH.
-  # If set by the user, this wont change
+  # If set by the user, this won't change
   find_program(
     _matlab_main_tmp
     NAMES matlab)
diff --git a/Modules/FindOpenCL.cmake b/Modules/FindOpenCL.cmake
index 0db2dd2..5d79110 100644
--- a/Modules/FindOpenCL.cmake
+++ b/Modules/FindOpenCL.cmake
@@ -120,9 +120,12 @@
     NAMES OpenCL
     PATHS
       ENV AMDAPPSDKROOT
+      ENV CUDA_PATH
     PATH_SUFFIXES
       lib/x86_64
-      lib/x64)
+      lib/x64
+      lib
+      lib64)
 endif()
 
 set(OpenCL_LIBRARIES ${OpenCL_LIBRARY})
diff --git a/Modules/FindOpenGL.cmake b/Modules/FindOpenGL.cmake
index 11843ef..91db5af 100644
--- a/Modules/FindOpenGL.cmake
+++ b/Modules/FindOpenGL.cmake
@@ -84,12 +84,28 @@
 # ``OpenGL::GLX`` or ``OpenGL::EGL``.
 #
 # Projects may use the ``OpenGL::GL`` target (or ``OPENGL_LIBRARIES`` variable)
-# to use legacy GL.  By default, these will use the legacy libGL library file.
-# If ``OPENGL_gl_LIBRARY`` is empty or not found and GLVND is available, the
-# ``OpenGL::GL`` target will use GLVND ``OpenGL::OpenGL`` and ``OpenGL::GLX``
-# (and the ``OPENGL_LIBRARIES`` variable will use the corresponding libraries).
-# Thus, for non-EGL-based Linux targets, the ``OpenGL::GL`` target is most
-# portable.
+# to use legacy GL interfaces.  These will use the legacy GL library located
+# by ``OPENGL_gl_LIBRARY``, if available.  If ``OPENGL_gl_LIBRARY`` is empty or
+# not found and GLVND is available, the ``OpenGL::GL`` target will use GLVND
+# ``OpenGL::OpenGL`` and ``OpenGL::GLX`` (and the ``OPENGL_LIBRARIES``
+# variable will use the corresponding libraries).  Thus, for non-EGL-based
+# Linux targets, the ``OpenGL::GL`` target is most portable.
+#
+# A ``OpenGL_GL_PREFERENCE`` variable may be set to specify the preferred way
+# to provide legacy GL interfaces in case multiple choices are available.
+# The value may be one of:
+#
+# ``GLVND``
+#  If the GLVND OpenGL and GLX libraries are available, prefer them.
+#  This forces ``OPENGL_gl_LIBRARY`` to be empty.
+#  This is the default if components were requested (since components
+#  correspond to GLVND libraries) or if policy :policy:`CMP0072` is
+#  set to ``NEW``.
+#
+# ``LEGACY``
+#  Prefer to use the legacy libGL library, if available.
+#  This is the default if no components were requested and
+#  policy :policy:`CMP0072` is not set to ``NEW``.
 #
 # For EGL targets the client must rely on GLVND support on the user's system.
 # Linking should use the ``OpenGL::OpenGL OpenGL::EGL`` targets.  Using GLES*
@@ -179,13 +195,6 @@
     /opt/graphics/OpenGL/include /usr/X11R6/include
   )
 
-  find_library(OPENGL_gl_LIBRARY
-    NAMES GL MesaGL
-    PATHS /opt/graphics/OpenGL/lib
-          /usr/openwin/lib
-          /usr/shlib /usr/X11R6/lib
-          ${_OPENGL_LIB_PATH}
-  )
   # Search for the GLVND libraries.  We do this regardless of COMPONENTS; we'll
   # take into account the COMPONENTS logic later.
   find_library(OPENGL_opengl_LIBRARY
@@ -213,6 +222,70 @@
           /usr/shlib /usr/X11R6/lib
   )
 
+  set(_OpenGL_GL_POLICY_WARN 0)
+  if(NOT DEFINED OpenGL_GL_PREFERENCE)
+    set(OpenGL_GL_PREFERENCE "")
+  endif()
+  if(NOT OpenGL_GL_PREFERENCE STREQUAL "")
+    # A preference has been explicitly specified.
+    if(NOT OpenGL_GL_PREFERENCE MATCHES "^(GLVND|LEGACY)$")
+      message(FATAL_ERROR
+        "OpenGL_GL_PREFERENCE value '${OpenGL_GL_PREFERENCE}' not recognized.  "
+        "Allowed values are 'GLVND' and 'LEGACY'."
+        )
+    endif()
+  elseif(OpenGL_FIND_COMPONENTS)
+    # No preference was explicitly specified, but the caller did request
+    # at least one GLVND component.  Prefer GLVND for legacy GL.
+    set(OpenGL_GL_PREFERENCE "GLVND")
+  else()
+    # No preference was explicitly specified and no GLVND components were
+    # requested.  Use a policy to choose the default.
+    cmake_policy(GET CMP0072 _OpenGL_GL_POLICY)
+    if("x${_OpenGL_GL_POLICY}x" STREQUAL "xNEWx")
+      set(OpenGL_GL_PREFERENCE "GLVND")
+    else()
+      set(OpenGL_GL_PREFERENCE "LEGACY")
+      if("x${_OpenGL_GL_POLICY}x" STREQUAL "xx")
+        set(_OpenGL_GL_POLICY_WARN 1)
+      endif()
+    endif()
+    unset(_OpenGL_GL_POLICY)
+  endif()
+
+  if("x${OpenGL_GL_PREFERENCE}x" STREQUAL "xGLVNDx" AND OPENGL_opengl_LIBRARY AND OPENGL_glx_LIBRARY)
+    # We can provide legacy GL using GLVND libraries.
+    # Do not use any legacy GL library.
+    set(OPENGL_gl_LIBRARY "")
+  else()
+    # We cannot provide legacy GL using GLVND libraries.
+    # Search for the legacy GL library.
+    find_library(OPENGL_gl_LIBRARY
+      NAMES GL MesaGL
+      PATHS /opt/graphics/OpenGL/lib
+            /usr/openwin/lib
+            /usr/shlib /usr/X11R6/lib
+            ${_OPENGL_LIB_PATH}
+      )
+  endif()
+
+  if(_OpenGL_GL_POLICY_WARN AND OPENGL_gl_LIBRARY AND OPENGL_opengl_LIBRARY AND OPENGL_glx_LIBRARY)
+    message(AUTHOR_WARNING
+      "Policy CMP0072 is not set: FindOpenGL prefers GLVND by default when available.  "
+      "Run \"cmake --help-policy CMP0072\" for policy details.  "
+      "Use the cmake_policy command to set the policy and suppress this warning."
+      "\n"
+      "FindOpenGL found both a legacy GL library:\n"
+      "  OPENGL_gl_LIBRARY: ${OPENGL_gl_LIBRARY}\n"
+      "and GLVND libraries for OpenGL and GLX:\n"
+      "  OPENGL_opengl_LIBRARY: ${OPENGL_opengl_LIBRARY}\n"
+      "  OPENGL_glx_LIBRARY: ${OPENGL_glx_LIBRARY}\n"
+      "OpenGL_GL_PREFERENCE has not been set to \"GLVND\" or \"LEGACY\", so for "
+      "compatibility with CMake 3.10 and below the legacy GL library will be used."
+      )
+  endif()
+  unset(_OpenGL_GL_POLICY_WARN)
+
   # FPHSA cannot handle "this OR that is required", so we conditionally set what
   # it must look for.  First clear any previous config we might have done:
   set(_OpenGL_REQUIRED_VARS)
diff --git a/Modules/FindOpenMP.cmake b/Modules/FindOpenMP.cmake
index 489476b..893ddc6 100644
--- a/Modules/FindOpenMP.cmake
+++ b/Modules/FindOpenMP.cmake
@@ -75,6 +75,7 @@
 # the OpenMP specification implemented by the ``<lang>`` compiler.
 
 cmake_policy(PUSH)
+cmake_policy(SET CMP0012 NEW) # if() recognizes numbers and booleans
 cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced
 cmake_policy(SET CMP0057 NEW) # if IN_LIST
 
@@ -230,6 +231,7 @@
                 DOC "Path to the ${_OPENMP_IMPLICIT_LIB_PLAIN} library for OpenMP"
                 HINTS ${OpenMP_${LANG}_IMPLICIT_LINK_DIRS}
                 CMAKE_FIND_ROOT_PATH_BOTH
+                NO_DEFAULT_PATH
               )
             endif()
             mark_as_advanced(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY)
@@ -244,6 +246,8 @@
           find_library(OpenMP_libiomp5md_LIBRARY
             NAMES "libiomp5md"
             HINTS ${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES}
+            CMAKE_FIND_ROOT_PATH_BOTH
+            NO_DEFAULT_PATH
           )
           mark_as_advanced(OpenMP_libiomp5md_LIBRARY)
         else()
diff --git a/Modules/FindOpenSSL.cmake b/Modules/FindOpenSSL.cmake
index 0187e0d..c358ff1 100644
--- a/Modules/FindOpenSSL.cmake
+++ b/Modules/FindOpenSSL.cmake
@@ -110,7 +110,7 @@
     #   * MTd for static-debug
 
     # Implementation details:
-    # We are using the libraries located in the VC subdir instead of the parent directory eventhough :
+    # We are using the libraries located in the VC subdir instead of the parent directory even though :
     # libeay32MD.lib is identical to ../libeay32.lib, and
     # ssleay32MD.lib is identical to ../ssleay32.lib
     # enable OPENSSL_USE_STATIC_LIBS to use the static libs located in lib/VC/static
diff --git a/Modules/FindPythonLibs.cmake b/Modules/FindPythonLibs.cmake
index 63ec9a8..341d5d9 100644
--- a/Modules/FindPythonLibs.cmake
+++ b/Modules/FindPythonLibs.cmake
@@ -122,6 +122,7 @@
   if(WIN32)
     find_library(PYTHON_DEBUG_LIBRARY
       NAMES python${_CURRENT_VERSION_NO_DOTS}_d python
+      NAMES_PER_DIR
       HINTS ${_Python_LIBRARY_PATH_HINT}
       PATHS
       [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs/Debug
@@ -145,20 +146,18 @@
       python${_CURRENT_VERSION}m
       python${_CURRENT_VERSION}u
       python${_CURRENT_VERSION}
+    NAMES_PER_DIR
     HINTS
       ${_Python_LIBRARY_PATH_HINT}
     PATHS
       ${PYTHON_FRAMEWORK_LIBRARIES}
       [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs
       [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs
-    # Avoid finding the .dll in the PATH.  We want the .lib.
-    NO_SYSTEM_ENVIRONMENT_PATH
   )
   # Look for the static library in the Python config directory
   find_library(PYTHON_LIBRARY
     NAMES python${_CURRENT_VERSION_NO_DOTS} python${_CURRENT_VERSION}
-    # Avoid finding the .dll in the PATH.  We want the .lib.
-    NO_SYSTEM_ENVIRONMENT_PATH
+    NAMES_PER_DIR
     # This is where the static library is usually located
     PATH_SUFFIXES python${_CURRENT_VERSION}/config
   )
diff --git a/Modules/FindRuby.cmake b/Modules/FindRuby.cmake
index a9f8d35..bd9f835 100644
--- a/Modules/FindRuby.cmake
+++ b/Modules/FindRuby.cmake
@@ -59,6 +59,9 @@
 endif()
 
 if(NOT Ruby_FIND_VERSION_EXACT)
+  list(APPEND _RUBY_POSSIBLE_EXECUTABLE_NAMES ruby2.4 ruby24)
+  list(APPEND _RUBY_POSSIBLE_EXECUTABLE_NAMES ruby2.3 ruby23)
+  list(APPEND _RUBY_POSSIBLE_EXECUTABLE_NAMES ruby2.2 ruby22)
   list(APPEND _RUBY_POSSIBLE_EXECUTABLE_NAMES ruby2.1 ruby21)
   list(APPEND _RUBY_POSSIBLE_EXECUTABLE_NAMES ruby2.0 ruby20)
   list(APPEND _RUBY_POSSIBLE_EXECUTABLE_NAMES ruby1.9 ruby19)
@@ -156,20 +159,35 @@
    set(RUBY_VERSION_MINOR 8)
    set(RUBY_VERSION_PATCH 0)
    # check whether we found 1.9.x
-   if(${RUBY_EXECUTABLE} MATCHES "ruby1.?9")
+   if(${RUBY_EXECUTABLE} MATCHES "ruby1\\.?9")
       set(RUBY_VERSION_MAJOR 1)
       set(RUBY_VERSION_MINOR 9)
    endif()
    # check whether we found 2.0.x
-   if(${RUBY_EXECUTABLE} MATCHES "ruby2.?0")
+   if(${RUBY_EXECUTABLE} MATCHES "ruby2\\.?0")
       set(RUBY_VERSION_MAJOR 2)
       set(RUBY_VERSION_MINOR 0)
    endif()
    # check whether we found 2.1.x
-   if(${RUBY_EXECUTABLE} MATCHES "ruby2.?1")
+   if(${RUBY_EXECUTABLE} MATCHES "ruby2\\.?1")
       set(RUBY_VERSION_MAJOR 2)
       set(RUBY_VERSION_MINOR 1)
    endif()
+   # check whether we found 2.2.x
+   if(${RUBY_EXECUTABLE} MATCHES "ruby2\\.?2")
+      set(RUBY_VERSION_MAJOR 2)
+      set(RUBY_VERSION_MINOR 2)
+   endif()
+   # check whether we found 2.3.x
+   if(${RUBY_EXECUTABLE} MATCHES "ruby2\\.?3")
+      set(RUBY_VERSION_MAJOR 2)
+      set(RUBY_VERSION_MINOR 3)
+   endif()
+   # check whether we found 2.4.x
+   if(${RUBY_EXECUTABLE} MATCHES "ruby2\\.?4")
+      set(RUBY_VERSION_MAJOR 2)
+      set(RUBY_VERSION_MINOR 4)
+   endif()
 endif()
 
 if(RUBY_VERSION_MAJOR)
diff --git a/Modules/FindTCL.cmake b/Modules/FindTCL.cmake
index b6e24a3..a711493 100644
--- a/Modules/FindTCL.cmake
+++ b/Modules/FindTCL.cmake
@@ -26,7 +26,7 @@
 #
 #
 # In an effort to remove some clutter and clear up some issues for
-# people who are not necessarily Tcl/Tk gurus/developpers, some
+# people who are not necessarily Tcl/Tk gurus/developers, some
 # variables were moved or removed.  Changes compared to CMake 2.4 are:
 #
 # ::
diff --git a/Modules/FindTclStub.cmake b/Modules/FindTclStub.cmake
index 9711bd6..51fc029 100644
--- a/Modules/FindTclStub.cmake
+++ b/Modules/FindTclStub.cmake
@@ -32,7 +32,7 @@
 #
 #
 # In an effort to remove some clutter and clear up some issues for
-# people who are not necessarily Tcl/Tk gurus/developpers, some
+# people who are not necessarily Tcl/Tk gurus/developers, some
 # variables were moved or removed.  Changes compared to CMake 2.4 are:
 #
 # ::
diff --git a/Modules/FindwxWidgets.cmake b/Modules/FindwxWidgets.cmake
index be84999..e08afe4 100644
--- a/Modules/FindwxWidgets.cmake
+++ b/Modules/FindwxWidgets.cmake
@@ -915,7 +915,7 @@
 endif()
 unset(_wx_lib_missing)
 
-# Check if a specfic version was requested by find_package().
+# Check if a specific version was requested by find_package().
 if(wxWidgets_FOUND)
   find_file(_filename wx/version.h PATHS ${wxWidgets_INCLUDE_DIRS} NO_DEFAULT_PATH)
   dbg_msg("_filename:  ${_filename}")
diff --git a/Modules/FindwxWindows.cmake b/Modules/FindwxWindows.cmake
index 76eb6be..054a1bf 100644
--- a/Modules/FindwxWindows.cmake
+++ b/Modules/FindwxWindows.cmake
@@ -390,7 +390,7 @@
 
   if (NOT WXWINDOWS_USE_SHARED_LIBS)
     set(WXWINDOWS_LIBRARIES ${WXWINDOWS_LIBRARIES}
-      ##  these ones dont seem required, in particular  ctl3d32 is not neccesary (Jan Woetzel 07/2003)
+      ##  these ones don't seem required, in particular  ctl3d32 is not necessary (Jan Woetzel 07/2003)
       #   ctl3d32
       debug ${WXWINDOWS_STATIC_DEBUG_LIBRARY_ZLIB}   optimized ${WXWINDOWS_STATIC_LIBRARY_ZLIB}
       debug ${WXWINDOWS_STATIC_DEBUG_LIBRARY_REGEX}  optimized ${WXWINDOWS_STATIC_LIBRARY_REGEX}
@@ -546,7 +546,7 @@
   endif()
 
 
-  ## not neccessary in wxWindows 2.4.1 and 2.6.2
+  ## not necessary in wxWindows 2.4.1 and 2.6.2
   ## but it may fix a previous bug, see
   ## http://lists.wxwindows.org/cgi-bin/ezmlm-cgi?8:mss:37574:200305:mpdioeneabobmgjenoap
   option(WXWINDOWS_SET_DEFINITIONS "Set additional defines for wxWindows" OFF)
diff --git a/Modules/ITKCompatibility.cmake b/Modules/ITKCompatibility.cmake
index fef0653..7d211b6 100644
--- a/Modules/ITKCompatibility.cmake
+++ b/Modules/ITKCompatibility.cmake
@@ -2,6 +2,6 @@
 # file Copyright.txt or https://cmake.org/licensing for details.
 
 
-# work around an old bug in ITK prior to verison 3.0
+# work around an old bug in ITK prior to version 3.0
 set(TIFF_RIGHT_VERSION 1)
 
diff --git a/Modules/Platform/Windows-Flang-Fortran.cmake b/Modules/Platform/Windows-Flang-Fortran.cmake
new file mode 100644
index 0000000..a4b1cf1
--- /dev/null
+++ b/Modules/Platform/Windows-Flang-Fortran.cmake
@@ -0,0 +1,3 @@
+include(Platform/Windows-MSVC)
+__windows_compiler_msvc(Fortran)
+set(CMAKE_Fortran_COMPILE_OBJECT "<CMAKE_Fortran_COMPILER> ${_COMPILE_Fortran} <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>")
diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake
index 4719563..0737c12 100644
--- a/Modules/Platform/Windows-MSVC.cmake
+++ b/Modules/Platform/Windows-MSVC.cmake
@@ -48,7 +48,11 @@
 endif()
 
 if(NOT MSVC_VERSION)
-  if(CMAKE_C_SIMULATE_VERSION)
+  if("x${CMAKE_C_COMPILER_ID}" STREQUAL "xMSVC")
+    set(_compiler_version ${CMAKE_C_COMPILER_VERSION})
+  elseif("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC")
+    set(_compiler_version ${CMAKE_CXX_COMPILER_VERSION})
+  elseif(CMAKE_C_SIMULATE_VERSION)
     set(_compiler_version ${CMAKE_C_SIMULATE_VERSION})
   elseif(CMAKE_CXX_SIMULATE_VERSION)
     set(_compiler_version ${CMAKE_CXX_SIMULATE_VERSION})
diff --git a/Modules/Qt4Macros.cmake b/Modules/Qt4Macros.cmake
index 0478918..aee4028 100644
--- a/Modules/Qt4Macros.cmake
+++ b/Modules/Qt4Macros.cmake
@@ -151,7 +151,7 @@
       set(moc_target ${ARGV3})
    endif()
    QT4_CREATE_MOC_COMMAND(${abs_infile} ${_outfile} "${moc_flags}" "" "${moc_target}")
-   set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOMOC TRUE)  # dont run automoc on this file
+   set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOMOC TRUE)  # don't run automoc on this file
 endmacro ()
 
 
diff --git a/Modules/SquishTestScript.cmake b/Modules/SquishTestScript.cmake
index cfdfaec..c0e1bea 100644
--- a/Modules/SquishTestScript.cmake
+++ b/Modules/SquishTestScript.cmake
@@ -34,7 +34,7 @@
 message(STATUS "squish_pre_command='${squish_pre_command}'")
 message(STATUS "squish_post_command='${squish_post_command}'")
 
-# parse enviornment variables
+# parse environment variables
 foreach(i ${squish_env_vars})
   message(STATUS "parsing env var key/value pair ${i}")
   string(REGEX MATCH "([^=]*)=(.*)" squish_env_name ${i})
diff --git a/Modules/UseEcos.cmake b/Modules/UseEcos.cmake
index 942bc38..700bfe6 100644
--- a/Modules/UseEcos.cmake
+++ b/Modules/UseEcos.cmake
@@ -181,7 +181,7 @@
 #the executable depends on ecos target.ld
    ECOS_ADD_TARGET_LIB(${ARGN})
 
-# when using nmake makefiles, the custom buildtype supresses the default cl.exe flags
+# when using nmake makefiles, the custom buildtype suppresses the default cl.exe flags
 # and the rules for creating objects are adjusted for gcc
    set(CMAKE_BUILD_TYPE CUSTOM_ECOS_BUILD)
    set(CMAKE_C_COMPILE_OBJECT     "<CMAKE_C_COMPILER>   <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>")
diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake
index 1182875..b5fc236 100644
--- a/Modules/UseJava.cmake
+++ b/Modules/UseJava.cmake
@@ -286,7 +286,7 @@
 #
 #    Example:
 #    create_javadoc(my_example_doc
-#      PACKAGES com.exmaple.foo com.example.bar
+#      PACKAGES com.example.foo com.example.bar
 #      SOURCEPATH "${CMAKE_CURRENT_SOURCE_DIR}"
 #      CLASSPATH ${CMAKE_JAVA_INCLUDE_PATH}
 #      WINDOWTITLE "My example"
@@ -481,6 +481,8 @@
     else()
         get_filename_component(_add_jar_OUTPUT_DIR ${_add_jar_OUTPUT_DIR} ABSOLUTE)
     endif()
+    # ensure output directory exists
+    file (MAKE_DIRECTORY "${_add_jar_OUTPUT_DIR}")
 
     if (_add_jar_ENTRY_POINT)
         set(_ENTRY_POINT_OPTION e)
@@ -515,7 +517,7 @@
        string(APPEND CMAKE_JAVA_INCLUDE_PATH_FINAL "${CMAKE_JAVA_INCLUDE_FLAG_SEP}${JAVA_INCLUDE_DIR}")
     endforeach()
 
-    set(CMAKE_JAVA_CLASS_OUTPUT_PATH "${_add_jar_OUTPUT_DIR}${CMAKE_FILES_DIRECTORY}/${_TARGET_NAME}.dir")
+    set(CMAKE_JAVA_CLASS_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_TARGET_NAME}.dir")
 
     set(_JAVA_TARGET_OUTPUT_NAME "${_TARGET_NAME}.jar")
     if (_add_jar_OUTPUT_NAME AND _add_jar_VERSION)
@@ -546,7 +548,7 @@
             list(APPEND _JAVA_COMPILE_FILELISTS ${_JAVA_FULL})
 
         elseif (_JAVA_EXT MATCHES ".java")
-            file(RELATIVE_PATH _JAVA_REL_BINARY_PATH ${_add_jar_OUTPUT_DIR} ${_JAVA_FULL})
+            file(RELATIVE_PATH _JAVA_REL_BINARY_PATH ${CMAKE_CURRENT_BINARY_DIR} ${_JAVA_FULL})
             file(RELATIVE_PATH _JAVA_REL_SOURCE_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${_JAVA_FULL})
             string(LENGTH ${_JAVA_REL_BINARY_PATH} _BIN_LEN)
             string(LENGTH ${_JAVA_REL_SOURCE_PATH} _SRC_LEN)
diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake
index c8b1cd7..b8bcd92 100644
--- a/Modules/UseSWIG.cmake
+++ b/Modules/UseSWIG.cmake
@@ -201,10 +201,32 @@
   if(SWIG_MODULE_${name}_EXTRA_FLAGS)
     set(swig_extra_flags ${swig_extra_flags} ${SWIG_MODULE_${name}_EXTRA_FLAGS})
   endif()
+  # IMPLICIT_DEPENDS below can not handle situations where a dependent file is
+  # removed. We need an extra step with timestamp and custom target, see #16830
+  # As this is needed only for Makefile generator do it conditionally
+  if(CMAKE_GENERATOR MATCHES "Make")
+    get_filename_component(swig_generated_timestamp
+      "${swig_generated_file_fullname}" NAME_WE)
+    set(swig_gen_target gen_${swig_generated_timestamp})
+    set(swig_generated_timestamp
+      "${swig_outdir}/${swig_generated_timestamp}.stamp")
+    set(swig_custom_output ${swig_generated_timestamp})
+    set(swig_custom_products
+      BYPRODUCTS "${swig_generated_file_fullname}" ${swig_extra_generated_files})
+    set(swig_timestamp_command
+      COMMAND ${CMAKE_COMMAND} -E touch ${swig_generated_timestamp})
+  else()
+    set(swig_custom_output
+      "${swig_generated_file_fullname}" ${swig_extra_generated_files})
+    set(swig_custom_products)
+    set(swig_timestamp_command)
+  endif()
   add_custom_command(
-    OUTPUT "${swig_generated_file_fullname}" ${swig_extra_generated_files}
+    OUTPUT ${swig_custom_output}
+    ${swig_custom_products}
     # Let's create the ${swig_outdir} at execution time, in case dir contains $(OutDir)
     COMMAND ${CMAKE_COMMAND} -E make_directory ${swig_outdir}
+    ${swig_timestamp_command}
     COMMAND "${SWIG_EXECUTABLE}"
     ARGS "-${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}"
     ${swig_source_file_flags}
@@ -219,6 +241,13 @@
     DEPENDS ${SWIG_MODULE_${name}_EXTRA_DEPS}
     IMPLICIT_DEPENDS CXX "${swig_source_file_fullname}"
     COMMENT "Swig source")
+  if(CMAKE_GENERATOR MATCHES "Make")
+    add_custom_target(${swig_gen_target} DEPENDS ${swig_generated_timestamp})
+  endif()
+  unset(swig_generated_timestamp)
+  unset(swig_custom_output)
+  unset(swig_custom_products)
+  unset(swig_timestamp_command)
   set_source_files_properties("${swig_generated_file_fullname}" ${swig_extra_generated_files}
     PROPERTIES GENERATED 1)
   set(${outfiles} "${swig_generated_file_fullname}" ${swig_extra_generated_files})
@@ -281,6 +310,10 @@
     ${_SAM_TYPE}
     ${swig_generated_sources}
     ${swig_other_sources})
+  if(CMAKE_GENERATOR MATCHES "Make")
+    # see IMPLICIT_DEPENDS above
+    add_dependencies(${SWIG_MODULE_${name}_REAL_NAME} ${swig_gen_target})
+  endif()
   if("${_SAM_TYPE}" STREQUAL "MODULE")
     set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES NO_SONAME ON)
   endif()
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index a4dd918..6c60675 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -216,6 +216,8 @@
   cmFileTimeComparison.cxx
   cmFileTimeComparison.h
   cmFortranParserImpl.cxx
+  cmFSPermissions.cxx
+  cmFSPermissions.h
   cmGeneratedFileStream.cxx
   cmGeneratorExpressionContext.cxx
   cmGeneratorExpressionContext.h
@@ -309,11 +311,14 @@
   cmPropertyMap.h
   cmQtAutoGen.cxx
   cmQtAutoGen.h
-  cmQtAutoGenDigest.h
+  cmQtAutoGenerator.cxx
+  cmQtAutoGenerator.h
   cmQtAutoGeneratorInitializer.cxx
   cmQtAutoGeneratorInitializer.h
-  cmQtAutoGenerators.cxx
-  cmQtAutoGenerators.h
+  cmQtAutoGeneratorMocUic.cxx
+  cmQtAutoGeneratorMocUic.h
+  cmQtAutoGeneratorRcc.cxx
+  cmQtAutoGeneratorRcc.h
   cmRST.cxx
   cmRST.h
   cmScriptGenerator.h
@@ -593,6 +598,7 @@
   cm_utf8.c
   cm_codecvt.hxx
   cm_codecvt.cxx
+  cm_thread.hxx
   )
 
 SET_PROPERTY(SOURCE cmProcessOutput.cxx APPEND PROPERTY COMPILE_DEFINITIONS
@@ -936,8 +942,13 @@
   endif()
 endif()
 
-if(WIN32)
+if(CYGWIN)
+  find_package(LibUUID)
+endif()
+if(WIN32 OR (CYGWIN AND LibUUID_FOUND))
   set(CPACK_SRCS ${CPACK_SRCS}
+    CPack/Wix/cmCMakeToWixPath.cxx
+    CPack/Wix/cmCMakeToWixPath.h
     CPack/WiX/cmCPackWIXGenerator.cxx
     CPack/WiX/cmCPackWIXGenerator.h
     CPack/WiX/cmWIXAccessControlList.cxx
@@ -958,7 +969,7 @@
     CPack/WiX/cmWIXShortcut.h
     CPack/WiX/cmWIXSourceWriter.cxx
     CPack/WiX/cmWIXSourceWriter.h
-  )
+    )
 endif()
 
 if(APPLE)
@@ -991,6 +1002,11 @@
       "See CMakeFiles/CMakeError.log for details of the failure.")
   endif()
 endif()
+if(CYGWIN AND LibUUID_FOUND)
+  target_link_libraries(CPackLib ${LibUUID_LIBRARIES})
+  include_directories(CPackLib ${LibUUID_INCLUDE_DIRS})
+  set_property(SOURCE CPack/cmCPackGeneratorFactory.cxx PROPERTY COMPILE_DEFINITIONS HAVE_LIBUUID)
+endif()
 if(CPACK_ENABLE_FREEBSD_PKG AND FREEBSD_PKG_INCLUDE_DIRS AND FREEBSD_PKG_LIBRARIES)
   target_link_libraries(CPackLib ${FREEBSD_PKG_LIBRARIES})
   include_directories(${FREEBSD_PKG_INCLUDE_DIRS})
@@ -1047,6 +1063,19 @@
 include (${CMake_BINARY_DIR}/Source/LocalUserOptions.cmake OPTIONAL)
 include (${CMake_SOURCE_DIR}/Source/LocalUserOptions.cmake OPTIONAL)
 
+if(WIN32)
+  # Add Windows executable version information.
+  configure_file("CMakeVersion.rc.in" "CMakeVersion.rc" @ONLY)
+
+  # We use a separate object library for this to work around a limitation of
+  # MinGW's windres tool with spaces in the path to the include directories.
+  add_library(CMakeVersion OBJECT "${CMAKE_CURRENT_BINARY_DIR}/CMakeVersion.rc")
+  set_property(TARGET CMakeVersion PROPERTY INCLUDE_DIRECTORIES "")
+  foreach(_tool ${_tools})
+    target_sources(${_tool} PRIVATE $<TARGET_OBJECTS:CMakeVersion>)
+  endforeach()
+endif()
+
 # Install tools
 
 foreach(_tool ${_tools})
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 4f8929b..eaa4679 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,5 +1,5 @@
 # CMake version number components.
 set(CMake_VERSION_MAJOR 3)
 set(CMake_VERSION_MINOR 10)
-set(CMake_VERSION_PATCH 0)
-set(CMake_VERSION_RC 5)
+set(CMake_VERSION_PATCH 20171120)
+#set(CMake_VERSION_RC 1)
diff --git a/Source/CMakeVersion.rc.in b/Source/CMakeVersion.rc.in
new file mode 100644
index 0000000..f4ca3d5
--- /dev/null
+++ b/Source/CMakeVersion.rc.in
@@ -0,0 +1,34 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#define VER_FILEVERSION             @CMake_VERSION_MAJOR@,@CMake_VERSION_MINOR@,@CMake_VERSION_PATCH@
+#define VER_FILEVERSION_STR         "@CMake_VERSION_MAJOR@.@CMake_VERSION_MINOR@.@CMake_VERSION_PATCH@\0"
+
+#define VER_PRODUCTVERSION          @CMake_VERSION_MAJOR@,@CMake_VERSION_MINOR@,@CMake_VERSION_PATCH@
+#define VER_PRODUCTVERSION_STR      "@CMake_VERSION@\0"
+
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION    	VER_FILEVERSION
+PRODUCTVERSION 	VER_PRODUCTVERSION
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904E4"
+        BEGIN
+            VALUE "FileVersion",      VER_FILEVERSION_STR
+            VALUE "ProductVersion",   VER_PRODUCTVERSION_STR
+        END
+    END
+
+    BLOCK "VarFileInfo"
+    BEGIN
+        /* The following line should only be modified for localized versions.     */
+        /* It consists of any number of WORD,WORD pairs, with each pair           */
+        /* describing a language,codepage combination supported by the file.      */
+        /*                                                                        */
+        /* For example, a file might have values "0x409,1252" indicating that it  */
+        /* supports English language (0x409) in the Windows ANSI codepage (1252). */
+
+        VALUE "Translation", 0x409, 1252
+    END
+END
diff --git a/Source/CPack/WiX/cmCMakeToWixPath.cxx b/Source/CPack/WiX/cmCMakeToWixPath.cxx
new file mode 100644
index 0000000..0b0e42a
--- /dev/null
+++ b/Source/CPack/WiX/cmCMakeToWixPath.cxx
@@ -0,0 +1,39 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmCMakeToWixPath.h"
+
+#include "cmSystemTools.h"
+
+#include <string>
+#include <vector>
+
+#ifdef __CYGWIN__
+#include <sys/cygwin.h>
+std::string CMakeToWixPath(const std::string& cygpath)
+{
+  std::vector<char> winpath_chars;
+  ssize_t winpath_size;
+
+  // Get the required buffer size.
+  winpath_size =
+    cygwin_conv_path(CCP_POSIX_TO_WIN_A, cygpath.c_str(), nullptr, 0);
+  if (winpath_size <= 0) {
+    return cygpath;
+  }
+
+  winpath_chars.assign(static_cast<size_t>(winpath_size) + 1, '\0');
+
+  winpath_size = cygwin_conv_path(CCP_POSIX_TO_WIN_A, cygpath.c_str(),
+                                  winpath_chars.data(), winpath_size);
+  if (winpath_size < 0) {
+    return cygpath;
+  }
+
+  return cmSystemTools::TrimWhitespace(winpath_chars.data());
+}
+#else
+std::string CMakeToWixPath(const std::string& path)
+{
+  return path;
+}
+#endif
diff --git a/Source/CPack/WiX/cmCMakeToWixPath.h b/Source/CPack/WiX/cmCMakeToWixPath.h
new file mode 100644
index 0000000..8bb9e04
--- /dev/null
+++ b/Source/CPack/WiX/cmCMakeToWixPath.h
@@ -0,0 +1,12 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmCMakeToWixPath_h
+#define cmCMakeToWixPath_h
+
+#include "cmConfigure.h" //IWYU pragma: keep
+
+#include <string>
+
+std::string CMakeToWixPath(const std::string& cygpath);
+
+#endif // cmCMakeToWixPath_h
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
index ba07d08..a0bc0ea 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
@@ -22,7 +22,13 @@
 #include "cmsys/FStream.hxx"
 #include "cmsys/SystemTools.hxx"
 
-#include <rpc.h> // for GUID generation
+#ifdef _WIN32
+#include <rpc.h> // for GUID generation (windows only)
+#else
+#include <uuid/uuid.h> // for GUID generation (libuuid)
+#endif
+
+#include "cmCMakeToWixPath.h"
 
 cmCPackWIXGenerator::cmCPackWIXGenerator()
   : Patch(0)
@@ -110,7 +116,7 @@
   std::ostringstream command;
   command << QuotePath(executable);
   command << " -nologo";
-  command << " -out " << QuotePath(packageFileNames.at(0));
+  command << " -out " << QuotePath(CMakeToWixPath(packageFileNames.at(0)));
 
   for (std::string const& ext : this->LightExtensions) {
     command << " -ext " << QuotePath(ext);
@@ -270,11 +276,12 @@
     std::string objectFilename =
       this->CPackTopLevel + "/" + uniqueBaseName + ".wixobj";
 
-    if (!RunCandleCommand(sourceFilename, objectFilename)) {
+    if (!RunCandleCommand(CMakeToWixPath(sourceFilename),
+                          CMakeToWixPath(objectFilename))) {
       return false;
     }
 
-    objectFiles << " " << QuotePath(objectFilename);
+    objectFiles << " " << QuotePath(CMakeToWixPath(objectFilename));
   }
 
   AppendUserSuppliedExtraObjects(objectFiles);
@@ -320,10 +327,10 @@
   CopyDefinition(includeFile, "CPACK_PACKAGE_VENDOR");
   CopyDefinition(includeFile, "CPACK_PACKAGE_NAME");
   CopyDefinition(includeFile, "CPACK_PACKAGE_VERSION");
-  CopyDefinition(includeFile, "CPACK_WIX_LICENSE_RTF");
-  CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_ICON");
-  CopyDefinition(includeFile, "CPACK_WIX_UI_BANNER");
-  CopyDefinition(includeFile, "CPACK_WIX_UI_DIALOG");
+  CopyDefinition(includeFile, "CPACK_WIX_LICENSE_RTF", DefinitionType::PATH);
+  CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_ICON", DefinitionType::PATH);
+  CopyDefinition(includeFile, "CPACK_WIX_UI_BANNER", DefinitionType::PATH);
+  CopyDefinition(includeFile, "CPACK_WIX_UI_DIALOG", DefinitionType::PATH);
   SetOptionIfNotSet("CPACK_WIX_PROGRAM_MENU_FOLDER",
                     GetOption("CPACK_PACKAGE_NAME"));
   CopyDefinition(includeFile, "CPACK_WIX_PROGRAM_MENU_FOLDER");
@@ -390,11 +397,16 @@
 }
 
 void cmCPackWIXGenerator::CopyDefinition(cmWIXSourceWriter& source,
-                                         std::string const& name)
+                                         std::string const& name,
+                                         DefinitionType type)
 {
   const char* value = GetOption(name.c_str());
   if (value) {
-    AddDefinition(source, name, value);
+    if (type == DefinitionType::PATH) {
+      AddDefinition(source, name, CMakeToWixPath(value));
+    } else {
+      AddDefinition(source, name, value);
+    }
   }
 }
 
@@ -966,6 +978,7 @@
 
 std::string cmCPackWIXGenerator::GenerateGUID()
 {
+#ifdef _WIN32
   UUID guid;
   UuidCreate(&guid);
 
@@ -975,6 +988,14 @@
   std::string result =
     cmsys::Encoding::ToNarrow(reinterpret_cast<wchar_t*>(tmp));
   RpcStringFreeW(&tmp);
+#else
+  uuid_t guid;
+  char guid_ch[37] = { 0 };
+
+  uuid_generate(guid);
+  uuid_unparse(guid, guid_ch);
+  std::string result = guid_ch;
+#endif
 
   return cmSystemTools::UpperCase(result);
 }
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h
index b2633a7..128a04d 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.h
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.h
@@ -48,6 +48,12 @@
   typedef std::map<std::string, size_t> ambiguity_map_t;
   typedef std::set<std::string> extension_set_t;
 
+  enum class DefinitionType
+  {
+    STRING,
+    PATH
+  };
+
   bool InitializeWiXConfiguration();
 
   bool PackageFilesImpl();
@@ -58,7 +64,8 @@
 
   void CreateWiXProductFragmentIncludeFile();
 
-  void CopyDefinition(cmWIXSourceWriter& source, std::string const& name);
+  void CopyDefinition(cmWIXSourceWriter& source, std::string const& name,
+                      DefinitionType type = DefinitionType::STRING);
 
   void AddDefinition(cmWIXSourceWriter& source, std::string const& name,
                      std::string const& value);
diff --git a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
index b4cd1a3..dd3caf9 100644
--- a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
+++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
@@ -11,6 +11,8 @@
 
 #include "cm_sys_stat.h"
 
+#include "cmCMakeToWixPath.h"
+
 cmWIXFilesSourceWriter::cmWIXFilesSourceWriter(cmCPackLog* logger,
                                                std::string const& filename,
                                                GuidType componentGuidType)
@@ -139,7 +141,7 @@
   patch.ApplyFragment(componentId, *this);
   BeginElement("File");
   AddAttribute("Id", fileId);
-  AddAttribute("Source", filePath);
+  AddAttribute("Source", CMakeToWixPath(filePath));
   AddAttribute("KeyPath", "yes");
 
   mode_t fileMode = 0;
diff --git a/Source/CPack/WiX/cmWIXPatchParser.cxx b/Source/CPack/WiX/cmWIXPatchParser.cxx
index e6aeed3..c6ca944 100644
--- a/Source/CPack/WiX/cmWIXPatchParser.cxx
+++ b/Source/CPack/WiX/cmWIXPatchParser.cxx
@@ -90,7 +90,7 @@
     }
   }
 
-  /* add any additional attributes for the fragement */
+  /* add any additional attributes for the fragment */
   if (!new_element) {
     ReportValidationError("No 'Id' specified for 'CPackWixFragment' element");
   } else {
diff --git a/Source/CPack/bills-comments.txt b/Source/CPack/bills-comments.txt
index c3b4ee8..1aaf9af 100644
--- a/Source/CPack/bills-comments.txt
+++ b/Source/CPack/bills-comments.txt
@@ -31,7 +31,7 @@
 
 
 cmCPackGenericGenerator::InstallProject is used for both source and binary
-packages.  It is controled based on values set in CPACK_ variables.
+packages.  It is controlled based on values set in CPACK_ variables.
 
 
 InstallProject
diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx
index 1e1543f..bb35623 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -411,6 +411,7 @@
   std::string temp_image = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
   temp_image += "/temp.dmg";
 
+  std::string create_error;
   std::ostringstream temp_image_command;
   temp_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
   temp_image_command << " create";
@@ -421,9 +422,11 @@
   temp_image_command << " -format " << temp_image_format;
   temp_image_command << " \"" << temp_image << "\"";
 
-  if (!this->RunCommand(temp_image_command)) {
+  if (!this->RunCommand(temp_image_command, &create_error)) {
     cmCPackLogger(cmCPackLog::LOG_ERROR,
-                  "Error generating temporary disk image." << std::endl);
+                  "Error generating temporary disk image." << std::endl
+                                                           << create_error
+                                                           << std::endl);
 
     return 0;
   }
@@ -464,15 +467,17 @@
 
     // Optionally set the custom icon flag for the image ...
     if (!had_error && !cpack_package_icon.empty()) {
+      std::string error;
       std::ostringstream setfile_command;
       setfile_command << this->GetOption("CPACK_COMMAND_SETFILE");
       setfile_command << " -a C";
       setfile_command << " \"" << temp_mount << "\"";
 
-      if (!this->RunCommand(setfile_command)) {
+      if (!this->RunCommand(setfile_command, &error)) {
         cmCPackLogger(cmCPackLog::LOG_ERROR,
                       "Error assigning custom icon to temporary disk image."
-                        << std::endl);
+                        << std::endl
+                        << error << std::endl);
 
         had_error = true;
       }
@@ -717,9 +722,12 @@
   final_image_command << " zlib-level=9";
   final_image_command << " -o \"" << output_file << "\"";
 
-  if (!this->RunCommand(final_image_command)) {
+  std::string convert_error;
+
+  if (!this->RunCommand(final_image_command, &convert_error)) {
     cmCPackLogger(cmCPackLog::LOG_ERROR, "Error compressing disk image."
-                    << std::endl);
+                    << std::endl
+                    << convert_error << std::endl);
 
     return 0;
   }
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index ecb5adb..be75a9f 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -12,6 +12,7 @@
 #include "cmCPackComponentGroup.h"
 #include "cmCPackLog.h"
 #include "cmCryptoHash.h"
+#include "cmFSPermissions.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
@@ -201,6 +202,29 @@
     cmSystemTools::PutEnv("DESTDIR=");
   }
 
+  // prepare default created directory permissions
+  mode_t default_dir_mode_v = 0;
+  mode_t* default_dir_mode = nullptr;
+  const char* default_dir_install_permissions =
+    this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
+  if (default_dir_install_permissions && *default_dir_install_permissions) {
+    std::vector<std::string> items;
+    cmSystemTools::ExpandListArgument(default_dir_install_permissions, items);
+    for (const auto& arg : items) {
+      if (!cmFSPermissions::stringToModeT(arg, default_dir_mode_v)) {
+        cmCPackLogger(cmCPackLog::LOG_ERROR, "Invalid permission value '"
+                        << arg
+                        << "'."
+                           " CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS "
+                           "value is invalid."
+                        << std::endl);
+        return 0;
+      }
+    }
+
+    default_dir_mode = &default_dir_mode_v;
+  }
+
   // If the CPackConfig file sets CPACK_INSTALL_COMMANDS then run them
   // as listed
   if (!this->InstallProjectViaInstallCommands(setDestDir,
@@ -218,15 +242,15 @@
   // If the CPackConfig file sets CPACK_INSTALLED_DIRECTORIES
   // then glob it and copy it to CPACK_TEMPORARY_DIRECTORY
   // This is used in Source packaging
-  if (!this->InstallProjectViaInstalledDirectories(setDestDir,
-                                                   tempInstallDirectory)) {
+  if (!this->InstallProjectViaInstalledDirectories(
+        setDestDir, tempInstallDirectory, default_dir_mode)) {
     return 0;
   }
 
   // If the project is a CMAKE project then run pre-install
   // and then read the cmake_install script to run it
-  if (!this->InstallProjectViaInstallCMakeProjects(setDestDir,
-                                                   bareTempInstallDirectory)) {
+  if (!this->InstallProjectViaInstallCMakeProjects(
+        setDestDir, bareTempInstallDirectory, default_dir_mode)) {
     return 0;
   }
 
@@ -274,7 +298,8 @@
 }
 
 int cmCPackGenerator::InstallProjectViaInstalledDirectories(
-  bool setDestDir, const std::string& tempInstallDirectory)
+  bool setDestDir, const std::string& tempInstallDirectory,
+  const mode_t* default_dir_mode)
 {
   (void)setDestDir;
   (void)tempInstallDirectory;
@@ -385,7 +410,8 @@
           // make sure directory exists for symlink
           std::string destDir =
             cmSystemTools::GetFilenamePath(symlinked.second);
-          if (!destDir.empty() && !cmSystemTools::MakeDirectory(destDir)) {
+          if (!destDir.empty() &&
+              !cmSystemTools::MakeDirectory(destDir, default_dir_mode)) {
             cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot create dir: "
                             << destDir << "\nTrying to create symlink: "
                             << symlinked.second << "--> " << symlinked.first
@@ -464,7 +490,8 @@
 }
 
 int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
-  bool setDestDir, const std::string& baseTempInstallDirectory)
+  bool setDestDir, const std::string& baseTempInstallDirectory,
+  const mode_t* default_dir_mode)
 {
   const char* cmakeProjects = this->GetOption("CPACK_INSTALL_CMAKE_PROJECTS");
   const char* cmakeGenerator = this->GetOption("CPACK_CMAKE_GENERATOR");
@@ -631,6 +658,13 @@
           }
         }
 
+        const char* default_dir_inst_permissions =
+          this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
+        if (default_dir_inst_permissions && *default_dir_inst_permissions) {
+          mf.AddDefinition("CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS",
+                           default_dir_inst_permissions);
+        }
+
         if (!setDestDir) {
           tempInstallDirectory += this->GetPackagingInstallPrefix();
         }
@@ -690,7 +724,7 @@
           cmCPackLogger(cmCPackLog::LOG_DEBUG, "- Creating directory: '"
                           << dir << "'" << std::endl);
 
-          if (!cmsys::SystemTools::MakeDirectory(dir.c_str())) {
+          if (!cmsys::SystemTools::MakeDirectory(dir, default_dir_mode)) {
             cmCPackLogger(
               cmCPackLog::LOG_ERROR,
               "Problem creating temporary directory: " << dir << std::endl);
@@ -700,8 +734,8 @@
           mf.AddDefinition("CMAKE_INSTALL_PREFIX",
                            tempInstallDirectory.c_str());
 
-          if (!cmsys::SystemTools::MakeDirectory(
-                tempInstallDirectory.c_str())) {
+          if (!cmsys::SystemTools::MakeDirectory(tempInstallDirectory,
+                                                 default_dir_mode)) {
             cmCPackLogger(cmCPackLog::LOG_ERROR,
                           "Problem creating temporary directory: "
                             << tempInstallDirectory << std::endl);
diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h
index 4e3a6e0..8100b66 100644
--- a/Source/CPack/cmCPackGenerator.h
+++ b/Source/CPack/cmCPackGenerator.h
@@ -12,6 +12,7 @@
 
 #include "cmCPackComponentGroup.h"
 #include "cmSystemTools.h"
+#include "cm_sys_stat.h"
 
 class cmCPackLog;
 class cmInstalledFile;
@@ -168,9 +169,11 @@
   virtual int InstallProjectViaInstallScript(
     bool setDestDir, const std::string& tempInstallDirectory);
   virtual int InstallProjectViaInstalledDirectories(
-    bool setDestDir, const std::string& tempInstallDirectory);
+    bool setDestDir, const std::string& tempInstallDirectory,
+    const mode_t* default_dir_mode);
   virtual int InstallProjectViaInstallCMakeProjects(
-    bool setDestDir, const std::string& tempInstallDirectory);
+    bool setDestDir, const std::string& tempInstallDirectory,
+    const mode_t* default_dir_mode);
 
   /**
    * The various level of support of
diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx
index 4b81bbc..47e7527 100644
--- a/Source/CPack/cmCPackGeneratorFactory.cxx
+++ b/Source/CPack/cmCPackGeneratorFactory.cxx
@@ -40,7 +40,7 @@
 #include "cmCPackRPMGenerator.h"
 #endif
 
-#ifdef _WIN32
+#if defined(_WIN32) || (defined(__CYGWIN__) && defined(HAVE_LIBUUID))
 #include "WiX/cmCPackWIXGenerator.h"
 #endif
 
@@ -87,7 +87,7 @@
     this->RegisterGenerator("7Z", "7-Zip file format",
                             cmCPack7zGenerator::CreateGenerator);
   }
-#ifdef _WIN32
+#if defined(_WIN32) || (defined(__CYGWIN__) && defined(HAVE_LIBUUID))
   if (cmCPackWIXGenerator::CanGenerate()) {
     this->RegisterGenerator("WIX", "MSI file format via WiX tools",
                             cmCPackWIXGenerator::CreateGenerator);
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index a0d68a0..b603758 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -10,6 +10,7 @@
 #include "cmake.h"
 
 #include "cmsys/Process.h"
+#include <chrono>
 #include <stdlib.h>
 
 cmCTestBuildAndTestHandler::cmCTestBuildAndTestHandler()
@@ -192,7 +193,7 @@
 
   // we need to honor the timeout specified, the timeout include cmake, build
   // and test time
-  double clock_start = cmSystemTools::GetTime();
+  auto clock_start = std::chrono::steady_clock::now();
 
   // make sure the binary dir is there
   out << "Internal cmake changing into directory: " << this->BinaryDir
@@ -222,10 +223,12 @@
     this->BuildTargets.push_back("");
   }
   for (std::string const& tar : this->BuildTargets) {
-    double remainingTime = 0;
+    std::chrono::duration<double> remainingTime = std::chrono::seconds(0);
     if (this->Timeout > 0) {
-      remainingTime = this->Timeout - cmSystemTools::GetTime() + clock_start;
-      if (remainingTime <= 0) {
+      remainingTime = std::chrono::duration<double>(this->Timeout) -
+        std::chrono::duration_cast<std::chrono::seconds>(
+                        std::chrono::steady_clock::now() - clock_start);
+      if (remainingTime <= std::chrono::seconds(0)) {
         if (outstring) {
           *outstring = "--build-and-test timeout exceeded. ";
         }
@@ -248,7 +251,7 @@
     int retVal = cm.GetGlobalGenerator()->Build(
       this->SourceDir, this->BinaryDir, this->BuildProject, tar, output,
       this->BuildMakeProgram, config, !this->BuildNoClean, false, false,
-      remainingTime);
+      remainingTime.count());
     out << output;
     // if the build failed then return
     if (retVal) {
@@ -320,10 +323,12 @@
   out << "\n";
 
   // how much time is remaining
-  double remainingTime = 0;
+  std::chrono::duration<double> remainingTime = std::chrono::seconds(0);
   if (this->Timeout > 0) {
-    remainingTime = this->Timeout - cmSystemTools::GetTime() + clock_start;
-    if (remainingTime <= 0) {
+    remainingTime = std::chrono::duration<double>(this->Timeout) -
+      std::chrono::duration_cast<std::chrono::seconds>(
+                      std::chrono::steady_clock::now() - clock_start);
+    if (remainingTime <= std::chrono::seconds(0)) {
       if (outstring) {
         *outstring = "--build-and-test timeout exceeded. ";
       }
@@ -332,7 +337,7 @@
   }
 
   int runTestRes = this->CTest->RunTest(testCommand, &outs, &retval, nullptr,
-                                        remainingTime, nullptr);
+                                        remainingTime.count(), nullptr);
 
   if (runTestRes != cmsysProcess_State_Exited || retval != 0) {
     out << "Test command failed: " << testCommand[0] << "\n";
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index f4fc769..f25c9c3 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -17,6 +17,7 @@
 #include <set>
 #include <stdlib.h>
 #include <string.h>
+#include <type_traits>
 
 static const char* cmCTestErrorMatches[] = {
   "^[Bb]us [Ee]rror",
@@ -327,7 +328,7 @@
 
   // Create a last build log
   cmGeneratedFileStream ofs;
-  double elapsed_time_start = cmSystemTools::GetTime();
+  auto elapsed_time_start = std::chrono::steady_clock::now();
   if (!this->StartLogFile("Build", ofs)) {
     cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create build log file"
                  << std::endl);
@@ -406,7 +407,7 @@
 
   // Remember start build time
   this->StartBuild = this->CTest->CurrentTime();
-  this->StartBuildTime = cmSystemTools::GetTime();
+  this->StartBuildTime = std::chrono::system_clock::now();
   int retVal = 0;
   int res = cmsysProcess_State_Exited;
   if (!this->CTest->GetShowOnly()) {
@@ -420,8 +421,9 @@
 
   // Remember end build time and calculate elapsed time
   this->EndBuild = this->CTest->CurrentTime();
-  this->EndBuildTime = cmSystemTools::GetTime();
-  double elapsed_build_time = cmSystemTools::GetTime() - elapsed_time_start;
+  this->EndBuildTime = std::chrono::system_clock::now();
+  auto elapsed_build_time =
+    std::chrono::steady_clock::now() - elapsed_time_start;
 
   // Cleanups strings in the errors and warnings list.
   if (!this->SimplifySourceDir.empty()) {
@@ -486,8 +488,7 @@
   this->CTest->GenerateSubprojectsOutput(xml);
   xml.StartElement("Build");
   xml.Element("StartDateTime", this->StartBuild);
-  xml.Element("StartBuildTime",
-              static_cast<unsigned int>(this->StartBuildTime));
+  xml.Element("StartBuildTime", this->StartBuildTime);
   xml.Element("BuildCommand", this->GetMakeCommand());
 }
 
@@ -633,8 +634,8 @@
   }
 }
 
-void cmCTestBuildHandler::GenerateXMLFooter(cmXMLWriter& xml,
-                                            double elapsed_build_time)
+void cmCTestBuildHandler::GenerateXMLFooter(
+  cmXMLWriter& xml, std::chrono::duration<double> elapsed_build_time)
 {
   xml.StartElement("Log");
   xml.Attribute("Encoding", "base64");
@@ -642,9 +643,11 @@
   xml.EndElement(); // Log
 
   xml.Element("EndDateTime", this->EndBuild);
-  xml.Element("EndBuildTime", static_cast<unsigned int>(this->EndBuildTime));
-  xml.Element("ElapsedMinutes",
-              static_cast<int>(elapsed_build_time / 6) / 10.0);
+  xml.Element("EndBuildTime", this->EndBuildTime);
+  xml.Element(
+    "ElapsedMinutes",
+    std::chrono::duration_cast<std::chrono::minutes>(elapsed_build_time)
+      .count());
   xml.EndElement(); // Build
   this->CTest->EndXML(xml);
 }
diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h
index 6e71ad6..d1b9b2e 100644
--- a/Source/CTest/cmCTestBuildHandler.h
+++ b/Source/CTest/cmCTestBuildHandler.h
@@ -9,6 +9,7 @@
 
 #include "cmProcessOutput.h"
 #include "cmsys/RegularExpression.hxx"
+#include <chrono>
 #include <deque>
 #include <iosfwd>
 #include <stddef.h>
@@ -86,14 +87,15 @@
   void GenerateXMLHeader(cmXMLWriter& xml);
   void GenerateXMLLaunched(cmXMLWriter& xml);
   void GenerateXMLLogScraped(cmXMLWriter& xml);
-  void GenerateXMLFooter(cmXMLWriter& xml, double elapsed_build_time);
+  void GenerateXMLFooter(cmXMLWriter& xml,
+                         std::chrono::duration<double> elapsed_build_time);
   bool IsLaunchedErrorFile(const char* fname);
   bool IsLaunchedWarningFile(const char* fname);
 
   std::string StartBuild;
   std::string EndBuild;
-  double StartBuildTime;
-  double EndBuildTime;
+  std::chrono::system_clock::time_point StartBuildTime;
+  std::chrono::system_clock::time_point EndBuildTime;
 
   std::vector<std::string> CustomErrorMatches;
   std::vector<std::string> CustomErrorExceptions;
diff --git a/Source/CTest/cmCTestConfigureHandler.cxx b/Source/CTest/cmCTestConfigureHandler.cxx
index 56a038e..ab77986 100644
--- a/Source/CTest/cmCTestConfigureHandler.cxx
+++ b/Source/CTest/cmCTestConfigureHandler.cxx
@@ -4,11 +4,12 @@
 
 #include "cmCTest.h"
 #include "cmGeneratedFileStream.h"
-#include "cmSystemTools.h"
 #include "cmXMLWriter.h"
 
+#include <chrono>
 #include <ostream>
 #include <string>
+#include <type_traits>
 
 cmCTestConfigureHandler::cmCTestConfigureHandler()
 {
@@ -43,7 +44,7 @@
     return -1;
   }
 
-  double elapsed_time_start = cmSystemTools::GetTime();
+  auto elapsed_time_start = std::chrono::steady_clock::now();
   std::string output;
   int retVal = 0;
   int res = 0;
@@ -55,8 +56,7 @@
       return 1;
     }
     std::string start_time = this->CTest->CurrentTime();
-    unsigned int start_time_time =
-      static_cast<unsigned int>(cmSystemTools::GetTime());
+    auto start_time_time = std::chrono::system_clock::now();
 
     cmGeneratedFileStream ofs;
     this->StartLogFile("Configure", ofs);
@@ -82,12 +82,11 @@
       xml.Element("Log", output);
       xml.Element("ConfigureStatus", retVal);
       xml.Element("EndDateTime", this->CTest->CurrentTime());
-      xml.Element("EndConfigureTime",
-                  static_cast<unsigned int>(cmSystemTools::GetTime()));
-      xml.Element(
-        "ElapsedMinutes",
-        static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start) / 6) /
-          10.0);
+      xml.Element("EndConfigureTime", std::chrono::system_clock::now());
+      xml.Element("ElapsedMinutes",
+                  std::chrono::duration_cast<std::chrono::minutes>(
+                    std::chrono::steady_clock::now() - elapsed_time_start)
+                    .count());
       xml.EndElement(); // Configure
       this->CTest->EndXML(xml);
     }
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index 56eeceb..bbfe9bd 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -21,11 +21,13 @@
 #include "cmsys/Process.h"
 #include "cmsys/RegularExpression.hxx"
 #include <algorithm>
+#include <chrono>
 #include <iomanip>
 #include <iterator>
 #include <sstream>
 #include <stdio.h>
 #include <stdlib.h>
+#include <type_traits>
 #include <utility>
 
 class cmMakefile;
@@ -173,14 +175,13 @@
   this->CTest->StartXML(xml, this->AppendXML);
   xml.StartElement("CoverageLog");
   xml.Element("StartDateTime", this->CTest->CurrentTime());
-  xml.Element("StartTime",
-              static_cast<unsigned int>(cmSystemTools::GetTime()));
+  xml.Element("StartTime", std::chrono::system_clock::now());
 }
 
 void cmCTestCoverageHandler::EndCoverageLogXML(cmXMLWriter& xml)
 {
   xml.Element("EndDateTime", this->CTest->CurrentTime());
-  xml.Element("EndTime", static_cast<unsigned int>(cmSystemTools::GetTime()));
+  xml.Element("EndTime", std::chrono::system_clock::now());
   xml.EndElement(); // CoverageLog
   this->CTest->EndXML(xml);
 }
@@ -281,8 +282,7 @@
   }
 
   std::string coverage_start_time = this->CTest->CurrentTime();
-  unsigned int coverage_start_time_time =
-    static_cast<unsigned int>(cmSystemTools::GetTime());
+  auto coverage_start_time_time = std::chrono::system_clock::now();
   std::string sourceDir =
     this->CTest->GetCTestConfiguration("SourceDirectory");
   std::string binaryDir = this->CTest->GetCTestConfiguration("BuildDirectory");
@@ -290,13 +290,14 @@
   this->LoadLabels();
 
   cmGeneratedFileStream ofs;
-  double elapsed_time_start = cmSystemTools::GetTime();
+  auto elapsed_time_start = std::chrono::steady_clock::now();
   if (!this->StartLogFile("Coverage", ofs)) {
     cmCTestLog(this->CTest, ERROR_MESSAGE,
                "Cannot create LastCoverage.log file" << std::endl);
   }
 
-  ofs << "Performing coverage: " << elapsed_time_start << std::endl;
+  ofs << "Performing coverage: "
+      << elapsed_time_start.time_since_epoch().count() << std::endl;
   this->CleanCoverageLogFiles(ofs);
 
   cmSystemTools::ConvertToUnixSlashes(sourceDir);
@@ -619,12 +620,11 @@
   covSumXML.Element("LOC", total_lines);
   covSumXML.Element("PercentCoverage", percent_coverage);
   covSumXML.Element("EndDateTime", end_time);
-  covSumXML.Element("EndTime",
-                    static_cast<unsigned int>(cmSystemTools::GetTime()));
-  covSumXML.Element(
-    "ElapsedMinutes",
-    static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start) / 6) /
-      10.0);
+  covSumXML.Element("EndTime", std::chrono::system_clock::now());
+  covSumXML.Element("ElapsedMinutes",
+                    std::chrono::duration_cast<std::chrono::minutes>(
+                      std::chrono::steady_clock::now() - elapsed_time_start)
+                      .count());
   covSumXML.EndElement(); // Coverage
   this->CTest->EndXML(covSumXML);
 
@@ -1963,12 +1963,11 @@
     return 0;
   }
   this->CTest->StartXML(xml, this->AppendXML);
-  double elapsed_time_start = cmSystemTools::GetTime();
+  auto elapsed_time_start = std::chrono::steady_clock::now();
   std::string coverage_start_time = this->CTest->CurrentTime();
   xml.StartElement("Coverage");
   xml.Element("StartDateTime", coverage_start_time);
-  xml.Element("StartTime",
-              static_cast<unsigned int>(cmSystemTools::GetTime()));
+  xml.Element("StartTime", std::chrono::system_clock::now());
   std::string stdline;
   std::string errline;
   // expected output:
@@ -2089,11 +2088,11 @@
   xml.Element("LOC", total_functions);
   xml.Element("PercentCoverage", SAFEDIV(percent_coverage, number_files));
   xml.Element("EndDateTime", end_time);
-  xml.Element("EndTime", static_cast<unsigned int>(cmSystemTools::GetTime()));
-  xml.Element(
-    "ElapsedMinutes",
-    static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start) / 6) /
-      10.0);
+  xml.Element("EndTime", std::chrono::system_clock::now());
+  xml.Element("ElapsedMinutes",
+              std::chrono::duration_cast<std::chrono::minutes>(
+                std::chrono::steady_clock::now() - elapsed_time_start)
+                .count());
   xml.EndElement(); // Coverage
   this->CTest->EndXML(xml);
 
diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx
index 3efb039..2e7874d 100644
--- a/Source/CTest/cmCTestMemCheckHandler.cxx
+++ b/Source/CTest/cmCTestMemCheckHandler.cxx
@@ -10,9 +10,11 @@
 #include "cmsys/FStream.hxx"
 #include "cmsys/Glob.hxx"
 #include "cmsys/RegularExpression.hxx"
+#include <chrono>
 #include <iostream>
 #include <sstream>
 #include <string.h>
+#include <type_traits>
 
 struct CatToErrorType
 {
@@ -408,8 +410,10 @@
 
   xml.Element("EndDateTime", this->EndTest);
   xml.Element("EndTestTime", this->EndTestTime);
-  xml.Element("ElapsedMinutes",
-              static_cast<int>(this->ElapsedTestingTime / 6) / 10.0);
+  xml.Element(
+    "ElapsedMinutes",
+    std::chrono::duration_cast<std::chrono::minutes>(this->ElapsedTestingTime)
+      .count());
 
   xml.EndElement(); // DynamicAnalysis
   this->CTest->EndXML(xml);
@@ -844,7 +848,7 @@
   cmsys::RegularExpression vgABR("== .*pthread_mutex_unlock: mutex is "
                                  "locked by a different thread");
   std::vector<std::string::size_type> nonValGrindOutput;
-  double sttime = cmSystemTools::GetTime();
+  auto sttime = std::chrono::steady_clock::now();
   cmCTestOptionalLog(this->CTest, DEBUG,
                      "Start test: " << lines.size() << std::endl, this->Quiet);
   std::string::size_type totalOutputSize = 0;
@@ -918,7 +922,10 @@
     }
   }
   cmCTestOptionalLog(this->CTest, DEBUG, "End test (elapsed: "
-                       << (cmSystemTools::GetTime() - sttime) << std::endl,
+                       << std::chrono::duration_cast<std::chrono::seconds>(
+                            std::chrono::steady_clock::now() - sttime)
+                            .count()
+                       << "s)" << std::endl,
                      this->Quiet);
   log = ostr.str();
   this->DefectCount += defects;
@@ -929,7 +936,7 @@
   const std::string& str, std::string& log, std::vector<int>& results)
 {
   log.clear();
-  double sttime = cmSystemTools::GetTime();
+  auto sttime = std::chrono::steady_clock::now();
   std::vector<std::string> lines;
   cmSystemTools::Split(str.c_str(), lines);
   cmCTestOptionalLog(this->CTest, DEBUG,
@@ -961,7 +968,10 @@
     defects++;
   }
   cmCTestOptionalLog(this->CTest, DEBUG, "End test (elapsed: "
-                       << (cmSystemTools::GetTime() - sttime) << std::endl,
+                       << std::chrono::duration_cast<std::chrono::seconds>(
+                            std::chrono::steady_clock::now() - sttime)
+                            .count()
+                       << "s)" << std::endl,
                      this->Quiet);
   if (defects) {
     // only put the output of Bounds Checker if there were
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 6a7bdc0..ae07feb 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -326,10 +326,22 @@
   }
 
   if (allTestsFailedTestLoadCheck) {
+    // Find out whether there are any non RUN_SERIAL tests left, so that the
+    // correct warning may be displayed.
+    bool onlyRunSerialTestsLeft = true;
+    for (auto const& test : copy) {
+      if (!this->Properties[test]->RunSerial) {
+        onlyRunSerialTestsLeft = false;
+      }
+    }
     cmCTestLog(this->CTest, HANDLER_OUTPUT, "***** WAITING, ");
+
     if (this->SerialTestRunning) {
       cmCTestLog(this->CTest, HANDLER_OUTPUT,
                  "Waiting for RUN_SERIAL test to finish.");
+    } else if (onlyRunSerialTestsLeft) {
+      cmCTestLog(this->CTest, HANDLER_OUTPUT,
+                 "Only RUN_SERIAL tests remain, awaiting available slot.");
     } else {
       /* clang-format off */
       cmCTestLog(this->CTest, HANDLER_OUTPUT,
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index abdb643..99531af 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -14,6 +14,7 @@
 #include "cmsys/Base64.h"
 #include "cmsys/Process.h"
 #include "cmsys/RegularExpression.hxx"
+#include <chrono>
 #include <iomanip>
 #include <sstream>
 #include <stdio.h>
@@ -46,11 +47,12 @@
 bool cmCTestRunTest::CheckOutput()
 {
   // Read lines for up to 0.1 seconds of total time.
-  double timeout = 0.1;
-  double timeEnd = cmSystemTools::GetTime() + timeout;
+  std::chrono::duration<double> timeout = std::chrono::milliseconds(100);
+  auto timeEnd = std::chrono::steady_clock::now() + timeout;
   std::string line;
-  while ((timeout = timeEnd - cmSystemTools::GetTime(), timeout > 0)) {
-    int p = this->TestProcess->GetNextOutputLine(line, timeout);
+  while ((timeout = timeEnd - std::chrono::steady_clock::now(),
+          timeout > std::chrono::seconds(0))) {
+    int p = this->TestProcess->GetNextOutputLine(line, timeout.count());
     if (p == cmsysProcess_Pipe_None) {
       // Process has terminated and all output read.
       return false;
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index fdd9622..3bf27a0 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -5,10 +5,12 @@
 #include "cmsys/Directory.hxx"
 #include "cmsys/Process.h"
 #include <map>
+#include <ratio>
 #include <sstream>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <type_traits>
 #include <utility>
 
 #include "cmCTest.h"
@@ -79,9 +81,9 @@
   this->CMake = nullptr;
   this->GlobalGenerator = nullptr;
 
-  this->ScriptStartTime = 0;
+  this->ScriptStartTime = std::chrono::steady_clock::time_point();
 
-  // the *60 is becuase the settings are in minutes but GetTime is seconds
+  // the *60 is because the settings are in minutes but GetTime is seconds
   this->MinimumInterval = 30 * 60;
   this->ContinuousDuration = -1;
 }
@@ -111,7 +113,7 @@
   this->ContinuousDuration = -1;
 
   // what time in seconds did this script start running
-  this->ScriptStartTime = 0;
+  this->ScriptStartTime = std::chrono::steady_clock::time_point();
 
   delete this->Makefile;
   this->Makefile = nullptr;
@@ -158,11 +160,10 @@
 {
   if (this->Makefile) {
     // set the current elapsed time
-    char timeString[20];
-    int itime = static_cast<unsigned int>(cmSystemTools::GetTime() -
-                                          this->ScriptStartTime);
-    sprintf(timeString, "%i", itime);
-    this->Makefile->AddDefinition("CTEST_ELAPSED_TIME", timeString);
+    auto itime = std::chrono::duration_cast<std::chrono::seconds>(
+      std::chrono::steady_clock::now() - this->ScriptStartTime);
+    auto timeString = std::to_string(itime.count());
+    this->Makefile->AddDefinition("CTEST_ELAPSED_TIME", timeString.c_str());
   }
 }
 
@@ -507,7 +508,7 @@
 
   int result;
 
-  this->ScriptStartTime = cmSystemTools::GetTime();
+  this->ScriptStartTime = std::chrono::steady_clock::now();
 
   // read in the script
   if (pscope) {
@@ -558,22 +559,27 @@
   // for a continuous, do we ned to run it more than once?
   if (this->ContinuousDuration >= 0) {
     this->UpdateElapsedTime();
-    double ending_time = cmSystemTools::GetTime() + this->ContinuousDuration;
+    auto ending_time = std::chrono::steady_clock::now() +
+      std::chrono::duration<double>(this->ContinuousDuration);
     if (this->EmptyBinDirOnce) {
       this->EmptyBinDir = true;
     }
     do {
-      double interval = cmSystemTools::GetTime();
+      auto startOfInterval = std::chrono::steady_clock::now();
       result = this->RunConfigurationDashboard();
-      interval = cmSystemTools::GetTime() - interval;
-      if (interval < this->MinimumInterval) {
-        this->SleepInSeconds(
-          static_cast<unsigned int>(this->MinimumInterval - interval));
+      auto interval = std::chrono::steady_clock::now() - startOfInterval;
+      auto minimumInterval =
+        std::chrono::duration<double>(this->MinimumInterval);
+      if (interval < minimumInterval) {
+        auto sleepTime = std::chrono::duration_cast<std::chrono::seconds>(
+                           minimumInterval - interval)
+                           .count();
+        this->SleepInSeconds(static_cast<unsigned int>(sleepTime));
       }
       if (this->EmptyBinDirOnce) {
         this->EmptyBinDir = false;
       }
-    } while (cmSystemTools::GetTime() < ending_time);
+    } while (std::chrono::steady_clock::now() < ending_time);
   }
   // otherwise just run it once
   else {
@@ -830,7 +836,7 @@
     }
   }
 
-  // if all was succesful, delete the backup dirs to free up disk space
+  // if all was successful, delete the backup dirs to free up disk space
   if (this->Backup) {
     cmSystemTools::RemoveADirectory(this->BackupSourceDir);
     cmSystemTools::RemoveADirectory(this->BackupBinaryDir);
@@ -967,7 +973,9 @@
     return 1.0e7;
   }
 
-  double timelimit = atof(timelimitS);
+  auto timelimit = std::chrono::duration<double>(atof(timelimitS));
 
-  return timelimit - cmSystemTools::GetTime() + this->ScriptStartTime;
+  auto duration = std::chrono::duration_cast<std::chrono::duration<double>>(
+    std::chrono::steady_clock::now() - this->ScriptStartTime);
+  return (timelimit - duration).count();
 }
diff --git a/Source/CTest/cmCTestScriptHandler.h b/Source/CTest/cmCTestScriptHandler.h
index b6cd97b..2090d04 100644
--- a/Source/CTest/cmCTestScriptHandler.h
+++ b/Source/CTest/cmCTestScriptHandler.h
@@ -7,6 +7,7 @@
 
 #include "cmCTestGenericHandler.h"
 
+#include <chrono>
 #include <string>
 #include <vector>
 
@@ -104,6 +105,7 @@
 
   void CreateCMake();
   cmake* GetCMake() { return this->CMake; }
+
 private:
   // reads in a script
   int ReadInScript(const std::string& total_script_arg);
@@ -156,7 +158,7 @@
   double ContinuousDuration;
 
   // what time in seconds did this script start running
-  double ScriptStartTime;
+  std::chrono::steady_clock::time_point ScriptStartTime;
 
   cmMakefile* Makefile;
   cmGlobalGenerator* GlobalGenerator;
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index e51e168..86fee7a 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -6,6 +6,7 @@
 #include "cm_jsoncpp_reader.h"
 #include "cm_jsoncpp_value.h"
 #include "cmsys/Process.h"
+#include <chrono>
 #include <sstream>
 #include <stdio.h>
 #include <stdlib.h>
@@ -496,10 +497,11 @@
           ? ""
           : this->GetOption("RetryCount");
 
-        int delay = retryDelay.empty()
-          ? atoi(this->CTest->GetCTestConfiguration("CTestSubmitRetryDelay")
-                   .c_str())
-          : atoi(retryDelay.c_str());
+        auto delay = std::chrono::duration<double>(
+          retryDelay.empty()
+            ? atoi(this->CTest->GetCTestConfiguration("CTestSubmitRetryDelay")
+                     .c_str())
+            : atoi(retryDelay.c_str()));
         int count = retryCount.empty()
           ? atoi(this->CTest->GetCTestConfiguration("CTestSubmitRetryCount")
                    .c_str())
@@ -507,12 +509,12 @@
 
         for (int i = 0; i < count; i++) {
           cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
-                             "   Submit failed, waiting " << delay
+                             "   Submit failed, waiting " << delay.count()
                                                           << " seconds...\n",
                              this->Quiet);
 
-          double stop = cmSystemTools::GetTime() + delay;
-          while (cmSystemTools::GetTime() < stop) {
+          auto stop = std::chrono::steady_clock::now() + delay;
+          while (std::chrono::steady_clock::now() < stop) {
             cmSystemTools::Delay(100);
           }
 
@@ -1031,11 +1033,15 @@
   std::string retryCountString = this->GetOption("RetryCount") == nullptr
     ? ""
     : this->GetOption("RetryCount");
-  unsigned long retryDelay = 0;
+  auto retryDelay = std::chrono::seconds(0);
   if (!retryDelayString.empty()) {
-    if (!cmSystemTools::StringToULong(retryDelayString.c_str(), &retryDelay)) {
+    unsigned long retryDelayValue = 0;
+    if (!cmSystemTools::StringToULong(retryDelayString.c_str(),
+                                      &retryDelayValue)) {
       cmCTestLog(this->CTest, WARNING, "Invalid value for 'RETRY_DELAY' : "
                    << retryDelayString << std::endl);
+    } else {
+      retryDelay = std::chrono::seconds(retryDelayValue);
     }
   }
   unsigned long retryCount = 0;
@@ -1063,6 +1069,8 @@
   if (subproject) {
     str << "subproject=" << curl.Escape(subproject) << "&";
   }
+  auto timeNow =
+    std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
   str << "stamp=" << curl.Escape(this->CTest->GetCurrentTag()) << "-"
       << curl.Escape(this->CTest->GetTestModelString()) << "&"
       << "model=" << curl.Escape(this->CTest->GetTestModelString()) << "&"
@@ -1071,8 +1079,8 @@
       << "site=" << curl.Escape(this->CTest->GetCTestConfiguration("Site"))
       << "&"
       << "track=" << curl.Escape(this->CTest->GetTestModelString()) << "&"
-      << "starttime=" << static_cast<int>(cmSystemTools::GetTime()) << "&"
-      << "endtime=" << static_cast<int>(cmSystemTools::GetTime()) << "&"
+      << "starttime=" << timeNow << "&"
+      << "endtime=" << timeNow << "&"
       << "datafilesmd5[0]=" << md5sum << "&"
       << "type=" << curl.Escape(typeString);
   std::string fields = str.str();
@@ -1087,12 +1095,12 @@
     // If request failed, wait and retry.
     for (unsigned long i = 0; i < retryCount; i++) {
       cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
-                         "   Request failed, waiting " << retryDelay
+                         "   Request failed, waiting " << retryDelay.count()
                                                        << " seconds...\n",
                          this->Quiet);
 
-      double stop = cmSystemTools::GetTime() + static_cast<double>(retryDelay);
-      while (cmSystemTools::GetTime() < stop) {
+      auto stop = std::chrono::steady_clock::now() + retryDelay;
+      while (std::chrono::steady_clock::now() < stop) {
         cmSystemTools::Delay(100);
       }
 
@@ -1161,12 +1169,12 @@
     // If upload failed, wait and retry.
     for (unsigned long i = 0; i < retryCount; i++) {
       cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
-                         "   Upload failed, waiting " << retryDelay
+                         "   Upload failed, waiting " << retryDelay.count()
                                                       << " seconds...\n",
                          this->Quiet);
 
-      double stop = cmSystemTools::GetTime() + static_cast<double>(retryDelay);
-      while (cmSystemTools::GetTime() < stop) {
+      auto stop = std::chrono::steady_clock::now() + retryDelay;
+      while (std::chrono::steady_clock::now() < stop) {
         cmSystemTools::Delay(100);
       }
 
@@ -1521,7 +1529,7 @@
       this->CTest->GetCTestConfiguration("DropLocation");
 
     // change to the build directory so that we can uses a relative path
-    // on windows since scp dosn't support "c:" a drive in the path
+    // on windows since scp doesn't support "c:" a drive in the path
     cmWorkingDirectory workdir(buildDirectory);
 
     if (!this->SubmitUsingSCP(this->CTest->GetCTestConfiguration("ScpCommand"),
@@ -1540,7 +1548,7 @@
     std::string location = this->CTest->GetCTestConfiguration("DropLocation");
 
     // change to the build directory so that we can uses a relative path
-    // on windows since scp dosn't support "c:" a drive in the path
+    // on windows since scp doesn't support "c:" a drive in the path
     cmWorkingDirectory workdir(buildDirectory);
     cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                        "   Change directory: " << buildDirectory << std::endl,
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index c7ed927..e7c719c 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCTestTestHandler.h"
 #include <algorithm>
+#include <chrono>
 #include <cmsys/Base64.h>
 #include <cmsys/Directory.hxx>
 #include <cmsys/RegularExpression.hxx>
@@ -15,6 +16,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
+#include <type_traits>
 
 #include "cmAlgorithms.h"
 #include "cmCTest.h"
@@ -346,7 +348,7 @@
 {
   this->Superclass::Initialize();
 
-  this->ElapsedTestingTime = -1;
+  this->ElapsedTestingTime = std::chrono::duration<double>();
 
   this->TestResults.clear();
 
@@ -484,12 +486,11 @@
   int total;
 
   // start the real time clock
-  double clock_start, clock_finish;
-  clock_start = cmSystemTools::GetTime();
+  auto clock_start = std::chrono::steady_clock::now();
 
   this->ProcessDirectory(passed, failed);
 
-  clock_finish = cmSystemTools::GetTime();
+  auto clock_finish = std::chrono::steady_clock::now();
 
   total = int(passed.size()) + int(failed.size());
 
@@ -540,7 +541,10 @@
       this->PrintLabelOrSubprojectSummary(false);
     }
     char realBuf[1024];
-    sprintf(realBuf, "%6.2f sec", clock_finish - clock_start);
+    auto durationInMs = std::chrono::duration_cast<std::chrono::milliseconds>(
+                          clock_finish - clock_start)
+                          .count();
+    sprintf(realBuf, "%6.2f sec", static_cast<double>(durationInMs) / 1000.0);
     cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
                        "\nTotal Test time (real) = " << realBuf << "\n",
                        this->Quiet);
@@ -1200,8 +1204,8 @@
 {
   this->ComputeTestList();
   this->StartTest = this->CTest->CurrentTime();
-  this->StartTestTime = static_cast<unsigned int>(cmSystemTools::GetTime());
-  double elapsed_time_start = cmSystemTools::GetTime();
+  this->StartTestTime = std::chrono::system_clock::now();
+  auto elapsed_time_start = std::chrono::steady_clock::now();
 
   cmCTestMultiProcessHandler* parallel = this->CTest->GetBatchJobs()
     ? new cmCTestBatchTestHandler
@@ -1267,8 +1271,9 @@
   }
   delete parallel;
   this->EndTest = this->CTest->CurrentTime();
-  this->EndTestTime = static_cast<unsigned int>(cmSystemTools::GetTime());
-  this->ElapsedTestingTime = cmSystemTools::GetTime() - elapsed_time_start;
+  this->EndTestTime = std::chrono::system_clock::now();
+  this->ElapsedTestingTime =
+    std::chrono::steady_clock::now() - elapsed_time_start;
   *this->LogFile << "End testing: " << this->CTest->CurrentTime() << std::endl;
 }
 
@@ -1373,8 +1378,10 @@
 
   xml.Element("EndDateTime", this->EndTest);
   xml.Element("EndTestTime", this->EndTestTime);
-  xml.Element("ElapsedMinutes",
-              static_cast<int>(this->ElapsedTestingTime / 6) / 10.0);
+  xml.Element(
+    "ElapsedMinutes",
+    std::chrono::duration_cast<std::chrono::minutes>(this->ElapsedTestingTime)
+      .count());
   xml.EndElement(); // Testing
   this->CTest->EndXML(xml);
 }
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index 394d20e..8572e7b 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -8,6 +8,7 @@
 #include "cmCTestGenericHandler.h"
 
 #include "cmsys/RegularExpression.hxx"
+#include <chrono>
 #include <iosfwd>
 #include <map>
 #include <set>
@@ -39,7 +40,7 @@
   int ProcessHandler() override;
 
   /**
-   * When both -R and -I are used should te resulting test list be the
+   * When both -R and -I are used should the resulting test list be the
    * intersection or the union of the lists. By default it is the
    * intersection.
    */
@@ -198,7 +199,7 @@
   //! Clean test output to specified length
   bool CleanTestOutput(std::string& output, size_t length);
 
-  double ElapsedTestingTime;
+  std::chrono::duration<double> ElapsedTestingTime;
 
   typedef std::vector<cmCTestTestResult> TestResultsVector;
   TestResultsVector TestResults;
@@ -206,8 +207,8 @@
   std::vector<std::string> CustomTestsIgnore;
   std::string StartTest;
   std::string EndTest;
-  unsigned int StartTestTime;
-  unsigned int EndTestTime;
+  std::chrono::system_clock::time_point StartTestTime;
+  std::chrono::system_clock::time_point EndTestTime;
   bool MemCheck;
   int CustomMaximumPassedTestOutputSize;
   int CustomMaximumFailedTestOutputSize;
diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx
index 786ed5e..f86d4a3 100644
--- a/Source/CTest/cmCTestUpdateHandler.cxx
+++ b/Source/CTest/cmCTestUpdateHandler.cxx
@@ -17,8 +17,10 @@
 #include "cmVersion.h"
 #include "cmXMLWriter.h"
 
+#include <chrono>
 #include <memory> // IWYU pragma: keep
 #include <sstream>
+#include <type_traits>
 
 static const char* cmCTestUpdateHandlerUpdateStrings[] = {
   "Unknown", "CVS", "SVN", "BZR", "GIT", "HG", "P4"
@@ -175,9 +177,8 @@
     return -1;
   }
   std::string start_time = this->CTest->CurrentTime();
-  unsigned int start_time_time =
-    static_cast<unsigned int>(cmSystemTools::GetTime());
-  double elapsed_time_start = cmSystemTools::GetTime();
+  auto start_time_time = std::chrono::system_clock::now();
+  auto elapsed_time_start = std::chrono::steady_clock::now();
 
   bool updated = vc->Update();
   std::string buildname =
@@ -224,11 +225,11 @@
   cmCTestOptionalLog(this->CTest, DEBUG, "End" << std::endl, this->Quiet);
   std::string end_time = this->CTest->CurrentTime();
   xml.Element("EndDateTime", end_time);
-  xml.Element("EndTime", static_cast<unsigned int>(cmSystemTools::GetTime()));
-  xml.Element(
-    "ElapsedMinutes",
-    static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start) / 6) /
-      10.0);
+  xml.Element("EndTime", std::chrono::system_clock::now());
+  xml.Element("ElapsedMinutes",
+              std::chrono::duration_cast<std::chrono::minutes>(
+                std::chrono::steady_clock::now() - elapsed_time_start)
+                .count());
 
   xml.StartElement("UpdateReturnStatus");
   if (localModifications) {
diff --git a/Source/CTest/cmParseGTMCoverage.cxx b/Source/CTest/cmParseGTMCoverage.cxx
index 9948ede..f965048 100644
--- a/Source/CTest/cmParseGTMCoverage.cxx
+++ b/Source/CTest/cmParseGTMCoverage.cxx
@@ -93,7 +93,7 @@
         // This section accounts for lines that were previously marked
         // as non-executable code (-1), if the parser comes back with
         // a non-zero count, increase the count by 1 to push the line
-        // into the executable code set in addtion to the count found.
+        // into the executable code set in addition to the count found.
         if (coverageVector[lineoffset + linenumber] == -1 && count > 0) {
           coverageVector[lineoffset + linenumber] += count + 1;
         } else {
diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx
index f3c191b..78dd598 100644
--- a/Source/CTest/cmProcess.cxx
+++ b/Source/CTest/cmProcess.cxx
@@ -3,8 +3,8 @@
 #include "cmProcess.h"
 
 #include "cmProcessOutput.h"
-#include "cmSystemTools.h"
 #include <iostream>
+#include <type_traits>
 
 cmProcess::cmProcess()
 {
@@ -13,7 +13,7 @@
   this->TotalTime = 0;
   this->ExitValue = 0;
   this->Id = 0;
-  this->StartTime = 0;
+  this->StartTime = std::chrono::steady_clock::time_point();
 }
 
 cmProcess::~cmProcess()
@@ -35,7 +35,7 @@
   if (this->Command.empty()) {
     return false;
   }
-  this->StartTime = cmSystemTools::GetTime();
+  this->StartTime = std::chrono::steady_clock::now();
   this->ProcessArgs.clear();
   // put the command as arg0
   this->ProcessArgs.push_back(this->Command.c_str());
@@ -143,7 +143,11 @@
 
   // Record exit information.
   this->ExitValue = cmsysProcess_GetExitValue(this->Process);
-  this->TotalTime = cmSystemTools::GetTime() - this->StartTime;
+  this->TotalTime =
+    static_cast<double>(std::chrono::duration_cast<std::chrono::milliseconds>(
+                          std::chrono::steady_clock::now() - this->StartTime)
+                          .count()) /
+    1000.0;
   // Because of a processor clock scew the runtime may become slightly
   // negative. If someone changed the system clock while the process was
   // running this may be even more. Make sure not to report a negative
@@ -231,7 +235,7 @@
 void cmProcess::ResetStartTime()
 {
   cmsysProcess_ResetStartTime(this->Process);
-  this->StartTime = cmSystemTools::GetTime();
+  this->StartTime = std::chrono::steady_clock::now();
 }
 
 int cmProcess::GetExitException()
diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h
index dfb02fe..ddd69b6 100644
--- a/Source/CTest/cmProcess.h
+++ b/Source/CTest/cmProcess.h
@@ -6,6 +6,7 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmsys/Process.h"
+#include <chrono>
 #include <string>
 #include <vector>
 
@@ -50,7 +51,7 @@
 
 private:
   double Timeout;
-  double StartTime;
+  std::chrono::steady_clock::time_point StartTime;
   double TotalTime;
   cmsysProcess* Process;
   class Buffer : public std::vector<char>
diff --git a/Source/LexerParser/cmCommandArgumentLexer.cxx b/Source/LexerParser/cmCommandArgumentLexer.cxx
index bf6bc2f..6b4fc85 100644
--- a/Source/LexerParser/cmCommandArgumentLexer.cxx
+++ b/Source/LexerParser/cmCommandArgumentLexer.cxx
@@ -674,6 +674,13 @@
 /* Include the set of tokens from the parser.  */
 #include "cmCommandArgumentParserTokens.h"
 
+static const char *DCURLYVariable = "${";
+static const char *RCURLYVariable = "}";
+static const char *ATVariable = "@";
+static const char *DOLLARVariable = "$";
+static const char *LCURLYVariable = "{";
+static const char *BSLASHVariable = "\\";
+
 /*--------------------------------------------------------------------------*/
 
 #define INITIAL 0
@@ -1011,7 +1018,7 @@
 {
   //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
   //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
-  yylvalp->str = yyextra->DCURLYVariable;
+  yylvalp->str = DCURLYVariable;
   return cal_DCURLY;
 }
 	YY_BREAK
@@ -1020,7 +1027,7 @@
 {
   //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
   //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
-  yylvalp->str = yyextra->RCURLYVariable;
+  yylvalp->str = RCURLYVariable;
   return cal_RCURLY;
 }
 	YY_BREAK
@@ -1029,7 +1036,7 @@
 {
   //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
   //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
-  yylvalp->str = yyextra->ATVariable;
+  yylvalp->str = ATVariable;
   return cal_AT;
 }
 	YY_BREAK
@@ -1064,7 +1071,7 @@
 YY_RULE_SETUP
 {
   //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
-  yylvalp->str = yyextra->DOLLARVariable;
+  yylvalp->str = DOLLARVariable;
   return cal_DOLLAR;
 }
 	YY_BREAK
@@ -1072,7 +1079,7 @@
 YY_RULE_SETUP
 {
   //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
-  yylvalp->str = yyextra->LCURLYVariable;
+  yylvalp->str = LCURLYVariable;
   return cal_LCURLY;
 }
 	YY_BREAK
@@ -1080,7 +1087,7 @@
 YY_RULE_SETUP
 {
   //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
-  yylvalp->str = yyextra->BSLASHVariable;
+  yylvalp->str = BSLASHVariable;
   return cal_BSLASH;
 }
 	YY_BREAK
@@ -1088,7 +1095,7 @@
 YY_RULE_SETUP
 {
   //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
-  yylvalp->str = yyextra->BSLASHVariable;
+  yylvalp->str = BSLASHVariable;
   return cal_SYMBOL;
 }
 	YY_BREAK
diff --git a/Source/LexerParser/cmCommandArgumentLexer.in.l b/Source/LexerParser/cmCommandArgumentLexer.in.l
index acf18f3..5927b9e 100644
--- a/Source/LexerParser/cmCommandArgumentLexer.in.l
+++ b/Source/LexerParser/cmCommandArgumentLexer.in.l
@@ -28,6 +28,13 @@
 /* Include the set of tokens from the parser.  */
 #include "cmCommandArgumentParserTokens.h"
 
+static const char *DCURLYVariable = "${";
+static const char *RCURLYVariable = "}";
+static const char *ATVariable = "@";
+static const char *DOLLARVariable = "$";
+static const char *LCURLYVariable = "{";
+static const char *BSLASHVariable = "\\";
+
 /*--------------------------------------------------------------------------*/
 %}
 
@@ -63,21 +70,21 @@
 "${" {
   //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
   //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
-  yylvalp->str = yyextra->DCURLYVariable;
+  yylvalp->str = DCURLYVariable;
   return cal_DCURLY;
 }
 
 "}" {
   //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
   //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
-  yylvalp->str = yyextra->RCURLYVariable;
+  yylvalp->str = RCURLYVariable;
   return cal_RCURLY;
 }
 
 "@" {
   //std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
   //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
-  yylvalp->str = yyextra->ATVariable;
+  yylvalp->str = ATVariable;
   return cal_AT;
 }
 
@@ -103,25 +110,25 @@
 
 "$" {
   //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
-  yylvalp->str = yyextra->DOLLARVariable;
+  yylvalp->str = DOLLARVariable;
   return cal_DOLLAR;
 }
 
 "{" {
   //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
-  yylvalp->str = yyextra->LCURLYVariable;
+  yylvalp->str = LCURLYVariable;
   return cal_LCURLY;
 }
 
 <ESCAPES>"\\" {
   //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
-  yylvalp->str = yyextra->BSLASHVariable;
+  yylvalp->str = BSLASHVariable;
   return cal_BSLASH;
 }
 
 <NOESCAPES>"\\" {
   //yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
-  yylvalp->str = yyextra->BSLASHVariable;
+  yylvalp->str = BSLASHVariable;
   return cal_SYMBOL;
 }
 
diff --git a/Source/Modules/FindLibUUID.cmake b/Source/Modules/FindLibUUID.cmake
new file mode 100644
index 0000000..17f11c1
--- /dev/null
+++ b/Source/Modules/FindLibUUID.cmake
@@ -0,0 +1,85 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+FindLibUUID
+------------
+
+Find LibUUID include directory and library.
+
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+An :ref:`imported target <Imported targets>` named
+``LibUUID::LibUUID`` is provided if LibUUID has been found.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This module defines the following variables:
+
+``LibUUID_FOUND``
+  True if LibUUID was found, false otherwise.
+``LibUUID_INCLUDE_DIRS``
+  Include directories needed to include LibUUID headers.
+``LibUUID_LIBRARIES``
+  Libraries needed to link to LibUUID.
+
+Cache Variables
+^^^^^^^^^^^^^^^
+
+This module uses the following cache variables:
+
+``LibUUID_LIBRARY``
+  The location of the LibUUID library file.
+``LibUUID_INCLUDE_DIR``
+  The location of the LibUUID include directory containing ``uuid/uuid.h``.
+
+The cache variables should not be used by project code.
+They may be set by end users to point at LibUUID components.
+#]=======================================================================]
+
+#-----------------------------------------------------------------------------
+if(CYGWIN)
+  # Note: on current version of Cygwin, linking to libuuid.dll.a doesn't
+  #       import the right symbols sometimes. Fix this by linking directly
+  #       to the DLL that provides the symbols, instead.
+  set(old_suffixes ${CMAKE_FIND_LIBRARY_SUFFIXES})
+  set(CMAKE_FIND_LIBRARY_SUFFIXES .dll)
+  find_library(LibUUID_LIBRARY
+    NAMES cyguuid-1.dll
+    )
+  set(CMAKE_FIND_LIBRARY_SUFFIXES ${old_suffixes})
+else()
+  find_library(LibUUID_LIBRARY
+    NAMES uuid
+    )
+endif()
+mark_as_advanced(LibUUID_LIBRARY)
+
+find_path(LibUUID_INCLUDE_DIR
+  NAMES uuid/uuid.h
+  )
+mark_as_advanced(LibUUID_INCLUDE_DIR)
+
+#-----------------------------------------------------------------------------
+include(${CMAKE_CURRENT_LIST_DIR}/../../Modules/FindPackageHandleStandardArgs.cmake)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibUUID
+  FOUND_VAR LibUUID_FOUND
+  REQUIRED_VARS LibUUID_LIBRARY LibUUID_INCLUDE_DIR
+  )
+set(LIBUUID_FOUND ${LibUUID_FOUND})
+
+#-----------------------------------------------------------------------------
+# Provide documented result variables and targets.
+if(LibUUID_FOUND)
+  set(LibUUID_INCLUDE_DIRS ${LibUUID_INCLUDE_DIR})
+  set(LibUUID_LIBRARIES ${LibUUID_LIBRARY})
+  if(NOT TARGET LibUUID::LibUUID)
+    add_library(LibUUID::LibUUID UNKNOWN IMPORTED)
+    set_target_properties(LibUUID::LibUUID PROPERTIES
+      IMPORTED_LOCATION "${LibUUID_LIBRARY}"
+      INTERFACE_INCLUDE_DIRECTORIES "${LibUUID_INCLUDE_DIRS}"
+      )
+  endif()
+endif()
diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt
index 9e9df78..b38797b 100644
--- a/Source/QtDialog/CMakeLists.txt
+++ b/Source/QtDialog/CMakeLists.txt
@@ -33,6 +33,12 @@
       PROPERTY COMPILE_DEFINITIONS USE_QXcbIntegrationPlugin)
   endif()
 
+  if(CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES)
+    list(APPEND CMake_QT_LIBRARIES ${CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES})
+    set_property(SOURCE CMakeSetup.cxx
+      PROPERTY COMPILE_DEFINITIONS USE_QWindowsIntegrationPlugin)
+  endif()
+
   # We need to install platform plugin and add qt.conf for Qt5 on Mac and Windows.
   # FIXME: This should be part of Qt5 CMake scripts, but unfortunatelly
   # Qt5 support is missing there.
@@ -65,7 +71,7 @@
       install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
         DESTINATION "${CMAKE_INSTALL_PREFIX}/Resources"
         ${COMPONENT})
-    elseif(WIN32)
+    elseif(WIN32 AND NOT CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES)
       install_qt5_plugin("Qt5::QWindowsIntegrationPlugin" QT_PLUGINS)
       file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
         "[Paths]\nPlugins = ../${_qt_plugin_dir}\n")
diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx
index ca0b015..bfd43cf 100644
--- a/Source/QtDialog/CMakeSetup.cxx
+++ b/Source/QtDialog/CMakeSetup.cxx
@@ -44,6 +44,10 @@
 Q_IMPORT_PLUGIN(QXcbIntegrationPlugin);
 #endif
 
+#if defined(USE_QWindowsIntegrationPlugin)
+Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
+#endif
+
 int main(int argc, char** argv)
 {
   cmsys::Encoding::CommandLineArguments encoding_args =
diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx
index bbb2395..5be9ec3 100644
--- a/Source/QtDialog/CMakeSetupDialog.cxx
+++ b/Source/QtDialog/CMakeSetupDialog.cxx
@@ -188,6 +188,9 @@
   connect(this->Output, SIGNAL(customContextMenuRequested(const QPoint&)),
           this, SLOT(doOutputContextMenu(const QPoint&)));
 
+  // disable open project button
+  this->OpenProjectButton->setDisabled(true);
+
   // start the cmake worker thread
   this->CMakeThread = new QCMakeThread(this);
   QObject::connect(this->CMakeThread, SIGNAL(cmakeInitialized()), this,
@@ -249,6 +252,10 @@
                    SIGNAL(outputMessage(QString)), this,
                    SLOT(message(QString)));
 
+  QObject::connect(this->CMakeThread->cmakeInstance(),
+                   SIGNAL(openPossible(bool)), this->OpenProjectButton,
+                   SLOT(setEnabled(bool)));
+
   QObject::connect(this->groupedCheck, SIGNAL(toggled(bool)), this,
                    SLOT(setGroupedView(bool)));
   QObject::connect(this->advancedCheck, SIGNAL(toggled(bool)), this,
@@ -492,24 +499,10 @@
   this->ConfigureNeeded = true;
 }
 
-QString CMakeSetupDialog::getProjectFilename()
-{
-  QStringList nameFilter;
-  nameFilter << "*.sln"
-             << "*.xcodeproj";
-  QDir directory(this->BinaryDirectory->currentText());
-  QStringList nlnFile = directory.entryList(nameFilter);
-
-  if (nlnFile.count() == 1) {
-    return this->BinaryDirectory->currentText() + "/" + nlnFile.at(0);
-  }
-
-  return QString();
-}
-
 void CMakeSetupDialog::doOpenProject()
 {
-  QDesktopServices::openUrl(QUrl::fromLocalFile(this->getProjectFilename()));
+  QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(), "open",
+                            Qt::QueuedConnection);
 }
 
 void CMakeSetupDialog::closeEvent(QCloseEvent* e)
@@ -630,11 +623,6 @@
     this->BinaryDirectory->setEditText(dir);
     this->BinaryDirectory->blockSignals(false);
   }
-  if (!this->getProjectFilename().isEmpty()) {
-    this->OpenProjectButton->setEnabled(true);
-  } else {
-    this->OpenProjectButton->setEnabled(false);
-  }
 }
 
 void CMakeSetupDialog::doBinaryBrowse()
@@ -1039,9 +1027,6 @@
     this->GenerateButton->setEnabled(true);
     this->GenerateAction->setEnabled(true);
     this->ConfigureButton->setEnabled(true);
-    if (!this->getProjectFilename().isEmpty()) {
-      this->OpenProjectButton->setEnabled(true);
-    }
     this->ConfigureButton->setText(tr("&Configure"));
     this->GenerateButton->setText(tr("&Generate"));
   } else if (s == ReadyGenerate) {
@@ -1049,9 +1034,6 @@
     this->GenerateButton->setEnabled(true);
     this->GenerateAction->setEnabled(true);
     this->ConfigureButton->setEnabled(true);
-    if (!this->getProjectFilename().isEmpty()) {
-      this->OpenProjectButton->setEnabled(true);
-    }
     this->ConfigureButton->setText(tr("&Configure"));
     this->GenerateButton->setText(tr("&Generate"));
   }
diff --git a/Source/QtDialog/CMakeSetupDialog.h b/Source/QtDialog/CMakeSetupDialog.h
index 0da28d8..7b767e5 100644
--- a/Source/QtDialog/CMakeSetupDialog.h
+++ b/Source/QtDialog/CMakeSetupDialog.h
@@ -31,7 +31,6 @@
   void initialize();
   void doConfigure();
   void doGenerate();
-  QString getProjectFilename();
   void doOpenProject();
   void doInstallForCommandLine();
   void doHelp();
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx
index d473d9b..7e94a27 100644
--- a/Source/QtDialog/QCMake.cxx
+++ b/Source/QtDialog/QCMake.cxx
@@ -115,6 +115,8 @@
     if (toolset) {
       this->setToolset(QString::fromLocal8Bit(toolset));
     }
+
+    checkOpenPossible();
   }
 }
 
@@ -183,6 +185,26 @@
 #endif
 
   emit this->generateDone(err);
+  checkOpenPossible();
+}
+
+void QCMake::open()
+{
+#ifdef Q_OS_WIN
+  UINT lastErrorMode = SetErrorMode(0);
+#endif
+
+  InterruptFlag = 0;
+  cmSystemTools::ResetErrorOccuredFlag();
+
+  auto successful = this->CMakeInstance->Open(
+    this->BinaryDirectory.toLocal8Bit().data(), false);
+
+#ifdef Q_OS_WIN
+  SetErrorMode(lastErrorMode);
+#endif
+
+  emit this->openDone(successful);
 }
 
 void QCMake::setProperties(const QCMakePropertyList& newProps)
@@ -450,3 +472,10 @@
 {
   this->WarnUnusedMode = value;
 }
+
+void QCMake::checkOpenPossible()
+{
+  auto data = this->BinaryDirectory.toLocal8Bit().data();
+  auto possible = this->CMakeInstance->Open(data, true);
+  emit openPossible(possible);
+}
diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h
index 3b8cea7..6fae7e3 100644
--- a/Source/QtDialog/QCMake.h
+++ b/Source/QtDialog/QCMake.h
@@ -80,6 +80,8 @@
   void configure();
   /// generate the files
   void generate();
+  /// open the project
+  void open();
   /// set the property values
   void setProperties(const QCMakePropertyList&);
   /// interrupt the configure or generate process (if connecting, make a direct
@@ -111,6 +113,8 @@
   void setWarnUninitializedMode(bool value);
   /// set whether to run cmake with warnings about unused variables
   void setWarnUnusedMode(bool value);
+  /// check if project IDE open is possible and emit openPossible signal
+  void checkOpenPossible();
 
 public:
   /// get the list of cache properties
@@ -151,6 +155,10 @@
   void debugOutputChanged(bool);
   /// signal when the toolset changes
   void toolsetChanged(const QString& toolset);
+  /// signal when open is done
+  void openDone(bool successful);
+  /// signal when open is done
+  void openPossible(bool possible);
 
 protected:
   cmake* CMakeInstance;
diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx
index a8d5b2e..f4b4f66 100644
--- a/Source/cmAddCustomTargetCommand.cxx
+++ b/Source/cmAddCustomTargetCommand.cxx
@@ -8,7 +8,7 @@
 #include "cmGeneratorExpression.h"
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
-#include "cmPolicies.h"
+#include "cmStateTypes.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmake.h"
@@ -160,35 +160,9 @@
   if (nameOk) {
     nameOk = targetName.find(':') == std::string::npos;
   }
-  if (!nameOk) {
-    cmake::MessageType messageType = cmake::AUTHOR_WARNING;
-    std::ostringstream e;
-    bool issueMessage = false;
-    switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0037)) {
-      case cmPolicies::WARN:
-        e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0037) << "\n";
-        issueMessage = true;
-      case cmPolicies::OLD:
-        break;
-      case cmPolicies::NEW:
-      case cmPolicies::REQUIRED_IF_USED:
-      case cmPolicies::REQUIRED_ALWAYS:
-        issueMessage = true;
-        messageType = cmake::FATAL_ERROR;
-    }
-    if (issueMessage) {
-      /* clang-format off */
-      e << "The target name \"" << targetName <<
-          "\" is reserved or not valid for certain "
-          "CMake features, such as generator expressions, and may result "
-          "in undefined behavior.";
-      /* clang-format on */
-      this->Makefile->IssueMessage(messageType, e.str());
-
-      if (messageType == cmake::FATAL_ERROR) {
-        return false;
-      }
-    }
+  if (!nameOk &&
+      !this->Makefile->CheckCMP0037(targetName, cmStateEnums::UTILITY)) {
+    return false;
   }
 
   // Store the last command line finished.
diff --git a/Source/cmAddExecutableCommand.cxx b/Source/cmAddExecutableCommand.cxx
index 1d0376f..b9e200a 100644
--- a/Source/cmAddExecutableCommand.cxx
+++ b/Source/cmAddExecutableCommand.cxx
@@ -7,10 +7,8 @@
 #include "cmGeneratorExpression.h"
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
-#include "cmPolicies.h"
 #include "cmStateTypes.h"
 #include "cmTarget.h"
-#include "cmake.h"
 
 class cmExecutionStatus;
 
@@ -18,7 +16,7 @@
 bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args,
                                          cmExecutionStatus&)
 {
-  if (args.size() < 2) {
+  if (args.empty()) {
     this->SetError("called with incorrect number of arguments");
     return false;
   }
@@ -63,35 +61,9 @@
   if (nameOk && !importTarget && !isAlias) {
     nameOk = exename.find(':') == std::string::npos;
   }
-  if (!nameOk) {
-    cmake::MessageType messageType = cmake::AUTHOR_WARNING;
-    std::ostringstream e;
-    bool issueMessage = false;
-    switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0037)) {
-      case cmPolicies::WARN:
-        e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0037) << "\n";
-        issueMessage = true;
-      case cmPolicies::OLD:
-        break;
-      case cmPolicies::NEW:
-      case cmPolicies::REQUIRED_IF_USED:
-      case cmPolicies::REQUIRED_ALWAYS:
-        issueMessage = true;
-        messageType = cmake::FATAL_ERROR;
-    }
-    if (issueMessage) {
-      /* clang-format off */
-      e << "The target name \"" << exename <<
-          "\" is reserved or not valid for certain "
-          "CMake features, such as generator expressions, and may result "
-          "in undefined behavior.";
-      /* clang-format on */
-      this->Makefile->IssueMessage(messageType, e.str());
-
-      if (messageType == cmake::FATAL_ERROR) {
-        return false;
-      }
-    }
+  if (!nameOk &&
+      !this->Makefile->CheckCMP0037(exename, cmStateEnums::EXECUTABLE)) {
+    return false;
   }
 
   // Special modifiers are not allowed with IMPORTED signature.
@@ -140,8 +112,7 @@
     if (!aliasedTarget) {
       std::ostringstream e;
       e << "cannot create ALIAS target \"" << exename << "\" because target \""
-        << aliasedName << "\" does not already "
-                          "exist.";
+        << aliasedName << "\" does not already exist.";
       this->SetError(e.str());
       return false;
     }
@@ -149,15 +120,15 @@
     if (type != cmStateEnums::EXECUTABLE) {
       std::ostringstream e;
       e << "cannot create ALIAS target \"" << exename << "\" because target \""
-        << aliasedName << "\" is not an "
-                          "executable.";
+        << aliasedName << "\" is not an executable.";
       this->SetError(e.str());
       return false;
     }
-    if (aliasedTarget->IsImported()) {
+    if (aliasedTarget->IsImported() &&
+        !aliasedTarget->IsImportedGloballyVisible()) {
       std::ostringstream e;
       e << "cannot create ALIAS target \"" << exename << "\" because target \""
-        << aliasedName << "\" is IMPORTED.";
+        << aliasedName << "\" is imported but not globally visible.";
       this->SetError(e.str());
       return false;
     }
@@ -191,12 +162,6 @@
     }
   }
 
-  if (s == args.end()) {
-    this->SetError(
-      "called with incorrect number of arguments, no sources provided");
-    return false;
-  }
-
   std::vector<std::string> srclists(s, args.end());
   cmTarget* tgt =
     this->Makefile->AddExecutable(exename.c_str(), srclists, excludeFromAll);
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx
index ebf1763..0fcffdd 100644
--- a/Source/cmAddLibraryCommand.cxx
+++ b/Source/cmAddLibraryCommand.cxx
@@ -7,7 +7,6 @@
 #include "cmGeneratorExpression.h"
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
-#include "cmPolicies.h"
 #include "cmState.h"
 #include "cmStateTypes.h"
 #include "cmSystemTools.h"
@@ -175,35 +174,8 @@
   if (nameOk && !importTarget && !isAlias) {
     nameOk = libName.find(':') == std::string::npos;
   }
-  if (!nameOk) {
-    cmake::MessageType messageType = cmake::AUTHOR_WARNING;
-    std::ostringstream e;
-    bool issueMessage = false;
-    switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0037)) {
-      case cmPolicies::WARN:
-        if (type != cmStateEnums::INTERFACE_LIBRARY) {
-          e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0037) << "\n";
-          issueMessage = true;
-        }
-      case cmPolicies::OLD:
-        break;
-      case cmPolicies::NEW:
-      case cmPolicies::REQUIRED_IF_USED:
-      case cmPolicies::REQUIRED_ALWAYS:
-        issueMessage = true;
-        messageType = cmake::FATAL_ERROR;
-    }
-    if (issueMessage) {
-      e << "The target name \"" << libName
-        << "\" is reserved or not valid for certain "
-           "CMake features, such as generator expressions, and may result "
-           "in undefined behavior.";
-      this->Makefile->IssueMessage(messageType, e.str());
-
-      if (messageType == cmake::FATAL_ERROR) {
-        return false;
-      }
-    }
+  if (!nameOk && !this->Makefile->CheckCMP0037(libName, type)) {
+    return false;
   }
 
   if (isAlias) {
@@ -256,13 +228,6 @@
       this->SetError(e.str());
       return false;
     }
-    if (aliasedTarget->IsImported()) {
-      std::ostringstream e;
-      e << "cannot create ALIAS target \"" << libName << "\" because target \""
-        << aliasedName << "\" is IMPORTED.";
-      this->SetError(e.str());
-      return false;
-    }
     this->Makefile->AddAlias(libName, aliasedName);
     return true;
   }
@@ -362,14 +327,6 @@
     return true;
   }
 
-  if (s == args.end()) {
-    std::string msg = "You have called ADD_LIBRARY for library ";
-    msg += args[0];
-    msg += " without any source files. This typically indicates a problem ";
-    msg += "with your CMakeLists.txt file";
-    cmSystemTools::Message(msg.c_str(), "Warning");
-  }
-
   srclists.insert(srclists.end(), s, args.end());
 
   this->Makefile->AddLibrary(libName, type, srclists, excludeFromAll);
diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h
index 69d0ed6..3380b78 100644
--- a/Source/cmAlgorithms.h
+++ b/Source/cmAlgorithms.h
@@ -43,22 +43,6 @@
 }
 
 template <typename T, size_t N>
-const T* cmArrayBegin(const T (&a)[N])
-{
-  return a;
-}
-template <typename T, size_t N>
-const T* cmArrayEnd(const T (&a)[N])
-{
-  return a + N;
-}
-template <typename T, size_t N>
-size_t cmArraySize(const T (&)[N])
-{
-  return N;
-}
-
-template <typename T, size_t N>
 bool cmHasLiteralPrefix(const T& str1, const char (&str2)[N])
 {
   return cmHasLiteralPrefixImpl(str1, str2, N - 1);
@@ -418,6 +402,67 @@
 
 #endif
 
+#if __cplusplus >= 201703L || defined(_MSVC_LANG) && _MSVC_LANG >= 201703L
+
+using std::size;
+
+#else
+
+// std::size backport from C++17.
+template <class C>
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+constexpr
+#endif
+  auto
+  size(C const& c) -> decltype(c.size())
+{
+  return c.size();
+}
+
+template <typename T, size_t N>
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+constexpr
+#endif
+  std::size_t
+  size(const T (&)[N]) throw()
+{
+  return N;
+}
+
+#endif
+
+#if __cplusplus >= 201402L || defined(_MSVC_LANG) && _MSVC_LANG >= 201402L
+
+using std::cbegin;
+using std::cend;
+
+#else
+
+// std::c{begin,end} backport from C++14
+template <class C>
+#if defined(_MSC_VER) && _MSC_VER < 1900
+auto cbegin(C const& c)
+#else
+constexpr auto cbegin(C const& c) noexcept(noexcept(std::begin(c)))
+#endif
+  -> decltype(std::begin(c))
+{
+  return std::begin(c);
+}
+
+template <class C>
+#if defined(_MSC_VER) && _MSC_VER < 1900
+auto cend(C const& c)
+#else
+constexpr auto cend(C const& c) noexcept(noexcept(std::end(c)))
+#endif
+  -> decltype(std::end(c))
+{
+  return std::end(c);
+}
+
+#endif
+
 } // namespace cm
 
 #endif
diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx
index 847a416..fcdc632 100644
--- a/Source/cmAuxSourceDirectoryCommand.cxx
+++ b/Source/cmAuxSourceDirectoryCommand.cxx
@@ -54,10 +54,8 @@
         std::string ext = file.substr(dotpos + 1);
         std::string base = file.substr(0, dotpos);
         // Process only source files
-        std::vector<std::string> const& srcExts =
-          this->Makefile->GetCMakeInstance()->GetSourceExtensions();
-        if (!base.empty() &&
-            std::find(srcExts.begin(), srcExts.end(), ext) != srcExts.end()) {
+        auto cm = this->Makefile->GetCMakeInstance();
+        if (!base.empty() && cm->IsSourceExtension(ext)) {
           std::string fullname = templateDirectory;
           fullname += "/";
           fullname += file;
diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx
index 5106f52..662dd74 100644
--- a/Source/cmCMakeHostSystemInformationCommand.cxx
+++ b/Source/cmCMakeHostSystemInformationCommand.cxx
@@ -8,6 +8,9 @@
 #include "cmsys/SystemInformation.hxx"
 
 #if defined(_WIN32)
+#include "cmAlgorithms.h"
+#include "cmGlobalGenerator.h"
+#include "cmGlobalVisualStudio15Generator.h"
 #include "cmSystemTools.h"
 #include "cmVSSetupHelper.h"
 #define HAVE_VS_SETUP_HELPER
@@ -127,6 +130,17 @@
     value = this->ValueToString(info.GetOSPlatform());
 #ifdef HAVE_VS_SETUP_HELPER
   } else if (key == "VS_15_DIR") {
+    // If generating for the VS 15 IDE, use the same instance.
+    cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
+    if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 15 ")) {
+      cmGlobalVisualStudio15Generator* vs15gen =
+        static_cast<cmGlobalVisualStudio15Generator*>(gg);
+      if (vs15gen->GetVSInstance(value)) {
+        return true;
+      }
+    }
+
+    // Otherwise, find a VS 15 instance ourselves.
     cmVSSetupAPIHelper vsSetupAPIHelper;
     if (vsSetupAPIHelper.GetVSInstanceInfo(value)) {
       cmSystemTools::ConvertToUnixSlashes(value);
diff --git a/Source/cmCMakeHostSystemInformationCommand.h b/Source/cmCMakeHostSystemInformationCommand.h
index bfff8f1..b871641 100644
--- a/Source/cmCMakeHostSystemInformationCommand.h
+++ b/Source/cmCMakeHostSystemInformationCommand.h
@@ -20,7 +20,7 @@
  * \brief Query host system specific information
  *
  * cmCMakeHostSystemInformationCommand queries system information of
- * the sytem on which CMake runs.
+ * the system on which CMake runs.
  */
 class cmCMakeHostSystemInformationCommand : public cmCommand
 {
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 4ea1493..d358e3d 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -12,6 +12,7 @@
 #include "cmsys/String.hxx"
 #include "cmsys/SystemInformation.hxx"
 #include <algorithm>
+#include <chrono>
 #include <ctype.h>
 #include <iostream>
 #include <map>
@@ -281,7 +282,6 @@
   this->GlobalTimeout = 0;
   this->LastStopTimeout = 24 * 60 * 60;
   this->CompressXMLFiles = false;
-  this->CTestConfigFile.clear();
   this->ScheduleType.clear();
   this->StopTime.clear();
   this->NextDayStopTime = false;
@@ -622,12 +622,9 @@
   if (this->SuppressUpdatingCTestConfiguration) {
     return true;
   }
-  std::string fileName = this->CTestConfigFile;
-  if (fileName.empty()) {
-    fileName = this->BinaryDir + "/CTestConfiguration.ini";
-    if (!cmSystemTools::FileExists(fileName.c_str())) {
-      fileName = this->BinaryDir + "/DartConfiguration.tcl";
-    }
+  std::string fileName = this->BinaryDir + "/CTestConfiguration.ini";
+  if (!cmSystemTools::FileExists(fileName.c_str())) {
+    fileName = this->BinaryDir + "/DartConfiguration.tcl";
   }
   cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
              "UpdateCTestConfiguration  from :" << fileName << "\n");
@@ -1421,7 +1418,7 @@
     std::string note_time = this->CurrentTime();
     xml.StartElement("Note");
     xml.Attribute("Name", file);
-    xml.Element("Time", cmSystemTools::GetTime());
+    xml.Element("Time", std::chrono::system_clock::now());
     xml.Element("DateTime", note_time);
     xml.StartElement("Text");
     cmsys::ifstream ifs(file.c_str());
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index dbd67dc..a2d6fc3 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -487,7 +487,6 @@
   /** Map of configuration properties */
   typedef std::map<std::string, std::string> CTestConfigurationMap;
 
-  std::string CTestConfigFile;
   // TODO: The ctest configuration should be a hierarchy of
   // configuration option sources: command-line, script, ini file.
   // Then the ini file can get re-loaded whenever it changes without
diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h
index e9e6570..28cba85 100644
--- a/Source/cmCacheManager.h
+++ b/Source/cmCacheManager.h
@@ -107,7 +107,7 @@
                  std::set<std::string>& excludes,
                  std::set<std::string>& includes);
 
-  ///! Save cache for given makefile.  Saves to ouput path/CMakeCache.txt
+  ///! Save cache for given makefile.  Saves to output path/CMakeCache.txt
   bool SaveCache(const std::string& path);
 
   ///! Delete the cache given
diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx
index 6ae58d6..bf314bd 100644
--- a/Source/cmCommandArgumentParserHelper.cxx
+++ b/Source/cmCommandArgumentParserHelper.cxx
@@ -21,13 +21,6 @@
   this->FileLine = -1;
   this->FileName = nullptr;
   this->RemoveEmpty = true;
-  this->EmptyVariable[0] = 0;
-  strcpy(this->DCURLYVariable, "${");
-  strcpy(this->RCURLYVariable, "}");
-  strcpy(this->ATVariable, "@");
-  strcpy(this->DOLLARVariable, "$");
-  strcpy(this->LCURLYVariable, "{");
-  strcpy(this->BSLASHVariable, "\\");
 
   this->NoEscapeMode = false;
   this->ReplaceAtSyntax = false;
@@ -44,10 +37,10 @@
   this->FileName = file;
 }
 
-char* cmCommandArgumentParserHelper::AddString(const std::string& str)
+const char* cmCommandArgumentParserHelper::AddString(const std::string& str)
 {
   if (str.empty()) {
-    return this->EmptyVariable;
+    return "";
   }
   char* stVal = new char[str.size() + 1];
   strcpy(stVal, str.c_str());
@@ -55,14 +48,14 @@
   return stVal;
 }
 
-char* cmCommandArgumentParserHelper::ExpandSpecialVariable(const char* key,
-                                                           const char* var)
+const char* cmCommandArgumentParserHelper::ExpandSpecialVariable(
+  const char* key, const char* var)
 {
   if (!key) {
     return this->ExpandVariable(var);
   }
   if (!var) {
-    return this->EmptyVariable;
+    return "";
   }
   if (strcmp(key, "ENV") == 0) {
     std::string str;
@@ -72,7 +65,7 @@
       }
       return this->AddString(str);
     }
-    return this->EmptyVariable;
+    return "";
   }
   if (strcmp(key, "CACHE") == 0) {
     if (const char* c =
@@ -82,7 +75,7 @@
       }
       return this->AddString(c);
     }
-    return this->EmptyVariable;
+    return "";
   }
   std::ostringstream e;
   e << "Syntax $" << key << "{} is not supported.  "
@@ -91,7 +84,7 @@
   return nullptr;
 }
 
-char* cmCommandArgumentParserHelper::ExpandVariable(const char* var)
+const char* cmCommandArgumentParserHelper::ExpandVariable(const char* var)
 {
   if (!var) {
     return nullptr;
@@ -125,11 +118,11 @@
   return this->AddString(value ? value : "");
 }
 
-char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var)
+const char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var)
 {
   if (this->ReplaceAtSyntax) {
     // try to expand the variable
-    char* ret = this->ExpandVariable(var);
+    const char* ret = this->ExpandVariable(var);
     // if the return was 0 and we want to replace empty strings
     // then return an empty string
     if (!ret && this->RemoveEmpty) {
@@ -150,7 +143,8 @@
   return this->AddString(ref);
 }
 
-char* cmCommandArgumentParserHelper::CombineUnions(char* in1, char* in2)
+const char* cmCommandArgumentParserHelper::CombineUnions(const char* in1,
+                                                         const char* in2)
 {
   if (!in1) {
     return in2;
@@ -176,10 +170,11 @@
   if (len == 0) {
     return;
   }
-  pt->str = new char[len + 1];
-  strncpy(pt->str, str, len);
-  pt->str[len] = 0;
-  this->Variables.push_back(pt->str);
+  char* out = new char[len + 1];
+  strncpy(out, str, len);
+  out[len] = 0;
+  pt->str = out;
+  this->Variables.push_back(out);
 }
 
 bool cmCommandArgumentParserHelper::HandleEscapeSymbol(
diff --git a/Source/cmCommandArgumentParserHelper.h b/Source/cmCommandArgumentParserHelper.h
index cb2a390..098c000 100644
--- a/Source/cmCommandArgumentParserHelper.h
+++ b/Source/cmCommandArgumentParserHelper.h
@@ -17,7 +17,7 @@
 public:
   struct ParserType
   {
-    char* str;
+    const char* str;
   };
 
   cmCommandArgumentParserHelper();
@@ -35,11 +35,11 @@
   void Error(const char* str);
 
   // For yacc
-  char* CombineUnions(char* in1, char* in2);
+  const char* CombineUnions(const char* in1, const char* in2);
 
-  char* ExpandSpecialVariable(const char* key, const char* var);
-  char* ExpandVariable(const char* var);
-  char* ExpandVariableForAt(const char* var);
+  const char* ExpandSpecialVariable(const char* key, const char* var);
+  const char* ExpandVariable(const char* var);
+  const char* ExpandVariableForAt(const char* var);
   void SetResult(const char* value);
 
   void SetMakefile(const cmMakefile* mf);
@@ -53,13 +53,6 @@
   void SetRemoveEmpty(bool b) { this->RemoveEmpty = b; }
 
   const char* GetError() { return this->ErrorString.c_str(); }
-  char EmptyVariable[1];
-  char DCURLYVariable[3];
-  char RCURLYVariable[3];
-  char ATVariable[3];
-  char DOLLARVariable[3];
-  char LCURLYVariable[3];
-  char BSLASHVariable[3];
 
 private:
   std::string::size_type InputBufferPos;
@@ -69,7 +62,7 @@
   void Print(const char* place, const char* str);
   void SafePrintMissing(const char* str, int line, int cnt);
 
-  char* AddString(const std::string& str);
+  const char* AddString(const std::string& str);
 
   void CleanupParser();
   void SetError(std::string const& msg);
diff --git a/Source/cmConvertMSBuildXMLToJSON.py b/Source/cmConvertMSBuildXMLToJSON.py
index 93ab8a8..92569e7 100644
--- a/Source/cmConvertMSBuildXMLToJSON.py
+++ b/Source/cmConvertMSBuildXMLToJSON.py
@@ -343,7 +343,7 @@
 
 
 def __preprocess_arguments(root):
-    """Preprocesses occurrances of Argument within the root.
+    """Preprocesses occurrences of Argument within the root.
 
     Argument XML values reference other values within the document by name. The
     referenced value does not contain a switch. This function will add the
diff --git a/Source/cmCurl.cxx b/Source/cmCurl.cxx
index 341b8c0..8ef8bff 100644
--- a/Source/cmCurl.cxx
+++ b/Source/cmCurl.cxx
@@ -56,3 +56,41 @@
 #endif
   return e;
 }
+
+std::string cmCurlSetNETRCOption(::CURL* curl, const std::string& netrc_level,
+                                 const std::string& netrc_file)
+{
+  std::string e;
+  CURL_NETRC_OPTION curl_netrc_level = CURL_NETRC_LAST;
+  ::CURLcode res;
+
+  if (!netrc_level.empty()) {
+    if (netrc_level == "OPTIONAL") {
+      curl_netrc_level = CURL_NETRC_OPTIONAL;
+    } else if (netrc_level == "REQUIRED") {
+      curl_netrc_level = CURL_NETRC_REQUIRED;
+    } else if (netrc_level == "IGNORED") {
+      curl_netrc_level = CURL_NETRC_IGNORED;
+    } else {
+      e = "NETRC accepts OPTIONAL, IGNORED or REQUIRED but got: ";
+      e += netrc_level;
+      return e;
+    }
+  }
+
+  if (curl_netrc_level != CURL_NETRC_LAST &&
+      curl_netrc_level != CURL_NETRC_IGNORED) {
+    res = ::curl_easy_setopt(curl, CURLOPT_NETRC, curl_netrc_level);
+    check_curl_result(res, "Unable to set netrc level: ");
+    if (!e.empty()) {
+      return e;
+    }
+
+    // check to see if a .netrc file has been specified
+    if (!netrc_file.empty()) {
+      res = ::curl_easy_setopt(curl, CURLOPT_NETRC_FILE, netrc_file.c_str());
+      check_curl_result(res, "Unable to set .netrc file path : ");
+    }
+  }
+  return e;
+}
diff --git a/Source/cmCurl.h b/Source/cmCurl.h
index 0688bb2..fe7eb80 100644
--- a/Source/cmCurl.h
+++ b/Source/cmCurl.h
@@ -9,5 +9,7 @@
 #include <string>
 
 std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile = nullptr);
+std::string cmCurlSetNETRCOption(::CURL* curl, const std::string& netrc_level,
+                                 const std::string& netrc_file);
 
 #endif
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 7f0cb97..7985d0f 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -591,7 +591,7 @@
     std::string::size_type commaPos = input.find(',', nameStartPos);
     std::string::size_type nextOpenPos = input.find("$<", nameStartPos);
     if (commaPos == std::string::npos    // Implied 'this' target
-        || closePos == std::string::npos // Imcomplete expression.
+        || closePos == std::string::npos // Incomplete expression.
         || closePos < commaPos           // Implied 'this' target
         || nextOpenPos < commaPos)       // Non-literal
     {
diff --git a/Source/cmExternalMakefileProjectGenerator.cxx b/Source/cmExternalMakefileProjectGenerator.cxx
index 825ec65..fecd821 100644
--- a/Source/cmExternalMakefileProjectGenerator.cxx
+++ b/Source/cmExternalMakefileProjectGenerator.cxx
@@ -24,6 +24,13 @@
   return fullName;
 }
 
+bool cmExternalMakefileProjectGenerator::Open(
+  const std::string& /*bindir*/, const std::string& /*projectName*/,
+  bool /*dryRun*/)
+{
+  return false;
+}
+
 cmExternalMakefileProjectGeneratorFactory::
   cmExternalMakefileProjectGeneratorFactory(const std::string& n,
                                             const std::string& doc)
diff --git a/Source/cmExternalMakefileProjectGenerator.h b/Source/cmExternalMakefileProjectGenerator.h
index a1734ee..7f332a8 100644
--- a/Source/cmExternalMakefileProjectGenerator.h
+++ b/Source/cmExternalMakefileProjectGenerator.h
@@ -55,6 +55,9 @@
   void SetName(const std::string& n) { Name = n; }
   std::string GetName() const { return Name; }
 
+  virtual bool Open(const std::string& bindir, const std::string& projectName,
+                    bool dryRun);
+
 protected:
   ///! Contains the names of the global generators support by this generator.
   std::vector<std::string> SupportedGlobalGenerators;
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index 9c9b75b..76fc8f1 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -345,8 +345,7 @@
   all_files_map_t allFiles;
   std::vector<std::string> cFiles;
 
-  std::vector<std::string> const& srcExts =
-    this->GlobalGenerator->GetCMakeInstance()->GetSourceExtensions();
+  auto cm = this->GlobalGenerator->GetCMakeInstance();
 
   for (cmLocalGenerator* lg : lgs) {
     cmMakefile* makefile = lg->GetMakefile();
@@ -377,12 +376,7 @@
             std::string lang = s->GetLanguage();
             if (lang == "C" || lang == "CXX") {
               std::string const& srcext = s->GetExtension();
-              for (std::string const& ext : srcExts) {
-                if (srcext == ext) {
-                  isCFile = true;
-                  break;
-                }
-              }
+              isCFile = cm->IsSourceExtension(srcext);
             }
 
             std::string const& fullPath = s->GetFullPath();
diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx
index 5a02d54..383942b 100644
--- a/Source/cmExtraCodeLiteGenerator.cxx
+++ b/Source/cmExtraCodeLiteGenerator.cxx
@@ -198,8 +198,7 @@
   std::map<std::string, cmSourceFile*>& cFiles,
   std::set<std::string>& otherFiles)
 {
-  const std::vector<std::string>& srcExts =
-    this->GlobalGenerator->GetCMakeInstance()->GetSourceExtensions();
+  auto cm = this->GlobalGenerator->GetCMakeInstance();
 
   std::string projectType;
   switch (gt->GetType()) {
@@ -233,12 +232,7 @@
         std::string lang = s->GetLanguage();
         if (lang == "C" || lang == "CXX") {
           std::string const& srcext = s->GetExtension();
-          for (std::string const& ext : srcExts) {
-            if (srcext == ext) {
-              isCFile = true;
-              break;
-            }
-          }
+          isCFile = cm->IsSourceExtension(srcext);
         }
 
         // then put it accordingly into one of the two containers
diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx
index 73a9c85..3d72ae3 100644
--- a/Source/cmExtraSublimeTextGenerator.cxx
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -400,3 +400,26 @@
 
   return definesString;
 }
+
+bool cmExtraSublimeTextGenerator::Open(const std::string& bindir,
+                                       const std::string& projectName,
+                                       bool dryRun)
+{
+  const char* sublExecutable =
+    this->GlobalGenerator->GetCMakeInstance()->GetCacheDefinition(
+      "CMAKE_SUBLIMETEXT_EXECUTABLE");
+  if (!sublExecutable) {
+    return false;
+  }
+  if (cmSystemTools::IsNOTFOUND(sublExecutable)) {
+    return false;
+  }
+
+  std::string filename = bindir + "/" + projectName + ".sublime-project";
+  if (dryRun) {
+    return cmSystemTools::FileExists(filename, true);
+  }
+
+  return cmSystemTools::RunSingleCommand(
+    { sublExecutable, "--project", filename });
+}
diff --git a/Source/cmExtraSublimeTextGenerator.h b/Source/cmExtraSublimeTextGenerator.h
index 7fb304e..57ba1cf 100644
--- a/Source/cmExtraSublimeTextGenerator.h
+++ b/Source/cmExtraSublimeTextGenerator.h
@@ -65,6 +65,9 @@
   std::string ComputeDefines(cmSourceFile* source, cmLocalGenerator* lg,
                              cmGeneratorTarget* gtgt);
 
+  bool Open(const std::string& bindir, const std::string& projectName,
+            bool dryRun) override;
+
   bool ExcludeBuildFolder;
   std::string EnvSettings;
 };
diff --git a/Source/cmFSPermissions.cxx b/Source/cmFSPermissions.cxx
new file mode 100644
index 0000000..4015a51
--- /dev/null
+++ b/Source/cmFSPermissions.cxx
@@ -0,0 +1,34 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmFSPermissions.h"
+
+bool cmFSPermissions::stringToModeT(std::string const& arg,
+                                    mode_t& permissions)
+{
+  if (arg == "OWNER_READ") {
+    permissions |= mode_owner_read;
+  } else if (arg == "OWNER_WRITE") {
+    permissions |= mode_owner_write;
+  } else if (arg == "OWNER_EXECUTE") {
+    permissions |= mode_owner_execute;
+  } else if (arg == "GROUP_READ") {
+    permissions |= mode_group_read;
+  } else if (arg == "GROUP_WRITE") {
+    permissions |= mode_group_write;
+  } else if (arg == "GROUP_EXECUTE") {
+    permissions |= mode_group_execute;
+  } else if (arg == "WORLD_READ") {
+    permissions |= mode_world_read;
+  } else if (arg == "WORLD_WRITE") {
+    permissions |= mode_world_write;
+  } else if (arg == "WORLD_EXECUTE") {
+    permissions |= mode_world_execute;
+  } else if (arg == "SETUID") {
+    permissions |= mode_setuid;
+  } else if (arg == "SETGID") {
+    permissions |= mode_setgid;
+  } else {
+    return false;
+  }
+  return true;
+}
diff --git a/Source/cmFSPermissions.h b/Source/cmFSPermissions.h
new file mode 100644
index 0000000..7a6e708
--- /dev/null
+++ b/Source/cmFSPermissions.h
@@ -0,0 +1,45 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmFSPermissions_h
+#define cmFSPermissions_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cm_sys_stat.h"
+
+#include <string>
+
+namespace cmFSPermissions {
+
+// Table of permissions flags.
+#if defined(_WIN32) && !defined(__CYGWIN__)
+static const mode_t mode_owner_read = S_IREAD;
+static const mode_t mode_owner_write = S_IWRITE;
+static const mode_t mode_owner_execute = S_IEXEC;
+static const mode_t mode_group_read = 040;
+static const mode_t mode_group_write = 020;
+static const mode_t mode_group_execute = 010;
+static const mode_t mode_world_read = 04;
+static const mode_t mode_world_write = 02;
+static const mode_t mode_world_execute = 01;
+static const mode_t mode_setuid = 04000;
+static const mode_t mode_setgid = 02000;
+#else
+static const mode_t mode_owner_read = S_IRUSR;
+static const mode_t mode_owner_write = S_IWUSR;
+static const mode_t mode_owner_execute = S_IXUSR;
+static const mode_t mode_group_read = S_IRGRP;
+static const mode_t mode_group_write = S_IWGRP;
+static const mode_t mode_group_execute = S_IXGRP;
+static const mode_t mode_world_read = S_IROTH;
+static const mode_t mode_world_write = S_IWOTH;
+static const mode_t mode_world_execute = S_IXOTH;
+static const mode_t mode_setuid = S_ISUID;
+static const mode_t mode_setgid = S_ISGID;
+#endif
+
+bool stringToModeT(std::string const& arg, mode_t& permissions);
+
+} // ns
+
+#endif
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index fdd5f0c..88185bd 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -20,6 +20,7 @@
 #include "cmAlgorithms.h"
 #include "cmCommandArgumentsHelper.h"
 #include "cmCryptoHash.h"
+#include "cmFSPermissions.h"
 #include "cmFileLockPool.h"
 #include "cmFileTimeComparison.h"
 #include "cmGeneratorExpression.h"
@@ -50,32 +51,7 @@
 
 class cmSystemToolsFileTime;
 
-// Table of permissions flags.
-#if defined(_WIN32) && !defined(__CYGWIN__)
-static mode_t mode_owner_read = S_IREAD;
-static mode_t mode_owner_write = S_IWRITE;
-static mode_t mode_owner_execute = S_IEXEC;
-static mode_t mode_group_read = 040;
-static mode_t mode_group_write = 020;
-static mode_t mode_group_execute = 010;
-static mode_t mode_world_read = 04;
-static mode_t mode_world_write = 02;
-static mode_t mode_world_execute = 01;
-static mode_t mode_setuid = 04000;
-static mode_t mode_setgid = 02000;
-#else
-static mode_t mode_owner_read = S_IRUSR;
-static mode_t mode_owner_write = S_IWUSR;
-static mode_t mode_owner_execute = S_IXUSR;
-static mode_t mode_group_read = S_IRGRP;
-static mode_t mode_group_write = S_IWGRP;
-static mode_t mode_group_execute = S_IXGRP;
-static mode_t mode_world_read = S_IROTH;
-static mode_t mode_world_write = S_IWOTH;
-static mode_t mode_world_execute = S_IXOTH;
-static mode_t mode_setuid = S_ISUID;
-static mode_t mode_setgid = S_ISGID;
-#endif
+using namespace cmFSPermissions;
 
 #if defined(_WIN32)
 // libcurl doesn't support file:// urls for unicode filenames on Windows.
@@ -1099,29 +1075,7 @@
   // Translate an argument to a permissions bit.
   bool CheckPermissions(std::string const& arg, mode_t& permissions)
   {
-    if (arg == "OWNER_READ") {
-      permissions |= mode_owner_read;
-    } else if (arg == "OWNER_WRITE") {
-      permissions |= mode_owner_write;
-    } else if (arg == "OWNER_EXECUTE") {
-      permissions |= mode_owner_execute;
-    } else if (arg == "GROUP_READ") {
-      permissions |= mode_group_read;
-    } else if (arg == "GROUP_WRITE") {
-      permissions |= mode_group_write;
-    } else if (arg == "GROUP_EXECUTE") {
-      permissions |= mode_group_execute;
-    } else if (arg == "WORLD_READ") {
-      permissions |= mode_world_read;
-    } else if (arg == "WORLD_WRITE") {
-      permissions |= mode_world_write;
-    } else if (arg == "WORLD_EXECUTE") {
-      permissions |= mode_world_execute;
-    } else if (arg == "SETUID") {
-      permissions |= mode_setuid;
-    } else if (arg == "SETGID") {
-      permissions |= mode_setgid;
-    } else {
+    if (!cmFSPermissions::stringToModeT(arg, permissions)) {
       std::ostringstream e;
       e << this->Name << " given invalid permission \"" << arg << "\".";
       this->FileCommand->SetError(e.str());
@@ -2015,9 +1969,30 @@
     this->DestDirLength = int(sdestdir.size());
   }
 
+  // check if default dir creation permissions were set
+  mode_t default_dir_mode_v = 0;
+  mode_t* default_dir_mode = nullptr;
+  const char* default_dir_install_permissions = this->Makefile->GetDefinition(
+    "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
+  if (default_dir_install_permissions && *default_dir_install_permissions) {
+    std::vector<std::string> items;
+    cmSystemTools::ExpandListArgument(default_dir_install_permissions, items);
+    for (const auto& arg : items) {
+      if (!this->CheckPermissions(arg, default_dir_mode_v)) {
+        std::ostringstream e;
+        e << this->FileCommand->GetError()
+          << " Set with CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS variable.";
+        this->FileCommand->SetError(e.str());
+        return false;
+      }
+    }
+
+    default_dir_mode = &default_dir_mode_v;
+  }
+
   if (this->InstallType != cmInstallType_DIRECTORY) {
     if (!cmSystemTools::FileExists(destination.c_str())) {
-      if (!cmSystemTools::MakeDirectory(destination.c_str())) {
+      if (!cmSystemTools::MakeDirectory(destination, default_dir_mode)) {
         std::string errstring = "cannot create directory: " + destination +
           ". Maybe need administrative privileges.";
         this->FileCommand->SetError(errstring);
@@ -2626,6 +2601,9 @@
   std::string statusVar;
   bool tls_verify = this->Makefile->IsOn("CMAKE_TLS_VERIFY");
   const char* cainfo = this->Makefile->GetDefinition("CMAKE_TLS_CAINFO");
+  std::string netrc_level = this->Makefile->GetSafeDefinition("CMAKE_NETRC");
+  std::string netrc_file =
+    this->Makefile->GetSafeDefinition("CMAKE_NETRC_FILE");
   std::string expectedHash;
   std::string hashMatchMSG;
   std::unique_ptr<cmCryptoHash> hash;
@@ -2681,6 +2659,22 @@
         this->SetError("TLS_CAFILE missing file value.");
         return false;
       }
+    } else if (*i == "NETRC_FILE") {
+      ++i;
+      if (i != args.end()) {
+        netrc_file = *i;
+      } else {
+        this->SetError("DOWNLOAD missing file value for NETRC_FILE.");
+        return false;
+      }
+    } else if (*i == "NETRC") {
+      ++i;
+      if (i != args.end()) {
+        netrc_level = *i;
+      } else {
+        this->SetError("DOWNLOAD missing level value for NETRC.");
+        return false;
+      }
     } else if (*i == "EXPECTED_MD5") {
       ++i;
       if (i == args.end()) {
@@ -2822,6 +2816,16 @@
     return false;
   }
 
+  // check to see if netrc parameters have been specified
+  // local command args takes precedence over CMAKE_NETRC*
+  netrc_level = cmSystemTools::UpperCase(netrc_level);
+  std::string const& netrc_option_err =
+    cmCurlSetNETRCOption(curl, netrc_level, netrc_file);
+  if (!netrc_option_err.empty()) {
+    this->SetError(netrc_option_err);
+    return false;
+  }
+
   cmFileCommandVectorOfChar chunkDebug;
 
   res = ::curl_easy_setopt(curl, CURLOPT_WRITEDATA, &fout);
@@ -2964,6 +2968,9 @@
   std::string statusVar;
   bool showProgress = false;
   std::string userpwd;
+  std::string netrc_level = this->Makefile->GetSafeDefinition("CMAKE_NETRC");
+  std::string netrc_file =
+    this->Makefile->GetSafeDefinition("CMAKE_NETRC_FILE");
 
   std::vector<std::string> curl_headers;
 
@@ -3000,6 +3007,22 @@
       statusVar = *i;
     } else if (*i == "SHOW_PROGRESS") {
       showProgress = true;
+    } else if (*i == "NETRC_FILE") {
+      ++i;
+      if (i != args.end()) {
+        netrc_file = *i;
+      } else {
+        this->SetError("UPLOAD missing file value for NETRC_FILE.");
+        return false;
+      }
+    } else if (*i == "NETRC") {
+      ++i;
+      if (i != args.end()) {
+        netrc_level = *i;
+      } else {
+        this->SetError("UPLOAD missing level value for NETRC.");
+        return false;
+      }
     } else if (*i == "USERPWD") {
       ++i;
       if (i == args.end()) {
@@ -3132,6 +3155,16 @@
     check_curl_result(res, "UPLOAD cannot set user password: ");
   }
 
+  // check to see if netrc parameters have been specified
+  // local command args takes precedence over CMAKE_NETRC*
+  netrc_level = cmSystemTools::UpperCase(netrc_level);
+  std::string const& netrc_option_err =
+    cmCurlSetNETRCOption(curl, netrc_level, netrc_file);
+  if (!netrc_option_err.empty()) {
+    this->SetError(netrc_option_err);
+    return false;
+  }
+
   struct curl_slist* headers = nullptr;
   for (std::string const& h : curl_headers) {
     headers = ::curl_slist_append(headers, h.c_str());
diff --git a/Source/cmFilePathChecksum.cxx b/Source/cmFilePathChecksum.cxx
index f9afeef..f84360e 100644
--- a/Source/cmFilePathChecksum.cxx
+++ b/Source/cmFilePathChecksum.cxx
@@ -34,10 +34,10 @@
                                          std::string const& projectSrcDir,
                                          std::string const& projectBinDir)
 {
-  this->parentDirs[0].first = cmsys::SystemTools::GetRealPath(currentSrcDir);
-  this->parentDirs[1].first = cmsys::SystemTools::GetRealPath(currentBinDir);
-  this->parentDirs[2].first = cmsys::SystemTools::GetRealPath(projectSrcDir);
-  this->parentDirs[3].first = cmsys::SystemTools::GetRealPath(projectBinDir);
+  this->parentDirs[0].first = cmSystemTools::GetRealPath(currentSrcDir);
+  this->parentDirs[1].first = cmSystemTools::GetRealPath(currentBinDir);
+  this->parentDirs[2].first = cmSystemTools::GetRealPath(projectSrcDir);
+  this->parentDirs[3].first = cmSystemTools::GetRealPath(projectBinDir);
 
   this->parentDirs[0].second = "CurrentSource";
   this->parentDirs[1].second = "CurrentBinary";
@@ -50,7 +50,7 @@
   std::string relPath;
   std::string relSeed;
   {
-    std::string const fileReal = cmsys::SystemTools::GetRealPath(filePath);
+    std::string const fileReal = cmSystemTools::GetRealPath(filePath);
     std::string parentDir;
     // Find closest project parent directory
     for (auto const& pDir : this->parentDirs) {
diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx
index 8142962..f771150 100644
--- a/Source/cmFindCommon.cxx
+++ b/Source/cmFindCommon.cxx
@@ -329,7 +329,7 @@
   std::set<std::string> ignored;
   this->GetIgnoredPaths(ignored);
 
-  // Combine the seperate path types, filtering out ignores
+  // Combine the separate path types, filtering out ignores
   this->SearchPaths.clear();
   std::vector<PathLabel>& allLabels = this->PathGroupLabelMap[PathGroup::All];
   for (PathLabel const& l : allLabels) {
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 5a72655..103dc5f 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -590,7 +590,7 @@
     this->AddFindDefinition(exact, this->VersionExact ? "1" : "0");
   }
 
-  // Push on to the pacakge stack
+  // Push on to the package stack
   this->Makefile->FindPackageModuleStack.push_back(this->Name);
 }
 
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx
index 542a860..df288bd 100644
--- a/Source/cmForEachCommand.cxx
+++ b/Source/cmForEachCommand.cxx
@@ -7,6 +7,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "cmAlgorithms.h"
 #include "cmExecutionStatus.h"
 #include "cmMakefile.h"
 #include "cmSystemTools.h"
@@ -121,7 +122,7 @@
   }
 
   // create a function blocker
-  cmForEachFunctionBlocker* f = new cmForEachFunctionBlocker(this->Makefile);
+  auto f = cm::make_unique<cmForEachFunctionBlocker>(this->Makefile);
   if (args.size() > 1) {
     if (args[1] == "RANGE") {
       int start = 0;
@@ -175,7 +176,7 @@
   } else {
     f->Args = args;
   }
-  this->Makefile->AddFunctionBlocker(f);
+  this->Makefile->AddFunctionBlocker(f.release());
 
   return true;
 }
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index fea20ba..7fe0cbe 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -1035,7 +1035,7 @@
         // No error. We just skip cyclic references.
         return std::string();
       case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
-        for (size_t i = 1; i < cmArraySize(targetPropertyTransitiveWhitelist);
+        for (size_t i = 1; i < cm::size(targetPropertyTransitiveWhitelist);
              ++i) {
           if (targetPropertyTransitiveWhitelist[i] == propertyName) {
             // No error. We're not going to find anything new here.
@@ -1443,7 +1443,7 @@
     context->HadContextSensitiveCondition = true;
     context->HadHeadSensitiveCondition = true;
 
-    for (size_t i = 1; i < cmArraySize(targetPolicyWhitelist); ++i) {
+    for (size_t i = 1; i < cm::size(targetPolicyWhitelist); ++i) {
       const char* policy = targetPolicyWhitelist[i];
       if (parameters.front() == policy) {
         cmLocalGenerator* lg = context->HeadTarget->GetLocalGenerator();
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index a31e415..b3e3393 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -489,7 +489,7 @@
     char const* sourceFullPath = (*si)->GetFullPath().c_str();
     cmSourceGroup* sourceGroup =
       this->Makefile->FindSourceGroup(sourceFullPath, sourceGroups);
-    std::string sgPath(sourceGroup->GetFullName());
+    std::string sgPath = sourceGroup->GetFullName();
     cmSystemTools::ConvertToUnixSlashes(sgPath);
     cmGlobalGhsMultiGenerator::AddFilesUpToPath(
       this->GetFolderBuildStreams(), &this->FolderBuildStreams,
@@ -608,7 +608,7 @@
   cmSourceGroup* sourceGroup =
     localGhsMultiGenerator->GetMakefile()->FindSourceGroup(sourceFullPath,
                                                            sourceGroups);
-  std::string const sgPath(sourceGroup->GetFullName());
+  std::string const& sgPath = sourceGroup->GetFullName();
   dir_max += sgPath;
   dir_max += "/Objs/libs/";
   dir_max += generatorTarget->Target->GetName();
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 05efff3..6e903fb 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -111,6 +111,26 @@
   delete this->ExtraGenerator;
 }
 
+bool cmGlobalGenerator::SetGeneratorInstance(std::string const& i,
+                                             cmMakefile* mf)
+{
+  if (i.empty()) {
+    return true;
+  }
+
+  std::ostringstream e;
+  /* clang-format off */
+  e <<
+    "Generator\n"
+    "  " << this->GetName() << "\n"
+    "does not support instance specification, but instance\n"
+    "  " << i << "\n"
+    "was specified.";
+  /* clang-format on */
+  mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+  return false;
+}
+
 bool cmGlobalGenerator::SetGeneratorPlatform(std::string const& p,
                                              cmMakefile* mf)
 {
@@ -261,6 +281,43 @@
 {
 }
 
+bool cmGlobalGenerator::CheckTargetsForMissingSources() const
+{
+  bool failed = false;
+  for (cmLocalGenerator* localGen : this->LocalGenerators) {
+    const std::vector<cmGeneratorTarget*>& targets =
+      localGen->GetGeneratorTargets();
+
+    for (cmGeneratorTarget* target : targets) {
+      if (target->GetType() == cmStateEnums::TargetType::GLOBAL_TARGET ||
+          target->GetType() == cmStateEnums::TargetType::INTERFACE_LIBRARY ||
+          target->GetType() == cmStateEnums::TargetType::UTILITY) {
+        continue;
+      }
+
+      std::vector<std::string> configs;
+      target->Makefile->GetConfigurations(configs);
+      std::vector<cmSourceFile*> srcs;
+      if (configs.empty()) {
+        target->GetSourceFiles(srcs, "");
+      } else {
+        for (std::vector<std::string>::const_iterator ci = configs.begin();
+             ci != configs.end() && srcs.empty(); ++ci) {
+          target->GetSourceFiles(srcs, *ci);
+        }
+      }
+      if (srcs.empty()) {
+        std::ostringstream e;
+        e << "No SOURCES given to target: " << target->GetName();
+        this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
+                                               target->GetBacktrace());
+        failed = true;
+      }
+    }
+  }
+  return failed;
+}
+
 bool cmGlobalGenerator::IsExportedTargetsFile(
   const std::string& filename) const
 {
@@ -491,6 +548,13 @@
   }
 
   if (readCMakeSystem) {
+    // Tell the generator about the instance, if any.
+    std::string instance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE");
+    if (!this->SetGeneratorInstance(instance, mf)) {
+      cmSystemTools::SetFatalErrorOccured();
+      return;
+    }
+
     // Find the native build tool for this generator.
     if (!this->FindMakeProgram(mf)) {
       return;
@@ -898,7 +962,7 @@
     }
   } else {
     // if no language is found then check to see if it is already an
-    // ouput extension for some language.  In that case it should be ignored
+    // output extension for some language.  In that case it should be ignored
     // and in this map, so it will not be compiled but will just be used.
     std::string const& ext = source.GetExtension();
     if (!ext.empty()) {
@@ -1250,7 +1314,10 @@
 #ifdef CMAKE_BUILD_WITH_CMAKE
   // Iterate through all targets and set up automoc for those which have
   // the AUTOMOC, AUTOUIC or AUTORCC property set
-  cmQtAutoGenDigestUPV autogenDigests = this->CreateQtAutoGeneratorsTargets();
+  auto autogenInits = this->CreateQtAutoGenInitializers();
+  for (auto& autoGen : autogenInits) {
+    autoGen->InitCustomTargets();
+  }
 #endif
 
   // Add generator specific helper commands
@@ -1271,10 +1338,11 @@
   }
 
 #ifdef CMAKE_BUILD_WITH_CMAKE
-  for (cmQtAutoGenDigestUP const& digest : autogenDigests) {
-    cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(*digest);
+  for (auto& autoGen : autogenInits) {
+    autoGen->SetupCustomTargets();
+    autoGen.reset(nullptr);
   }
-  autogenDigests.clear();
+  autogenInits.clear();
 #endif
 
   for (cmLocalGenerator* localGen : this->LocalGenerators) {
@@ -1292,6 +1360,11 @@
     localGen->TraceDependencies();
   }
 
+  // Make sure that all (non-imported) targets have source files added!
+  if (this->CheckTargetsForMissingSources()) {
+    return false;
+  }
+
   this->ForceLinkerLanguages();
 
   // Compute the manifest of main targets generated.
@@ -1400,9 +1473,10 @@
   return true;
 }
 
-cmQtAutoGenDigestUPV cmGlobalGenerator::CreateQtAutoGeneratorsTargets()
+std::vector<std::unique_ptr<cmQtAutoGeneratorInitializer>>
+cmGlobalGenerator::CreateQtAutoGenInitializers()
 {
-  cmQtAutoGenDigestUPV autogenDigests;
+  std::vector<std::unique_ptr<cmQtAutoGeneratorInitializer>> autogenInits;
 
 #ifdef CMAKE_BUILD_WITH_CMAKE
   for (cmLocalGenerator* localGen : this->LocalGenerators) {
@@ -1438,25 +1512,12 @@
         continue;
       }
 
-      {
-        cmQtAutoGenDigestUP digest(new cmQtAutoGenDigest(target));
-        digest->QtVersionMajor = std::move(qtVersionMajor);
-        digest->QtVersionMinor =
-          cmQtAutoGeneratorInitializer::GetQtMinorVersion(
-            target, digest->QtVersionMajor);
-        digest->MocEnabled = mocEnabled;
-        digest->UicEnabled = uicEnabled;
-        digest->RccEnabled = rccEnabled;
-        autogenDigests.emplace_back(std::move(digest));
-      }
+      autogenInits.emplace_back(new cmQtAutoGeneratorInitializer(
+        target, mocEnabled, uicEnabled, rccEnabled, qtVersionMajor));
     }
   }
-  // Initialize autogen targets
-  for (const cmQtAutoGenDigestUP& digest : autogenDigests) {
-    cmQtAutoGeneratorInitializer::InitializeAutogenTarget(*digest);
-  }
 #endif
-  return autogenDigests;
+  return autogenInits;
 }
 
 cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer(
@@ -1824,6 +1885,16 @@
   return retVal;
 }
 
+bool cmGlobalGenerator::Open(const std::string& bindir,
+                             const std::string& projectName, bool dryRun)
+{
+  if (this->ExtraGenerator) {
+    return this->ExtraGenerator->Open(bindir, projectName, dryRun);
+  }
+
+  return false;
+}
+
 std::string cmGlobalGenerator::GenerateCMakeBuildCommand(
   const std::string& target, const std::string& config,
   const std::string& native, bool ignoreErrors)
@@ -2141,6 +2212,45 @@
   return s;
 }
 
+bool cmGlobalGenerator::CheckCMP0037(std::string const& targetName,
+                                     std::string const& reason) const
+{
+  cmTarget* tgt = this->FindTarget(targetName);
+  if (!tgt) {
+    return true;
+  }
+  cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+  std::ostringstream e;
+  bool issueMessage = false;
+  switch (tgt->GetPolicyStatusCMP0037()) {
+    case cmPolicies::WARN:
+      e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0037) << "\n";
+      issueMessage = true;
+      CM_FALLTHROUGH;
+    case cmPolicies::OLD:
+      break;
+    case cmPolicies::NEW:
+    case cmPolicies::REQUIRED_IF_USED:
+    case cmPolicies::REQUIRED_ALWAYS:
+      issueMessage = true;
+      messageType = cmake::FATAL_ERROR;
+      break;
+  }
+  if (issueMessage) {
+    e << "The target name \"" << targetName << "\" is reserved " << reason
+      << ".";
+    if (messageType == cmake::AUTHOR_WARNING) {
+      e << "  It may result in undefined behavior.";
+    }
+    this->GetCMakeInstance()->IssueMessage(messageType, e.str(),
+                                           tgt->GetBacktrace());
+    if (messageType == cmake::FATAL_ERROR) {
+      return false;
+    }
+  }
+  return true;
+}
+
 void cmGlobalGenerator::CreateDefaultGlobalTargets(
   std::vector<GlobalTargetInfo>& targets)
 {
@@ -2156,6 +2266,20 @@
   std::vector<GlobalTargetInfo>& targets)
 {
   cmMakefile* mf = this->Makefiles[0];
+  std::string configFile = mf->GetCurrentBinaryDirectory();
+  configFile += "/CPackConfig.cmake";
+  if (!cmSystemTools::FileExists(configFile.c_str())) {
+    return;
+  }
+
+  const char* reservedTargets[] = { "package", "PACKAGE" };
+  for (const char* const* tn = cm::cbegin(reservedTargets);
+       tn != cm::cend(reservedTargets); ++tn) {
+    if (!this->CheckCMP0037(*tn, "when CPack packaging is enabled")) {
+      return;
+    }
+  }
+
   const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir();
   GlobalTargetInfo gti;
   gti.Name = this->GetPackageTargetName();
@@ -2169,8 +2293,6 @@
     singleLine.push_back(cmakeCfgIntDir);
   }
   singleLine.push_back("--config");
-  std::string configFile = mf->GetCurrentBinaryDirectory();
-  configFile += "/CPackConfig.cmake";
   std::string relConfigFile = "./CPackConfig.cmake";
   singleLine.push_back(relConfigFile);
   gti.CommandLines.push_back(singleLine);
@@ -2183,61 +2305,81 @@
       gti.Depends.push_back(this->GetAllTargetName());
     }
   }
-  if (cmSystemTools::FileExists(configFile.c_str())) {
-    targets.push_back(gti);
-  }
+  targets.push_back(gti);
 }
 
 void cmGlobalGenerator::AddGlobalTarget_PackageSource(
   std::vector<GlobalTargetInfo>& targets)
 {
-  cmMakefile* mf = this->Makefiles[0];
   const char* packageSourceTargetName = this->GetPackageSourceTargetName();
-  if (packageSourceTargetName) {
-    GlobalTargetInfo gti;
-    gti.Name = packageSourceTargetName;
-    gti.Message = "Run CPack packaging tool for source...";
-    gti.WorkingDir = mf->GetCurrentBinaryDirectory();
-    gti.UsesTerminal = true;
-    cmCustomCommandLine singleLine;
-    singleLine.push_back(cmSystemTools::GetCPackCommand());
-    singleLine.push_back("--config");
-    std::string configFile = mf->GetCurrentBinaryDirectory();
-    configFile += "/CPackSourceConfig.cmake";
-    std::string relConfigFile = "./CPackSourceConfig.cmake";
-    singleLine.push_back(relConfigFile);
-    if (cmSystemTools::FileExists(configFile.c_str())) {
-      singleLine.push_back(configFile);
-      gti.CommandLines.push_back(singleLine);
-      targets.push_back(gti);
+  if (!packageSourceTargetName) {
+    return;
+  }
+
+  cmMakefile* mf = this->Makefiles[0];
+  std::string configFile = mf->GetCurrentBinaryDirectory();
+  configFile += "/CPackSourceConfig.cmake";
+  if (!cmSystemTools::FileExists(configFile.c_str())) {
+    return;
+  }
+
+  const char* reservedTargets[] = { "package_source" };
+  for (const char* const* tn = cm::cbegin(reservedTargets);
+       tn != cm::cend(reservedTargets); ++tn) {
+    if (!this->CheckCMP0037(*tn, "when CPack source packaging is enabled")) {
+      return;
     }
   }
+
+  GlobalTargetInfo gti;
+  gti.Name = packageSourceTargetName;
+  gti.Message = "Run CPack packaging tool for source...";
+  gti.WorkingDir = mf->GetCurrentBinaryDirectory();
+  gti.UsesTerminal = true;
+  cmCustomCommandLine singleLine;
+  singleLine.push_back(cmSystemTools::GetCPackCommand());
+  singleLine.push_back("--config");
+  std::string relConfigFile = "./CPackSourceConfig.cmake";
+  singleLine.push_back(relConfigFile);
+  singleLine.push_back(configFile);
+  gti.CommandLines.push_back(singleLine);
+  targets.push_back(gti);
 }
 
 void cmGlobalGenerator::AddGlobalTarget_Test(
   std::vector<GlobalTargetInfo>& targets)
 {
   cmMakefile* mf = this->Makefiles[0];
-  const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir();
-  if (mf->IsOn("CMAKE_TESTING_ENABLED")) {
-    GlobalTargetInfo gti;
-    gti.Name = this->GetTestTargetName();
-    gti.Message = "Running tests...";
-    gti.UsesTerminal = true;
-    cmCustomCommandLine singleLine;
-    singleLine.push_back(cmSystemTools::GetCTestCommand());
-    singleLine.push_back("--force-new-ctest-process");
-    if (cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.') {
-      singleLine.push_back("-C");
-      singleLine.push_back(cmakeCfgIntDir);
-    } else // TODO: This is a hack. Should be something to do with the
-           // generator
-    {
-      singleLine.push_back("$(ARGS)");
-    }
-    gti.CommandLines.push_back(singleLine);
-    targets.push_back(gti);
+  if (!mf->IsOn("CMAKE_TESTING_ENABLED")) {
+    return;
   }
+
+  const char* reservedTargets[] = { "test", "RUN_TESTS" };
+  for (const char* const* tn = cm::cbegin(reservedTargets);
+       tn != cm::cend(reservedTargets); ++tn) {
+    if (!this->CheckCMP0037(*tn, "when CTest testing is enabled")) {
+      return;
+    }
+  }
+
+  const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir();
+  GlobalTargetInfo gti;
+  gti.Name = this->GetTestTargetName();
+  gti.Message = "Running tests...";
+  gti.UsesTerminal = true;
+  cmCustomCommandLine singleLine;
+  singleLine.push_back(cmSystemTools::GetCTestCommand());
+  singleLine.push_back("--force-new-ctest-process");
+  if (cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.') {
+    singleLine.push_back("-C");
+    singleLine.push_back(cmakeCfgIntDir);
+  } else // TODO: This is a hack. Should be something to do with the
+         // generator
+  {
+    singleLine.push_back("$(ARGS)");
+  }
+  gti.CommandLines.push_back(singleLine);
+  targets.push_back(gti);
 }
 
 void cmGlobalGenerator::AddGlobalTarget_EditCache(
@@ -2503,14 +2645,13 @@
   // by one or more of the cmake generators.
 
   // Adding additional targets to this list will require a policy!
-  const char* reservedTargets[] = {
-    "all",        "ALL_BUILD", "help",       "install",        "INSTALL",
-    "preinstall", "clean",     "edit_cache", "rebuild_cache",  "test",
-    "RUN_TESTS",  "package",   "PACKAGE",    "package_source", "ZERO_CHECK"
-  };
+  const char* reservedTargets[] = { "all",       "ALL_BUILD",  "help",
+                                    "install",   "INSTALL",    "preinstall",
+                                    "clean",     "edit_cache", "rebuild_cache",
+                                    "ZERO_CHECK" };
 
-  return std::find(cmArrayBegin(reservedTargets), cmArrayEnd(reservedTargets),
-                   name) != cmArrayEnd(reservedTargets);
+  return std::find(cm::cbegin(reservedTargets), cm::cend(reservedTargets),
+                   name) != cm::cend(reservedTargets);
 }
 
 void cmGlobalGenerator::SetExternalMakefileProjectGenerator(
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 18ca682..99f33e5 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -15,7 +15,6 @@
 
 #include "cmCustomCommandLines.h"
 #include "cmExportSetMap.h"
-#include "cmQtAutoGenDigest.h"
 #include "cmStateSnapshot.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
@@ -33,6 +32,7 @@
 class cmLocalGenerator;
 class cmMakefile;
 class cmOutputConverter;
+class cmQtAutoGeneratorInitializer;
 class cmSourceFile;
 class cmStateDirectory;
 class cmake;
@@ -70,6 +70,9 @@
   /** Tell the generator about the target system.  */
   virtual bool SetSystemName(std::string const&, cmMakefile*) { return true; }
 
+  /** Set the generator-specific instance.  Returns true if supported.  */
+  virtual bool SetGeneratorInstance(std::string const& i, cmMakefile* mf);
+
   /** Set the generator-specific platform name.  Returns true if platform
       is supported and false otherwise.  */
   virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf);
@@ -162,6 +165,12 @@
             std::vector<std::string> const& nativeOptions =
               std::vector<std::string>());
 
+  /**
+   * Open a generated IDE project given the following information.
+   */
+  virtual bool Open(const std::string& bindir, const std::string& projectName,
+                    bool dryRun);
+
   virtual void GenerateBuildCommand(
     std::vector<std::string>& makeCommand, const std::string& makeProgram,
     const std::string& projectName, const std::string& projectDir,
@@ -424,7 +433,8 @@
   virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const;
 
   // Qt auto generators
-  cmQtAutoGenDigestUPV CreateQtAutoGeneratorsTargets();
+  std::vector<std::unique_ptr<cmQtAutoGeneratorInitializer>>
+  CreateQtAutoGenInitializers();
 
   std::string SelectMakeProgram(const std::string& makeProgram,
                                 const std::string& makeDefault = "") const;
@@ -533,6 +543,8 @@
 
   virtual void ForceLinkerLanguages();
 
+  bool CheckTargetsForMissingSources() const;
+
   void CreateLocalGenerators();
 
   void CheckCompilerIdCompatibility(cmMakefile* mf,
@@ -557,6 +569,9 @@
 
   void ClearGeneratorMembers();
 
+  bool CheckCMP0037(std::string const& targetName,
+                    std::string const& reason) const;
+
   void IndexMakefile(cmMakefile* mf);
 
   virtual const char* GetBuildIgnoreErrorsFlag() const { return nullptr; }
diff --git a/Source/cmGlobalKdevelopGenerator.cxx b/Source/cmGlobalKdevelopGenerator.cxx
index b1e630e..80aadb9 100644
--- a/Source/cmGlobalKdevelopGenerator.cxx
+++ b/Source/cmGlobalKdevelopGenerator.cxx
@@ -110,7 +110,7 @@
            nullptr)) {
         files.insert(tmp);
         tmp = cmSystemTools::GetFilenameName(tmp);
-        // add all files which dont match the default
+        // add all files which don't match the default
         // */CMakeLists.txt;*cmake; to the file pattern
         if ((tmp != "CMakeLists.txt") &&
             (strstr(tmp.c_str(), ".cmake") == nullptr)) {
diff --git a/Source/cmGlobalVisualStudio15Generator.cxx b/Source/cmGlobalVisualStudio15Generator.cxx
index d2bf7cc..014d93d 100644
--- a/Source/cmGlobalVisualStudio15Generator.cxx
+++ b/Source/cmGlobalVisualStudio15Generator.cxx
@@ -111,6 +111,53 @@
   }
 }
 
+bool cmGlobalVisualStudio15Generator::SetGeneratorInstance(
+  std::string const& i, cmMakefile* mf)
+{
+  if (!i.empty()) {
+    if (!this->vsSetupAPIHelper.SetVSInstance(i)) {
+      std::ostringstream e;
+      /* clang-format off */
+      e <<
+        "Generator\n"
+        "  " << this->GetName() << "\n"
+        "could not find specified instance of Visual Studio:\n"
+        "  " << i;
+      /* clang-format on */
+      mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+      return false;
+    }
+  }
+
+  std::string vsInstance;
+  if (!this->vsSetupAPIHelper.GetVSInstanceInfo(vsInstance)) {
+    std::ostringstream e;
+    /* clang-format off */
+    e <<
+      "Generator\n"
+      "  " << this->GetName() << "\n"
+      "could not find any instance of Visual Studio.\n";
+    /* clang-format on */
+    mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+    return false;
+  }
+
+  // Save the selected instance persistently.
+  std::string genInstance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE");
+  if (vsInstance != genInstance) {
+    this->CMakeInstance->AddCacheEntry(
+      "CMAKE_GENERATOR_INSTANCE", vsInstance.c_str(),
+      "Generator instance identifier.", cmStateEnums::INTERNAL);
+  }
+
+  return true;
+}
+
+bool cmGlobalVisualStudio15Generator::GetVSInstance(std::string& dir) const
+{
+  return vsSetupAPIHelper.GetVSInstanceInfo(dir);
+}
+
 bool cmGlobalVisualStudio15Generator::InitializeWindows(cmMakefile* mf)
 {
   // If the Win 8.1 SDK is installed then we can select a SDK matching
diff --git a/Source/cmGlobalVisualStudio15Generator.h b/Source/cmGlobalVisualStudio15Generator.h
index e934882..852a4e7 100644
--- a/Source/cmGlobalVisualStudio15Generator.h
+++ b/Source/cmGlobalVisualStudio15Generator.h
@@ -27,6 +27,11 @@
   virtual void WriteSLNHeader(std::ostream& fout);
 
   virtual const char* GetToolsVersion() { return "15.0"; }
+
+  bool SetGeneratorInstance(std::string const& i, cmMakefile* mf) override;
+
+  bool GetVSInstance(std::string& dir) const;
+
 protected:
   bool InitializeWindows(cmMakefile* mf) override;
   virtual bool SelectWindowsStoreToolset(std::string& toolset) const;
diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx
index 3b45c90..8a9a3fb 100644
--- a/Source/cmGlobalVisualStudio71Generator.cxx
+++ b/Source/cmGlobalVisualStudio71Generator.cxx
@@ -222,7 +222,7 @@
   }
 }
 
-// ouput standard header for dsw file
+// output standard header for dsw file
 void cmGlobalVisualStudio71Generator::WriteSLNHeader(std::ostream& fout)
 {
   fout << "Microsoft Visual Studio Solution File, Format Version 8.00\n";
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index cc1d1a2..dee874f 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -146,7 +146,7 @@
   }
 }
 
-// ouput standard header for dsw file
+// output standard header for dsw file
 void cmGlobalVisualStudio8Generator::WriteSLNHeader(std::ostream& fout)
 {
   fout << "Microsoft Visual Studio Solution File, Format Version 9.00\n";
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index 0651536..99600df 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -4,7 +4,10 @@
 #include "cmGlobalVisualStudioGenerator.h"
 
 #include "cmsys/Encoding.hxx"
+#include <future>
 #include <iostream>
+#include <objbase.h>
+#include <shellapi.h>
 #include <windows.h>
 
 #include "cmAlgorithms.h"
@@ -103,15 +106,6 @@
   // Configure CMake Visual Studio macros, for this user on this version
   // of Visual Studio.
   this->ConfigureCMakeVisualStudioMacros();
-
-  // Add CMakeLists.txt with custom command to rerun CMake.
-  for (std::vector<cmLocalGenerator*>::const_iterator lgi =
-         this->LocalGenerators.begin();
-       lgi != this->LocalGenerators.end(); ++lgi) {
-    cmLocalVisualStudioGenerator* lg =
-      static_cast<cmLocalVisualStudioGenerator*>(*lgi);
-    lg->AddCMakeListsRules();
-  }
 }
 
 void cmGlobalVisualStudioGenerator::ComputeTargetObjectDirectory(
@@ -928,3 +922,33 @@
                           commandLines, "Auto build dll exports", ".");
   commands.push_back(command);
 }
+
+static bool OpenSolution(std::string sln)
+{
+  HRESULT comInitialized =
+    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
+  if (FAILED(comInitialized)) {
+    return false;
+  }
+
+  HINSTANCE hi =
+    ShellExecuteA(NULL, "open", sln.c_str(), NULL, NULL, SW_SHOWNORMAL);
+
+  CoUninitialize();
+
+  return reinterpret_cast<intptr_t>(hi) > 32;
+}
+
+bool cmGlobalVisualStudioGenerator::Open(const std::string& bindir,
+                                         const std::string& projectName,
+                                         bool dryRun)
+{
+  std::string buildDir = cmSystemTools::ConvertToOutputPath(bindir.c_str());
+  std::string sln = buildDir + "\\" + projectName + ".sln";
+
+  if (dryRun) {
+    return cmSystemTools::FileExists(sln, true);
+  }
+
+  return std::async(std::launch::async, OpenSolution, sln).get();
+}
diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h
index 62bfd3b..55a6813 100644
--- a/Source/cmGlobalVisualStudioGenerator.h
+++ b/Source/cmGlobalVisualStudioGenerator.h
@@ -131,6 +131,9 @@
                               std::vector<cmCustomCommand>& commands,
                               std::string const& configName);
 
+  bool Open(const std::string& bindir, const std::string& projectName,
+            bool dryRun) override;
+
 protected:
   virtual void AddExtraIDETargets();
 
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index c79ee47..41fe5d2 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -35,6 +35,11 @@
 
 struct cmLinkImplementation;
 
+#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(__APPLE__)
+#define HAVE_APPLICATION_SERVICES
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
 #if defined(CMAKE_BUILD_WITH_CMAKE)
 #include "cmXMLParser.h"
 
@@ -287,6 +292,35 @@
   this->ComputeArchitectures(mf);
 }
 
+bool cmGlobalXCodeGenerator::Open(const std::string& bindir,
+                                  const std::string& projectName, bool dryRun)
+{
+  bool ret = false;
+
+#ifdef HAVE_APPLICATION_SERVICES
+  std::string url = bindir + "/" + projectName + ".xcodeproj";
+
+  if (dryRun) {
+    return cmSystemTools::FileExists(url, false);
+  }
+
+  CFStringRef cfStr = CFStringCreateWithCString(
+    kCFAllocatorDefault, url.c_str(), kCFStringEncodingUTF8);
+  if (cfStr) {
+    CFURLRef cfUrl = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, cfStr,
+                                                   kCFURLPOSIXPathStyle, true);
+    if (cfUrl) {
+      OSStatus err = LSOpenCFURLRef(cfUrl, nullptr);
+      ret = err == noErr;
+      CFRelease(cfUrl);
+    }
+    CFRelease(cfStr);
+  }
+#endif
+
+  return ret;
+}
+
 void cmGlobalXCodeGenerator::GenerateBuildCommand(
   std::vector<std::string>& makeCommand, const std::string& makeProgram,
   const std::string& projectName, const std::string& /*projectDir*/,
@@ -334,14 +368,13 @@
 
 void cmGlobalXCodeGenerator::AddExtraIDETargets()
 {
-  std::map<std::string, std::vector<cmLocalGenerator*>>::iterator it;
   // make sure extra targets are added before calling
   // the parent generate which will call trace depends
-  for (it = this->ProjectMap.begin(); it != this->ProjectMap.end(); ++it) {
-    cmLocalGenerator* root = it->second[0];
+  for (auto keyVal : this->ProjectMap) {
+    cmLocalGenerator* root = keyVal.second[0];
     this->SetGenerationRoot(root);
     // add ALL_BUILD, INSTALL, etc
-    this->AddExtraTargets(root, it->second);
+    this->AddExtraTargets(root, keyVal.second);
   }
 }
 
@@ -351,12 +384,22 @@
   if (cmSystemTools::GetErrorOccuredFlag()) {
     return;
   }
-  std::map<std::string, std::vector<cmLocalGenerator*>>::iterator it;
-  for (it = this->ProjectMap.begin(); it != this->ProjectMap.end(); ++it) {
-    cmLocalGenerator* root = it->second[0];
+  for (auto keyVal : this->ProjectMap) {
+    cmLocalGenerator* root = keyVal.second[0];
+
+    bool generateTopLevelProjectOnly =
+      root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY");
+
+    if (generateTopLevelProjectOnly) {
+      cmStateSnapshot snp = root->GetStateSnapshot();
+      if (snp.GetBuildsystemDirectoryParent().IsValid()) {
+        continue;
+      }
+    }
+
     this->SetGenerationRoot(root);
     // now create the project
-    this->OutputXCodeProject(root, it->second);
+    this->OutputXCodeProject(root, keyVal.second);
   }
 }
 
@@ -404,12 +447,6 @@
   cmGeneratorTarget* allBuildGt = new cmGeneratorTarget(allbuild, root);
   root->AddGeneratorTarget(allBuildGt);
 
-  // Refer to the main build configuration file for easy editing.
-  std::string listfile = root->GetCurrentSourceDirectory();
-  listfile += "/";
-  listfile += "CMakeLists.txt";
-  allBuildGt->AddSource(listfile);
-
   // Add XCODE depend helper
   std::string dir = root->GetCurrentBinaryDirectory();
   cmCustomCommandLine makeHelper;
@@ -442,8 +479,7 @@
       continue;
     }
 
-    const std::vector<cmGeneratorTarget*>& tgts = gen->GetGeneratorTargets();
-    for (auto target : tgts) {
+    for (auto target : gen->GetGeneratorTargets()) {
       if (target->GetType() == cmStateEnums::GLOBAL_TARGET) {
         continue;
       }
@@ -479,12 +515,6 @@
           !target->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
         allbuild->AddUtility(target->GetName());
       }
-
-      // Refer to the build configuration file for easy editing.
-      listfile = gen->GetCurrentSourceDirectory();
-      listfile += "/";
-      listfile += "CMakeLists.txt";
-      target->AddSource(listfile);
     }
   }
 }
@@ -516,10 +546,9 @@
   makefileStream << "space:= $(empty) $(empty)\n";
   makefileStream << "spaceplus:= $(empty)\\ $(empty)\n\n";
 
-  for (std::vector<std::string>::const_iterator i = lfiles.begin();
-       i != lfiles.end(); ++i) {
+  for (const auto& lfile : lfiles) {
     makefileStream << "TARGETS += $(subst $(space),$(spaceplus),$(wildcard "
-                   << this->ConvertToRelativeForMake(i->c_str()) << "))\n";
+                   << this->ConvertToRelativeForMake(lfile.c_str()) << "))\n";
   }
 
   std::string checkCache = root->GetBinaryDirectory();
@@ -728,9 +757,8 @@
     cmSystemTools::ExpandListArgument(extraFileAttributes, attributes);
 
     // Store the attributes.
-    for (std::vector<std::string>::const_iterator ai = attributes.begin();
-         ai != attributes.end(); ++ai) {
-      attrs->AddObject(this->CreateString(*ai));
+    for (const auto& attribute : attributes) {
+      attrs->AddObject(this->CreateString(attribute));
     }
   }
 
@@ -925,12 +953,10 @@
   cmLocalGenerator* gen, std::vector<cmXCodeObject*>& targets)
 {
   this->SetCurrentLocalGenerator(gen);
-  const std::vector<cmGeneratorTarget*>& tgts =
-    this->CurrentLocalGenerator->GetGeneratorTargets();
   typedef std::map<std::string, cmGeneratorTarget*, cmCompareTargets>
     cmSortedTargets;
   cmSortedTargets sortedTargets;
-  for (auto tgt : tgts) {
+  for (auto tgt : this->CurrentLocalGenerator->GetGeneratorTargets()) {
     sortedTargets[tgt->GetName()] = tgt;
   }
   for (auto& sortedTarget : sortedTargets) {
@@ -962,6 +988,13 @@
     if (!gtgt->GetConfigCommonSourceFiles(classes)) {
       return false;
     }
+
+    // Add CMakeLists.txt file for user convenience.
+    std::string listfile =
+      gtgt->GetLocalGenerator()->GetCurrentSourceDirectory();
+    listfile += "/CMakeLists.txt";
+    classes.push_back(gtgt->Makefile->GetOrCreateSource(listfile));
+
     std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare());
 
     gtgt->ComputeObjectMapping();
@@ -970,21 +1003,20 @@
     std::vector<cmXCodeObject*> headerFiles;
     std::vector<cmXCodeObject*> resourceFiles;
     std::vector<cmXCodeObject*> sourceFiles;
-    for (std::vector<cmSourceFile*>::const_iterator i = classes.begin();
-         i != classes.end(); ++i) {
-      cmXCodeObject* xsf =
-        this->CreateXCodeSourceFile(this->CurrentLocalGenerator, *i, gtgt);
+    for (auto sourceFile : classes) {
+      cmXCodeObject* xsf = this->CreateXCodeSourceFile(
+        this->CurrentLocalGenerator, sourceFile, gtgt);
       cmXCodeObject* fr = xsf->GetObject("fileRef");
       cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType");
 
       cmGeneratorTarget::SourceFileFlags tsFlags =
-        gtgt->GetTargetSourceFileFlags(*i);
+        gtgt->GetTargetSourceFileFlags(sourceFile);
 
       if (filetype && filetype->GetString() == "compiled.mach-o.objfile") {
-        if ((*i)->GetObjectLibrary().empty()) {
+        if (sourceFile->GetObjectLibrary().empty()) {
           externalObjFiles.push_back(xsf);
         }
-      } else if (this->IsHeaderFile(*i) ||
+      } else if (this->IsHeaderFile(sourceFile) ||
                  (tsFlags.Type ==
                   cmGeneratorTarget::SourceFileTypePrivateHeader) ||
                  (tsFlags.Type ==
@@ -992,12 +1024,13 @@
         headerFiles.push_back(xsf);
       } else if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource) {
         resourceFiles.push_back(xsf);
-      } else if (!(*i)->GetPropertyAsBool("HEADER_FILE_ONLY")) {
+      } else if (!sourceFile->GetPropertyAsBool("HEADER_FILE_ONLY")) {
         // Include this file in the build if it has a known language
         // and has not been listed as an ignored extension for this
         // generator.
-        if (!this->CurrentLocalGenerator->GetSourceFileLanguage(**i).empty() &&
-            !this->IgnoreFile((*i)->GetExtension().c_str())) {
+        if (!this->CurrentLocalGenerator->GetSourceFileLanguage(*sourceFile)
+               .empty() &&
+            !this->IgnoreFile(sourceFile->GetExtension().c_str())) {
           sourceFiles.push_back(xsf);
         }
       }
@@ -1009,12 +1042,11 @@
       // within the target.)
       std::vector<cmSourceFile const*> objs;
       gtgt->GetExternalObjects(objs, "");
-      for (std::vector<cmSourceFile const*>::const_iterator oi = objs.begin();
-           oi != objs.end(); ++oi) {
-        if ((*oi)->GetObjectLibrary().empty()) {
+      for (auto sourceFile : objs) {
+        if (sourceFile->GetObjectLibrary().empty()) {
           continue;
         }
-        std::string const& obj = (*oi)->GetFullPath();
+        std::string const& obj = sourceFile->GetFullPath();
         cmXCodeObject* xsf =
           this->CreateXCodeSourceFileFromPath(obj, gtgt, "", nullptr);
         externalObjFiles.push_back(xsf);
@@ -1087,16 +1119,14 @@
       typedef std::map<std::string, std::vector<cmSourceFile*>>
         mapOfVectorOfSourceFiles;
       mapOfVectorOfSourceFiles bundleFiles;
-      for (std::vector<cmSourceFile*>::const_iterator i = classes.begin();
-           i != classes.end(); ++i) {
+      for (auto sourceFile : classes) {
         cmGeneratorTarget::SourceFileFlags tsFlags =
-          gtgt->GetTargetSourceFileFlags(*i);
+          gtgt->GetTargetSourceFileFlags(sourceFile);
         if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) {
-          bundleFiles[tsFlags.MacFolder].push_back(*i);
+          bundleFiles[tsFlags.MacFolder].push_back(sourceFile);
         }
       }
-      mapOfVectorOfSourceFiles::iterator mit;
-      for (mit = bundleFiles.begin(); mit != bundleFiles.end(); ++mit) {
+      for (auto keySources : bundleFiles) {
         cmXCodeObject* copyFilesBuildPhase =
           this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase);
         copyFilesBuildPhase->SetComment("Copy files");
@@ -1107,13 +1137,13 @@
         std::ostringstream ostr;
         if (gtgt->IsFrameworkOnApple()) {
           // dstPath in frameworks is relative to Versions/<version>
-          ostr << mit->first;
-        } else if (mit->first != "MacOS") {
+          ostr << keySources.first;
+        } else if (keySources.first != "MacOS") {
           if (gtgt->Target->GetMakefile()->PlatformIsAppleIos()) {
-            ostr << mit->first;
+            ostr << keySources.first;
           } else {
             // dstPath in bundles is relative to Contents/MacOS
-            ostr << "../" << mit->first;
+            ostr << "../" << keySources.first;
           }
         }
         copyFilesBuildPhase->AddAttribute("dstPath",
@@ -1122,10 +1152,9 @@
                                           this->CreateString("0"));
         buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
         copyFilesBuildPhase->AddAttribute("files", buildFiles);
-        std::vector<cmSourceFile*>::iterator sfIt;
-        for (sfIt = mit->second.begin(); sfIt != mit->second.end(); ++sfIt) {
+        for (auto sourceFile : keySources.second) {
           cmXCodeObject* xsf = this->CreateXCodeSourceFile(
-            this->CurrentLocalGenerator, *sfIt, gtgt);
+            this->CurrentLocalGenerator, sourceFile, gtgt);
           buildFiles->AddObject(xsf);
         }
         contentBuildPhases.push_back(copyFilesBuildPhase);
@@ -1138,16 +1167,14 @@
       typedef std::map<std::string, std::vector<cmSourceFile*>>
         mapOfVectorOfSourceFiles;
       mapOfVectorOfSourceFiles bundleFiles;
-      for (std::vector<cmSourceFile*>::const_iterator i = classes.begin();
-           i != classes.end(); ++i) {
+      for (auto sourceFile : classes) {
         cmGeneratorTarget::SourceFileFlags tsFlags =
-          gtgt->GetTargetSourceFileFlags(*i);
+          gtgt->GetTargetSourceFileFlags(sourceFile);
         if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) {
-          bundleFiles[tsFlags.MacFolder].push_back(*i);
+          bundleFiles[tsFlags.MacFolder].push_back(sourceFile);
         }
       }
-      mapOfVectorOfSourceFiles::iterator mit;
-      for (mit = bundleFiles.begin(); mit != bundleFiles.end(); ++mit) {
+      for (auto keySources : bundleFiles) {
         cmXCodeObject* copyFilesBuildPhase =
           this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase);
         copyFilesBuildPhase->SetComment("Copy files");
@@ -1155,16 +1182,15 @@
                                           this->CreateString("2147483647"));
         copyFilesBuildPhase->AddAttribute("dstSubfolderSpec",
                                           this->CreateString("7"));
-        copyFilesBuildPhase->AddAttribute("dstPath",
-                                          this->CreateString(mit->first));
+        copyFilesBuildPhase->AddAttribute(
+          "dstPath", this->CreateString(keySources.first));
         copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
                                           this->CreateString("0"));
         buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
         copyFilesBuildPhase->AddAttribute("files", buildFiles);
-        std::vector<cmSourceFile*>::iterator sfIt;
-        for (sfIt = mit->second.begin(); sfIt != mit->second.end(); ++sfIt) {
+        for (auto sourceFile : keySources.second) {
           cmXCodeObject* xsf = this->CreateXCodeSourceFile(
-            this->CurrentLocalGenerator, *sfIt, gtgt);
+            this->CurrentLocalGenerator, sourceFile, gtgt);
           buildFiles->AddObject(xsf);
         }
         contentBuildPhases.push_back(copyFilesBuildPhase);
@@ -1203,11 +1229,9 @@
 
 void cmGlobalXCodeGenerator::ForceLinkerLanguages()
 {
-  for (auto& localGenerator : this->LocalGenerators) {
-    const std::vector<cmGeneratorTarget*>& tgts =
-      localGenerator->GetGeneratorTargets();
+  for (auto localGenerator : this->LocalGenerators) {
     // All targets depend on the build-system check target.
-    for (auto tgt : tgts) {
+    for (auto tgt : localGenerator->GetGeneratorTargets()) {
       // This makes sure all targets link using the proper language.
       this->ForceLinkerLanguage(tgt);
     }
@@ -1229,8 +1253,8 @@
   }
 
   // If the language is compiled as a source trust Xcode to link with it.
-  cmLinkImplementation const* impl = gtgt->GetLinkImplementation("NOCONFIG");
-  for (auto const& Language : impl->Languages) {
+  for (auto const& Language :
+       gtgt->GetLinkImplementation("NOCONFIG")->Languages) {
     if (Language == llang) {
       return;
     }
@@ -1330,10 +1354,9 @@
   }
   // add all the sources
   std::vector<cmCustomCommand> commands;
-  for (std::vector<cmSourceFile*>::const_iterator i = classes.begin();
-       i != classes.end(); ++i) {
-    if ((*i)->GetCustomCommand()) {
-      commands.push_back(*(*i)->GetCustomCommand());
+  for (auto sourceFile : classes) {
+    if (sourceFile->GetCustomCommand()) {
+      commands.push_back(*sourceFile->GetCustomCommand());
     }
   }
   // create prebuild phase
@@ -1365,10 +1388,8 @@
   if (resourceBuildPhase) {
     buildPhases->AddObject(resourceBuildPhase);
   }
-  std::vector<cmXCodeObject*>::iterator cit;
-  for (cit = contentBuildPhases.begin(); cit != contentBuildPhases.end();
-       ++cit) {
-    buildPhases->AddObject(*cit);
+  for (auto obj : contentBuildPhases) {
+    buildPhases->AddObject(obj);
   }
   if (sourceBuildPhase) {
     buildPhases->AddObject(sourceBuildPhase);
@@ -1491,12 +1512,9 @@
   makefile += name;
   makefile += ".make";
 
-  for (std::vector<std::string>::const_iterator currentConfig =
-         this->CurrentConfigurationTypes.begin();
-       currentConfig != this->CurrentConfigurationTypes.end();
-       currentConfig++) {
+  for (const auto& currentConfig : this->CurrentConfigurationTypes) {
     this->CreateCustomRulesMakefile(makefile.c_str(), target, commands,
-                                    *currentConfig);
+                                    currentConfig);
   }
 
   std::string cdir = this->CurrentLocalGenerator->GetCurrentBinaryDirectory();
@@ -1976,8 +1994,7 @@
   }
   // Add framework search paths needed for linking.
   if (cmComputeLinkInformation* cli = gtgt->GetLinkInformation(configName)) {
-    std::vector<std::string> const& fwDirs = cli->GetFrameworkPaths();
-    for (auto const& fwDir : fwDirs) {
+    for (auto const& fwDir : cli->GetFrameworkPaths()) {
       if (emitted.insert(fwDir).second) {
         std::string incpath = this->XCodeEscapePath(fwDir);
         if (emitSystemIncludes &&
@@ -2142,9 +2159,7 @@
     // runpath dirs needs to be unique to prevent corruption
     std::set<std::string> unique_dirs;
 
-    for (std::vector<std::string>::const_iterator i = runtimeDirs.begin();
-         i != runtimeDirs.end(); ++i) {
-      std::string runpath = *i;
+    for (auto runpath : runtimeDirs) {
       runpath = this->ExpandCFGIntDir(runpath, configName);
 
       if (unique_dirs.find(runpath) == unique_dirs.end()) {
@@ -2204,8 +2219,7 @@
   // put this last so it can override existing settings
   // Convert "XCODE_ATTRIBUTE_*" properties directly.
   {
-    std::vector<std::string> const& props = gtgt->GetPropertyKeys();
-    for (auto const& prop : props) {
+    for (auto const& prop : gtgt->GetPropertyKeys()) {
       if (prop.find("XCODE_ATTRIBUTE_") == 0) {
         std::string attribute = prop.substr(16);
         this->FilterConfigurationAttribute(configName, attribute);
@@ -2259,16 +2273,22 @@
   this->XCodeObjectMap[gtgt] = target;
 
   // Add source files without build rules for editing convenience.
-  if (gtgt->GetType() == cmStateEnums::UTILITY) {
+  if (gtgt->GetType() == cmStateEnums::UTILITY &&
+      gtgt->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
     std::vector<cmSourceFile*> sources;
     if (!gtgt->GetConfigCommonSourceFiles(sources)) {
       return nullptr;
     }
 
-    for (std::vector<cmSourceFile*>::const_iterator i = sources.begin();
-         i != sources.end(); ++i) {
-      if (!(*i)->GetPropertyAsBool("GENERATED")) {
-        this->CreateXCodeFileReference(*i, gtgt);
+    // Add CMakeLists.txt file for user convenience.
+    std::string listfile =
+      gtgt->GetLocalGenerator()->GetCurrentSourceDirectory();
+    listfile += "/CMakeLists.txt";
+    sources.push_back(gtgt->Makefile->GetOrCreateSource(listfile));
+
+    for (auto sourceFile : sources) {
+      if (!sourceFile->GetPropertyAsBool("GENERATED")) {
+        this->CreateXCodeFileReference(sourceFile, gtgt);
       }
     }
   }
@@ -2537,17 +2557,10 @@
     target->GetObject("buildConfigurationList")->GetObject();
   cmXCodeObject* buildConfigs =
     configurationList->GetObject("buildConfigurations");
-  std::vector<cmXCodeObject*> list = buildConfigs->GetObjectList();
-  // each configuration and the target itself has a buildSettings in it
-  // list.push_back(target);
-  for (auto& i : list) {
-    if (!configName.empty()) {
-      if (i->GetObject("name")->GetString() == configName) {
-        cmXCodeObject* settings = i->GetObject("buildSettings");
-        this->AppendOrAddBuildSetting(settings, attribute, value);
-      }
-    } else {
-      cmXCodeObject* settings = i->GetObject("buildSettings");
+  for (auto obj : buildConfigs->GetObjectList()) {
+    if (configName.empty() ||
+        obj->GetObject("name")->GetString() == configName) {
+      cmXCodeObject* settings = obj->GetObject("buildSettings");
       this->AppendOrAddBuildSetting(settings, attribute, value);
     }
   }
@@ -2565,8 +2578,7 @@
   }
 
   // Add dependencies on other CMake targets.
-  TargetDependSet const& deps = this->GetTargetDirectDepends(gt);
-  for (auto dep : deps) {
+  for (const auto& dep : this->GetTargetDirectDepends(gt)) {
     if (cmXCodeObject* dptarget = this->FindXCodeTarget(dep)) {
       this->AddDependTarget(target, dptarget);
     }
@@ -2581,14 +2593,13 @@
       const char* sep = "";
       std::vector<cmSourceFile const*> objs;
       gt->GetExternalObjects(objs, configName);
-      for (std::vector<cmSourceFile const*>::const_iterator oi = objs.begin();
-           oi != objs.end(); ++oi) {
-        if ((*oi)->GetObjectLibrary().empty()) {
+      for (auto sourceFile : objs) {
+        if (sourceFile->GetObjectLibrary().empty()) {
           continue;
         }
         linkObjs += sep;
         sep = " ";
-        linkObjs += this->XCodeEscapePath((*oi)->GetFullPath());
+        linkObjs += this->XCodeEscapePath(sourceFile->GetFullPath());
       }
       this->AppendBuildSettingAttribute(
         target, this->GetTargetLinkFlagsVar(gt), linkObjs.c_str(), configName);
@@ -2608,18 +2619,14 @@
     cmComputeLinkInformation& cli = *pcli;
 
     // Add dependencies directly on library files.
-    {
-      std::vector<std::string> const& libDeps = cli.GetDepends();
-      for (auto const& libDep : libDeps) {
-        target->AddDependLibrary(configName, libDep);
-      }
+    for (auto const& libDep : cli.GetDepends()) {
+      target->AddDependLibrary(configName, libDep);
     }
 
     // add the library search paths
     {
-      std::vector<std::string> const& libDirs = cli.GetDirectories();
       std::string linkDirs;
-      for (auto const& libDir : libDirs) {
+      for (auto const& libDir : cli.GetDirectories()) {
         if (!libDir.empty() && libDir != "/usr/lib") {
           // Now add the same one but append
           // $(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) to it:
@@ -2638,9 +2645,7 @@
     {
       std::string linkLibs;
       const char* sep = "";
-      typedef cmComputeLinkInformation::ItemVector ItemVector;
-      ItemVector const& libNames = cli.GetItems();
-      for (auto const& libName : libNames) {
+      for (auto const& libName : cli.GetItems()) {
         linkLibs += sep;
         sep = " ";
         if (libName.IsPath) {
@@ -2666,11 +2671,9 @@
   for (auto& generator : generators) {
     cmMakefile* mf = generator->GetMakefile();
     std::vector<cmSourceGroup> sourceGroups = mf->GetSourceGroups();
-    const std::vector<cmGeneratorTarget*>& tgts =
-      generator->GetGeneratorTargets();
-    for (auto gtgt : tgts) {
+    for (auto gtgt : generator->GetGeneratorTargets()) {
       // Same skipping logic here as in CreateXCodeTargets so that we do not
-      // end up with (empty anyhow) ALL_BUILD and XCODE_DEPEND_HELPER source
+      // end up with (empty anyhow) ZERO_CHECK, install, or test source
       // groups:
       //
       if (gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) {
@@ -2679,6 +2682,9 @@
       if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
         continue;
       }
+      if (gtgt->GetName() == CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
+        continue;
+      }
 
       // add the soon to be generated Info.plist file as a source for a
       // MACOSX_BUNDLE file
@@ -2688,11 +2694,8 @@
         gtgt->AddSource(plist);
       }
 
-      std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
-        gtgt->GetAllConfigSources();
-
       // Put cmSourceFile instances in proper groups:
-      for (auto const& si : sources) {
+      for (auto const& si : gtgt->GetAllConfigSources()) {
         cmSourceFile const* sf = si.Source;
         if (this->XcodeVersion >= 50 && !sf->GetObjectLibrary().empty()) {
           // Object library files go on the link line instead.
@@ -2706,6 +2709,20 @@
         std::string key = GetGroupMapKeyFromPath(gtgt, source);
         this->GroupMap[key] = pbxgroup;
       }
+
+      // Add CMakeLists.txt file for user convenience.
+      {
+        std::string listfile =
+          gtgt->GetLocalGenerator()->GetCurrentSourceDirectory();
+        listfile += "/CMakeLists.txt";
+        cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(listfile);
+        std::string const& source = sf->GetFullPath();
+        cmSourceGroup* sourceGroup =
+          mf->FindSourceGroup(source.c_str(), sourceGroups);
+        cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(gtgt, sourceGroup);
+        std::string key = GetGroupMapKeyFromPath(gtgt, source);
+        this->GroupMap[key] = pbxgroup;
+      }
     }
   }
   return true;
@@ -2780,18 +2797,17 @@
   // If it's the default source group (empty name) then put the source file
   // directly in the tgroup...
   //
-  if (std::string(sg->GetFullName()).empty()) {
+  if (sg->GetFullName().empty()) {
     this->GroupNameMap[s] = tgroup;
     return tgroup;
   }
 
   // It's a recursive folder structure, let's find the real parent group
-  if (std::string(sg->GetFullName()) != std::string(sg->GetName())) {
-    std::vector<std::string> folders =
-      cmSystemTools::tokenize(sg->GetFullName(), "\\");
+  if (sg->GetFullName() != sg->GetName()) {
     std::string curr_folder = target;
     curr_folder += "/";
-    for (auto const& folder : folders) {
+    for (auto const& folder :
+         cmSystemTools::tokenize(sg->GetFullName(), "\\")) {
       curr_folder += folder;
       std::map<std::string, cmXCodeObject*>::iterator i_folder =
         this->GroupNameMap.find(curr_folder);
@@ -2896,10 +2912,9 @@
     this->CreateObject(cmXCodeObject::OBJECT_LIST);
   typedef std::vector<std::pair<std::string, cmXCodeObject*>> Configs;
   Configs configs;
-  const char* defaultConfigName = "Debug";
-  for (unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i) {
-    const char* name = this->CurrentConfigurationTypes[i].c_str();
-    if (0 == i) {
+  std::string defaultConfigName;
+  for (const auto& name : this->CurrentConfigurationTypes) {
+    if (defaultConfigName.empty()) {
       defaultConfigName = name;
     }
     cmXCodeObject* config =
@@ -2907,6 +2922,9 @@
     config->AddAttribute("name", this->CreateString(name));
     configs.push_back(std::make_pair(name, config));
   }
+  if (defaultConfigName.empty()) {
+    defaultConfigName = "Debug";
+  }
   for (auto& config : configs) {
     buildConfigurations->AddObject(config.second);
   }
@@ -2971,16 +2989,14 @@
 
     // Put this last so it can override existing settings
     // Convert "CMAKE_XCODE_ATTRIBUTE_*" variables directly.
-    std::vector<std::string> vars = this->CurrentMakefile->GetDefinitions();
-    for (std::vector<std::string>::const_iterator d = vars.begin();
-         d != vars.end(); ++d) {
-      if (d->find("CMAKE_XCODE_ATTRIBUTE_") == 0) {
-        std::string attribute = d->substr(22);
+    for (const auto& var : this->CurrentMakefile->GetDefinitions()) {
+      if (var.find("CMAKE_XCODE_ATTRIBUTE_") == 0) {
+        std::string attribute = var.substr(22);
         this->FilterConfigurationAttribute(config.first, attribute);
         if (!attribute.empty()) {
           cmGeneratorExpression ge;
           std::string processed =
-            ge.Parse(this->CurrentMakefile->GetDefinition(*d))
+            ge.Parse(this->CurrentMakefile->GetDefinition(var))
               ->Evaluate(this->CurrentLocalGenerator, config.first);
           buildSettingsForCfg->AddAttribute(attribute,
                                             this->CreateString(processed));
@@ -3096,10 +3112,7 @@
     "# link.  This forces Xcode to relink the targets from scratch.  It\n"
     "# does not seem to check these dependencies itself.\n";
   /* clang-format on */
-  for (std::vector<std::string>::const_iterator ct =
-         this->CurrentConfigurationTypes.begin();
-       ct != this->CurrentConfigurationTypes.end(); ++ct) {
-    std::string configName = *ct;
+  for (const auto& configName : this->CurrentConfigurationTypes) {
     for (auto target : targets) {
       cmGeneratorTarget* gt = target->GetTarget();
 
@@ -3109,7 +3122,7 @@
           gt->GetType() == cmStateEnums::SHARED_LIBRARY ||
           gt->GetType() == cmStateEnums::MODULE_LIBRARY) {
         // Declare an entry point for the target post-build phase.
-        makefileStream << this->PostBuildMakeTarget(gt->GetName(), *ct)
+        makefileStream << this->PostBuildMakeTarget(gt->GetName(), configName)
                        << ":\n";
       }
 
@@ -3122,21 +3135,19 @@
 
         // Add this target to the post-build phases of its dependencies.
         std::map<std::string, cmXCodeObject::StringVec>::const_iterator y =
-          target->GetDependTargets().find(*ct);
+          target->GetDependTargets().find(configName);
         if (y != target->GetDependTargets().end()) {
-          std::vector<std::string> const& deptgts = y->second;
-          for (auto const& deptgt : deptgts) {
-            makefileStream << this->PostBuildMakeTarget(deptgt, *ct) << ": "
-                           << trel << "\n";
+          for (auto const& deptgt : y->second) {
+            makefileStream << this->PostBuildMakeTarget(deptgt, configName)
+                           << ": " << trel << "\n";
           }
         }
 
         std::vector<cmGeneratorTarget*> objlibs;
         gt->GetObjectLibrariesCMP0026(objlibs);
-        for (std::vector<cmGeneratorTarget*>::const_iterator it =
-               objlibs.begin();
-             it != objlibs.end(); ++it) {
-          makefileStream << this->PostBuildMakeTarget((*it)->GetName(), *ct)
+        for (auto objLib : objlibs) {
+          makefileStream << this->PostBuildMakeTarget(objLib->GetName(),
+                                                      configName)
                          << ": " << trel << "\n";
         }
 
@@ -3145,23 +3156,20 @@
 
         // List dependencies if any exist.
         std::map<std::string, cmXCodeObject::StringVec>::const_iterator x =
-          target->GetDependLibraries().find(*ct);
+          target->GetDependLibraries().find(configName);
         if (x != target->GetDependLibraries().end()) {
-          std::vector<std::string> const& deplibs = x->second;
-          for (auto const& deplib : deplibs) {
+          for (auto const& deplib : x->second) {
             std::string file = this->ConvertToRelativeForMake(deplib.c_str());
             makefileStream << "\\\n\t" << file;
             dummyRules.insert(file);
           }
         }
 
-        for (std::vector<cmGeneratorTarget*>::const_iterator it =
-               objlibs.begin();
-             it != objlibs.end(); ++it) {
+        for (auto objLib : objlibs) {
 
-          const std::string objLibName = (*it)->GetName();
+          const std::string objLibName = objLib->GetName();
           std::string d = this->GetObjectsNormalDirectory(this->CurrentProject,
-                                                          configName, *it);
+                                                          configName, objLib);
           d += "lib";
           d += objLibName;
           d += ".a";
@@ -3181,7 +3189,7 @@
         if (this->Architectures.size() > 1) {
           std::string universal = this->GetObjectsNormalDirectory(
             this->CurrentProject, configName, gt);
-          for (auto& architecture : this->Architectures) {
+          for (const auto& architecture : this->Architectures) {
             std::string universalFile = universal;
             universalFile += architecture;
             universalFile += "/";
@@ -3212,7 +3220,7 @@
     return;
   }
   // Skip local generators that are excluded from this project.
-  for (auto& generator : generators) {
+  for (auto generator : generators) {
     if (this->IsExcluded(root, generator)) {
       continue;
     }
@@ -3234,9 +3242,9 @@
   }
   this->WriteXCodePBXProj(fout, root, generators);
 
-  // Since the lowest available Xcode version for testing was 7.0,
+  // Since the lowest available Xcode version for testing was 6.4,
   // I'm setting this as a limit then
-  if (this->XcodeVersion >= 70) {
+  if (this->XcodeVersion >= 64) {
     if (root->GetMakefile()->GetCMakeInstance()->GetIsInTryCompile() ||
         root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_SCHEME")) {
       this->OutputXCodeSharedSchemes(xcodeDir);
@@ -3258,10 +3266,7 @@
   // collect all tests for the targets
   std::map<std::string, cmXCodeScheme::TestObjects> testables;
 
-  for (std::vector<cmXCodeObject*>::const_iterator i =
-         this->XCodeObjects.begin();
-       i != this->XCodeObjects.end(); ++i) {
-    cmXCodeObject* obj = *i;
+  for (auto obj : this->XCodeObjects) {
     if (obj->GetType() != cmXCodeObject::OBJECT ||
         obj->GetIsA() != cmXCodeObject::PBXNativeTarget) {
       continue;
@@ -3280,10 +3285,7 @@
   }
 
   // generate scheme
-  for (std::vector<cmXCodeObject*>::const_iterator i =
-         this->XCodeObjects.begin();
-       i != this->XCodeObjects.end(); ++i) {
-    cmXCodeObject* obj = *i;
+  for (auto obj : this->XCodeObjects) {
     if (obj->GetType() == cmXCodeObject::OBJECT &&
         (obj->GetIsA() == cmXCodeObject::PBXNativeTarget ||
          obj->GetIsA() == cmXCodeObject::PBXAggregateTarget)) {
@@ -3512,17 +3514,17 @@
   }
 
   // Flag value with escaped quotes and backslashes.
-  for (const char* c = flag.c_str(); *c; ++c) {
-    if (*c == '\'') {
+  for (auto c : flag) {
+    if (c == '\'') {
       if (this->XcodeVersion >= 40) {
         flags += "'\\''";
       } else {
         flags += "\\'";
       }
-    } else if (*c == '\\') {
+    } else if (c == '\\') {
       flags += "\\\\";
     } else {
-      flags += *c;
+      flags += c;
     }
   }
 
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index e9ca91c..b758e97 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -55,6 +55,13 @@
    */
   void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
                       bool optional) override;
+
+  /**
+   * Open a generated IDE project given the following information.
+   */
+  bool Open(const std::string& bindir, const std::string& projectName,
+            bool dryRun) override;
+
   /**
    * Try running cmake and building a file. This is used for dynalically
    * loaded commands, not as part of the usual build process.
diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx
index 4c30607..7bd6cb9 100644
--- a/Source/cmIncludeDirectoryCommand.cxx
+++ b/Source/cmIncludeDirectoryCommand.cxx
@@ -77,7 +77,7 @@
 // do a lot of cleanup on the arguments because this is one place where folks
 // sometimes take the output of a program and pass it directly into this
 // command not thinking that a single argument could be filled with spaces
-// and newlines etc liek below:
+// and newlines etc like below:
 //
 // "   /foo/bar
 //    /boo/hoo /dingle/berry "
diff --git a/Source/cmLinkedTree.h b/Source/cmLinkedTree.h
index 8865e23..975f052 100644
--- a/Source/cmLinkedTree.h
+++ b/Source/cmLinkedTree.h
@@ -137,7 +137,7 @@
 
   iterator Push(iterator it) { return Push_impl(it, T()); }
 
-  iterator Push(iterator it, T t) { return Push_impl(it, t); }
+  iterator Push(iterator it, T t) { return Push_impl(it, std::move(t)); }
 
   bool IsLast(iterator it) { return it.Position == this->Data.size(); }
 
@@ -177,12 +177,12 @@
 
   T* GetPointer(PositionType pos) { return &this->Data[pos]; }
 
-  iterator Push_impl(iterator it, T t)
+  iterator Push_impl(iterator it, T&& t)
   {
     assert(this->UpPositions.size() == this->Data.size());
     assert(it.Position <= this->UpPositions.size());
     this->UpPositions.push_back(it.Position);
-    this->Data.push_back(t);
+    this->Data.push_back(std::move(t));
     return iterator(this, this->UpPositions.size());
   }
 
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index 8e8a54d..cbcf200 100644
--- a/Source/cmListFileCache.cxx
+++ b/Source/cmListFileCache.cxx
@@ -438,6 +438,19 @@
   }
 }
 
+size_t cmListFileBacktrace::Depth() const
+{
+  size_t depth = 0;
+  if (this->Cur == nullptr) {
+    return 0;
+  }
+
+  for (Entry* i = this->Cur->Up; i; i = i->Up) {
+    depth++;
+  }
+  return depth;
+}
+
 std::ostream& operator<<(std::ostream& os, cmListFileContext const& lfc)
 {
   os << lfc.FilePath;
diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h
index 349ddef..1f9e374 100644
--- a/Source/cmListFileCache.h
+++ b/Source/cmListFileCache.h
@@ -6,6 +6,7 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include <iosfwd>
+#include <stddef.h>
 #include <string>
 #include <vector>
 
@@ -138,6 +139,9 @@
   // Print the call stack below the top of the backtrace.
   void PrintCallStack(std::ostream& out) const;
 
+  // Get the number of 'frames' in this backtrace
+  size_t Depth() const;
+
 private:
   struct Entry;
 
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 1a088ea..c8d94c0 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -135,8 +135,8 @@
     this->VariableMappings[compilerOptionSysroot] =
       this->Makefile->GetSafeDefinition(compilerOptionSysroot);
 
-    for (const char* const* replaceIter = cmArrayBegin(ruleReplaceVars);
-         replaceIter != cmArrayEnd(ruleReplaceVars); ++replaceIter) {
+    for (const char* const* replaceIter = cm::cbegin(ruleReplaceVars);
+         replaceIter != cm::cend(ruleReplaceVars); ++replaceIter) {
       std::string actualReplace = *replaceIter;
       if (actualReplace.find("${LANG}") != std::string::npos) {
         cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang);
@@ -222,7 +222,14 @@
 
 void cmLocalGenerator::GenerateTestFiles()
 {
+  std::string file = this->StateSnapshot.GetDirectory().GetCurrentBinary();
+  file += "/";
+  file += "CTestTestfile.cmake";
+
   if (!this->Makefile->IsOn("CMAKE_TESTING_ENABLED")) {
+    if (cmSystemTools::FileExists(file)) {
+      cmSystemTools::RemoveFile(file);
+    }
     return;
   }
 
@@ -231,10 +238,6 @@
   const std::string& config =
     this->Makefile->GetConfigurations(configurationTypes, false);
 
-  std::string file = this->StateSnapshot.GetDirectory().GetCurrentBinary();
-  file += "/";
-  file += "CTestTestfile.cmake";
-
   cmGeneratedFileStream fout(file.c_str());
   fout.SetCopyIfDifferent(true);
 
@@ -484,6 +487,20 @@
     /* clang-format on */
   }
 
+  // Write default directory permissions.
+  if (const char* defaultDirPermissions = this->Makefile->GetDefinition(
+        "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS")) {
+    /* clang-format off */
+    fout <<
+      "# Set default install directory permissions.\n"
+      "if(NOT DEFINED CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS)\n"
+      "  set(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS \""
+         << defaultDirPermissions << "\")\n"
+      "endif()\n"
+      "\n";
+    /* clang-format on */
+  }
+
   // Ask each install generator to write its code.
   std::vector<cmInstallGenerator*> const& installers =
     this->Makefile->GetInstallGenerators();
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index d8030b7..f01ed7a 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -36,6 +36,13 @@
   cmLocalVisualStudio7Generator* LocalGenerator;
 };
 
+class cmLocalVisualStudio7Generator::AllConfigSources
+{
+public:
+  std::vector<cmGeneratorTarget::AllConfigSource> Sources;
+  std::map<cmSourceFile const*, size_t> Index;
+};
+
 extern cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[];
 
 static void cmConvertToWindowsSlash(std::string& s)
@@ -83,29 +90,6 @@
   this->WriteStampFiles();
 }
 
-void cmLocalVisualStudio7Generator::AddCMakeListsRules()
-{
-  // Create the regeneration custom rule.
-  if (!this->Makefile->IsOn("CMAKE_SUPPRESS_REGENERATION")) {
-    // Create a rule to regenerate the build system when the target
-    // specification source changes.
-    if (cmSourceFile* sf = this->CreateVCProjBuildRule()) {
-      // Add the rule to targets that need it.
-      const std::vector<cmGeneratorTarget*>& tgts =
-        this->GetGeneratorTargets();
-      for (std::vector<cmGeneratorTarget*>::const_iterator l = tgts.begin();
-           l != tgts.end(); ++l) {
-        if ((*l)->GetType() == cmStateEnums::GLOBAL_TARGET) {
-          continue;
-        }
-        if ((*l)->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
-          (*l)->AddSource(sf->GetFullPath());
-        }
-      }
-    }
-  }
-}
-
 void cmLocalVisualStudio7Generator::FixGlobalTargets()
 {
   // Visual Studio .NET 2003 Service Pack 1 will not run post-build
@@ -239,19 +223,29 @@
 
 cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule()
 {
+  if (this->Makefile->IsOn("CMAKE_SUPPRESS_REGENERATION")) {
+    return nullptr;
+  }
+
+  std::string makefileIn = this->GetCurrentSourceDirectory();
+  makefileIn += "/";
+  makefileIn += "CMakeLists.txt";
+  makefileIn = cmSystemTools::CollapseFullPath(makefileIn);
+  if (cmSourceFile* file = this->Makefile->GetSource(makefileIn)) {
+    if (file->GetCustomCommand()) {
+      return file;
+    }
+  }
+  if (!cmSystemTools::FileExists(makefileIn)) {
+    return nullptr;
+  }
+
   std::string stampName = this->GetCurrentBinaryDirectory();
   stampName += "/";
   stampName += cmake::GetCMakeFilesDirectoryPostSlash();
   stampName += "generate.stamp";
   cmCustomCommandLine commandLine;
   commandLine.push_back(cmSystemTools::GetCMakeCommand());
-  std::string makefileIn = this->GetCurrentSourceDirectory();
-  makefileIn += "/";
-  makefileIn += "CMakeLists.txt";
-  makefileIn = cmSystemTools::CollapseFullPath(makefileIn.c_str());
-  if (!cmSystemTools::FileExists(makefileIn.c_str())) {
-    return 0;
-  }
   std::string comment = "Building Custom Rule ";
   comment += makefileIn;
   std::string args;
@@ -275,10 +269,13 @@
     fullpathStampName.c_str(), listFiles, makefileIn.c_str(), commandLines,
     comment.c_str(), no_working_directory, true, false);
   if (cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str())) {
+    // Finalize the source file path now since we're adding this after
+    // the generator validated all project-named sources.
+    file->GetFullPath();
     return file;
   } else {
     cmSystemTools::Error("Error adding rule for ", makefileIn.c_str());
-    return 0;
+    return nullptr;
   }
 }
 
@@ -1368,13 +1365,26 @@
   // We may be modifying the source groups temporarily, so make a copy.
   std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
 
-  std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
-    target->GetAllConfigSources();
-  std::map<cmSourceFile const*, size_t> sourcesIndex;
+  AllConfigSources sources;
+  sources.Sources = target->GetAllConfigSources();
 
-  for (size_t si = 0; si < sources.size(); ++si) {
-    cmSourceFile const* sf = sources[si].Source;
-    sourcesIndex[sf] = si;
+  // Add CMakeLists.txt file with rule to re-run CMake for user convenience.
+  if (target->GetType() != cmStateEnums::GLOBAL_TARGET &&
+      target->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
+    if (cmSourceFile const* sf = this->CreateVCProjBuildRule()) {
+      cmGeneratorTarget::AllConfigSource acs;
+      acs.Source = sf;
+      acs.Kind = cmGeneratorTarget::SourceKindCustomCommand;
+      for (size_t ci = 0; ci < configs.size(); ++ci) {
+        acs.Configs.push_back(ci);
+      }
+      sources.Sources.emplace_back(std::move(acs));
+    }
+  }
+
+  for (size_t si = 0; si < sources.Sources.size(); ++si) {
+    cmSourceFile const* sf = sources.Sources[si].Source;
+    sources.Index[sf] = si;
     if (!sf->GetObjectLibrary().empty()) {
       if (this->FortranProject) {
         // Intel Fortran does not support per-config source locations
@@ -1400,7 +1410,7 @@
   // Loop through every source group.
   for (unsigned int i = 0; i < sourceGroups.size(); ++i) {
     cmSourceGroup sg = sourceGroups[i];
-    this->WriteGroup(&sg, target, fout, libName, configs, sourcesIndex);
+    this->WriteGroup(&sg, target, fout, libName, configs, sources);
   }
 
   fout << "\t</Files>\n";
@@ -1567,7 +1577,7 @@
 bool cmLocalVisualStudio7Generator::WriteGroup(
   const cmSourceGroup* sg, cmGeneratorTarget* target, std::ostream& fout,
   const std::string& libName, std::vector<std::string> const& configs,
-  std::map<cmSourceFile const*, size_t> const& sourcesIndex)
+  AllConfigSources const& sources)
 {
   cmGlobalVisualStudio7Generator* gg =
     static_cast<cmGlobalVisualStudio7Generator*>(this->GlobalGenerator);
@@ -1579,7 +1589,7 @@
   std::ostringstream tmpOut;
   for (unsigned int i = 0; i < children.size(); ++i) {
     if (this->WriteGroup(&children[i], target, tmpOut, libName, configs,
-                         sourcesIndex)) {
+                         sources)) {
       hasChildrenWithSources = true;
     }
   }
@@ -1590,14 +1600,11 @@
   }
 
   // If the group has a name, write the header.
-  std::string name = sg->GetName();
+  std::string const& name = sg->GetName();
   if (!name.empty()) {
     this->WriteVCProjBeginGroup(fout, name.c_str(), "");
   }
 
-  std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
-    target->GetAllConfigSources();
-
   // Loop through each source in the source group.
   for (std::vector<const cmSourceFile*>::const_iterator sf =
          sourceFiles.begin();
@@ -1608,10 +1615,11 @@
         target->GetType() == cmStateEnums::GLOBAL_TARGET) {
       // Look up the source kind and configs.
       std::map<cmSourceFile const*, size_t>::const_iterator map_it =
-        sourcesIndex.find(*sf);
+        sources.Index.find(*sf);
       // The map entry must exist because we populated it earlier.
-      assert(map_it != sourcesIndex.end());
-      cmGeneratorTarget::AllConfigSource const& acs = sources[map_it->second];
+      assert(map_it != sources.Index.end());
+      cmGeneratorTarget::AllConfigSource const& acs =
+        sources.Sources[map_it->second];
 
       FCInfo fcinfo(this, target, acs, configs);
 
diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h
index 7a77574..48f2e1a 100644
--- a/Source/cmLocalVisualStudio7Generator.h
+++ b/Source/cmLocalVisualStudio7Generator.h
@@ -65,7 +65,6 @@
 
   virtual void ReadAndStoreExternalGUID(const std::string& name,
                                         const char* path);
-  virtual void AddCMakeListsRules();
 
 protected:
   void CreateSingleVCProj(const std::string& lname, cmGeneratorTarget* tgt);
@@ -117,10 +116,11 @@
                        FCInfo& fcinfo);
   void WriteTargetVersionAttribute(std::ostream& fout, cmGeneratorTarget* gt);
 
+  class AllConfigSources;
   bool WriteGroup(const cmSourceGroup* sg, cmGeneratorTarget* target,
                   std::ostream& fout, const std::string& libName,
                   std::vector<std::string> const& configs,
-                  std::map<cmSourceFile const*, size_t> const& sourcesIndex);
+                  AllConfigSources const& sources);
 
   friend class cmLocalVisualStudio7GeneratorFCInfo;
   friend class cmLocalVisualStudio7GeneratorInternals;
diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h
index cba24fe..ace2f89 100644
--- a/Source/cmLocalVisualStudioGenerator.h
+++ b/Source/cmLocalVisualStudioGenerator.h
@@ -44,8 +44,6 @@
   virtual std::string ComputeLongestObjectDirectory(
     cmGeneratorTarget const*) const = 0;
 
-  virtual void AddCMakeListsRules() = 0;
-
   virtual void ComputeObjectFilenames(
     std::map<cmSourceFile const*, std::string>& mapping,
     cmGeneratorTarget const* = 0);
diff --git a/Source/cmLocalXCodeGenerator.cxx b/Source/cmLocalXCodeGenerator.cxx
index 853e66c..457d1fd 100644
--- a/Source/cmLocalXCodeGenerator.cxx
+++ b/Source/cmLocalXCodeGenerator.cxx
@@ -42,8 +42,7 @@
 {
   cmLocalGenerator::Generate();
 
-  const std::vector<cmGeneratorTarget*>& targets = this->GetGeneratorTargets();
-  for (auto target : targets) {
+  for (auto target : this->GetGeneratorTargets()) {
     target->HasMacOSXRpathInstallNameDir("");
   }
 }
@@ -52,8 +51,7 @@
 {
   cmLocalGenerator::GenerateInstallRules();
 
-  const std::vector<cmGeneratorTarget*>& targets = this->GetGeneratorTargets();
-  for (auto target : targets) {
+  for (auto target : this->GetGeneratorTargets()) {
     target->HasMacOSXRpathInstallNameDir("");
   }
 }
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 5643c97..0855e79 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <assert.h>
 #include <ctype.h>
+#include <iterator>
 #include <memory> // IWYU pragma: keep
 #include <sstream>
 #include <stdlib.h>
@@ -122,6 +123,42 @@
   this->GetCMakeInstance()->IssueMessage(t, text, this->GetBacktrace());
 }
 
+bool cmMakefile::CheckCMP0037(std::string const& targetName,
+                              cmStateEnums::TargetType targetType) const
+{
+  cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+  std::ostringstream e;
+  bool issueMessage = false;
+  switch (this->GetPolicyStatus(cmPolicies::CMP0037)) {
+    case cmPolicies::WARN:
+      if (targetType != cmStateEnums::INTERFACE_LIBRARY) {
+        e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0037) << "\n";
+        issueMessage = true;
+      }
+      CM_FALLTHROUGH;
+    case cmPolicies::OLD:
+      break;
+    case cmPolicies::NEW:
+    case cmPolicies::REQUIRED_IF_USED:
+    case cmPolicies::REQUIRED_ALWAYS:
+      issueMessage = true;
+      messageType = cmake::FATAL_ERROR;
+      break;
+  }
+  if (issueMessage) {
+    e << "The target name \"" << targetName
+      << "\" is reserved or not valid for certain "
+         "CMake features, such as generator expressions, and may result "
+         "in undefined behavior.";
+    this->IssueMessage(messageType, e.str());
+
+    if (messageType == cmake::FATAL_ERROR) {
+      return false;
+    }
+  }
+  return true;
+}
+
 cmStringRange cmMakefile::GetIncludeDirectoriesEntries() const
 {
   return this->StateSnapshot.GetDirectory().GetIncludeDirectoriesEntries();
@@ -562,7 +599,7 @@
         << "\"cmake --help-policy CMP0000\".";
     switch (this->GetPolicyStatus(cmPolicies::CMP0000)) {
       case cmPolicies::WARN:
-        // Warn because the user did not provide a mimimum required
+        // Warn because the user did not provide a minimum required
         // version.
         this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING,
                                                msg.str(), this->Backtrace);
@@ -1913,7 +1950,7 @@
 
   // first look for source group starting with the same as the one we want
   for (cmSourceGroup const& srcGroup : this->SourceGroups) {
-    std::string sgName = srcGroup.GetName();
+    std::string const& sgName = srcGroup.GetName();
     if (sgName == name[0]) {
       sg = const_cast<cmSourceGroup*>(&srcGroup);
       break;
@@ -1977,7 +2014,8 @@
   }
   // build the whole source group path
   for (++i; i <= lastElement; ++i) {
-    sg->AddChild(cmSourceGroup(name[i].c_str(), nullptr, sg->GetFullName()));
+    sg->AddChild(
+      cmSourceGroup(name[i].c_str(), nullptr, sg->GetFullName().c_str()));
     sg = sg->LookupChild(name[i].c_str());
   }
 
@@ -3083,9 +3121,16 @@
 cmSourceFile* cmMakefile::GetSource(const std::string& sourceName) const
 {
   cmSourceFileLocation sfl(this, sourceName);
-  for (cmSourceFile* sf : this->SourceFiles) {
-    if (sf->Matches(sfl)) {
-      return sf;
+  auto name = this->GetCMakeInstance()->StripExtension(sfl.GetName());
+#if defined(_WIN32) || defined(__APPLE__)
+  name = cmSystemTools::LowerCase(name);
+#endif
+  auto sfsi = this->SourceFileSearchIndex.find(name);
+  if (sfsi != this->SourceFileSearchIndex.end()) {
+    for (auto sf : sfsi->second) {
+      if (sf->Matches(sfl)) {
+        return sf;
+      }
     }
   }
   return nullptr;
@@ -3099,6 +3144,14 @@
     sf->SetProperty("GENERATED", "1");
   }
   this->SourceFiles.push_back(sf);
+
+  auto name =
+    this->GetCMakeInstance()->StripExtension(sf->GetLocation().GetName());
+#if defined(_WIN32) || defined(__APPLE__)
+  name = cmSystemTools::LowerCase(name);
+#endif
+  this->SourceFileSearchIndex[name].push_back(sf);
+
   return sf;
 }
 
@@ -3186,6 +3239,7 @@
   // do a configure
   cm.SetHomeDirectory(srcdir);
   cm.SetHomeOutputDirectory(bindir);
+  cm.SetGeneratorInstance(this->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE"));
   cm.SetGeneratorPlatform(this->GetSafeDefinition("CMAKE_GENERATOR_PLATFORM"));
   cm.SetGeneratorToolset(this->GetSafeDefinition("CMAKE_GENERATOR_TOOLSET"));
   cm.LoadCache();
@@ -3281,6 +3335,13 @@
   return this->GlobalGenerator;
 }
 
+void cmMakefile::GetTestNames(std::vector<std::string>& testNames)
+{
+  for (const auto& iter : Tests) {
+    testNames.push_back(iter.first);
+  }
+}
+
 #ifdef CMAKE_BUILD_WITH_CMAKE
 cmVariableWatch* cmMakefile::GetVariableWatch() const
 {
@@ -3980,7 +4041,7 @@
 
   // Deprecate old policies, especially those that require a lot
   // of code to maintain the old behavior.
-  if (status == cmPolicies::OLD && id <= cmPolicies::CMP0036) {
+  if (status == cmPolicies::OLD && id <= cmPolicies::CMP0054) {
     this->IssueMessage(cmake::DEPRECATION_WARNING,
                        cmPolicies::GetPolicyDeprecatedWarning(id));
   }
@@ -4133,15 +4194,15 @@
   assert(cmGeneratorExpression::Find(feature) == std::string::npos);
 
   bool isCFeature =
-    std::find_if(cmArrayBegin(C_FEATURES) + 1, cmArrayEnd(C_FEATURES),
-                 cmStrCmp(feature)) != cmArrayEnd(C_FEATURES);
+    std::find_if(cm::cbegin(C_FEATURES) + 1, cm::cend(C_FEATURES),
+                 cmStrCmp(feature)) != cm::cend(C_FEATURES);
   if (isCFeature) {
     lang = "C";
     return true;
   }
   bool isCxxFeature =
-    std::find_if(cmArrayBegin(CXX_FEATURES) + 1, cmArrayEnd(CXX_FEATURES),
-                 cmStrCmp(feature)) != cmArrayEnd(CXX_FEATURES);
+    std::find_if(cm::cbegin(CXX_FEATURES) + 1, cm::cend(CXX_FEATURES),
+                 cmStrCmp(feature)) != cm::cend(CXX_FEATURES);
   if (isCxxFeature) {
     lang = "CXX";
     return true;
@@ -4230,8 +4291,8 @@
     // Return true so the caller does not try to lookup the default standard.
     return true;
   }
-  if (std::find_if(cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS),
-                   cmStrCmp(defaultCStandard)) == cmArrayEnd(C_STANDARDS)) {
+  if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
+                   cmStrCmp(defaultCStandard)) == cm::cend(C_STANDARDS)) {
     std::ostringstream e;
     e << "The CMAKE_C_STANDARD_DEFAULT variable contains an "
          "invalid value: \""
@@ -4251,8 +4312,8 @@
     existingCStandard = defaultCStandard;
   }
 
-  if (std::find_if(cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS),
-                   cmStrCmp(existingCStandard)) == cmArrayEnd(C_STANDARDS)) {
+  if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
+                   cmStrCmp(existingCStandard)) == cm::cend(C_STANDARDS)) {
     std::ostringstream e;
     e << "The C_STANDARD property on target \"" << target->GetName()
       << "\" contained an invalid value: \"" << existingCStandard << "\".";
@@ -4261,23 +4322,23 @@
   }
 
   const char* const* existingCIt = existingCStandard
-    ? std::find_if(cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS),
+    ? std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
                    cmStrCmp(existingCStandard))
-    : cmArrayEnd(C_STANDARDS);
+    : cm::cend(C_STANDARDS);
 
   if (needC11 && existingCStandard &&
-      existingCIt < std::find_if(cmArrayBegin(C_STANDARDS),
-                                 cmArrayEnd(C_STANDARDS), cmStrCmp("11"))) {
+      existingCIt < std::find_if(cm::cbegin(C_STANDARDS),
+                                 cm::cend(C_STANDARDS), cmStrCmp("11"))) {
     return false;
   }
   if (needC99 && existingCStandard &&
-      existingCIt < std::find_if(cmArrayBegin(C_STANDARDS),
-                                 cmArrayEnd(C_STANDARDS), cmStrCmp("99"))) {
+      existingCIt < std::find_if(cm::cbegin(C_STANDARDS),
+                                 cm::cend(C_STANDARDS), cmStrCmp("99"))) {
     return false;
   }
   if (needC90 && existingCStandard &&
-      existingCIt < std::find_if(cmArrayBegin(C_STANDARDS),
-                                 cmArrayEnd(C_STANDARDS), cmStrCmp("90"))) {
+      existingCIt < std::find_if(cm::cbegin(C_STANDARDS),
+                                 cm::cend(C_STANDARDS), cmStrCmp("90"))) {
     return false;
   }
   return true;
@@ -4289,16 +4350,16 @@
 {
   if (lang == "C") {
     const char* const* rhsIt = std::find_if(
-      cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS), cmStrCmp(rhs));
+      cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), cmStrCmp(rhs));
 
-    return std::find_if(rhsIt, cmArrayEnd(C_STANDARDS), cmStrCmp(lhs)) !=
-      cmArrayEnd(C_STANDARDS);
+    return std::find_if(rhsIt, cm::cend(C_STANDARDS), cmStrCmp(lhs)) !=
+      cm::cend(C_STANDARDS);
   }
   const char* const* rhsIt = std::find_if(
-    cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS), cmStrCmp(rhs));
+    cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), cmStrCmp(rhs));
 
-  return std::find_if(rhsIt, cmArrayEnd(CXX_STANDARDS), cmStrCmp(lhs)) !=
-    cmArrayEnd(CXX_STANDARDS);
+  return std::find_if(rhsIt, cm::cend(CXX_STANDARDS), cmStrCmp(lhs)) !=
+    cm::cend(CXX_STANDARDS);
 }
 
 bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
@@ -4314,9 +4375,8 @@
     // Return true so the caller does not try to lookup the default standard.
     return true;
   }
-  if (std::find_if(cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS),
-                   cmStrCmp(defaultCxxStandard)) ==
-      cmArrayEnd(CXX_STANDARDS)) {
+  if (std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
+                   cmStrCmp(defaultCxxStandard)) == cm::cend(CXX_STANDARDS)) {
     std::ostringstream e;
     e << "The CMAKE_CXX_STANDARD_DEFAULT variable contains an "
          "invalid value: \""
@@ -4337,9 +4397,8 @@
     existingCxxStandard = defaultCxxStandard;
   }
 
-  if (std::find_if(cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS),
-                   cmStrCmp(existingCxxStandard)) ==
-      cmArrayEnd(CXX_STANDARDS)) {
+  if (std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
+                   cmStrCmp(existingCxxStandard)) == cm::cend(CXX_STANDARDS)) {
     std::ostringstream e;
     e << "The CXX_STANDARD property on target \"" << target->GetName()
       << "\" contained an invalid value: \"" << existingCxxStandard << "\".";
@@ -4348,32 +4407,28 @@
   }
 
   const char* const* existingCxxIt = existingCxxStandard
-    ? std::find_if(cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS),
+    ? std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
                    cmStrCmp(existingCxxStandard))
-    : cmArrayEnd(CXX_STANDARDS);
+    : cm::cend(CXX_STANDARDS);
 
   if (needCxx17 &&
-      existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS),
-                                   cmArrayEnd(CXX_STANDARDS),
-                                   cmStrCmp("17"))) {
+      existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS),
+                                   cm::cend(CXX_STANDARDS), cmStrCmp("17"))) {
     return false;
   }
   if (needCxx14 &&
-      existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS),
-                                   cmArrayEnd(CXX_STANDARDS),
-                                   cmStrCmp("14"))) {
+      existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS),
+                                   cm::cend(CXX_STANDARDS), cmStrCmp("14"))) {
     return false;
   }
   if (needCxx11 &&
-      existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS),
-                                   cmArrayEnd(CXX_STANDARDS),
-                                   cmStrCmp("11"))) {
+      existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS),
+                                   cm::cend(CXX_STANDARDS), cmStrCmp("11"))) {
     return false;
   }
   if (needCxx98 &&
-      existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS),
-                                   cmArrayEnd(CXX_STANDARDS),
-                                   cmStrCmp("98"))) {
+      existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS),
+                                   cm::cend(CXX_STANDARDS), cmStrCmp("98"))) {
     return false;
   }
   return true;
@@ -4423,9 +4478,9 @@
 
   const char* existingCxxStandard = target->GetProperty("CXX_STANDARD");
   if (existingCxxStandard) {
-    if (std::find_if(cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS),
+    if (std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
                      cmStrCmp(existingCxxStandard)) ==
-        cmArrayEnd(CXX_STANDARDS)) {
+        cm::cend(CXX_STANDARDS)) {
       std::ostringstream e;
       e << "The CXX_STANDARD property on target \"" << target->GetName()
         << "\" contained an invalid value: \"" << existingCxxStandard << "\".";
@@ -4439,9 +4494,9 @@
     }
   }
   const char* const* existingCxxIt = existingCxxStandard
-    ? std::find_if(cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS),
+    ? std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
                    cmStrCmp(existingCxxStandard))
-    : cmArrayEnd(CXX_STANDARDS);
+    : cm::cend(CXX_STANDARDS);
 
   bool setCxx98 = needCxx98 && !existingCxxStandard;
   bool setCxx11 = needCxx11 && !existingCxxStandard;
@@ -4449,23 +4504,22 @@
   bool setCxx17 = needCxx17 && !existingCxxStandard;
 
   if (needCxx17 && existingCxxStandard &&
-      existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS),
-                                   cmArrayEnd(CXX_STANDARDS),
-                                   cmStrCmp("17"))) {
+      existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS),
+                                   cm::cend(CXX_STANDARDS), cmStrCmp("17"))) {
     setCxx17 = true;
   } else if (needCxx14 && existingCxxStandard &&
-             existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS),
-                                          cmArrayEnd(CXX_STANDARDS),
+             existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS),
+                                          cm::cend(CXX_STANDARDS),
                                           cmStrCmp("14"))) {
     setCxx14 = true;
   } else if (needCxx11 && existingCxxStandard &&
-             existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS),
-                                          cmArrayEnd(CXX_STANDARDS),
+             existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS),
+                                          cm::cend(CXX_STANDARDS),
                                           cmStrCmp("11"))) {
     setCxx11 = true;
   } else if (needCxx98 && existingCxxStandard &&
-             existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS),
-                                          cmArrayEnd(CXX_STANDARDS),
+             existingCxxIt < std::find_if(cm::cbegin(CXX_STANDARDS),
+                                          cm::cend(CXX_STANDARDS),
                                           cmStrCmp("98"))) {
     setCxx98 = true;
   }
@@ -4522,8 +4576,8 @@
 
   const char* existingCStandard = target->GetProperty("C_STANDARD");
   if (existingCStandard) {
-    if (std::find_if(cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS),
-                     cmStrCmp(existingCStandard)) == cmArrayEnd(C_STANDARDS)) {
+    if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
+                     cmStrCmp(existingCStandard)) == cm::cend(C_STANDARDS)) {
       std::ostringstream e;
       e << "The C_STANDARD property on target \"" << target->GetName()
         << "\" contained an invalid value: \"" << existingCStandard << "\".";
@@ -4537,26 +4591,26 @@
     }
   }
   const char* const* existingCIt = existingCStandard
-    ? std::find_if(cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS),
+    ? std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
                    cmStrCmp(existingCStandard))
-    : cmArrayEnd(C_STANDARDS);
+    : cm::cend(C_STANDARDS);
 
   bool setC90 = needC90 && !existingCStandard;
   bool setC99 = needC99 && !existingCStandard;
   bool setC11 = needC11 && !existingCStandard;
 
   if (needC11 && existingCStandard &&
-      existingCIt < std::find_if(cmArrayBegin(C_STANDARDS),
-                                 cmArrayEnd(C_STANDARDS), cmStrCmp("11"))) {
+      existingCIt < std::find_if(cm::cbegin(C_STANDARDS),
+                                 cm::cend(C_STANDARDS), cmStrCmp("11"))) {
     setC11 = true;
   } else if (needC99 && existingCStandard &&
-             existingCIt < std::find_if(cmArrayBegin(C_STANDARDS),
-                                        cmArrayEnd(C_STANDARDS),
+             existingCIt < std::find_if(cm::cbegin(C_STANDARDS),
+                                        cm::cend(C_STANDARDS),
                                         cmStrCmp("99"))) {
     setC99 = true;
   } else if (needC90 && existingCStandard &&
-             existingCIt < std::find_if(cmArrayBegin(C_STANDARDS),
-                                        cmArrayEnd(C_STANDARDS),
+             existingCIt < std::find_if(cm::cbegin(C_STANDARDS),
+                                        cm::cend(C_STANDARDS),
                                         cmStrCmp("90"))) {
     setC90 = true;
   }
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 0273f5b..7c27aef 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -561,7 +561,7 @@
                        bool atOnly, bool escapeQuotes) const;
 
   /**
-   * Copy file but change lines acording to ConfigureString
+   * Copy file but change lines according to ConfigureString
    */
   int ConfigureFile(const char* infile, const char* outfile, bool copyonly,
                     bool atOnly, bool escapeQuotes,
@@ -617,6 +617,11 @@
   cmGlobalGenerator* GetGlobalGenerator() const;
 
   /**
+   * Get all the test names this makefile knows about
+   */
+  void GetTestNames(std::vector<std::string>& testNames);
+
+  /**
    * Get all the source files this makefile knows about
    */
   const std::vector<cmSourceFile*>& GetSourceFiles() const
@@ -665,6 +670,10 @@
   {
     return this->InstallGenerators;
   }
+  const std::vector<cmInstallGenerator*>& GetInstallGenerators() const
+  {
+    return this->InstallGenerators;
+  }
 
   void AddTestGenerator(cmTestGenerator* g)
   {
@@ -737,6 +746,9 @@
   /** Set whether or not to report a CMP0000 violation.  */
   void SetCheckCMP0000(bool b) { this->CheckCMP0000 = b; }
 
+  bool CheckCMP0037(std::string const& targetName,
+                    cmStateEnums::TargetType targetType) const;
+
   cmStringRange GetIncludeDirectoriesEntries() const;
   cmBacktraceRange GetIncludeDirectoriesBacktraces() const;
   cmStringRange GetCompileOptionsEntries() const;
@@ -793,7 +805,7 @@
   void RemoveExportBuildFileGeneratorCMP0024(cmExportBuildFileGenerator* gen);
   void AddExportBuildFileGenerator(cmExportBuildFileGenerator* gen);
 
-  // Maintain a stack of pacakge names to determine the depth of find modules
+  // Maintain a stack of package names to determine the depth of find modules
   // we are currently being called with
   std::deque<std::string> FindPackageModuleStack;
 
@@ -809,7 +821,18 @@
   // libraries, classes, and executables
   mutable cmTargets Targets;
   std::map<std::string, std::string> AliasTargets;
-  std::vector<cmSourceFile*> SourceFiles;
+
+  typedef std::vector<cmSourceFile*> SourceFileVec;
+  SourceFileVec SourceFiles;
+
+  // Because cmSourceFile names are compared in a fuzzy way (see
+  // cmSourceFileLocation::Match()) we can't have a straight mapping from
+  // filename to cmSourceFile.  To make lookups more efficient we store the
+  // Name portion of the cmSourceFileLocation and then compare on the list of
+  // cmSourceFiles that might match that name.  Note that on platforms which
+  // have a case-insensitive filesystem we store the key in all lowercase.
+  typedef std::unordered_map<std::string, SourceFileVec> SourceFileMap;
+  SourceFileMap SourceFileSearchIndex;
 
   // Tests
   std::map<std::string, cmTest*> Tests;
diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx
index 43fb5f5..5a341bd 100644
--- a/Source/cmMessageCommand.cxx
+++ b/Source/cmMessageCommand.cxx
@@ -63,7 +63,7 @@
   std::string message = cmJoin(cmMakeRange(i, args.end()), std::string());
 
   if (type != cmake::MESSAGE) {
-    // we've overriden the message type, above, so display it directly
+    // we've overridden the message type, above, so display it directly
     cmMessenger* m = this->Makefile->GetMessenger();
     m->DisplayMessage(type, message, this->Makefile->GetBacktrace());
   } else {
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index 6c33e2b..c39f927 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -211,7 +211,10 @@
          "Define file(GENERATE) behavior for relative paths.", 3, 10, 0,      \
          cmPolicies::WARN)                                                    \
   SELECT(POLICY, CMP0071, "Let AUTOMOC and AUTOUIC process GENERATED files.", \
-         3, 10, 0, cmPolicies::WARN)
+         3, 10, 0, cmPolicies::WARN)                                          \
+  SELECT(POLICY, CMP0072,                                                     \
+         "FindOpenGL prefers GLVND by default when available.", 3, 11, 0,     \
+         cmPolicies::WARN)
 
 #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
 #define CM_FOR_EACH_POLICY_ID(POLICY)                                         \
@@ -225,6 +228,7 @@
   F(CMP0021)                                                                  \
   F(CMP0022)                                                                  \
   F(CMP0027)                                                                  \
+  F(CMP0037)                                                                  \
   F(CMP0038)                                                                  \
   F(CMP0041)                                                                  \
   F(CMP0042)                                                                  \
diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx
index 5e89978..b9dd392 100644
--- a/Source/cmQtAutoGen.cxx
+++ b/Source/cmQtAutoGen.cxx
@@ -9,6 +9,7 @@
 #include "cmsys/RegularExpression.hxx"
 
 #include <algorithm>
+#include <iterator>
 #include <sstream>
 #include <stddef.h>
 
@@ -79,16 +80,6 @@
   baseOpts.insert(baseOpts.end(), extraOpts.begin(), extraOpts.end());
 }
 
-static std::string utilStripCR(std::string const& line)
-{
-  // Strip CR characters rcc may have printed (possibly more than one!).
-  std::string::size_type cr = line.find('\r');
-  if (cr != std::string::npos) {
-    return line.substr(0, cr);
-  }
-  return line;
-}
-
 /// @brief Reads the resource files list from from a .qrc file - Qt4 version
 /// @return True if the .qrc file was successfully parsed
 static bool RccListInputsQt4(std::string const& fileName,
@@ -106,10 +97,10 @@
       qrcContents = osst.str();
     } else {
       if (errorMessage != nullptr) {
-        std::ostringstream ost;
-        ost << "rcc file not readable:\n"
-            << "  " << cmQtAutoGen::Quoted(fileName) << "\n";
-        *errorMessage = ost.str();
+        std::string& err = *errorMessage;
+        err = "rcc file not readable:\n  ";
+        err += cmQtAutoGen::Quoted(fileName);
+        err += "\n";
       }
       allGood = false;
     }
@@ -145,6 +136,7 @@
 /// @brief Reads the resource files list from from a .qrc file - Qt5 version
 /// @return True if the .qrc file was successfully parsed
 static bool RccListInputsQt5(std::string const& rccCommand,
+                             std::vector<std::string> const& rccListOptions,
                              std::string const& fileName,
                              std::vector<std::string>& files,
                              std::string* errorMessage)
@@ -154,24 +146,6 @@
     return false;
   }
 
-  // Read rcc features
-  bool hasDashDashList = false;
-  {
-    std::vector<std::string> command;
-    command.push_back(rccCommand);
-    command.push_back("--help");
-    std::string rccStdOut;
-    std::string rccStdErr;
-    int retVal = 0;
-    bool result = cmSystemTools::RunSingleCommand(
-      command, &rccStdOut, &rccStdErr, &retVal, nullptr,
-      cmSystemTools::OUTPUT_NONE, 0.0, cmProcessOutput::Auto);
-    if (result && retVal == 0 &&
-        rccStdOut.find("--list") != std::string::npos) {
-      hasDashDashList = true;
-    }
-  }
-
   std::string const fileDir = cmSystemTools::GetFilenamePath(fileName);
   std::string const fileNameName = cmSystemTools::GetFilenameName(fileName);
 
@@ -183,7 +157,8 @@
   {
     std::vector<std::string> command;
     command.push_back(rccCommand);
-    command.push_back(hasDashDashList ? "--list" : "-list");
+    command.insert(command.end(), rccListOptions.begin(),
+                   rccListOptions.end());
     command.push_back(fileNameName);
     result = cmSystemTools::RunSingleCommand(
       command, &rccStdOut, &rccStdErr, &retVal, fileDir.c_str(),
@@ -191,22 +166,32 @@
   }
   if (!result || retVal) {
     if (errorMessage != nullptr) {
-      std::ostringstream ost;
-      ost << "rcc list process failed for\n  " << cmQtAutoGen::Quoted(fileName)
-          << "\n"
-          << rccStdOut << "\n"
-          << rccStdErr << "\n";
-      *errorMessage = ost.str();
+      std::string& err = *errorMessage;
+      err = "rcc list process failed for:\n  ";
+      err += cmQtAutoGen::Quoted(fileName);
+      err += "\n";
+      err += rccStdOut;
+      err += "\n";
+      err += rccStdErr;
+      err += "\n";
     }
     return false;
   }
 
+  // Lambda to strip CR characters
+  auto StripCR = [](std::string& line) {
+    std::string::size_type cr = line.find('\r');
+    if (cr != std::string::npos) {
+      line = line.substr(0, cr);
+    }
+  };
+
   // Parse rcc std output
   {
     std::istringstream ostr(rccStdOut);
     std::string oline;
     while (std::getline(ostr, oline)) {
-      oline = utilStripCR(oline);
+      StripCR(oline);
       if (!oline.empty()) {
         files.push_back(oline);
       }
@@ -217,17 +202,17 @@
     std::istringstream estr(rccStdErr);
     std::string eline;
     while (std::getline(estr, eline)) {
-      eline = utilStripCR(eline);
+      StripCR(eline);
       if (cmHasLiteralPrefix(eline, "RCC: Error in")) {
         static std::string searchString = "Cannot find file '";
 
         std::string::size_type pos = eline.find(searchString);
         if (pos == std::string::npos) {
           if (errorMessage != nullptr) {
-            std::ostringstream ost;
-            ost << "rcc lists unparsable output:\n"
-                << cmQtAutoGen::Quoted(eline) << "\n";
-            *errorMessage = ost.str();
+            std::string& err = *errorMessage;
+            err = "rcc lists unparsable output:\n";
+            err += cmQtAutoGen::Quoted(eline);
+            err += "\n";
           }
           return false;
         }
@@ -301,8 +286,7 @@
                                  "\r", "\\r",  "\t", "\\t",  "\v", "\\v" };
 
   std::string res = text;
-  for (const char* const* it = cmArrayBegin(rep); it != cmArrayEnd(rep);
-       it += 2) {
+  for (const char* const* it = cm::cbegin(rep); it != cm::cend(rep); it += 2) {
     cmSystemTools::ReplaceString(res, *it, *(it + 1));
   }
   res = '"' + res;
@@ -349,25 +333,26 @@
   MergeOptions(baseOpts, newOpts, valueOpts, isQt5);
 }
 
-bool cmQtAutoGen::RccListInputs(std::string const& qtMajorVersion,
-                                std::string const& rccCommand,
+bool cmQtAutoGen::RccListInputs(std::string const& rccCommand,
+                                std::vector<std::string> const& rccListOptions,
                                 std::string const& fileName,
                                 std::vector<std::string>& files,
                                 std::string* errorMessage)
 {
   bool allGood = false;
   if (cmSystemTools::FileExists(fileName.c_str())) {
-    if (qtMajorVersion == "4") {
+    if (rccListOptions.empty()) {
       allGood = RccListInputsQt4(fileName, files, errorMessage);
     } else {
-      allGood = RccListInputsQt5(rccCommand, fileName, files, errorMessage);
+      allGood = RccListInputsQt5(rccCommand, rccListOptions, fileName, files,
+                                 errorMessage);
     }
   } else {
     if (errorMessage != nullptr) {
-      std::ostringstream ost;
-      ost << "rcc file does not exist:\n"
-          << "  " << cmQtAutoGen::Quoted(fileName) << "\n";
-      *errorMessage = ost.str();
+      std::string& err = *errorMessage;
+      err = "rcc resource file does not exist:\n  ";
+      err += cmQtAutoGen::Quoted(fileName);
+      err += "\n";
     }
   }
   return allGood;
diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h
index acc092f..e769e93 100644
--- a/Source/cmQtAutoGen.h
+++ b/Source/cmQtAutoGen.h
@@ -61,9 +61,9 @@
 
   /// @brief Reads the resource files list from from a .qrc file
   /// @arg fileName Must be the absolute path of the .qrc file
-  /// @return True if the rcc file was successfully parsed
-  static bool RccListInputs(std::string const& qtMajorVersion,
-                            std::string const& rccCommand,
+  /// @return True if the rcc file was successfully read
+  static bool RccListInputs(std::string const& rccCommand,
+                            std::vector<std::string> const& rccListOptions,
                             std::string const& fileName,
                             std::vector<std::string>& files,
                             std::string* errorMessage = nullptr);
diff --git a/Source/cmQtAutoGenDigest.h b/Source/cmQtAutoGenDigest.h
deleted file mode 100644
index 677c397..0000000
--- a/Source/cmQtAutoGenDigest.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
-   file Copyright.txt or https://cmake.org/licensing for details.  */
-#ifndef cmQtAutoGenDigest_h
-#define cmQtAutoGenDigest_h
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include <memory>
-#include <string>
-#include <vector>
-
-class cmGeneratorTarget;
-
-class cmQtAutoGenDigestQrc
-{
-public:
-  cmQtAutoGenDigestQrc()
-    : Generated(false)
-    , Unique(false)
-  {
-  }
-
-public:
-  std::string QrcFile;
-  std::string QrcName;
-  std::string PathChecksum;
-  std::string RccFile;
-  bool Generated;
-  bool Unique;
-  std::vector<std::string> Options;
-  std::vector<std::string> Resources;
-};
-
-/** \class cmQtAutoGenDigest
- * \brief Filtered set of QtAutogen variables for a specific target
- */
-class cmQtAutoGenDigest
-{
-public:
-  cmQtAutoGenDigest(cmGeneratorTarget* target)
-    : Target(target)
-    , MocEnabled(false)
-    , UicEnabled(false)
-    , RccEnabled(false)
-  {
-  }
-
-public:
-  cmGeneratorTarget* Target;
-  std::string QtVersionMajor;
-  std::string QtVersionMinor;
-  bool MocEnabled;
-  bool UicEnabled;
-  bool RccEnabled;
-  std::vector<std::string> Headers;
-  std::vector<std::string> Sources;
-  std::vector<cmQtAutoGenDigestQrc> Qrcs;
-};
-
-// Utility types
-typedef std::unique_ptr<cmQtAutoGenDigest> cmQtAutoGenDigestUP;
-typedef std::vector<cmQtAutoGenDigestUP> cmQtAutoGenDigestUPV;
-
-#endif
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
new file mode 100644
index 0000000..52193af
--- /dev/null
+++ b/Source/cmQtAutoGenerator.cxx
@@ -0,0 +1,320 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmQtAutoGen.h"
+#include "cmQtAutoGenerator.h"
+
+#include "cmsys/FStream.hxx"
+#include "cmsys/Terminal.h"
+
+#include "cmAlgorithms.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+// -- Static functions
+
+static std::string HeadLine(std::string const& title)
+{
+  std::string head = title;
+  head += '\n';
+  head.append(head.size() - 1, '-');
+  head += '\n';
+  return head;
+}
+
+static std::string QuotedCommand(std::vector<std::string> const& command)
+{
+  std::string res;
+  for (std::string const& item : command) {
+    if (!res.empty()) {
+      res.push_back(' ');
+    }
+    std::string const cesc = cmQtAutoGen::Quoted(item);
+    if (item.empty() || (cesc.size() > (item.size() + 2)) ||
+        (cesc.find(' ') != std::string::npos)) {
+      res += cesc;
+    } else {
+      res += item;
+    }
+  }
+  return res;
+}
+
+// -- Class methods
+
+cmQtAutoGenerator::cmQtAutoGenerator()
+  : Verbose(cmSystemTools::HasEnv("VERBOSE"))
+  , ColorOutput(true)
+{
+  {
+    std::string colorEnv;
+    cmSystemTools::GetEnv("COLOR", colorEnv);
+    if (!colorEnv.empty()) {
+      this->ColorOutput = cmSystemTools::IsOn(colorEnv.c_str());
+    }
+  }
+}
+
+bool cmQtAutoGenerator::Run(std::string const& infoFile,
+                            std::string const& config)
+{
+  // Info settings
+  this->InfoFile = infoFile;
+  cmSystemTools::ConvertToUnixSlashes(this->InfoFile);
+  this->InfoDir = cmSystemTools::GetFilenamePath(infoFile);
+  this->InfoConfig = config;
+
+  cmake cm(cmake::RoleScript);
+  cm.SetHomeOutputDirectory(this->InfoDir);
+  cm.SetHomeDirectory(this->InfoDir);
+  cm.GetCurrentSnapshot().SetDefaultDefinitions();
+  cmGlobalGenerator gg(&cm);
+
+  cmStateSnapshot snapshot = cm.GetCurrentSnapshot();
+  snapshot.GetDirectory().SetCurrentBinary(this->InfoDir);
+  snapshot.GetDirectory().SetCurrentSource(this->InfoDir);
+
+  auto makefile = cm::make_unique<cmMakefile>(&gg, snapshot);
+  gg.SetCurrentMakefile(makefile.get());
+
+  return this->Process(makefile.get());
+}
+
+void cmQtAutoGenerator::LogBold(std::string const& message) const
+{
+  cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue |
+                                     cmsysTerminal_Color_ForegroundBold,
+                                   message.c_str(), true, this->ColorOutput);
+}
+
+void cmQtAutoGenerator::LogInfo(cmQtAutoGen::Generator genType,
+                                std::string const& message) const
+{
+  std::string msg = cmQtAutoGen::GeneratorName(genType);
+  msg += ": ";
+  msg += message;
+  if (msg.back() != '\n') {
+    msg.push_back('\n');
+  }
+  cmSystemTools::Stdout(msg.c_str(), msg.size());
+}
+
+void cmQtAutoGenerator::LogWarning(cmQtAutoGen::Generator genType,
+                                   std::string const& message) const
+{
+  std::string msg = cmQtAutoGen::GeneratorName(genType);
+  msg += " warning:";
+  if (message.find('\n') == std::string::npos) {
+    // Single line message
+    msg.push_back(' ');
+  } else {
+    // Multi line message
+    msg.push_back('\n');
+  }
+  // Message
+  msg += message;
+  if (msg.back() != '\n') {
+    msg.push_back('\n');
+  }
+  msg.push_back('\n');
+  cmSystemTools::Stdout(msg.c_str(), msg.size());
+}
+
+void cmQtAutoGenerator::LogFileWarning(cmQtAutoGen::Generator genType,
+                                       std::string const& filename,
+                                       std::string const& message) const
+{
+  std::string msg = "  ";
+  msg += cmQtAutoGen::Quoted(filename);
+  msg.push_back('\n');
+  // Message
+  msg += message;
+  this->LogWarning(genType, msg);
+}
+
+void cmQtAutoGenerator::LogError(cmQtAutoGen::Generator genType,
+                                 std::string const& message) const
+{
+  std::string msg;
+  msg.push_back('\n');
+  msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " error");
+  // Message
+  msg += message;
+  if (msg.back() != '\n') {
+    msg.push_back('\n');
+  }
+  msg.push_back('\n');
+  cmSystemTools::Stderr(msg.c_str(), msg.size());
+}
+
+void cmQtAutoGenerator::LogFileError(cmQtAutoGen::Generator genType,
+                                     std::string const& filename,
+                                     std::string const& message) const
+{
+  std::string emsg = "  ";
+  emsg += cmQtAutoGen::Quoted(filename);
+  emsg += '\n';
+  // Message
+  emsg += message;
+  this->LogError(genType, emsg);
+}
+
+void cmQtAutoGenerator::LogCommandError(
+  cmQtAutoGen::Generator genType, std::string const& message,
+  std::vector<std::string> const& command, std::string const& output) const
+{
+  std::string msg;
+  msg.push_back('\n');
+  msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " subprocess error");
+  msg += message;
+  if (msg.back() != '\n') {
+    msg.push_back('\n');
+  }
+  msg.push_back('\n');
+  msg += HeadLine("Command");
+  msg += QuotedCommand(command);
+  if (msg.back() != '\n') {
+    msg.push_back('\n');
+  }
+  msg.push_back('\n');
+  msg += HeadLine("Output");
+  msg += output;
+  if (msg.back() != '\n') {
+    msg.push_back('\n');
+  }
+  msg.push_back('\n');
+  cmSystemTools::Stderr(msg.c_str(), msg.size());
+}
+
+/**
+ * @brief Generates the parent directory of the given file on demand
+ * @return True on success
+ */
+bool cmQtAutoGenerator::MakeParentDirectory(cmQtAutoGen::Generator genType,
+                                            std::string const& filename) const
+{
+  bool success = true;
+  std::string const dirName = cmSystemTools::GetFilenamePath(filename);
+  if (!dirName.empty()) {
+    if (!cmSystemTools::MakeDirectory(dirName)) {
+      this->LogFileError(genType, filename,
+                         "Could not create parent directory");
+      success = false;
+    }
+  }
+  return success;
+}
+
+/**
+ * @brief Tests if buildFile is older than sourceFile
+ * @return True if buildFile  is older than sourceFile.
+ *         False may indicate an error.
+ */
+bool cmQtAutoGenerator::FileIsOlderThan(std::string const& buildFile,
+                                        std::string const& sourceFile,
+                                        std::string* error)
+{
+  int result = 0;
+  if (cmSystemTools::FileTimeCompare(buildFile, sourceFile, &result)) {
+    return (result < 0);
+  }
+  if (error != nullptr) {
+    error->append(
+      "File modification time comparison failed for the files\n  ");
+    error->append(cmQtAutoGen::Quoted(buildFile));
+    error->append("\nand\n  ");
+    error->append(cmQtAutoGen::Quoted(sourceFile));
+  }
+  return false;
+}
+
+bool cmQtAutoGenerator::FileRead(std::string& content,
+                                 std::string const& filename,
+                                 std::string* error)
+{
+  bool success = false;
+  if (cmSystemTools::FileExists(filename)) {
+    std::size_t const length = cmSystemTools::FileLength(filename);
+    cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary));
+    if (ifs) {
+      content.resize(length);
+      ifs.read(&content.front(), content.size());
+      if (ifs) {
+        success = true;
+      } else {
+        content.clear();
+        if (error != nullptr) {
+          error->append("Reading from the file failed.");
+        }
+      }
+    } else if (error != nullptr) {
+      error->append("Opening the file for reading failed.");
+    }
+  } else if (error != nullptr) {
+    error->append("The file does not exist.");
+  }
+  return success;
+}
+
+bool cmQtAutoGenerator::FileWrite(cmQtAutoGen::Generator genType,
+                                  std::string const& filename,
+                                  std::string const& content)
+{
+  std::string error;
+  // Make sure the parent directory exists
+  if (this->MakeParentDirectory(genType, filename)) {
+    cmsys::ofstream outfile;
+    outfile.open(filename.c_str(),
+                 (std::ios::out | std::ios::binary | std::ios::trunc));
+    if (outfile) {
+      outfile << content;
+      // Check for write errors
+      if (!outfile.good()) {
+        error = "File writing failed";
+      }
+    } else {
+      error = "Opening file for writing failed";
+    }
+  }
+  if (!error.empty()) {
+    this->LogFileError(genType, filename, error);
+    return false;
+  }
+  return true;
+}
+
+bool cmQtAutoGenerator::FileDiffers(std::string const& filename,
+                                    std::string const& content)
+{
+  bool differs = true;
+  {
+    std::string oldContents;
+    if (this->FileRead(oldContents, filename)) {
+      differs = (oldContents != content);
+    }
+  }
+  return differs;
+}
+
+/**
+ * @brief Runs a command and returns true on success
+ * @return True on success
+ */
+bool cmQtAutoGenerator::RunCommand(std::vector<std::string> const& command,
+                                   std::string& output) const
+{
+  // Log command
+  if (this->Verbose) {
+    std::string qcmd = QuotedCommand(command);
+    qcmd.push_back('\n');
+    cmSystemTools::Stdout(qcmd.c_str(), qcmd.size());
+  }
+  // Execute command
+  int retVal = 0;
+  bool res = cmSystemTools::RunSingleCommand(
+    command, &output, &output, &retVal, nullptr, cmSystemTools::OUTPUT_NONE);
+  return (res && (retVal == 0));
+}
diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h
new file mode 100644
index 0000000..285340d
--- /dev/null
+++ b/Source/cmQtAutoGenerator.h
@@ -0,0 +1,76 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmQtAutoGenerator_h
+#define cmQtAutoGenerator_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmQtAutoGen.h"
+
+#include <string>
+#include <vector>
+
+class cmMakefile;
+
+class cmQtAutoGenerator
+{
+  CM_DISABLE_COPY(cmQtAutoGenerator)
+public:
+  cmQtAutoGenerator();
+  virtual ~cmQtAutoGenerator() = default;
+  bool Run(std::string const& infoFile, std::string const& config);
+
+  std::string const& GetInfoFile() const { return InfoFile; }
+  std::string const& GetInfoDir() const { return InfoDir; }
+  std::string const& GetInfoConfig() const { return InfoConfig; }
+  bool GetVerbose() const { return Verbose; }
+
+protected:
+  // -- Central processing
+  virtual bool Process(cmMakefile* makefile) = 0;
+
+  // -- Log info
+  void LogBold(std::string const& message) const;
+  void LogInfo(cmQtAutoGen::Generator genType,
+               std::string const& message) const;
+  // -- Log warning
+  void LogWarning(cmQtAutoGen::Generator genType,
+                  std::string const& message) const;
+  void LogFileWarning(cmQtAutoGen::Generator genType,
+                      std::string const& filename,
+                      std::string const& message) const;
+  // -- Log error
+  void LogError(cmQtAutoGen::Generator genType,
+                std::string const& message) const;
+  void LogFileError(cmQtAutoGen::Generator genType,
+                    std::string const& filename,
+                    std::string const& message) const;
+  void LogCommandError(cmQtAutoGen::Generator genType,
+                       std::string const& message,
+                       std::vector<std::string> const& command,
+                       std::string const& output) const;
+  // -- Utility
+  bool MakeParentDirectory(cmQtAutoGen::Generator genType,
+                           std::string const& filename) const;
+  bool FileIsOlderThan(std::string const& buildFile,
+                       std::string const& sourceFile,
+                       std::string* error = nullptr);
+  bool FileRead(std::string& content, std::string const& filename,
+                std::string* error = nullptr);
+  bool FileWrite(cmQtAutoGen::Generator genType, std::string const& filename,
+                 std::string const& content);
+  bool FileDiffers(std::string const& filename, std::string const& content);
+  bool RunCommand(std::vector<std::string> const& command,
+                  std::string& output) const;
+
+private:
+  // -- Info settings
+  std::string InfoFile;
+  std::string InfoDir;
+  std::string InfoConfig;
+  // -- Settings
+  bool Verbose;
+  bool ColorOutput;
+};
+
+#endif
diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx
index c7550e6..d9a5a9a 100644
--- a/Source/cmQtAutoGeneratorInitializer.cxx
+++ b/Source/cmQtAutoGeneratorInitializer.cxx
@@ -14,6 +14,7 @@
 #include "cmMakefile.h"
 #include "cmOutputConverter.h"
 #include "cmPolicies.h"
+#include "cmProcessOutput.h"
 #include "cmSourceFile.h"
 #include "cmSourceGroup.h"
 #include "cmState.h"
@@ -51,118 +52,6 @@
   return std::string(SafeString(sf->GetProperty(key)));
 }
 
-static cmQtAutoGen::MultiConfig AutogenMultiConfig(
-  cmGlobalGenerator* globalGen)
-{
-  if (!globalGen->IsMultiConfig()) {
-    return cmQtAutoGen::SINGLE;
-  }
-
-  // FIXME: Xcode does not support per-config sources, yet.
-  //        (EXCLUDED_SOURCE_FILE_NAMES)
-  // if (globalGen->GetName().find("Xcode") != std::string::npos) {
-  //  return cmQtAutoGen::FULL;
-  //}
-
-  // FIXME: Visual Studio does not support per-config sources, yet.
-  //        (EXCLUDED_SOURCE_FILE_NAMES)
-  // if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
-  //  return cmQtAutoGen::FULL;
-  //}
-
-  return cmQtAutoGen::WRAP;
-}
-
-static std::string GetAutogenTargetName(cmGeneratorTarget const* target)
-{
-  std::string autogenTargetName = target->GetName();
-  autogenTargetName += "_autogen";
-  return autogenTargetName;
-}
-
-static std::string GetAutogenTargetFilesDir(cmGeneratorTarget const* target)
-{
-  cmMakefile* makefile = target->Target->GetMakefile();
-  std::string targetDir = makefile->GetCurrentBinaryDirectory();
-  targetDir += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();
-  targetDir += "/";
-  targetDir += GetAutogenTargetName(target);
-  targetDir += ".dir";
-  return targetDir;
-}
-
-static std::string GetAutogenTargetBuildDir(cmGeneratorTarget const* target)
-{
-  std::string targetDir = GetSafeProperty(target, "AUTOGEN_BUILD_DIR");
-  if (targetDir.empty()) {
-    cmMakefile* makefile = target->Target->GetMakefile();
-    targetDir = makefile->GetCurrentBinaryDirectory();
-    targetDir += "/";
-    targetDir += GetAutogenTargetName(target);
-  }
-  return targetDir;
-}
-
-std::string cmQtAutoGeneratorInitializer::GetQtMajorVersion(
-  cmGeneratorTarget const* target)
-{
-  cmMakefile* makefile = target->Target->GetMakefile();
-  std::string qtMajor = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
-  if (qtMajor.empty()) {
-    qtMajor = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
-  }
-  const char* targetQtVersion =
-    target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "");
-  if (targetQtVersion != nullptr) {
-    qtMajor = targetQtVersion;
-  }
-  return qtMajor;
-}
-
-std::string cmQtAutoGeneratorInitializer::GetQtMinorVersion(
-  cmGeneratorTarget const* target, std::string const& qtVersionMajor)
-{
-  cmMakefile* makefile = target->Target->GetMakefile();
-  std::string qtMinor;
-  if (qtVersionMajor == "5") {
-    qtMinor = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR");
-  }
-  if (qtMinor.empty()) {
-    qtMinor = makefile->GetSafeDefinition("QT_VERSION_MINOR");
-  }
-
-  const char* targetQtVersion =
-    target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", "");
-  if (targetQtVersion != nullptr) {
-    qtMinor = targetQtVersion;
-  }
-  return qtMinor;
-}
-
-static bool QtVersionGreaterOrEqual(std::string const& major,
-                                    std::string const& minor,
-                                    unsigned long requestMajor,
-                                    unsigned long requestMinor)
-{
-  unsigned long majorUL(0);
-  unsigned long minorUL(0);
-  if (cmSystemTools::StringToULong(major.c_str(), &majorUL) &&
-      cmSystemTools::StringToULong(minor.c_str(), &minorUL)) {
-    return (majorUL > requestMajor) ||
-      (majorUL == requestMajor && minorUL >= requestMinor);
-  }
-  return false;
-}
-
-static void GetConfigs(cmMakefile* makefile, std::string& configDefault,
-                       std::vector<std::string>& configsList)
-{
-  configDefault = makefile->GetConfigurations(configsList);
-  if (configsList.empty()) {
-    configsList.push_back(configDefault);
-  }
-}
-
 static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
                                  std::string const& value)
 {
@@ -258,48 +147,24 @@
                            false);
 }
 
-static std::vector<std::string> AddGeneratedSource(
-  cmGeneratorTarget* target, std::string const& filename,
-  cmQtAutoGen::MultiConfig multiConfig,
-  const std::vector<std::string>& configsList, cmQtAutoGen::Generator genType)
+static std::string FileProjectRelativePath(cmMakefile* makefile,
+                                           std::string const& fileName)
 {
-  std::vector<std::string> genFiles;
-  // Register source file in makefile and source group
-  if (multiConfig != cmQtAutoGen::FULL) {
-    genFiles.push_back(filename);
-  } else {
-    for (std::string const& cfg : configsList) {
-      genFiles.push_back(
-        cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg));
-    }
-  }
+  std::string res;
   {
-    cmMakefile* makefile = target->Target->GetMakefile();
-    for (std::string const& genFile : genFiles) {
-      {
-        cmSourceFile* gFile = makefile->GetOrCreateSource(genFile, true);
-        gFile->SetProperty("GENERATED", "1");
-        gFile->SetProperty("SKIP_AUTOGEN", "On");
-      }
-      AddToSourceGroup(makefile, genFile, genType);
+    std::string pSource = cmSystemTools::RelativePath(
+      makefile->GetCurrentSourceDirectory(), fileName.c_str());
+    std::string pBinary = cmSystemTools::RelativePath(
+      makefile->GetCurrentBinaryDirectory(), fileName.c_str());
+    if (pSource.size() < pBinary.size()) {
+      res = std::move(pSource);
+    } else if (pBinary.size() < fileName.size()) {
+      res = std::move(pBinary);
+    } else {
+      res = fileName;
     }
   }
-
-  // Add source file to target
-  if (multiConfig != cmQtAutoGen::FULL) {
-    target->AddSource(filename);
-  } else {
-    for (std::string const& cfg : configsList) {
-      std::string src = "$<$<CONFIG:";
-      src += cfg;
-      src += ">:";
-      src += cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg);
-      src += ">";
-      target->AddSource(src);
-    }
-  }
-
-  return genFiles;
+  return res;
 }
 
 /* @brief Tests if targetDepend is a STATIC_LIBRARY and if any of its
@@ -346,23 +211,271 @@
   return cycle;
 }
 
-struct cmQtAutoGenSetup
+cmQtAutoGeneratorInitializer::cmQtAutoGeneratorInitializer(
+  cmGeneratorTarget* target, bool mocEnabled, bool uicEnabled, bool rccEnabled,
+  std::string const& qtVersionMajor)
+  : Target(target)
+  , MocEnabled(mocEnabled)
+  , UicEnabled(uicEnabled)
+  , RccEnabled(rccEnabled)
+  , QtVersionMajor(qtVersionMajor)
+  , MultiConfig(cmQtAutoGen::WRAP)
 {
-  std::set<std::string> MocSkip;
-  std::set<std::string> UicSkip;
+  this->QtVersionMinor = cmQtAutoGeneratorInitializer::GetQtMinorVersion(
+    target, this->QtVersionMajor);
+}
 
-  std::map<std::string, std::string> ConfigMocIncludes;
-  std::map<std::string, std::string> ConfigMocDefines;
-  std::map<std::string, std::string> ConfigUicOptions;
-};
-
-static void SetupAcquireSkipFiles(cmQtAutoGenDigest const& digest,
-                                  cmQtAutoGenSetup& setup)
+void cmQtAutoGeneratorInitializer::InitCustomTargets()
 {
-  // Read skip files from makefile sources
+  cmMakefile* makefile = this->Target->Target->GetMakefile();
+  cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
+  cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator();
+
+  // Configurations
+  this->ConfigDefault = makefile->GetConfigurations(this->ConfigsList);
+  if (this->ConfigsList.empty()) {
+    this->ConfigsList.push_back(this->ConfigDefault);
+  }
+
+  // Multi configuration
   {
-    const std::vector<cmSourceFile*>& allSources =
-      digest.Target->Makefile->GetSourceFiles();
+    if (!globalGen->IsMultiConfig()) {
+      this->MultiConfig = cmQtAutoGen::SINGLE;
+    }
+
+    // FIXME: Xcode does not support per-config sources, yet.
+    //        (EXCLUDED_SOURCE_FILE_NAMES)
+    // if (globalGen->GetName().find("Xcode") != std::string::npos) {
+    //  return cmQtAutoGen::FULL;
+    //}
+
+    // FIXME: Visual Studio does not support per-config sources, yet.
+    //        (EXCLUDED_SOURCE_FILE_NAMES)
+    // if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
+    //  return cmQtAutoGen::FULL;
+    //}
+  }
+
+  // Autogen target name
+  this->AutogenTargetName = this->Target->GetName();
+  this->AutogenTargetName += "_autogen";
+
+  // Autogen directories
+  {
+    // Collapsed current binary directory
+    std::string const cbd = cmSystemTools::CollapseFullPath(
+      "", makefile->GetCurrentBinaryDirectory());
+
+    // Autogen info dir
+    this->DirInfo = cbd;
+    this->DirInfo += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();
+    this->DirInfo += "/";
+    this->DirInfo += this->AutogenTargetName;
+    this->DirInfo += ".dir";
+    cmSystemTools::ConvertToUnixSlashes(this->DirInfo);
+
+    // Autogen build dir
+    this->DirBuild = GetSafeProperty(this->Target, "AUTOGEN_BUILD_DIR");
+    if (this->DirBuild.empty()) {
+      this->DirBuild = cbd;
+      this->DirBuild += "/";
+      this->DirBuild += this->AutogenTargetName;
+    }
+    cmSystemTools::ConvertToUnixSlashes(this->DirBuild);
+
+    // Working directory
+    this->DirWork = cbd;
+    cmSystemTools::ConvertToUnixSlashes(this->DirWork);
+  }
+
+  // Autogen files
+  {
+    this->AutogenInfoFile = this->DirInfo;
+    this->AutogenInfoFile += "/AutogenInfo.cmake";
+
+    this->AutogenSettingsFile = this->DirInfo;
+    this->AutogenSettingsFile += "/AutogenOldSettings.cmake";
+  }
+
+  // Autogen target FOLDER property
+  {
+    const char* folder =
+      makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER");
+    if (folder == nullptr) {
+      folder =
+        makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER");
+    }
+    // Inherit FOLDER property from target (#13688)
+    if (folder == nullptr) {
+      folder = SafeString(this->Target->Target->GetProperty("FOLDER"));
+    }
+    if (folder != nullptr) {
+      this->AutogenFolder = folder;
+    }
+  }
+
+  std::set<std::string> autogenDependFiles;
+  std::set<cmTarget*> autogenDependTargets;
+  std::vector<std::string> autogenProvides;
+
+  // Remove build directories on cleanup
+  AddCleanFile(makefile, this->DirBuild);
+  // Remove old settings on cleanup
+  {
+    std::string base = this->DirInfo;
+    base += "/AutogenOldSettings";
+    if (this->MultiConfig == cmQtAutoGen::SINGLE) {
+      AddCleanFile(makefile, base.append(".cmake"));
+    } else {
+      for (std::string const& cfg : this->ConfigsList) {
+        std::string filename = base;
+        filename += "_";
+        filename += cfg;
+        filename += ".cmake";
+        AddCleanFile(makefile, filename);
+      }
+    }
+  }
+
+  // Add moc compilation to generated files list
+  if (this->MocEnabled) {
+    std::string const mocsComp = this->DirBuild + "/mocs_compilation.cpp";
+    auto files = this->AddGeneratedSource(mocsComp, cmQtAutoGen::MOC);
+    for (std::string& file : files) {
+      autogenProvides.push_back(std::move(file));
+    }
+  }
+
+  // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES
+  if (this->MocEnabled || this->UicEnabled) {
+    std::string includeDir = this->DirBuild + "/include";
+    if (this->MultiConfig != cmQtAutoGen::SINGLE) {
+      includeDir += "_$<CONFIG>";
+    }
+    this->Target->AddIncludeDirectory(includeDir, true);
+  }
+
+  // Acquire rcc executable and features
+  if (this->RccEnabled) {
+    {
+      std::string err;
+      if (this->QtVersionMajor == "5") {
+        cmGeneratorTarget* tgt =
+          localGen->FindGeneratorTargetToUse("Qt5::rcc");
+        if (tgt != nullptr) {
+          this->RccExecutable = SafeString(tgt->ImportedGetLocation(""));
+        } else {
+          err = "AUTORCC: Qt5::rcc target not found";
+        }
+      } else if (QtVersionMajor == "4") {
+        cmGeneratorTarget* tgt =
+          localGen->FindGeneratorTargetToUse("Qt4::rcc");
+        if (tgt != nullptr) {
+          this->RccExecutable = SafeString(tgt->ImportedGetLocation(""));
+        } else {
+          err = "AUTORCC: Qt4::rcc target not found";
+        }
+      } else {
+        err = "The AUTORCC feature supports only Qt 4 and Qt 5";
+      }
+      if (!err.empty()) {
+        err += " (";
+        err += this->Target->GetName();
+        err += ")";
+        cmSystemTools::Error(err.c_str());
+      }
+    }
+    // Detect if rcc supports (-)-list
+    if (!this->RccExecutable.empty() && (this->QtVersionMajor == "5")) {
+      std::vector<std::string> command;
+      command.push_back(this->RccExecutable);
+      command.push_back("--help");
+      std::string rccStdOut;
+      std::string rccStdErr;
+      int retVal = 0;
+      bool result = cmSystemTools::RunSingleCommand(
+        command, &rccStdOut, &rccStdErr, &retVal, nullptr,
+        cmSystemTools::OUTPUT_NONE, 0.0, cmProcessOutput::Auto);
+      if (result && retVal == 0 &&
+          rccStdOut.find("--list") != std::string::npos) {
+        this->RccListOptions.push_back("--list");
+      } else {
+        this->RccListOptions.push_back("-list");
+      }
+    }
+  }
+
+  // Extract relevant source files
+  std::vector<std::string> generatedSources;
+  std::vector<std::string> generatedHeaders;
+  {
+    std::string const qrcExt = "qrc";
+    std::vector<cmSourceFile*> srcFiles;
+    this->Target->GetConfigCommonSourceFiles(srcFiles);
+    for (cmSourceFile* sf : srcFiles) {
+      if (sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
+        continue;
+      }
+      // sf->GetExtension() is only valid after sf->GetFullPath() ...
+      std::string const& fPath = sf->GetFullPath();
+      std::string const& ext = sf->GetExtension();
+      // Register generated files that will be scanned by moc or uic
+      if (this->MocEnabled || this->UicEnabled) {
+        cmSystemTools::FileFormat const fileType =
+          cmSystemTools::GetFileFormat(ext.c_str());
+        if ((fileType == cmSystemTools::CXX_FILE_FORMAT) ||
+            (fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
+          std::string const absPath = cmSystemTools::GetRealPath(fPath);
+          if ((this->MocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) ||
+              (this->UicEnabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) {
+            // Register source
+            const bool generated = sf->GetPropertyAsBool("GENERATED");
+            if (fileType == cmSystemTools::HEADER_FILE_FORMAT) {
+              if (generated) {
+                generatedHeaders.push_back(absPath);
+              } else {
+                this->Headers.push_back(absPath);
+              }
+            } else {
+              if (generated) {
+                generatedSources.push_back(absPath);
+              } else {
+                this->Sources.push_back(absPath);
+              }
+            }
+          }
+        }
+      }
+      // Register rcc enabled files
+      if (this->RccEnabled && (ext == qrcExt) &&
+          !sf->GetPropertyAsBool("SKIP_AUTORCC")) {
+        // Register qrc file
+        {
+          Qrc qrc;
+          qrc.QrcFile = cmSystemTools::GetRealPath(fPath);
+          qrc.QrcName =
+            cmSystemTools::GetFilenameWithoutLastExtension(qrc.QrcFile);
+          qrc.Generated = sf->GetPropertyAsBool("GENERATED");
+          // RCC options
+          {
+            std::string const opts = GetSafeProperty(sf, "AUTORCC_OPTIONS");
+            if (!opts.empty()) {
+              cmSystemTools::ExpandListArgument(opts, qrc.Options);
+            }
+          }
+          this->Qrcs.push_back(std::move(qrc));
+        }
+      }
+    }
+    // cmGeneratorTarget::GetConfigCommonSourceFiles computes the target's
+    // sources meta data cache. Clear it so that OBJECT library targets that
+    // are AUTOGEN initialized after this target get their added
+    // mocs_compilation.cpp source acknowledged by this target.
+    this->Target->ClearSourcesCache();
+  }
+  // Read skip files from makefile sources
+  if (this->MocEnabled || this->UicEnabled) {
+    const std::vector<cmSourceFile*>& allSources = makefile->GetSourceFiles();
     for (cmSourceFile* sf : allSources) {
       // sf->GetExtension() is only valid after sf->GetFullPath() ...
       std::string const& fPath = sf->GetFullPath();
@@ -373,458 +486,21 @@
         continue;
       }
       const bool skipAll = sf->GetPropertyAsBool("SKIP_AUTOGEN");
-      const bool mocSkip = digest.MocEnabled &&
-        (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC"));
-      const bool uicSkip = digest.UicEnabled &&
-        (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC"));
+      const bool mocSkip =
+        this->MocEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC"));
+      const bool uicSkip =
+        this->UicEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC"));
       if (mocSkip || uicSkip) {
         std::string const absFile = cmSystemTools::GetRealPath(fPath);
         if (mocSkip) {
-          setup.MocSkip.insert(absFile);
+          this->MocSkip.insert(absFile);
         }
         if (uicSkip) {
-          setup.UicSkip.insert(absFile);
+          this->UicSkip.insert(absFile);
         }
       }
     }
   }
-}
-
-static void SetupAutoTargetMoc(cmQtAutoGenDigest const& digest,
-                               std::string const& configDefault,
-                               std::vector<std::string> const& configsList,
-                               cmQtAutoGenSetup& setup)
-{
-  cmGeneratorTarget const* target = digest.Target;
-  cmLocalGenerator* localGen = target->GetLocalGenerator();
-  cmMakefile* makefile = target->Target->GetMakefile();
-
-  AddDefinitionEscaped(makefile, "_moc_skip", setup.MocSkip);
-  AddDefinitionEscaped(makefile, "_moc_options",
-                       GetSafeProperty(target, "AUTOMOC_MOC_OPTIONS"));
-  AddDefinitionEscaped(makefile, "_moc_relaxed_mode",
-                       makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE"
-                                                                    : "FALSE");
-  AddDefinitionEscaped(makefile, "_moc_macro_names",
-                       GetSafeProperty(target, "AUTOMOC_MACRO_NAMES"));
-  AddDefinitionEscaped(makefile, "_moc_depend_filters",
-                       GetSafeProperty(target, "AUTOMOC_DEPEND_FILTERS"));
-
-  // Compiler predefines
-  if (target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES")) {
-    if (QtVersionGreaterOrEqual(digest.QtVersionMajor, digest.QtVersionMinor,
-                                5, 8)) {
-      AddDefinitionEscaped(
-        makefile, "_moc_predefs_cmd",
-        makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"));
-    }
-  }
-  // Moc includes and compile definitions
-  {
-    auto GetIncludeDirs = [target,
-                           localGen](std::string const& cfg) -> std::string {
-      // Get the include dirs for this target, without stripping the implicit
-      // include dirs off, see
-      // https://gitlab.kitware.com/cmake/cmake/issues/13667
-      std::vector<std::string> includeDirs;
-      localGen->GetIncludeDirectories(includeDirs, target, "CXX", cfg, false);
-      return cmJoin(includeDirs, ";");
-    };
-    auto GetCompileDefinitions =
-      [target, localGen](std::string const& cfg) -> std::string {
-      std::set<std::string> defines;
-      localGen->AddCompileDefinitions(defines, target, cfg, "CXX");
-      return cmJoin(defines, ";");
-    };
-
-    // Default configuration settings
-    std::string const includeDirs = GetIncludeDirs(configDefault);
-    std::string const compileDefs = GetCompileDefinitions(configDefault);
-    // Other configuration settings
-    for (std::string const& cfg : configsList) {
-      {
-        std::string const configIncludeDirs = GetIncludeDirs(cfg);
-        if (configIncludeDirs != includeDirs) {
-          setup.ConfigMocIncludes[cfg] = configIncludeDirs;
-        }
-      }
-      {
-        std::string const configCompileDefs = GetCompileDefinitions(cfg);
-        if (configCompileDefs != compileDefs) {
-          setup.ConfigMocDefines[cfg] = configCompileDefs;
-        }
-      }
-    }
-    AddDefinitionEscaped(makefile, "_moc_include_dirs", includeDirs);
-    AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs);
-  }
-
-  // Moc executable
-  {
-    std::string mocExec;
-    std::string err;
-
-    if (digest.QtVersionMajor == "5") {
-      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::moc");
-      if (tgt != nullptr) {
-        mocExec = SafeString(tgt->ImportedGetLocation(""));
-      } else {
-        err = "AUTOMOC: Qt5::moc target not found";
-      }
-    } else if (digest.QtVersionMajor == "4") {
-      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::moc");
-      if (tgt != nullptr) {
-        mocExec = SafeString(tgt->ImportedGetLocation(""));
-      } else {
-        err = "AUTOMOC: Qt4::moc target not found";
-      }
-    } else {
-      err = "The AUTOMOC feature supports only Qt 4 and Qt 5";
-    }
-
-    if (err.empty()) {
-      AddDefinitionEscaped(makefile, "_qt_moc_executable", mocExec);
-    } else {
-      err += " (" + target->GetName() + ")";
-      cmSystemTools::Error(err.c_str());
-    }
-  }
-}
-
-static void SetupAutoTargetUic(cmQtAutoGenDigest const& digest,
-                               std::string const& config,
-                               std::vector<std::string> const& configs,
-                               cmQtAutoGenSetup& setup)
-{
-  cmGeneratorTarget const* target = digest.Target;
-  cmMakefile* makefile = target->Target->GetMakefile();
-
-  // Uic search paths
-  {
-    std::vector<std::string> uicSearchPaths;
-    {
-      std::string const usp = GetSafeProperty(target, "AUTOUIC_SEARCH_PATHS");
-      if (!usp.empty()) {
-        cmSystemTools::ExpandListArgument(usp, uicSearchPaths);
-        std::string const srcDir = makefile->GetCurrentSourceDirectory();
-        for (std::string& path : uicSearchPaths) {
-          path = cmSystemTools::CollapseFullPath(path, srcDir);
-        }
-      }
-    }
-    AddDefinitionEscaped(makefile, "_uic_search_paths", uicSearchPaths);
-  }
-  // Uic target options
-  {
-    auto UicGetOpts = [target](std::string const& cfg) -> std::string {
-      std::vector<std::string> opts;
-      target->GetAutoUicOptions(opts, cfg);
-      return cmJoin(opts, ";");
-    };
-
-    // Default settings
-    std::string const uicOpts = UicGetOpts(config);
-    AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts);
-
-    // Configuration specific settings
-    for (std::string const& cfg : configs) {
-      std::string const configUicOpts = UicGetOpts(cfg);
-      if (configUicOpts != uicOpts) {
-        setup.ConfigUicOptions[cfg] = configUicOpts;
-      }
-    }
-  }
-  // .ui files skip and options
-  {
-    std::vector<std::string> uiFileFiles;
-    std::vector<std::vector<std::string>> uiFileOptions;
-    {
-      std::string const uiExt = "ui";
-      for (cmSourceFile* sf : makefile->GetSourceFiles()) {
-        // sf->GetExtension() is only valid after sf->GetFullPath() ...
-        std::string const& fPath = sf->GetFullPath();
-        if (sf->GetExtension() == uiExt) {
-          std::string const absFile = cmSystemTools::GetRealPath(fPath);
-          // Check if the file should be skipped
-          if (sf->GetPropertyAsBool("SKIP_AUTOUIC") ||
-              sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
-            setup.UicSkip.insert(absFile);
-          }
-          // Check if the files has uic options
-          std::string const uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS");
-          if (!uicOpts.empty()) {
-            // Check if file isn't skipped
-            if (setup.UicSkip.count(absFile) == 0) {
-              uiFileFiles.push_back(absFile);
-              std::vector<std::string> optsVec;
-              cmSystemTools::ExpandListArgument(uicOpts, optsVec);
-              uiFileOptions.push_back(std::move(optsVec));
-            }
-          }
-        }
-      }
-    }
-    AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles);
-    AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions);
-  }
-
-  AddDefinitionEscaped(makefile, "_uic_skip", setup.UicSkip);
-
-  // Uic executable
-  {
-    std::string err;
-    std::string uicExec;
-
-    cmLocalGenerator* localGen = target->GetLocalGenerator();
-    if (digest.QtVersionMajor == "5") {
-      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::uic");
-      if (tgt != nullptr) {
-        uicExec = SafeString(tgt->ImportedGetLocation(""));
-      } else {
-        // Project does not use Qt5Widgets, but has AUTOUIC ON anyway
-      }
-    } else if (digest.QtVersionMajor == "4") {
-      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::uic");
-      if (tgt != nullptr) {
-        uicExec = SafeString(tgt->ImportedGetLocation(""));
-      } else {
-        err = "AUTOUIC: Qt4::uic target not found";
-      }
-    } else {
-      err = "The AUTOUIC feature supports only Qt 4 and Qt 5";
-    }
-
-    if (err.empty()) {
-      AddDefinitionEscaped(makefile, "_qt_uic_executable", uicExec);
-    } else {
-      err += " (" + target->GetName() + ")";
-      cmSystemTools::Error(err.c_str());
-    }
-  }
-}
-
-static std::string RccGetExecutable(cmGeneratorTarget const* target,
-                                    std::string const& qtMajorVersion)
-{
-  std::string rccExec;
-  std::string err;
-
-  cmLocalGenerator* localGen = target->GetLocalGenerator();
-  if (qtMajorVersion == "5") {
-    cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::rcc");
-    if (tgt != nullptr) {
-      rccExec = SafeString(tgt->ImportedGetLocation(""));
-    } else {
-      err = "AUTORCC: Qt5::rcc target not found";
-    }
-  } else if (qtMajorVersion == "4") {
-    cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::rcc");
-    if (tgt != nullptr) {
-      rccExec = SafeString(tgt->ImportedGetLocation(""));
-    } else {
-      err = "AUTORCC: Qt4::rcc target not found";
-    }
-  } else {
-    err = "The AUTORCC feature supports only Qt 4 and Qt 5";
-  }
-
-  if (!err.empty()) {
-    err += " (" + target->GetName() + ")";
-    cmSystemTools::Error(err.c_str());
-  }
-  return rccExec;
-}
-
-static void SetupAutoTargetRcc(cmQtAutoGenDigest const& digest)
-{
-  std::vector<std::string> rccFiles;
-  std::vector<std::string> rccBuilds;
-  std::vector<std::vector<std::string>> rccOptions;
-  std::vector<std::vector<std::string>> rccInputs;
-
-  for (cmQtAutoGenDigestQrc const& qrcDigest : digest.Qrcs) {
-    rccFiles.push_back(qrcDigest.QrcFile);
-    rccBuilds.push_back(qrcDigest.RccFile);
-    rccOptions.push_back(qrcDigest.Options);
-    rccInputs.push_back(qrcDigest.Resources);
-  }
-
-  cmMakefile* makefile = digest.Target->Target->GetMakefile();
-  AddDefinitionEscaped(makefile, "_qt_rcc_executable",
-                       RccGetExecutable(digest.Target, digest.QtVersionMajor));
-  AddDefinitionEscaped(makefile, "_rcc_files", rccFiles);
-  AddDefinitionEscaped(makefile, "_rcc_builds", rccBuilds);
-  AddDefinitionEscaped(makefile, "_rcc_options", rccOptions);
-  AddDefinitionEscaped(makefile, "_rcc_inputs", rccInputs);
-}
-
-void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
-  cmQtAutoGenDigest& digest)
-{
-  cmGeneratorTarget* target = digest.Target;
-  cmMakefile* makefile = target->Target->GetMakefile();
-  cmLocalGenerator* localGen = target->GetLocalGenerator();
-  cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator();
-
-  std::string const autogenTargetName = GetAutogenTargetName(target);
-  std::string const autogenInfoDir = GetAutogenTargetFilesDir(target);
-  std::string const autogenBuildDir = GetAutogenTargetBuildDir(target);
-  std::string const workingDirectory =
-    cmSystemTools::CollapseFullPath("", makefile->GetCurrentBinaryDirectory());
-
-  cmQtAutoGen::MultiConfig const multiConfig = AutogenMultiConfig(globalGen);
-  std::string configDefault;
-  std::vector<std::string> configsList;
-  GetConfigs(makefile, configDefault, configsList);
-
-  std::set<std::string> autogenDependFiles;
-  std::set<cmTarget*> autogenDependTargets;
-  std::vector<std::string> autogenProvides;
-
-  // Remove build directories on cleanup
-  AddCleanFile(makefile, autogenBuildDir);
-  // Remove old settings on cleanup
-  {
-    std::string base = autogenInfoDir + "/AutogenOldSettings";
-    if (multiConfig == cmQtAutoGen::SINGLE) {
-      AddCleanFile(makefile, base.append(".cmake"));
-    } else {
-      for (std::string const& cfg : configsList) {
-        std::string filename = base;
-        filename += "_";
-        filename += cfg;
-        filename += ".cmake";
-        AddCleanFile(makefile, filename);
-      }
-    }
-  }
-
-  // Compose command lines
-  cmCustomCommandLines commandLines;
-  {
-    cmCustomCommandLine currentLine;
-    currentLine.push_back(cmSystemTools::GetCMakeCommand());
-    currentLine.push_back("-E");
-    currentLine.push_back("cmake_autogen");
-    currentLine.push_back(autogenInfoDir);
-    currentLine.push_back("$<CONFIGURATION>");
-    commandLines.push_back(currentLine);
-  }
-
-  // Compose target comment
-  std::string autogenComment;
-  {
-    std::vector<std::string> toolNames;
-    if (digest.MocEnabled) {
-      toolNames.emplace_back("MOC");
-    }
-    if (digest.UicEnabled) {
-      toolNames.emplace_back("UIC");
-    }
-    if (digest.RccEnabled) {
-      toolNames.emplace_back("RCC");
-    }
-
-    std::string tools = toolNames.front();
-    toolNames.erase(toolNames.begin());
-    if (!toolNames.empty()) {
-      while (toolNames.size() > 1) {
-        tools += ", ";
-        tools += toolNames.front();
-        toolNames.erase(toolNames.begin());
-      }
-      tools += " and " + toolNames.front();
-    }
-    autogenComment = "Automatic " + tools + " for target " + target->GetName();
-  }
-
-  // Add moc compilation to generated files list
-  if (digest.MocEnabled) {
-    std::string const mocsComp = autogenBuildDir + "/mocs_compilation.cpp";
-    auto files = AddGeneratedSource(target, mocsComp, multiConfig, configsList,
-                                    cmQtAutoGen::MOC);
-    for (std::string& file : files) {
-      autogenProvides.push_back(std::move(file));
-    }
-  }
-
-  // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES
-  if (digest.MocEnabled || digest.UicEnabled) {
-    std::string includeDir = autogenBuildDir + "/include";
-    if (multiConfig != cmQtAutoGen::SINGLE) {
-      includeDir += "_$<CONFIG>";
-    }
-    target->AddIncludeDirectory(includeDir, true);
-  }
-
-  // Extract relevant source files
-  std::vector<std::string> generatedSources;
-  std::vector<std::string> generatedHeaders;
-  {
-    std::string const qrcExt = "qrc";
-    std::vector<cmSourceFile*> srcFiles;
-    target->GetConfigCommonSourceFiles(srcFiles);
-    for (cmSourceFile* sf : srcFiles) {
-      if (sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
-        continue;
-      }
-      // sf->GetExtension() is only valid after sf->GetFullPath() ...
-      std::string const& fPath = sf->GetFullPath();
-      std::string const& ext = sf->GetExtension();
-      // Register generated files that will be scanned by moc or uic
-      if (digest.MocEnabled || digest.UicEnabled) {
-        cmSystemTools::FileFormat const fileType =
-          cmSystemTools::GetFileFormat(ext.c_str());
-        if ((fileType == cmSystemTools::CXX_FILE_FORMAT) ||
-            (fileType == cmSystemTools::HEADER_FILE_FORMAT)) {
-          std::string const absPath = cmSystemTools::GetRealPath(fPath);
-          if ((digest.MocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) ||
-              (digest.UicEnabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) {
-            // Register source
-            const bool generated = sf->GetPropertyAsBool("GENERATED");
-            if (fileType == cmSystemTools::HEADER_FILE_FORMAT) {
-              if (generated) {
-                generatedHeaders.push_back(absPath);
-              } else {
-                digest.Headers.push_back(absPath);
-              }
-            } else {
-              if (generated) {
-                generatedSources.push_back(absPath);
-              } else {
-                digest.Sources.push_back(absPath);
-              }
-            }
-          }
-        }
-      }
-      // Register rcc enabled files
-      if (digest.RccEnabled && (ext == qrcExt) &&
-          !sf->GetPropertyAsBool("SKIP_AUTORCC")) {
-        // Register qrc file
-        {
-          cmQtAutoGenDigestQrc qrcDigest;
-          qrcDigest.QrcFile = cmSystemTools::GetRealPath(fPath);
-          qrcDigest.QrcName =
-            cmSystemTools::GetFilenameWithoutLastExtension(qrcDigest.QrcFile);
-          qrcDigest.Generated = sf->GetPropertyAsBool("GENERATED");
-          // RCC options
-          {
-            std::string const opts = GetSafeProperty(sf, "AUTORCC_OPTIONS");
-            if (!opts.empty()) {
-              cmSystemTools::ExpandListArgument(opts, qrcDigest.Options);
-            }
-          }
-          digest.Qrcs.push_back(std::move(qrcDigest));
-        }
-      }
-    }
-    // cmGeneratorTarget::GetConfigCommonSourceFiles computes the target's
-    // sources meta data cache. Clear it so that OBJECT library targets that
-    // are AUTOGEN initialized after this target get their added
-    // mocs_compilation.cpp source acknowledged by this target.
-    target->ClearSourcesCache();
-  }
 
   // Process GENERATED sources and headers
   if (!generatedSources.empty() || !generatedHeaders.empty()) {
@@ -832,7 +508,7 @@
     bool policyAccept = false;
     bool policyWarn = false;
     cmPolicies::PolicyStatus const CMP0071_status =
-      target->Makefile->GetPolicyStatus(cmPolicies::CMP0071);
+      makefile->GetPolicyStatus(cmPolicies::CMP0071);
     switch (CMP0071_status) {
       case cmPolicies::WARN:
         policyWarn = true;
@@ -851,11 +527,11 @@
     if (policyAccept) {
       // Accept GENERATED sources
       for (std::string const& absFile : generatedHeaders) {
-        digest.Headers.push_back(absFile);
+        this->Headers.push_back(absFile);
         autogenDependFiles.insert(absFile);
       }
       for (std::string const& absFile : generatedSources) {
-        digest.Sources.push_back(absFile);
+        this->Sources.push_back(absFile);
         autogenDependFiles.insert(absFile);
       }
     } else {
@@ -865,13 +541,13 @@
         msg += "\n";
         std::string tools;
         std::string property;
-        if (digest.MocEnabled && digest.UicEnabled) {
+        if (this->MocEnabled && this->UicEnabled) {
           tools = "AUTOMOC and AUTOUIC";
           property = "SKIP_AUTOGEN";
-        } else if (digest.MocEnabled) {
+        } else if (this->MocEnabled) {
           tools = "AUTOMOC";
           property = "SKIP_AUTOMOC";
-        } else if (digest.UicEnabled) {
+        } else if (this->UicEnabled) {
           tools = "AUTOUIC";
           property = "SKIP_AUTOUIC";
         }
@@ -896,57 +572,74 @@
         makefile->IssueMessage(cmake::AUTHOR_WARNING, msg);
       }
     }
+    // Clear lists
+    generatedSources.clear();
+    generatedHeaders.clear();
   }
   // Sort headers and sources
-  std::sort(digest.Headers.begin(), digest.Headers.end());
-  std::sort(digest.Sources.begin(), digest.Sources.end());
+  if (this->MocEnabled || this->UicEnabled) {
+    std::sort(this->Headers.begin(), this->Headers.end());
+    std::sort(this->Sources.begin(), this->Sources.end());
+  }
 
   // Process qrc files
-  if (!digest.Qrcs.empty()) {
-    const bool QtV5 = (digest.QtVersionMajor == "5");
-    std::string const rcc = RccGetExecutable(target, digest.QtVersionMajor);
+  if (!this->Qrcs.empty()) {
+    const bool QtV5 = (this->QtVersionMajor == "5");
     // Target rcc options
     std::vector<std::string> optionsTarget;
     cmSystemTools::ExpandListArgument(
-      GetSafeProperty(target, "AUTORCC_OPTIONS"), optionsTarget);
+      GetSafeProperty(this->Target, "AUTORCC_OPTIONS"), optionsTarget);
 
     // Check if file name is unique
-    for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
-      qrcDigest.Unique = true;
-      for (cmQtAutoGenDigestQrc const& qrcDig2 : digest.Qrcs) {
-        if ((&qrcDigest != &qrcDig2) &&
-            (qrcDigest.QrcName == qrcDig2.QrcName)) {
-          qrcDigest.Unique = false;
+    for (Qrc& qrc : this->Qrcs) {
+      qrc.Unique = true;
+      for (Qrc const& qrc2 : this->Qrcs) {
+        if ((&qrc != &qrc2) && (qrc.QrcName == qrc2.QrcName)) {
+          qrc.Unique = false;
           break;
         }
       }
     }
-    // Path checksum
+    // Path checksum and file names
     {
       cmFilePathChecksum const fpathCheckSum(makefile);
-      for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
-        qrcDigest.PathChecksum = fpathCheckSum.getPart(qrcDigest.QrcFile);
+      for (Qrc& qrc : this->Qrcs) {
+        qrc.PathChecksum = fpathCheckSum.getPart(qrc.QrcFile);
         // RCC output file name
-        std::string rccFile = autogenBuildDir + "/";
-        rccFile += qrcDigest.PathChecksum;
-        rccFile += "/qrc_";
-        rccFile += qrcDigest.QrcName;
-        rccFile += ".cpp";
-        qrcDigest.RccFile = std::move(rccFile);
+        {
+          std::string rccFile = this->DirBuild + "/";
+          rccFile += qrc.PathChecksum;
+          rccFile += "/qrc_";
+          rccFile += qrc.QrcName;
+          rccFile += ".cpp";
+          qrc.RccFile = std::move(rccFile);
+        }
+        {
+          std::string base = this->DirInfo;
+          base += "/RCC";
+          base += qrc.QrcName;
+          if (!qrc.Unique) {
+            base += qrc.PathChecksum;
+          }
+          qrc.InfoFile = base;
+          qrc.InfoFile += "Info.cmake";
+          qrc.SettingsFile = base;
+          qrc.SettingsFile += "Settings.cmake";
+        }
       }
     }
     // RCC options
-    for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
+    for (Qrc& qrc : this->Qrcs) {
       // Target options
       std::vector<std::string> opts = optionsTarget;
       // Merge computed "-name XYZ" option
       {
-        std::string name = qrcDigest.QrcName;
+        std::string name = qrc.QrcName;
         // Replace '-' with '_'. The former is not valid for symbol names.
         std::replace(name.begin(), name.end(), '-', '_');
-        if (!qrcDigest.Unique) {
+        if (!qrc.Unique) {
           name += "_";
-          name += qrcDigest.PathChecksum;
+          name += qrc.PathChecksum;
         }
         std::vector<std::string> nameOpts;
         nameOpts.emplace_back("-name");
@@ -954,254 +647,324 @@
         cmQtAutoGen::RccMergeOptions(opts, nameOpts, QtV5);
       }
       // Merge file option
-      cmQtAutoGen::RccMergeOptions(opts, qrcDigest.Options, QtV5);
-      qrcDigest.Options = std::move(opts);
+      cmQtAutoGen::RccMergeOptions(opts, qrc.Options, QtV5);
+      qrc.Options = std::move(opts);
     }
-    for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
+    for (Qrc& qrc : this->Qrcs) {
       // Register file at target
+      std::vector<std::string> const ccOutput =
+        this->AddGeneratedSource(qrc.RccFile, cmQtAutoGen::RCC);
+
+      cmCustomCommandLines commandLines;
       {
-        auto files = AddGeneratedSource(target, qrcDigest.RccFile, multiConfig,
-                                        configsList, cmQtAutoGen::RCC);
-        for (std::string& file : files) {
-          autogenProvides.push_back(std::move(file));
-        }
+        cmCustomCommandLine currentLine;
+        currentLine.push_back(cmSystemTools::GetCMakeCommand());
+        currentLine.push_back("-E");
+        currentLine.push_back("cmake_autorcc");
+        currentLine.push_back(qrc.InfoFile);
+        currentLine.push_back("$<CONFIGURATION>");
+        commandLines.push_back(std::move(currentLine));
       }
-      // Dependencies
-      if (qrcDigest.Generated) {
-        // Add the GENERATED .qrc file to the dependencies
-        autogenDependFiles.insert(qrcDigest.QrcFile);
-      } else {
-        // Add the resource files to the dependencies
+      std::string ccComment = "Automatic RCC for ";
+      ccComment += FileProjectRelativePath(makefile, qrc.QrcFile);
+
+      if (qrc.Generated) {
+        // Create custom rcc target
+        std::string ccName;
         {
-          std::string error;
-          if (cmQtAutoGen::RccListInputs(digest.QtVersionMajor, rcc,
-                                         qrcDigest.QrcFile,
-                                         qrcDigest.Resources, &error)) {
-            for (std::string const& fileName : qrcDigest.Resources) {
-              autogenDependFiles.insert(fileName);
-            }
-          } else {
-            cmSystemTools::Error(error.c_str());
+          ccName = this->Target->GetName();
+          ccName += "_arcc_";
+          ccName += qrc.QrcName;
+          if (!qrc.Unique) {
+            ccName += "_";
+            ccName += qrc.PathChecksum;
+          }
+          std::vector<std::string> ccDepends;
+          // Add the .qrc file to the custom target dependencies
+          ccDepends.push_back(qrc.QrcFile);
+
+          cmTarget* autoRccTarget = makefile->AddUtilityCommand(
+            ccName, true, this->DirWork.c_str(), ccOutput, ccDepends,
+            commandLines, false, ccComment.c_str());
+          // Create autogen generator target
+          localGen->AddGeneratorTarget(
+            new cmGeneratorTarget(autoRccTarget, localGen));
+
+          // Set FOLDER property in autogen target
+          if (!this->AutogenFolder.empty()) {
+            autoRccTarget->SetProperty("FOLDER", this->AutogenFolder.c_str());
           }
         }
-        // Run cmake again when .qrc file changes
-        makefile->AddCMakeDependFile(qrcDigest.QrcFile);
-      }
-    }
-  }
+        // Add autogen target to the origin target dependencies
+        this->Target->Target->AddUtility(ccName, makefile);
+      } else {
+        // Create custom rcc command
+        {
+          std::vector<std::string> ccByproducts;
+          std::vector<std::string> ccDepends;
+          // Add the .qrc file to the custom command dependencies
+          ccDepends.push_back(qrc.QrcFile);
 
-  // Add user defined autogen target dependencies
-  {
-    std::string const deps = GetSafeProperty(target, "AUTOGEN_TARGET_DEPENDS");
-    if (!deps.empty()) {
-      std::vector<std::string> extraDeps;
-      cmSystemTools::ExpandListArgument(deps, extraDeps);
-      for (std::string const& depName : extraDeps) {
-        // Allow target and file dependencies
-        auto* depTarget = makefile->FindTargetToUse(depName);
-        if (depTarget != nullptr) {
-          autogenDependTargets.insert(depTarget);
-        } else {
-          autogenDependFiles.insert(depName);
-        }
-      }
-    }
-  }
-
-  // Use PRE_BUILD on demand
-  bool usePRE_BUILD = false;
-  if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
-    // Under VS use a PRE_BUILD event instead of a separate target to
-    // reduce the number of targets loaded into the IDE.
-    // This also works around a VS 11 bug that may skip updating the target:
-    //  https://connect.microsoft.com/VisualStudio/feedback/details/769495
-    usePRE_BUILD = true;
-  }
-  // Disable PRE_BUILD in some cases
-  if (usePRE_BUILD) {
-    // Cannot use PRE_BUILD with file depends
-    if (!autogenDependFiles.empty()) {
-      usePRE_BUILD = false;
-    }
-  }
-  // Create the autogen target/command
-  if (usePRE_BUILD) {
-    // Add additional autogen target dependencies to origin target
-    for (cmTarget* depTarget : autogenDependTargets) {
-      target->Target->AddUtility(depTarget->GetName(), makefile);
-    }
-
-    // Add the pre-build command directly to bypass the OBJECT_LIBRARY
-    // rejection in cmMakefile::AddCustomCommandToTarget because we know
-    // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case.
-    //
-    // PRE_BUILD does not support file dependencies!
-    const std::vector<std::string> no_output;
-    const std::vector<std::string> no_deps;
-    cmCustomCommand cc(makefile, no_output, autogenProvides, no_deps,
-                       commandLines, autogenComment.c_str(),
-                       workingDirectory.c_str());
-    cc.SetEscapeOldStyle(false);
-    cc.SetEscapeAllowMakeVars(true);
-    target->Target->AddPreBuildCommand(cc);
-  } else {
-
-    // Convert file dependencies std::set to std::vector
-    std::vector<std::string> autogenDepends(autogenDependFiles.begin(),
-                                            autogenDependFiles.end());
-
-    // Add link library target dependencies to the autogen target dependencies
-    for (std::string const& config : configsList) {
-      cmLinkImplementationLibraries const* libs =
-        target->GetLinkImplementationLibraries(config);
-      if (libs != nullptr) {
-        for (cmLinkItem const& item : libs->Libraries) {
-          cmGeneratorTarget const* libTarget = item.Target;
-          if ((libTarget != nullptr) &&
-              !StaticLibraryCycle(target, libTarget, config)) {
-            std::string util;
-            if (configsList.size() > 1) {
-              util += "$<$<CONFIG:";
-              util += config;
-              util += ">:";
+          // Add the resource files to the dependencies
+          {
+            std::string error;
+            if (cmQtAutoGen::RccListInputs(this->RccExecutable,
+                                           this->RccListOptions, qrc.QrcFile,
+                                           qrc.Resources, &error)) {
+              for (std::string const& fileName : qrc.Resources) {
+                // Add resource file to the custom command dependencies
+                ccDepends.push_back(fileName);
+              }
+            } else {
+              cmSystemTools::Error(error.c_str());
             }
-            util += libTarget->GetName();
-            if (configsList.size() > 1) {
-              util += ">";
-            }
-            autogenDepends.push_back(util);
           }
+          makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends,
+                                             /*main_dependency*/ std::string(),
+                                             commandLines, ccComment.c_str(),
+                                             this->DirWork.c_str());
         }
+        // Reconfigure when .qrc file changes
+        makefile->AddCMakeDependFile(qrc.QrcFile);
       }
     }
+  }
 
-    // Create autogen target
-    cmTarget* autogenTarget = makefile->AddUtilityCommand(
-      autogenTargetName, true, workingDirectory.c_str(),
-      /*byproducts=*/autogenProvides, autogenDepends, commandLines, false,
-      autogenComment.c_str());
-    // Create autogen generator target
-    localGen->AddGeneratorTarget(
-      new cmGeneratorTarget(autogenTarget, localGen));
-
-    // Forward origin utilities to autogen target
-    for (std::string const& depName : target->Target->GetUtilities()) {
-      autogenTarget->AddUtility(depName, makefile);
-    }
-    // Add additional autogen target dependencies to autogen target
-    for (cmTarget* depTarget : autogenDependTargets) {
-      autogenTarget->AddUtility(depTarget->GetName(), makefile);
-    }
-
-    // Set FOLDER property in autogen target
+  // Create _autogen target
+  if (this->MocEnabled || this->UicEnabled) {
+    // Add user defined autogen target dependencies
     {
-      const char* autogenFolder =
-        makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER");
-      if (autogenFolder == nullptr) {
-        autogenFolder =
-          makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER");
-      }
-      // Inherit FOLDER property from target (#13688)
-      if (autogenFolder == nullptr) {
-        autogenFolder = SafeString(target->Target->GetProperty("FOLDER"));
-      }
-      if ((autogenFolder != nullptr) && (*autogenFolder != '\0')) {
-        autogenTarget->SetProperty("FOLDER", autogenFolder);
+      std::string const deps =
+        GetSafeProperty(this->Target, "AUTOGEN_TARGET_DEPENDS");
+      if (!deps.empty()) {
+        std::vector<std::string> extraDeps;
+        cmSystemTools::ExpandListArgument(deps, extraDeps);
+        for (std::string const& depName : extraDeps) {
+          // Allow target and file dependencies
+          auto* depTarget = makefile->FindTargetToUse(depName);
+          if (depTarget != nullptr) {
+            autogenDependTargets.insert(depTarget);
+          } else {
+            autogenDependFiles.insert(depName);
+          }
+        }
       }
     }
 
-    // Add autogen target to the origin target dependencies
-    target->Target->AddUtility(autogenTargetName, makefile);
+    // Compose target comment
+    std::string autogenComment;
+    {
+      std::string tools;
+      if (this->MocEnabled) {
+        tools += "MOC";
+      }
+      if (this->UicEnabled) {
+        if (!tools.empty()) {
+          tools += " and ";
+        }
+        tools += "UIC";
+      }
+      autogenComment = "Automatic ";
+      autogenComment += tools;
+      autogenComment += " for target ";
+      autogenComment += this->Target->GetName();
+    }
+
+    // Compose command lines
+    cmCustomCommandLines commandLines;
+    {
+      cmCustomCommandLine currentLine;
+      currentLine.push_back(cmSystemTools::GetCMakeCommand());
+      currentLine.push_back("-E");
+      currentLine.push_back("cmake_autogen");
+      currentLine.push_back(this->AutogenInfoFile);
+      currentLine.push_back("$<CONFIGURATION>");
+      commandLines.push_back(std::move(currentLine));
+    }
+
+    // Use PRE_BUILD on demand
+    bool usePRE_BUILD = false;
+    if (globalGen->GetName().find("Visual Studio") != std::string::npos) {
+      // Under VS use a PRE_BUILD event instead of a separate target to
+      // reduce the number of targets loaded into the IDE.
+      // This also works around a VS 11 bug that may skip updating the target:
+      //  https://connect.microsoft.com/VisualStudio/feedback/details/769495
+      usePRE_BUILD = true;
+    }
+    // Disable PRE_BUILD in some cases
+    if (usePRE_BUILD) {
+      // Cannot use PRE_BUILD with file depends
+      if (!autogenDependFiles.empty()) {
+        usePRE_BUILD = false;
+      }
+    }
+    // Create the autogen target/command
+    if (usePRE_BUILD) {
+      // Add additional autogen target dependencies to origin target
+      for (cmTarget* depTarget : autogenDependTargets) {
+        this->Target->Target->AddUtility(depTarget->GetName(), makefile);
+      }
+
+      // Add the pre-build command directly to bypass the OBJECT_LIBRARY
+      // rejection in cmMakefile::AddCustomCommandToTarget because we know
+      // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case.
+      //
+      // PRE_BUILD does not support file dependencies!
+      const std::vector<std::string> no_output;
+      const std::vector<std::string> no_deps;
+      cmCustomCommand cc(makefile, no_output, autogenProvides, no_deps,
+                         commandLines, autogenComment.c_str(),
+                         this->DirWork.c_str());
+      cc.SetEscapeOldStyle(false);
+      cc.SetEscapeAllowMakeVars(true);
+      this->Target->Target->AddPreBuildCommand(cc);
+    } else {
+
+      // Convert file dependencies std::set to std::vector
+      std::vector<std::string> autogenDepends(autogenDependFiles.begin(),
+                                              autogenDependFiles.end());
+
+      // Add link library target dependencies to the autogen target
+      // dependencies
+      for (std::string const& config : this->ConfigsList) {
+        cmLinkImplementationLibraries const* libs =
+          this->Target->GetLinkImplementationLibraries(config);
+        if (libs != nullptr) {
+          for (cmLinkItem const& item : libs->Libraries) {
+            cmGeneratorTarget const* libTarget = item.Target;
+            if ((libTarget != nullptr) &&
+                !StaticLibraryCycle(this->Target, libTarget, config)) {
+              std::string util;
+              if (this->ConfigsList.size() > 1) {
+                util += "$<$<CONFIG:";
+                util += config;
+                util += ">:";
+              }
+              util += libTarget->GetName();
+              if (this->ConfigsList.size() > 1) {
+                util += ">";
+              }
+              autogenDepends.push_back(util);
+            }
+          }
+        }
+      }
+
+      // Create autogen target
+      cmTarget* autogenTarget = makefile->AddUtilityCommand(
+        this->AutogenTargetName, true, this->DirWork.c_str(),
+        /*byproducts=*/autogenProvides, autogenDepends, commandLines, false,
+        autogenComment.c_str());
+      // Create autogen generator target
+      localGen->AddGeneratorTarget(
+        new cmGeneratorTarget(autogenTarget, localGen));
+
+      // Forward origin utilities to autogen target
+      for (std::string const& depName : this->Target->Target->GetUtilities()) {
+        autogenTarget->AddUtility(depName, makefile);
+      }
+      // Add additional autogen target dependencies to autogen target
+      for (cmTarget* depTarget : autogenDependTargets) {
+        autogenTarget->AddUtility(depTarget->GetName(), makefile);
+      }
+
+      // Set FOLDER property in autogen target
+      if (!this->AutogenFolder.empty()) {
+        autogenTarget->SetProperty("FOLDER", this->AutogenFolder.c_str());
+      }
+
+      // Add autogen target to the origin target dependencies
+      this->Target->Target->AddUtility(this->AutogenTargetName, makefile);
+    }
   }
 }
 
-void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
-  cmQtAutoGenDigest const& digest)
+void cmQtAutoGeneratorInitializer::SetupCustomTargets()
 {
-  cmGeneratorTarget const* target = digest.Target;
-  cmMakefile* makefile = target->Target->GetMakefile();
-  cmQtAutoGen::MultiConfig const multiConfig =
-    AutogenMultiConfig(target->GetGlobalGenerator());
+  cmMakefile* makefile = this->Target->Target->GetMakefile();
 
   // forget the variables added here afterwards again:
   cmMakefile::ScopePushPop varScope(makefile);
   static_cast<void>(varScope);
 
-  // Configurations
-  std::string configDefault;
-  std::vector<std::string> configsList;
+  // Configuration suffixes
   std::map<std::string, std::string> configSuffixes;
-  {
-    configDefault = makefile->GetConfigurations(configsList);
-    if (configsList.empty()) {
-      configsList.push_back("");
-    }
+  for (std::string const& cfg : this->ConfigsList) {
+    std::string& suffix = configSuffixes[cfg];
+    suffix = "_";
+    suffix += cfg;
   }
-  for (std::string const& cfg : configsList) {
-    configSuffixes[cfg] = "_" + cfg;
-  }
-
-  // Configurations settings buffers
-  cmQtAutoGenSetup setup;
 
   // Basic setup
   AddDefinitionEscaped(makefile, "_multi_config",
-                       cmQtAutoGen::MultiConfigName(multiConfig));
-  AddDefinitionEscaped(makefile, "_build_dir",
-                       GetAutogenTargetBuildDir(target));
-  AddDefinitionEscaped(makefile, "_sources", digest.Sources);
-  AddDefinitionEscaped(makefile, "_headers", digest.Headers);
-  AddDefinitionEscaped(makefile, "_qt_version_major", digest.QtVersionMajor);
-  AddDefinitionEscaped(makefile, "_qt_version_minor", digest.QtVersionMinor);
-  {
-    if (digest.MocEnabled || digest.UicEnabled) {
-      SetupAcquireSkipFiles(digest, setup);
-      if (digest.MocEnabled) {
-        SetupAutoTargetMoc(digest, configDefault, configsList, setup);
-      }
-      if (digest.UicEnabled) {
-        SetupAutoTargetUic(digest, configDefault, configsList, setup);
-      }
+                       cmQtAutoGen::MultiConfigName(this->MultiConfig));
+  AddDefinitionEscaped(makefile, "_build_dir", this->DirBuild);
+
+  if (this->MocEnabled || this->UicEnabled) {
+    AddDefinitionEscaped(makefile, "_qt_version_major", this->QtVersionMajor);
+    AddDefinitionEscaped(makefile, "_settings_file",
+                         this->AutogenSettingsFile);
+    AddDefinitionEscaped(makefile, "_sources", this->Sources);
+    AddDefinitionEscaped(makefile, "_headers", this->Headers);
+
+    if (this->MocEnabled) {
+      this->SetupCustomTargetsMoc();
     }
-    if (digest.RccEnabled) {
-      SetupAutoTargetRcc(digest);
+    if (this->UicEnabled) {
+      this->SetupCustomTargetsUic();
     }
   }
+  if (this->RccEnabled) {
+    AddDefinitionEscaped(makefile, "_qt_rcc_executable", this->RccExecutable);
+    AddDefinitionEscaped(makefile, "_qt_rcc_list_options",
+                         this->RccListOptions);
+  }
 
-  // Generate info file
-  {
-    std::string const infoDir = GetAutogenTargetFilesDir(target);
-    if (!cmSystemTools::MakeDirectory(infoDir)) {
-      std::string emsg = ("Could not create directory: ");
-      emsg += cmQtAutoGen::Quoted(infoDir);
-      cmSystemTools::Error(emsg.c_str());
-    }
-    std::string const infoFile = infoDir + "/AutogenInfo.cmake";
-    {
-      std::string infoFileIn = cmSystemTools::GetCMakeRoot();
-      infoFileIn += "/Modules/AutogenInfo.cmake.in";
-      makefile->ConfigureFile(infoFileIn.c_str(), infoFile.c_str(), false,
-                              true, false);
-    }
+  // Create info directory on demand
+  if (!cmSystemTools::MakeDirectory(this->DirInfo)) {
+    std::string emsg = ("Could not create directory: ");
+    emsg += cmQtAutoGen::Quoted(this->DirInfo);
+    cmSystemTools::Error(emsg.c_str());
+  }
 
-    // Append custom definitions to info file
-    // --------------------------------------
-
-    // Ensure we have write permission in case .in was read-only.
+  auto ReOpenInfoFile = [](cmsys::ofstream& ofs,
+                           std::string const& fileName) -> bool {
+    // Ensure we have write permission
     mode_t perm = 0;
 #if defined(_WIN32) && !defined(__CYGWIN__)
     mode_t mode_write = S_IWRITE;
 #else
     mode_t mode_write = S_IWUSR;
 #endif
-    cmSystemTools::GetPermissions(infoFile, perm);
+    cmSystemTools::GetPermissions(fileName, perm);
     if (!(perm & mode_write)) {
-      cmSystemTools::SetPermissions(infoFile, perm | mode_write);
+      cmSystemTools::SetPermissions(fileName, perm | mode_write);
     }
 
-    // Open and write file
-    cmsys::ofstream ofs(infoFile.c_str(), std::ios::app);
-    if (ofs) {
+    ofs.open(fileName.c_str(), std::ios::app);
+    if (!ofs) {
+      // File open error
+      std::string error = "Internal CMake error when trying to open file: ";
+      error += cmQtAutoGen::Quoted(fileName);
+      error += " for writing.";
+      cmSystemTools::Error(error.c_str());
+    }
+    return static_cast<bool>(ofs);
+  };
+
+  // Generate autogen target info file
+  if (this->MocEnabled || this->UicEnabled) {
+    {
+      std::string infoFileIn = cmSystemTools::GetCMakeRoot();
+      infoFileIn += "/Modules/AutogenInfo.cmake.in";
+      makefile->ConfigureFile(
+        infoFileIn.c_str(), this->AutogenInfoFile.c_str(), false, true, false);
+    }
+
+    // Append custom definitions to info file
+    // --------------------------------------
+    cmsys::ofstream ofs;
+    if (ReOpenInfoFile(ofs, this->AutogenInfoFile)) {
       auto OfsWriteMap = [&ofs](
         const char* key, std::map<std::string, std::string> const& map) {
         for (auto const& item : map) {
@@ -1211,15 +974,372 @@
       };
       ofs << "# Configurations options\n";
       OfsWriteMap("AM_CONFIG_SUFFIX", configSuffixes);
-      OfsWriteMap("AM_MOC_DEFINITIONS", setup.ConfigMocDefines);
-      OfsWriteMap("AM_MOC_INCLUDES", setup.ConfigMocIncludes);
-      OfsWriteMap("AM_UIC_TARGET_OPTIONS", setup.ConfigUicOptions);
-    } else {
-      // File open error
-      std::string error = "Internal CMake error when trying to open file: ";
-      error += cmQtAutoGen::Quoted(infoFile);
-      error += " for writing.";
-      cmSystemTools::Error(error.c_str());
+      OfsWriteMap("AM_MOC_DEFINITIONS", this->ConfigMocDefines);
+      OfsWriteMap("AM_MOC_INCLUDES", this->ConfigMocIncludes);
+      OfsWriteMap("AM_UIC_TARGET_OPTIONS", this->ConfigUicOptions);
+      // Settings files (only require for multi configuration generators)
+      if (this->MultiConfig != cmQtAutoGen::SINGLE) {
+        std::map<std::string, std::string> settingsFiles;
+        for (std::string const& cfg : this->ConfigsList) {
+          settingsFiles[cfg] = cmQtAutoGen::AppendFilenameSuffix(
+            this->AutogenSettingsFile, "_" + cfg);
+        }
+        OfsWriteMap("AM_SETTINGS_FILE", settingsFiles);
+      }
     }
   }
+
+  // Generate auto RCC info files
+  if (this->RccEnabled) {
+    std::string infoFileIn = cmSystemTools::GetCMakeRoot();
+    infoFileIn += "/Modules/AutoRccInfo.cmake.in";
+    for (Qrc const& qrc : this->Qrcs) {
+      // Configure info file
+      makefile->ConfigureFile(infoFileIn.c_str(), qrc.InfoFile.c_str(), false,
+                              true, false);
+
+      // Append custom definitions to info file
+      // --------------------------------------
+      cmsys::ofstream ofs;
+      if (ReOpenInfoFile(ofs, qrc.InfoFile)) {
+        {
+          ofs << "# Job\n";
+          auto OfsWrite = [&ofs](const char* key, std::string const& value) {
+            ofs << "set(" << key << " "
+                << cmOutputConverter::EscapeForCMake(value) << ")\n";
+
+          };
+          OfsWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile);
+          OfsWrite("ARCC_SOURCE", qrc.QrcFile);
+          OfsWrite("ARCC_OUTPUT", qrc.RccFile);
+          OfsWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";"));
+          OfsWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";"));
+        }
+        {
+          ofs << "# Configurations options\n";
+          auto OfsWriteMap = [&ofs](
+            const char* key, std::map<std::string, std::string> const& map) {
+            for (auto const& item : map) {
+              ofs << "set(" << key << "_" << item.first << " "
+                  << cmOutputConverter::EscapeForCMake(item.second) << ")\n";
+            }
+          };
+          OfsWriteMap("ARCC_CONFIG_SUFFIX", configSuffixes);
+
+          // Settings files (only require for multi configuration generators)
+          if (this->MultiConfig != cmQtAutoGen::SINGLE) {
+            std::map<std::string, std::string> settingsFiles;
+            for (std::string const& cfg : this->ConfigsList) {
+              settingsFiles[cfg] =
+                cmQtAutoGen::AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg);
+            }
+            OfsWriteMap("ARCC_SETTINGS_FILE", settingsFiles);
+          }
+        }
+      } else {
+        break;
+      }
+    }
+  }
+}
+
+void cmQtAutoGeneratorInitializer::SetupCustomTargetsMoc()
+{
+  cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
+  cmMakefile* makefile = this->Target->Target->GetMakefile();
+
+  AddDefinitionEscaped(makefile, "_moc_skip", this->MocSkip);
+  AddDefinitionEscaped(makefile, "_moc_options",
+                       GetSafeProperty(this->Target, "AUTOMOC_MOC_OPTIONS"));
+  AddDefinitionEscaped(makefile, "_moc_relaxed_mode",
+                       makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE"
+                                                                    : "FALSE");
+  AddDefinitionEscaped(makefile, "_moc_macro_names",
+                       GetSafeProperty(this->Target, "AUTOMOC_MACRO_NAMES"));
+  AddDefinitionEscaped(
+    makefile, "_moc_depend_filters",
+    GetSafeProperty(this->Target, "AUTOMOC_DEPEND_FILTERS"));
+
+  // Compiler predefines
+  if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") &&
+      this->QtVersionGreaterOrEqual(5, 8)) {
+    AddDefinitionEscaped(
+      makefile, "_moc_predefs_cmd",
+      makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND"));
+  }
+  // Moc includes and compile definitions
+  {
+    auto GetIncludeDirs = [this,
+                           localGen](std::string const& cfg) -> std::string {
+      // Get the include dirs for this target, without stripping the implicit
+      // include dirs off, see
+      // https://gitlab.kitware.com/cmake/cmake/issues/13667
+      std::vector<std::string> includeDirs;
+      localGen->GetIncludeDirectories(includeDirs, this->Target, "CXX", cfg,
+                                      false);
+      return cmJoin(includeDirs, ";");
+    };
+    auto GetCompileDefinitions =
+      [this, localGen](std::string const& cfg) -> std::string {
+      std::set<std::string> defines;
+      localGen->AddCompileDefinitions(defines, this->Target, cfg, "CXX");
+      return cmJoin(defines, ";");
+    };
+
+    // Default configuration settings
+    std::string const includeDirs = GetIncludeDirs(this->ConfigDefault);
+    std::string const compileDefs = GetCompileDefinitions(this->ConfigDefault);
+    // Other configuration settings
+    for (std::string const& cfg : this->ConfigsList) {
+      {
+        std::string const configIncludeDirs = GetIncludeDirs(cfg);
+        if (configIncludeDirs != includeDirs) {
+          this->ConfigMocIncludes[cfg] = configIncludeDirs;
+        }
+      }
+      {
+        std::string const configCompileDefs = GetCompileDefinitions(cfg);
+        if (configCompileDefs != compileDefs) {
+          this->ConfigMocDefines[cfg] = configCompileDefs;
+        }
+      }
+    }
+    AddDefinitionEscaped(makefile, "_moc_include_dirs", includeDirs);
+    AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs);
+  }
+
+  // Moc executable
+  {
+    std::string mocExec;
+    std::string err;
+
+    if (this->QtVersionMajor == "5") {
+      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::moc");
+      if (tgt != nullptr) {
+        mocExec = SafeString(tgt->ImportedGetLocation(""));
+      } else {
+        err = "AUTOMOC: Qt5::moc target not found";
+      }
+    } else if (this->QtVersionMajor == "4") {
+      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::moc");
+      if (tgt != nullptr) {
+        mocExec = SafeString(tgt->ImportedGetLocation(""));
+      } else {
+        err = "AUTOMOC: Qt4::moc target not found";
+      }
+    } else {
+      err = "The AUTOMOC feature supports only Qt 4 and Qt 5";
+    }
+
+    if (err.empty()) {
+      AddDefinitionEscaped(makefile, "_qt_moc_executable", mocExec);
+    } else {
+      err += " (";
+      err += this->Target->GetName();
+      err += ")";
+      cmSystemTools::Error(err.c_str());
+    }
+  }
+}
+
+void cmQtAutoGeneratorInitializer::SetupCustomTargetsUic()
+{
+  cmMakefile* makefile = this->Target->Target->GetMakefile();
+
+  // Uic search paths
+  {
+    std::vector<std::string> uicSearchPaths;
+    {
+      std::string const usp =
+        GetSafeProperty(this->Target, "AUTOUIC_SEARCH_PATHS");
+      if (!usp.empty()) {
+        cmSystemTools::ExpandListArgument(usp, uicSearchPaths);
+        std::string const srcDir = makefile->GetCurrentSourceDirectory();
+        for (std::string& path : uicSearchPaths) {
+          path = cmSystemTools::CollapseFullPath(path, srcDir);
+        }
+      }
+    }
+    AddDefinitionEscaped(makefile, "_uic_search_paths", uicSearchPaths);
+  }
+  // Uic target options
+  {
+    auto UicGetOpts = [this](std::string const& cfg) -> std::string {
+      std::vector<std::string> opts;
+      this->Target->GetAutoUicOptions(opts, cfg);
+      return cmJoin(opts, ";");
+    };
+
+    // Default settings
+    std::string const uicOpts = UicGetOpts(this->ConfigDefault);
+    AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts);
+
+    // Configuration specific settings
+    for (std::string const& cfg : this->ConfigsList) {
+      std::string const configUicOpts = UicGetOpts(cfg);
+      if (configUicOpts != uicOpts) {
+        this->ConfigUicOptions[cfg] = configUicOpts;
+      }
+    }
+  }
+  // .ui files skip and options
+  {
+    std::vector<std::string> uiFileFiles;
+    std::vector<std::vector<std::string>> uiFileOptions;
+    {
+      std::string const uiExt = "ui";
+      for (cmSourceFile* sf : makefile->GetSourceFiles()) {
+        // sf->GetExtension() is only valid after sf->GetFullPath() ...
+        std::string const& fPath = sf->GetFullPath();
+        if (sf->GetExtension() == uiExt) {
+          std::string const absFile = cmSystemTools::GetRealPath(fPath);
+          // Check if the .ui file should be skipped
+          if (sf->GetPropertyAsBool("SKIP_AUTOUIC") ||
+              sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
+            this->UicSkip.insert(absFile);
+          }
+          // Check if the .ui file has uic options
+          std::string const uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS");
+          if (!uicOpts.empty()) {
+            // Check if file isn't skipped
+            if (this->UicSkip.count(absFile) == 0) {
+              uiFileFiles.push_back(absFile);
+              std::vector<std::string> optsVec;
+              cmSystemTools::ExpandListArgument(uicOpts, optsVec);
+              uiFileOptions.push_back(std::move(optsVec));
+            }
+          }
+        }
+      }
+    }
+    AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles);
+    AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions);
+  }
+
+  AddDefinitionEscaped(makefile, "_uic_skip", this->UicSkip);
+
+  // Uic executable
+  {
+    std::string err;
+    std::string uicExec;
+
+    cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
+    if (this->QtVersionMajor == "5") {
+      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::uic");
+      if (tgt != nullptr) {
+        uicExec = SafeString(tgt->ImportedGetLocation(""));
+      } else {
+        // Project does not use Qt5Widgets, but has AUTOUIC ON anyway
+      }
+    } else if (this->QtVersionMajor == "4") {
+      cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::uic");
+      if (tgt != nullptr) {
+        uicExec = SafeString(tgt->ImportedGetLocation(""));
+      } else {
+        err = "AUTOUIC: Qt4::uic target not found";
+      }
+    } else {
+      err = "The AUTOUIC feature supports only Qt 4 and Qt 5";
+    }
+
+    if (err.empty()) {
+      AddDefinitionEscaped(makefile, "_qt_uic_executable", uicExec);
+    } else {
+      err += " (";
+      err += this->Target->GetName();
+      err += ")";
+      cmSystemTools::Error(err.c_str());
+    }
+  }
+}
+
+std::vector<std::string> cmQtAutoGeneratorInitializer::AddGeneratedSource(
+  std::string const& filename, cmQtAutoGen::Generator genType)
+{
+  std::vector<std::string> genFiles;
+  // Register source file in makefile and source group
+  if (this->MultiConfig != cmQtAutoGen::FULL) {
+    genFiles.push_back(filename);
+  } else {
+    for (std::string const& cfg : this->ConfigsList) {
+      genFiles.push_back(
+        cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg));
+    }
+  }
+  {
+    cmMakefile* makefile = this->Target->Target->GetMakefile();
+    for (std::string const& genFile : genFiles) {
+      {
+        cmSourceFile* gFile = makefile->GetOrCreateSource(genFile, true);
+        gFile->SetProperty("GENERATED", "1");
+        gFile->SetProperty("SKIP_AUTOGEN", "On");
+      }
+      AddToSourceGroup(makefile, genFile, genType);
+    }
+  }
+
+  // Add source file to target
+  if (this->MultiConfig != cmQtAutoGen::FULL) {
+    this->Target->AddSource(filename);
+  } else {
+    for (std::string const& cfg : this->ConfigsList) {
+      std::string src = "$<$<CONFIG:";
+      src += cfg;
+      src += ">:";
+      src += cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg);
+      src += ">";
+      this->Target->AddSource(src);
+    }
+  }
+
+  return genFiles;
+}
+
+std::string cmQtAutoGeneratorInitializer::GetQtMajorVersion(
+  cmGeneratorTarget const* target)
+{
+  cmMakefile* makefile = target->Target->GetMakefile();
+  std::string qtMajor = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
+  if (qtMajor.empty()) {
+    qtMajor = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
+  }
+  const char* targetQtVersion =
+    target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", "");
+  if (targetQtVersion != nullptr) {
+    qtMajor = targetQtVersion;
+  }
+  return qtMajor;
+}
+
+std::string cmQtAutoGeneratorInitializer::GetQtMinorVersion(
+  cmGeneratorTarget const* target, std::string const& qtVersionMajor)
+{
+  cmMakefile* makefile = target->Target->GetMakefile();
+  std::string qtMinor;
+  if (qtVersionMajor == "5") {
+    qtMinor = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR");
+  }
+  if (qtMinor.empty()) {
+    qtMinor = makefile->GetSafeDefinition("QT_VERSION_MINOR");
+  }
+
+  const char* targetQtVersion =
+    target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", "");
+  if (targetQtVersion != nullptr) {
+    qtMinor = targetQtVersion;
+  }
+  return qtMinor;
+}
+
+bool cmQtAutoGeneratorInitializer::QtVersionGreaterOrEqual(
+  unsigned long requestMajor, unsigned long requestMinor) const
+{
+  unsigned long majorUL(0);
+  unsigned long minorUL(0);
+  if (cmSystemTools::StringToULong(this->QtVersionMajor.c_str(), &majorUL) &&
+      cmSystemTools::StringToULong(this->QtVersionMinor.c_str(), &minorUL)) {
+    return (majorUL > requestMajor) ||
+      (majorUL == requestMajor && minorUL >= requestMinor);
+  }
+  return false;
 }
diff --git a/Source/cmQtAutoGeneratorInitializer.h b/Source/cmQtAutoGeneratorInitializer.h
index b8a5ae4..e06e1c4 100644
--- a/Source/cmQtAutoGeneratorInitializer.h
+++ b/Source/cmQtAutoGeneratorInitializer.h
@@ -4,9 +4,12 @@
 #define cmQtAutoGeneratorInitializer_h
 
 #include "cmConfigure.h" // IWYU pragma: keep
-#include "cmQtAutoGenDigest.h"
+#include "cmQtAutoGen.h"
 
+#include <map>
+#include <set>
 #include <string>
+#include <vector>
 
 class cmGeneratorTarget;
 
@@ -17,8 +20,78 @@
   static std::string GetQtMinorVersion(cmGeneratorTarget const* target,
                                        std::string const& qtVersionMajor);
 
-  static void InitializeAutogenTarget(cmQtAutoGenDigest& digest);
-  static void SetupAutoGenerateTarget(cmQtAutoGenDigest const& digest);
+  class Qrc
+  {
+  public:
+    Qrc()
+      : Generated(false)
+      , Unique(false)
+    {
+    }
+
+  public:
+    std::string QrcFile;
+    std::string QrcName;
+    std::string PathChecksum;
+    std::string InfoFile;
+    std::string SettingsFile;
+    std::string RccFile;
+    bool Generated;
+    bool Unique;
+    std::vector<std::string> Options;
+    std::vector<std::string> Resources;
+  };
+
+public:
+  cmQtAutoGeneratorInitializer(cmGeneratorTarget* target, bool mocEnabled,
+                               bool uicEnabled, bool rccEnabled,
+                               std::string const& qtVersionMajor);
+
+  void InitCustomTargets();
+  void SetupCustomTargets();
+
+private:
+  void SetupCustomTargetsMoc();
+  void SetupCustomTargetsUic();
+
+  std::vector<std::string> AddGeneratedSource(std::string const& filename,
+                                              cmQtAutoGen::Generator genType);
+
+  bool QtVersionGreaterOrEqual(unsigned long requestMajor,
+                               unsigned long requestMinor) const;
+
+private:
+  cmGeneratorTarget* Target;
+  bool MocEnabled;
+  bool UicEnabled;
+  bool RccEnabled;
+  // Qt
+  std::string QtVersionMajor;
+  std::string QtVersionMinor;
+  std::string RccExecutable;
+  std::vector<std::string> RccListOptions;
+  // Configurations
+  std::string ConfigDefault;
+  std::vector<std::string> ConfigsList;
+  cmQtAutoGen::MultiConfig MultiConfig;
+  // Names
+  std::string AutogenTargetName;
+  std::string AutogenFolder;
+  std::string AutogenInfoFile;
+  std::string AutogenSettingsFile;
+  // Directories
+  std::string DirInfo;
+  std::string DirBuild;
+  std::string DirWork;
+  // Sources
+  std::vector<std::string> Headers;
+  std::vector<std::string> Sources;
+  std::set<std::string> MocSkip;
+  std::set<std::string> UicSkip;
+  std::map<std::string, std::string> ConfigMocIncludes;
+  std::map<std::string, std::string> ConfigMocDefines;
+  std::map<std::string, std::string> ConfigUicOptions;
+  std::vector<Qrc> Qrcs;
 };
 
 #endif
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGeneratorMocUic.cxx
similarity index 69%
rename from Source/cmQtAutoGenerators.cxx
rename to Source/cmQtAutoGeneratorMocUic.cxx
index b329d38..0de02b5 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGeneratorMocUic.cxx
@@ -1,10 +1,8 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmQtAutoGen.h"
-#include "cmQtAutoGenerators.h"
+#include "cmQtAutoGeneratorMocUic.h"
 
-#include "cmsys/FStream.hxx"
-#include "cmsys/Terminal.h"
 #include <algorithm>
 #include <array>
 #include <list>
@@ -15,12 +13,8 @@
 
 #include "cmAlgorithms.h"
 #include "cmCryptoHash.h"
-#include "cmFilePathChecksum.h"
-#include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
 #include "cmOutputConverter.h"
-#include "cmStateDirectory.h"
-#include "cmStateSnapshot.h"
 #include "cmSystemTools.h"
 #include "cmake.h"
 
@@ -32,37 +26,9 @@
 
 static const char* SettingsKeyMoc = "AM_MOC_SETTINGS_HASH";
 static const char* SettingsKeyUic = "AM_UIC_SETTINGS_HASH";
-static const char* SettingsKeyRcc = "AM_RCC_SETTINGS_HASH";
 
 // -- Static functions
 
-static std::string HeadLine(std::string const& title)
-{
-  std::string head = title;
-  head += '\n';
-  head.append(head.size() - 1, '-');
-  head += '\n';
-  return head;
-}
-
-static std::string QuotedCommand(std::vector<std::string> const& command)
-{
-  std::string res;
-  for (std::string const& item : command) {
-    if (!res.empty()) {
-      res.push_back(' ');
-    }
-    std::string const cesc = cmQtAutoGen::Quoted(item);
-    if (item.empty() || (cesc.size() > (item.size() + 2)) ||
-        (cesc.find(' ') != std::string::npos)) {
-      res += cesc;
-    } else {
-      res += item;
-    }
-  }
-  return res;
-}
-
 static std::string SubDirPrefix(std::string const& fileName)
 {
   std::string res(cmSystemTools::GetFilenamePath(fileName));
@@ -72,56 +38,6 @@
   return res;
 }
 
-static bool ReadFile(std::string& content, std::string const& filename,
-                     std::string* error = nullptr)
-{
-  bool success = false;
-  if (cmSystemTools::FileExists(filename)) {
-    std::size_t const length = cmSystemTools::FileLength(filename);
-    cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary));
-    if (ifs) {
-      content.resize(length);
-      ifs.read(&content.front(), content.size());
-      if (ifs) {
-        success = true;
-      } else {
-        content.clear();
-        if (error != nullptr) {
-          error->append("Reading from the file failed.");
-        }
-      }
-    } else if (error != nullptr) {
-      error->append("Opening the file for reading failed.");
-    }
-  } else if (error != nullptr) {
-    error->append("The file does not exist.");
-  }
-  return success;
-}
-
-/**
- * @brief Tests if buildFile is older than sourceFile
- * @return True if buildFile  is older than sourceFile.
- *         False may indicate an error.
- */
-static bool FileIsOlderThan(std::string const& buildFile,
-                            std::string const& sourceFile,
-                            std::string* error = nullptr)
-{
-  int result = 0;
-  if (cmSystemTools::FileTimeCompare(buildFile, sourceFile, &result)) {
-    return (result < 0);
-  }
-  if (error != nullptr) {
-    error->append(
-      "File modification time comparison failed for the files\n  ");
-    error->append(cmQtAutoGen::Quoted(buildFile));
-    error->append("\nand\n  ");
-    error->append(cmQtAutoGen::Quoted(sourceFile));
-  }
-  return false;
-}
-
 static bool ListContains(std::vector<std::string> const& list,
                          std::string const& entry)
 {
@@ -130,25 +46,15 @@
 
 // -- Class methods
 
-cmQtAutoGenerators::cmQtAutoGenerators()
+cmQtAutoGeneratorMocUic::cmQtAutoGeneratorMocUic()
   : MultiConfig(cmQtAutoGen::WRAP)
   , IncludeProjectDirsBefore(false)
-  , Verbose(cmSystemTools::HasEnv("VERBOSE"))
-  , ColorOutput(true)
+  , QtVersionMajor(4)
   , MocSettingsChanged(false)
   , MocPredefsChanged(false)
   , MocRelaxedMode(false)
   , UicSettingsChanged(false)
-  , RccSettingsChanged(false)
 {
-  {
-    std::string colorEnv;
-    cmSystemTools::GetEnv("COLOR", colorEnv);
-    if (!colorEnv.empty()) {
-      this->ColorOutput = cmSystemTools::IsOn(colorEnv.c_str());
-    }
-  }
-
   // Precompile regular expressions
   this->MocRegExpInclude.compile(
     "[\n][ \t]*#[ \t]*include[ \t]+"
@@ -157,39 +63,7 @@
                                  "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
 }
 
-bool cmQtAutoGenerators::Run(std::string const& targetDirectory,
-                             std::string const& config)
-{
-  cmake cm(cmake::RoleScript);
-  cm.SetHomeOutputDirectory(targetDirectory);
-  cm.SetHomeDirectory(targetDirectory);
-  cm.GetCurrentSnapshot().SetDefaultDefinitions();
-  cmGlobalGenerator gg(&cm);
-
-  cmStateSnapshot snapshot = cm.GetCurrentSnapshot();
-  snapshot.GetDirectory().SetCurrentBinary(targetDirectory);
-  snapshot.GetDirectory().SetCurrentSource(targetDirectory);
-
-  auto makefile = cm::make_unique<cmMakefile>(&gg, snapshot);
-  gg.SetCurrentMakefile(makefile.get());
-
-  bool success = false;
-  if (this->InitInfoFile(makefile.get(), targetDirectory, config)) {
-    // Read latest settings
-    this->SettingsFileRead(makefile.get());
-    if (this->Process()) {
-      // Write current settings
-      if (this->SettingsFileWrite()) {
-        success = true;
-      }
-    }
-  }
-  return success;
-}
-
-bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile,
-                                      std::string const& targetDirectory,
-                                      std::string const& config)
+bool cmQtAutoGeneratorMocUic::InitInfoFile(cmMakefile* makefile)
 {
   // -- Meta
   this->HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions();
@@ -233,12 +107,12 @@
     }
     return lists;
   };
-  auto InfoGetConfig = [makefile, &config](const char* key) -> std::string {
+  auto InfoGetConfig = [makefile, this](const char* key) -> std::string {
     const char* valueConf = nullptr;
     {
       std::string keyConf = key;
       keyConf += '_';
-      keyConf += config;
+      keyConf += this->GetInfoConfig();
       valueConf = makefile->GetDefinition(keyConf);
     }
     if (valueConf == nullptr) {
@@ -254,11 +128,8 @@
   };
 
   // -- Read info file
-  this->InfoFile = cmSystemTools::CollapseFullPath(targetDirectory);
-  cmSystemTools::ConvertToUnixSlashes(this->InfoFile);
-  this->InfoFile += "/AutogenInfo.cmake";
-  if (!makefile->ReadListFile(this->InfoFile.c_str())) {
-    this->LogFileError(cmQtAutoGen::GEN, this->InfoFile,
+  if (!makefile->ReadListFile(this->GetInfoFile().c_str())) {
+    this->LogFileError(cmQtAutoGen::GEN, this->GetInfoFile(),
                        "File processing failed");
     return false;
   }
@@ -268,7 +139,14 @@
   this->ConfigSuffix = InfoGetConfig("AM_CONFIG_SUFFIX");
   if (this->ConfigSuffix.empty()) {
     this->ConfigSuffix = "_";
-    this->ConfigSuffix += config;
+    this->ConfigSuffix += this->GetInfoConfig();
+  }
+
+  this->SettingsFile = InfoGetConfig("AM_SETTINGS_FILE");
+  if (this->SettingsFile.empty()) {
+    this->LogFileError(cmQtAutoGen::GEN, this->GetInfoFile(),
+                       "Settings file name missing");
+    return false;
   }
 
   // - Files and directories
@@ -280,25 +158,18 @@
     InfoGetBool("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE");
   this->AutogenBuildDir = InfoGet("AM_BUILD_DIR");
   if (this->AutogenBuildDir.empty()) {
-    this->LogFileError(cmQtAutoGen::GEN, this->InfoFile,
+    this->LogFileError(cmQtAutoGen::GEN, this->GetInfoFile(),
                        "Autogen build directory missing");
     return false;
   }
 
   // - Qt environment
-  this->QtMajorVersion = InfoGet("AM_QT_VERSION_MAJOR");
-  this->QtMinorVersion = InfoGet("AM_QT_VERSION_MINOR");
+  if (!cmSystemTools::StringToULong(InfoGet("AM_QT_VERSION_MAJOR"),
+                                    &this->QtVersionMajor)) {
+    this->QtVersionMajor = 4;
+  }
   this->MocExecutable = InfoGet("AM_QT_MOC_EXECUTABLE");
   this->UicExecutable = InfoGet("AM_QT_UIC_EXECUTABLE");
-  this->RccExecutable = InfoGet("AM_QT_RCC_EXECUTABLE");
-
-  // Check Qt version
-  if ((this->QtMajorVersion != "4") && (this->QtMajorVersion != "5")) {
-    this->LogFileError(cmQtAutoGen::GEN, this->InfoFile,
-                       "Unsupported Qt version: " +
-                         cmQtAutoGen::Quoted(this->QtMajorVersion));
-    return false;
-  }
 
   // - Moc
   if (this->MocEnabled()) {
@@ -327,7 +198,7 @@
       std::vector<std::string> const mocDependFilters =
         InfoGetList("AM_MOC_DEPEND_FILTERS");
       // Insert Q_PLUGIN_METADATA dependency filter
-      if (this->QtMajorVersion != "4") {
+      if (this->QtVersionMajor != 4) {
         this->MocDependFilterPush("Q_PLUGIN_METADATA",
                                   "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\("
                                   "[^\\)]*FILE[ \t]*\"([^\"]+)\"");
@@ -344,7 +215,7 @@
         }
       } else {
         this->LogFileError(
-          cmQtAutoGen::MOC, this->InfoFile,
+          cmQtAutoGen::MOC, this->GetInfoFile(),
           "AUTOMOC_DEPEND_FILTERS list size is not a multiple of 2");
         return false;
       }
@@ -365,7 +236,7 @@
         std::ostringstream ost;
         ost << "files/options lists sizes missmatch (" << sources.size() << "/"
             << options.size() << ")";
-        this->LogFileError(cmQtAutoGen::UIC, this->InfoFile, ost.str());
+        this->LogFileError(cmQtAutoGen::UIC, this->GetInfoFile(), ost.str());
         return false;
       }
       auto fitEnd = sources.cend();
@@ -379,53 +250,6 @@
     }
   }
 
-  // - Rcc
-  if (this->RccEnabled()) {
-    // File lists
-    auto sources = InfoGetList("AM_RCC_SOURCES");
-    auto builds = InfoGetList("AM_RCC_BUILDS");
-    auto options = InfoGetLists("AM_RCC_OPTIONS");
-    auto inputs = InfoGetLists("AM_RCC_INPUTS");
-
-    if (sources.size() != builds.size()) {
-      std::ostringstream ost;
-      ost << "sources, builds lists sizes missmatch (" << sources.size() << "/"
-          << builds.size() << ")";
-      this->LogFileError(cmQtAutoGen::RCC, this->InfoFile, ost.str());
-      return false;
-    }
-    if (sources.size() != options.size()) {
-      std::ostringstream ost;
-      ost << "sources, options lists sizes missmatch (" << sources.size()
-          << "/" << options.size() << ")";
-      this->LogFileError(cmQtAutoGen::RCC, this->InfoFile, ost.str());
-      return false;
-    }
-    if (sources.size() != inputs.size()) {
-      std::ostringstream ost;
-      ost << "sources, inputs lists sizes missmatch (" << sources.size() << "/"
-          << inputs.size() << ")";
-      this->LogFileError(cmQtAutoGen::RCC, this->InfoFile, ost.str());
-      return false;
-    }
-    {
-      auto srcItEnd = sources.end();
-      auto srcIt = sources.begin();
-      auto bldIt = builds.begin();
-      auto optIt = options.begin();
-      auto inpIt = inputs.begin();
-      while (srcIt != srcItEnd) {
-        this->RccJobs.push_back(RccJob{ std::move(*srcIt), std::move(*bldIt),
-                                        std::move(*optIt),
-                                        std::move(*inpIt) });
-        ++srcIt;
-        ++bldIt;
-        ++optIt;
-        ++inpIt;
-      }
-    }
-  }
-
   // Initialize source file jobs
   {
     // Utility lambdas
@@ -585,21 +409,10 @@
     }
   }
 
-  // - Old settings file
-  {
-    this->SettingsFile = cmSystemTools::CollapseFullPath(targetDirectory);
-    cmSystemTools::ConvertToUnixSlashes(this->SettingsFile);
-    this->SettingsFile += "/AutogenOldSettings";
-    if (this->MultiConfig != cmQtAutoGen::SINGLE) {
-      this->SettingsFile += this->ConfigSuffix;
-    }
-    this->SettingsFile += ".cmake";
-  }
-
   return true;
 }
 
-void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile)
+void cmQtAutoGeneratorMocUic::SettingsFileRead(cmMakefile* makefile)
 {
   // Compose current settings strings
   {
@@ -631,20 +444,6 @@
       str += sep;
       this->SettingsStringUic = crypt.HashString(str);
     }
-    if (this->RccEnabled()) {
-      std::string str;
-      str += this->RccExecutable;
-      for (const RccJob& rccJob : this->RccJobs) {
-        str += sep;
-        str += rccJob.QrcFile;
-        str += sep;
-        str += rccJob.RccFile;
-        str += sep;
-        str += cmJoin(rccJob.Options, ";");
-      }
-      str += sep;
-      this->SettingsStringRcc = crypt.HashString(str);
-    }
   }
 
   // Read old settings
@@ -659,9 +458,6 @@
       if (!SMatch(SettingsKeyUic, this->SettingsStringUic)) {
         this->UicSettingsChanged = true;
       }
-      if (!SMatch(SettingsKeyRcc, this->SettingsStringRcc)) {
-        this->RccSettingsChanged = true;
-      }
     }
     // In case any setting changed remove the old settings file.
     // This triggers a full rebuild on the next run if the current
@@ -673,16 +469,15 @@
     // If the file could not be read re-generate everythiung.
     this->MocSettingsChanged = true;
     this->UicSettingsChanged = true;
-    this->RccSettingsChanged = true;
   }
 }
 
-bool cmQtAutoGenerators::SettingsFileWrite()
+bool cmQtAutoGeneratorMocUic::SettingsFileWrite()
 {
   bool success = true;
   // Only write if any setting changed
   if (this->SettingsChanged()) {
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       this->LogInfo(cmQtAutoGen::GEN, "Writing settings file " +
                       cmQtAutoGen::Quoted(this->SettingsFile));
     }
@@ -699,7 +494,6 @@
       };
       SettingAppend(SettingsKeyMoc, this->SettingsStringMoc);
       SettingAppend(SettingsKeyUic, this->SettingsStringUic);
-      SettingAppend(SettingsKeyRcc, this->SettingsStringRcc);
     }
     // Write settings file
     if (!this->FileWrite(cmQtAutoGen::GEN, this->SettingsFile, settings)) {
@@ -713,7 +507,7 @@
   return success;
 }
 
-bool cmQtAutoGenerators::Process()
+bool cmQtAutoGeneratorMocUic::Process(cmMakefile* makefile)
 {
   // the program goes through all .cpp files to see which moc files are
   // included. It is not really interesting how the moc file is named, but
@@ -723,6 +517,12 @@
   // moc file is included anywhere a moc_<filename>.cpp file is created and
   // included in the mocs_compilation.cpp file.
 
+  if (!this->InitInfoFile(makefile)) {
+    return false;
+  }
+  // Read latest settings
+  this->SettingsFileRead(makefile);
+
   // Create AUTOGEN include directory
   {
     std::string const incDirAbs = cmSystemTools::CollapseCombinedPath(
@@ -758,7 +558,8 @@
   if (!this->UicGenerateAll()) {
     return false;
   }
-  if (!this->RccGenerateAll()) {
+
+  if (!this->SettingsFileWrite()) {
     return false;
   }
 
@@ -768,12 +569,12 @@
 /**
  * @return True on success
  */
-bool cmQtAutoGenerators::ParseSourceFile(std::string const& absFilename,
-                                         const SourceJob& job)
+bool cmQtAutoGeneratorMocUic::ParseSourceFile(std::string const& absFilename,
+                                              const SourceJob& job)
 {
   std::string contentText;
   std::string error;
-  bool success = ReadFile(contentText, absFilename, &error);
+  bool success = this->FileRead(contentText, absFilename, &error);
   if (success) {
     if (!contentText.empty()) {
       if (job.Moc) {
@@ -796,12 +597,12 @@
 /**
  * @return True on success
  */
-bool cmQtAutoGenerators::ParseHeaderFile(std::string const& absFilename,
-                                         const SourceJob& job)
+bool cmQtAutoGeneratorMocUic::ParseHeaderFile(std::string const& absFilename,
+                                              const SourceJob& job)
 {
   std::string contentText;
   std::string error;
-  bool success = ReadFile(contentText, absFilename, &error);
+  bool success = this->FileRead(contentText, absFilename, &error);
   if (success) {
     if (!contentText.empty()) {
       if (job.Moc) {
@@ -824,15 +625,15 @@
 /**
  * @return True on success
  */
-bool cmQtAutoGenerators::ParsePostprocess()
+bool cmQtAutoGeneratorMocUic::ParsePostprocess()
 {
   bool success = true;
-  // Read missin dependecies
+  // Read missing dependencies
   for (auto& item : this->MocJobsIncluded) {
     if (!item->DependsValid) {
       std::string content;
       std::string error;
-      if (ReadFile(content, item->SourceFile, &error)) {
+      if (this->FileRead(content, item->SourceFile, &error)) {
         this->MocFindDepends(item->SourceFile, content, item->Depends);
         item->DependsValid = true;
       } else {
@@ -855,7 +656,7 @@
  * @brief Tests if the file should be ignored for moc scanning
  * @return True if the file should be ignored
  */
-bool cmQtAutoGenerators::MocSkip(std::string const& absFilename) const
+bool cmQtAutoGeneratorMocUic::MocSkip(std::string const& absFilename) const
 {
   if (this->MocEnabled()) {
     // Test if the file name is on the skip list
@@ -870,8 +671,8 @@
  * @brief Tests if the C++ content requires moc processing
  * @return True if moc is required
  */
-bool cmQtAutoGenerators::MocRequired(std::string const& contentText,
-                                     std::string* macroName)
+bool cmQtAutoGeneratorMocUic::MocRequired(std::string const& contentText,
+                                          std::string* macroName)
 {
   for (KeyRegExp& filter : this->MocMacroFilters) {
     // Run a simple find string operation before the expensive
@@ -889,7 +690,7 @@
   return false;
 }
 
-std::string cmQtAutoGenerators::MocStringMacros() const
+std::string cmQtAutoGeneratorMocUic::MocStringMacros() const
 {
   std::string res;
   const auto itB = this->MocMacroFilters.cbegin();
@@ -911,7 +712,7 @@
   return res;
 }
 
-std::string cmQtAutoGenerators::MocStringHeaders(
+std::string cmQtAutoGeneratorMocUic::MocStringHeaders(
   std::string const& fileBase) const
 {
   std::string res = fileBase;
@@ -921,7 +722,7 @@
   return res;
 }
 
-std::string cmQtAutoGenerators::MocFindIncludedHeader(
+std::string cmQtAutoGeneratorMocUic::MocFindIncludedHeader(
   std::string const& sourcePath, std::string const& includeBase) const
 {
   std::string header;
@@ -944,7 +745,7 @@
   return header;
 }
 
-bool cmQtAutoGenerators::MocFindIncludedFile(
+bool cmQtAutoGeneratorMocUic::MocFindIncludedFile(
   std::string& absFile, std::string const& sourcePath,
   std::string const& includeString) const
 {
@@ -974,8 +775,8 @@
   return success;
 }
 
-bool cmQtAutoGenerators::MocDependFilterPush(std::string const& key,
-                                             std::string const& regExp)
+bool cmQtAutoGeneratorMocUic::MocDependFilterPush(std::string const& key,
+                                                  std::string const& regExp)
 {
   std::string error;
   if (!key.empty()) {
@@ -1009,9 +810,9 @@
   return true;
 }
 
-void cmQtAutoGenerators::MocFindDepends(std::string const& absFilename,
-                                        std::string const& contentText,
-                                        std::set<std::string>& depends)
+void cmQtAutoGeneratorMocUic::MocFindDepends(std::string const& absFilename,
+                                             std::string const& contentText,
+                                             std::set<std::string>& depends)
 {
   if (this->MocDependFilters.empty() && contentText.empty()) {
     return;
@@ -1040,7 +841,7 @@
       std::string incFile;
       if (this->MocFindIncludedFile(incFile, sourcePath, match)) {
         depends.insert(incFile);
-        if (this->Verbose) {
+        if (this->GetVerbose()) {
           this->LogInfo(cmQtAutoGen::MOC, "Found dependency:\n  " +
                           cmQtAutoGen::Quoted(absFilename) + "\n  " +
                           cmQtAutoGen::Quoted(incFile));
@@ -1057,10 +858,10 @@
 /**
  * @return True on success
  */
-bool cmQtAutoGenerators::MocParseSourceContent(std::string const& absFilename,
-                                               std::string const& contentText)
+bool cmQtAutoGeneratorMocUic::MocParseSourceContent(
+  std::string const& absFilename, std::string const& contentText)
 {
-  if (this->Verbose) {
+  if (this->GetVerbose()) {
     this->LogInfo(cmQtAutoGen::MOC, "Checking: " + absFilename);
   }
 
@@ -1296,10 +1097,10 @@
   return true;
 }
 
-void cmQtAutoGenerators::MocParseHeaderContent(std::string const& absFilename,
-                                               std::string const& contentText)
+void cmQtAutoGeneratorMocUic::MocParseHeaderContent(
+  std::string const& absFilename, std::string const& contentText)
 {
-  if (this->Verbose) {
+  if (this->GetVerbose()) {
     this->LogInfo(cmQtAutoGen::MOC, "Checking: " + absFilename);
   }
 
@@ -1329,7 +1130,7 @@
   }
 }
 
-bool cmQtAutoGenerators::MocGenerateAll()
+bool cmQtAutoGeneratorMocUic::MocGenerateAll()
 {
   if (!this->MocEnabled()) {
     return true;
@@ -1384,7 +1185,7 @@
   if (!this->MocPredefsCmd.empty()) {
     if (this->MocSettingsChanged ||
         !cmSystemTools::FileExists(this->MocPredefsFileAbs)) {
-      if (this->Verbose) {
+      if (this->GetVerbose()) {
         this->LogBold("Generating MOC predefs " + this->MocPredefsFileRel);
       }
 
@@ -1419,7 +1220,7 @@
         }
       } else {
         // Touch to update the time stamp
-        if (this->Verbose) {
+        if (this->GetVerbose()) {
           this->LogInfo(cmQtAutoGen::MOC,
                         "Touching moc_predefs " + this->MocPredefsFileRel);
         }
@@ -1427,7 +1228,7 @@
       }
     }
 
-    // Add moc_predefs.h to moc file dependecies
+    // Add moc_predefs.h to moc file dependencies
     for (auto const& item : this->MocJobsIncluded) {
       item->Depends.insert(this->MocPredefsFileAbs);
     }
@@ -1470,7 +1271,7 @@
 
     if (this->FileDiffers(this->MocCompFileAbs, mocs)) {
       // Actually write mocs compilation file
-      if (this->Verbose) {
+      if (this->GetVerbose()) {
         this->LogBold("Generating MOC compilation " + this->MocCompFileRel);
       }
       if (!this->FileWrite(cmQtAutoGen::MOC, this->MocCompFileAbs, mocs)) {
@@ -1480,7 +1281,7 @@
       }
     } else if (autoNameGenerated) {
       // Only touch mocs compilation file
-      if (this->Verbose) {
+      if (this->GetVerbose()) {
         this->LogInfo(cmQtAutoGen::MOC,
                       "Touching mocs compilation " + this->MocCompFileRel);
       }
@@ -1494,8 +1295,8 @@
 /**
  * @return True on success
  */
-bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob,
-                                         bool* generated)
+bool cmQtAutoGeneratorMocUic::MocGenerateFile(const MocJobAuto& mocJob,
+                                              bool* generated)
 {
   bool success = true;
 
@@ -1505,7 +1306,7 @@
   bool generate = false;
   std::string generateReason;
   if (!generate && !cmSystemTools::FileExists(mocFileAbs.c_str())) {
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       generateReason = "Generating ";
       generateReason += cmQtAutoGen::Quoted(mocFileAbs);
       generateReason += " from its source file ";
@@ -1515,7 +1316,7 @@
     generate = true;
   }
   if (!generate && this->MocSettingsChanged) {
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       generateReason = "Generating ";
       generateReason += cmQtAutoGen::Quoted(mocFileAbs);
       generateReason += " from ";
@@ -1525,7 +1326,7 @@
     generate = true;
   }
   if (!generate && this->MocPredefsChanged) {
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       generateReason = "Generating ";
       generateReason += cmQtAutoGen::Quoted(mocFileAbs);
       generateReason += " from ";
@@ -1537,7 +1338,7 @@
   if (!generate) {
     std::string error;
     if (FileIsOlderThan(mocFileAbs, mocJob.SourceFile, &error)) {
-      if (this->Verbose) {
+      if (this->GetVerbose()) {
         generateReason = "Generating ";
         generateReason += cmQtAutoGen::Quoted(mocFileAbs);
         generateReason += " because it's older than its source file ";
@@ -1556,7 +1357,7 @@
     std::string error;
     for (std::string const& depFile : mocJob.Depends) {
       if (FileIsOlderThan(mocFileAbs, depFile, &error)) {
-        if (this->Verbose) {
+        if (this->GetVerbose()) {
           generateReason = "Generating ";
           generateReason += cmQtAutoGen::Quoted(mocFileAbs);
           generateReason += " from ";
@@ -1577,7 +1378,7 @@
 
   if (generate) {
     // Log
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       this->LogBold("Generating MOC source " + mocJob.BuildFileRel);
       this->LogInfo(cmQtAutoGen::MOC, generateReason);
     }
@@ -1627,7 +1428,7 @@
 /**
  * @brief Tests if the file name is in the skip list
  */
-bool cmQtAutoGenerators::UicSkip(std::string const& absFilename) const
+bool cmQtAutoGeneratorMocUic::UicSkip(std::string const& absFilename) const
 {
   if (this->UicEnabled()) {
     // Test if the file name is on the skip list
@@ -1638,10 +1439,10 @@
   return true;
 }
 
-bool cmQtAutoGenerators::UicParseContent(std::string const& absFilename,
-                                         std::string const& contentText)
+bool cmQtAutoGeneratorMocUic::UicParseContent(std::string const& absFilename,
+                                              std::string const& contentText)
 {
-  if (this->Verbose) {
+  if (this->GetVerbose()) {
     this->LogInfo(cmQtAutoGen::UIC, "Checking: " + absFilename);
   }
 
@@ -1689,9 +1490,9 @@
   return true;
 }
 
-bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile,
-                                             std::string const& sourceFile,
-                                             std::string const& includeString)
+bool cmQtAutoGeneratorMocUic::UicFindIncludedFile(
+  std::string& absFile, std::string const& sourceFile,
+  std::string const& includeString)
 {
   bool success = false;
   std::string searchFile =
@@ -1753,7 +1554,7 @@
   return success;
 }
 
-bool cmQtAutoGenerators::UicGenerateAll()
+bool cmQtAutoGeneratorMocUic::UicGenerateAll()
 {
   if (!this->UicEnabled()) {
     return true;
@@ -1817,7 +1618,7 @@
 /**
  * @return True on success
  */
-bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob)
+bool cmQtAutoGeneratorMocUic::UicGenerateFile(const UicJob& uicJob)
 {
   bool success = true;
 
@@ -1827,7 +1628,7 @@
   bool generate = false;
   std::string generateReason;
   if (!generate && !cmSystemTools::FileExists(uicFileAbs.c_str())) {
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       generateReason = "Generating ";
       generateReason += cmQtAutoGen::Quoted(uicFileAbs);
       generateReason += " from its source file ";
@@ -1837,7 +1638,7 @@
     generate = true;
   }
   if (!generate && this->UicSettingsChanged) {
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       generateReason = "Generating ";
       generateReason += cmQtAutoGen::Quoted(uicFileAbs);
       generateReason += " from ";
@@ -1849,7 +1650,7 @@
   if (!generate) {
     std::string error;
     if (FileIsOlderThan(uicFileAbs, uicJob.SourceFile, &error)) {
-      if (this->Verbose) {
+      if (this->GetVerbose()) {
         generateReason = "Generating ";
         generateReason += cmQtAutoGen::Quoted(uicFileAbs);
         generateReason += " because it's older than its source file ";
@@ -1865,7 +1666,7 @@
   }
   if (generate) {
     // Log
-    if (this->Verbose) {
+    if (this->GetVerbose()) {
       this->LogBold("Generating UIC header " + uicJob.BuildFileRel);
       this->LogInfo(cmQtAutoGen::UIC, generateReason);
     }
@@ -1880,7 +1681,7 @@
         auto optionIt = this->UicOptions.find(uicJob.SourceFile);
         if (optionIt != this->UicOptions.end()) {
           cmQtAutoGen::UicMergeOptions(allOpts, optionIt->second,
-                                       (this->QtMajorVersion == "5"));
+                                       (this->QtVersionMajor == 5));
         }
         cmd.insert(cmd.end(), allOpts.begin(), allOpts.end());
       }
@@ -1911,413 +1712,13 @@
   return success;
 }
 
-bool cmQtAutoGenerators::RccGenerateAll()
-{
-  if (!this->RccEnabled()) {
-    return true;
-  }
-
-  // Generate rcc files
-  for (const RccJob& rccJob : this->RccJobs) {
-    if (!this->RccGenerateFile(rccJob)) {
-      return false;
-    }
-  }
-  return true;
-}
-
-/**
- * @return True on success
- */
-bool cmQtAutoGenerators::RccGenerateFile(const RccJob& rccJob)
-{
-  bool success = true;
-  bool rccGenerated = false;
-
-  std::string rccFileAbs;
-  {
-    std::string suffix;
-    switch (this->MultiConfig) {
-      case cmQtAutoGen::SINGLE:
-        break;
-      case cmQtAutoGen::WRAP:
-        suffix = "_CMAKE";
-        suffix += this->ConfigSuffix;
-        suffix += "_";
-        break;
-      case cmQtAutoGen::FULL:
-        suffix = this->ConfigSuffix;
-        break;
-    }
-    rccFileAbs = cmQtAutoGen::AppendFilenameSuffix(rccJob.RccFile, suffix);
-  }
-  std::string const rccFileRel = cmSystemTools::RelativePath(
-    this->AutogenBuildDir.c_str(), rccFileAbs.c_str());
-
-  // Check if regeneration is required
-  bool generate = false;
-  std::string generateReason;
-  if (!cmSystemTools::FileExists(rccJob.QrcFile)) {
-    {
-      std::string error = "Could not find the file\n  ";
-      error += cmQtAutoGen::Quoted(rccJob.QrcFile);
-      this->LogError(cmQtAutoGen::RCC, error);
-    }
-    success = false;
-  }
-  if (success && !generate && !cmSystemTools::FileExists(rccFileAbs.c_str())) {
-    if (this->Verbose) {
-      generateReason = "Generating ";
-      generateReason += cmQtAutoGen::Quoted(rccFileAbs);
-      generateReason += " from its source file ";
-      generateReason += cmQtAutoGen::Quoted(rccJob.QrcFile);
-      generateReason += " because it doesn't exist";
-    }
-    generate = true;
-  }
-  if (success && !generate && this->RccSettingsChanged) {
-    if (this->Verbose) {
-      generateReason = "Generating ";
-      generateReason += cmQtAutoGen::Quoted(rccFileAbs);
-      generateReason += " from ";
-      generateReason += cmQtAutoGen::Quoted(rccJob.QrcFile);
-      generateReason += " because the RCC settings changed";
-    }
-    generate = true;
-  }
-  if (success && !generate) {
-    std::string error;
-    if (FileIsOlderThan(rccFileAbs, rccJob.QrcFile, &error)) {
-      if (this->Verbose) {
-        generateReason = "Generating ";
-        generateReason += cmQtAutoGen::Quoted(rccFileAbs);
-        generateReason += " because it is older than ";
-        generateReason += cmQtAutoGen::Quoted(rccJob.QrcFile);
-      }
-      generate = true;
-    } else {
-      if (!error.empty()) {
-        this->LogError(cmQtAutoGen::RCC, error);
-        success = false;
-      }
-    }
-  }
-  if (success && !generate) {
-    // Acquire input file list
-    std::vector<std::string> readFiles;
-    std::vector<std::string> const* files = nullptr;
-    if (!rccJob.Inputs.empty()) {
-      files = &rccJob.Inputs;
-    } else {
-      // Read input file list from qrc file
-      std::string error;
-      if (cmQtAutoGen::RccListInputs(this->QtMajorVersion, this->RccExecutable,
-                                     rccJob.QrcFile, readFiles, &error)) {
-        files = &readFiles;
-      } else {
-        this->LogFileError(cmQtAutoGen::RCC, rccJob.QrcFile, error);
-        success = false;
-      }
-    }
-    // Test if any input file is newer than the build file
-    if (files != nullptr) {
-      std::string error;
-      for (std::string const& resFile : *files) {
-        if (!cmSystemTools::FileExists(resFile.c_str())) {
-          error = "Could not find the file\n  ";
-          error += cmQtAutoGen::Quoted(resFile);
-          error += "\nwhich is listed in\n  ";
-          error += cmQtAutoGen::Quoted(rccJob.QrcFile);
-          break;
-        }
-        if (FileIsOlderThan(rccFileAbs, resFile, &error)) {
-          if (this->Verbose) {
-            generateReason = "Generating ";
-            generateReason += cmQtAutoGen::Quoted(rccFileAbs);
-            generateReason += " from ";
-            generateReason += cmQtAutoGen::Quoted(rccJob.QrcFile);
-            generateReason += " because it is older than ";
-            generateReason += cmQtAutoGen::Quoted(resFile);
-          }
-          generate = true;
-          break;
-        }
-        if (!error.empty()) {
-          break;
-        }
-      }
-      // Print error
-      if (!error.empty()) {
-        this->LogError(cmQtAutoGen::RCC, error);
-        success = false;
-      }
-    }
-  }
-  // Regenerate on demand
-  if (generate) {
-    // Log
-    if (this->Verbose) {
-      this->LogBold("Generating RCC source " + rccFileRel);
-      this->LogInfo(cmQtAutoGen::RCC, generateReason);
-    }
-
-    // Make sure the parent directory exists
-    if (this->MakeParentDirectory(cmQtAutoGen::RCC, rccFileAbs)) {
-      // Compose rcc command
-      std::vector<std::string> cmd;
-      cmd.push_back(this->RccExecutable);
-      cmd.insert(cmd.end(), rccJob.Options.begin(), rccJob.Options.end());
-      cmd.push_back("-o");
-      cmd.push_back(rccFileAbs);
-      cmd.push_back(rccJob.QrcFile);
-
-      std::string output;
-      if (this->RunCommand(cmd, output)) {
-        // Success
-        rccGenerated = true;
-      } else {
-        {
-          std::string emsg = "rcc failed for\n  ";
-          emsg += cmQtAutoGen::Quoted(rccJob.QrcFile);
-          this->LogCommandError(cmQtAutoGen::RCC, emsg, cmd, output);
-        }
-        cmSystemTools::RemoveFile(rccFileAbs);
-        success = false;
-      }
-    } else {
-      // Parent directory creation failed
-      success = false;
-    }
-  }
-
-  // Generate a wrapper source file on demand
-  if (success && (this->MultiConfig == cmQtAutoGen::WRAP)) {
-    // Wrapper file name
-    std::string const& wrapperFileAbs = rccJob.RccFile;
-    std::string const wrapperFileRel = cmSystemTools::RelativePath(
-      this->AutogenBuildDir.c_str(), wrapperFileAbs.c_str());
-    // Wrapper file content
-    std::string content = "// This is an autogenerated configuration "
-                          "wrapper file. Changes will be overwritten.\n"
-                          "#include \"";
-    content += cmSystemTools::GetFilenameName(rccFileRel);
-    content += "\"\n";
-    // Write content to file
-    if (this->FileDiffers(wrapperFileAbs, content)) {
-      // Write new wrapper file
-      if (this->Verbose) {
-        this->LogBold("Generating RCC wrapper " + wrapperFileRel);
-      }
-      if (!this->FileWrite(cmQtAutoGen::RCC, wrapperFileAbs, content)) {
-        this->LogFileError(cmQtAutoGen::RCC, wrapperFileAbs,
-                           "rcc wrapper file writing failed");
-        success = false;
-      }
-    } else if (rccGenerated) {
-      // Just touch the wrapper file
-      if (this->Verbose) {
-        this->LogInfo(cmQtAutoGen::RCC,
-                      "Touching RCC wrapper " + wrapperFileRel);
-      }
-      cmSystemTools::Touch(wrapperFileAbs, false);
-    }
-  }
-
-  return success;
-}
-
-void cmQtAutoGenerators::LogBold(std::string const& message) const
-{
-  cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue |
-                                     cmsysTerminal_Color_ForegroundBold,
-                                   message.c_str(), true, this->ColorOutput);
-}
-
-void cmQtAutoGenerators::LogInfo(cmQtAutoGen::Generator genType,
-                                 std::string const& message) const
-{
-  std::string msg = cmQtAutoGen::GeneratorName(genType);
-  msg += ": ";
-  msg += message;
-  if (msg.back() != '\n') {
-    msg.push_back('\n');
-  }
-  cmSystemTools::Stdout(msg.c_str(), msg.size());
-}
-
-void cmQtAutoGenerators::LogWarning(cmQtAutoGen::Generator genType,
-                                    std::string const& message) const
-{
-  std::string msg = cmQtAutoGen::GeneratorName(genType);
-  msg += " warning:";
-  if (message.find('\n') == std::string::npos) {
-    // Single line message
-    msg.push_back(' ');
-  } else {
-    // Multi line message
-    msg.push_back('\n');
-  }
-  // Message
-  msg += message;
-  if (msg.back() != '\n') {
-    msg.push_back('\n');
-  }
-  msg.push_back('\n');
-  cmSystemTools::Stdout(msg.c_str(), msg.size());
-}
-
-void cmQtAutoGenerators::LogFileWarning(cmQtAutoGen::Generator genType,
-                                        std::string const& filename,
-                                        std::string const& message) const
-{
-  std::string msg = "  ";
-  msg += cmQtAutoGen::Quoted(filename);
-  msg.push_back('\n');
-  // Message
-  msg += message;
-  this->LogWarning(genType, msg);
-}
-
-void cmQtAutoGenerators::LogError(cmQtAutoGen::Generator genType,
-                                  std::string const& message) const
-{
-  std::string msg;
-  msg.push_back('\n');
-  msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " error");
-  // Message
-  msg += message;
-  if (msg.back() != '\n') {
-    msg.push_back('\n');
-  }
-  msg.push_back('\n');
-  cmSystemTools::Stderr(msg.c_str(), msg.size());
-}
-
-void cmQtAutoGenerators::LogFileError(cmQtAutoGen::Generator genType,
-                                      std::string const& filename,
-                                      std::string const& message) const
-{
-  std::string emsg = "  ";
-  emsg += cmQtAutoGen::Quoted(filename);
-  emsg += '\n';
-  // Message
-  emsg += message;
-  this->LogError(genType, emsg);
-}
-
-void cmQtAutoGenerators::LogCommandError(
-  cmQtAutoGen::Generator genType, std::string const& message,
-  std::vector<std::string> const& command, std::string const& output) const
-{
-  std::string msg;
-  msg.push_back('\n');
-  msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " subprocess error");
-  msg += message;
-  if (msg.back() != '\n') {
-    msg.push_back('\n');
-  }
-  msg.push_back('\n');
-  msg += HeadLine("Command");
-  msg += QuotedCommand(command);
-  if (msg.back() != '\n') {
-    msg.push_back('\n');
-  }
-  msg.push_back('\n');
-  msg += HeadLine("Output");
-  msg += output;
-  if (msg.back() != '\n') {
-    msg.push_back('\n');
-  }
-  msg.push_back('\n');
-  cmSystemTools::Stderr(msg.c_str(), msg.size());
-}
-
-/**
- * @brief Generates the parent directory of the given file on demand
- * @return True on success
- */
-bool cmQtAutoGenerators::MakeParentDirectory(cmQtAutoGen::Generator genType,
-                                             std::string const& filename) const
-{
-  bool success = true;
-  std::string const dirName = cmSystemTools::GetFilenamePath(filename);
-  if (!dirName.empty()) {
-    if (!cmSystemTools::MakeDirectory(dirName)) {
-      this->LogFileError(genType, filename,
-                         "Could not create parent directory");
-      success = false;
-    }
-  }
-  return success;
-}
-
-bool cmQtAutoGenerators::FileDiffers(std::string const& filename,
-                                     std::string const& content)
-{
-  bool differs = true;
-  {
-    std::string oldContents;
-    if (ReadFile(oldContents, filename)) {
-      differs = (oldContents != content);
-    }
-  }
-  return differs;
-}
-
-bool cmQtAutoGenerators::FileWrite(cmQtAutoGen::Generator genType,
-                                   std::string const& filename,
-                                   std::string const& content)
-{
-  std::string error;
-  // Make sure the parent directory exists
-  if (this->MakeParentDirectory(genType, filename)) {
-    cmsys::ofstream outfile;
-    outfile.open(filename.c_str(),
-                 (std::ios::out | std::ios::binary | std::ios::trunc));
-    if (outfile) {
-      outfile << content;
-      // Check for write errors
-      if (!outfile.good()) {
-        error = "File writing failed";
-      }
-    } else {
-      error = "Opening file for writing failed";
-    }
-  }
-  if (!error.empty()) {
-    this->LogFileError(genType, filename, error);
-    return false;
-  }
-  return true;
-}
-
-/**
- * @brief Runs a command and returns true on success
- * @return True on success
- */
-bool cmQtAutoGenerators::RunCommand(std::vector<std::string> const& command,
-                                    std::string& output) const
-{
-  // Log command
-  if (this->Verbose) {
-    std::string qcmd = QuotedCommand(command);
-    qcmd.push_back('\n');
-    cmSystemTools::Stdout(qcmd.c_str(), qcmd.size());
-  }
-  // Execute command
-  int retVal = 0;
-  bool res = cmSystemTools::RunSingleCommand(
-    command, &output, &output, &retVal, nullptr, cmSystemTools::OUTPUT_NONE);
-  return (res && (retVal == 0));
-}
-
 /**
  * @brief Tries to find the header file to the given file base path by
  * appending different header extensions
  * @return True on success
  */
-bool cmQtAutoGenerators::FindHeader(std::string& header,
-                                    std::string const& testBasePath) const
+bool cmQtAutoGeneratorMocUic::FindHeader(std::string& header,
+                                         std::string const& testBasePath) const
 {
   for (std::string const& ext : this->HeaderExtensions) {
     std::string testFilePath(testBasePath);
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGeneratorMocUic.h
similarity index 68%
rename from Source/cmQtAutoGenerators.h
rename to Source/cmQtAutoGeneratorMocUic.h
index a7bb538..d510939 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGeneratorMocUic.h
@@ -1,12 +1,13 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
-#ifndef cmQtAutoGenerators_h
-#define cmQtAutoGenerators_h
+#ifndef cmQtAutoGeneratorMocUic_h
+#define cmQtAutoGeneratorMocUic_h
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cmFilePathChecksum.h"
 #include "cmQtAutoGen.h"
+#include "cmQtAutoGenerator.h"
 #include "cmsys/RegularExpression.hxx"
 
 #include <map>
@@ -17,12 +18,11 @@
 
 class cmMakefile;
 
-class cmQtAutoGenerators
+class cmQtAutoGeneratorMocUic : public cmQtAutoGenerator
 {
-  CM_DISABLE_COPY(cmQtAutoGenerators)
+  CM_DISABLE_COPY(cmQtAutoGeneratorMocUic)
 public:
-  cmQtAutoGenerators();
-  bool Run(std::string const& targetDirectory, std::string const& config);
+  cmQtAutoGeneratorMocUic();
 
 private:
   // -- Types
@@ -80,30 +80,19 @@
     std::string IncludeString;
   };
 
-  /// @brief RCC job
-  struct RccJob
-  {
-    std::string QrcFile;
-    std::string RccFile;
-    std::vector<std::string> Options;
-    std::vector<std::string> Inputs;
-  };
-
   // -- Initialization
-  bool InitInfoFile(cmMakefile* makefile, std::string const& targetDirectory,
-                    std::string const& config);
+  bool InitInfoFile(cmMakefile* makefile);
 
   // -- Settings file
   void SettingsFileRead(cmMakefile* makefile);
   bool SettingsFileWrite();
   bool SettingsChanged() const
   {
-    return (this->MocSettingsChanged || this->RccSettingsChanged ||
-            this->UicSettingsChanged);
+    return (this->MocSettingsChanged || this->UicSettingsChanged);
   }
 
   // -- Central processing
-  bool Process();
+  bool Process(cmMakefile* makefile) override;
 
   // -- Source parsing
   bool ParseSourceFile(std::string const& absFilename, const SourceJob& job);
@@ -146,54 +135,17 @@
   bool UicGenerateAll();
   bool UicGenerateFile(const UicJob& uicJob);
 
-  // -- Rcc
-  bool RccEnabled() const { return !this->RccExecutable.empty(); }
-  bool RccGenerateAll();
-  bool RccGenerateFile(const RccJob& rccJob);
-
-  // -- Log info
-  void LogBold(std::string const& message) const;
-  void LogInfo(cmQtAutoGen::Generator genType,
-               std::string const& message) const;
-  // -- Log warning
-  void LogWarning(cmQtAutoGen::Generator genType,
-                  std::string const& message) const;
-  void LogFileWarning(cmQtAutoGen::Generator genType,
-                      std::string const& filename,
-                      std::string const& message) const;
-  // -- Log error
-  void LogError(cmQtAutoGen::Generator genType,
-                std::string const& message) const;
-  void LogFileError(cmQtAutoGen::Generator genType,
-                    std::string const& filename,
-                    std::string const& message) const;
-  void LogCommandError(cmQtAutoGen::Generator genType,
-                       std::string const& message,
-                       std::vector<std::string> const& command,
-                       std::string const& output) const;
-
   // -- Utility
-  bool MakeParentDirectory(cmQtAutoGen::Generator genType,
-                           std::string const& filename) const;
-  bool FileDiffers(std::string const& filename, std::string const& content);
-  bool FileWrite(cmQtAutoGen::Generator genType, std::string const& filename,
-                 std::string const& content);
   bool FindHeader(std::string& header, std::string const& testBasePath) const;
-  bool RunCommand(std::vector<std::string> const& command,
-                  std::string& output) const;
 
   // -- Meta
-  std::string InfoFile;
   std::string ConfigSuffix;
   cmQtAutoGen::MultiConfig MultiConfig;
   // -- Settings
   bool IncludeProjectDirsBefore;
-  bool Verbose;
-  bool ColorOutput;
   std::string SettingsFile;
   std::string SettingsStringMoc;
   std::string SettingsStringUic;
-  std::string SettingsStringRcc;
   // -- Directories
   std::string ProjectSourceDir;
   std::string ProjectBinaryDir;
@@ -202,11 +154,9 @@
   std::string AutogenBuildDir;
   std::string AutogenIncludeDir;
   // -- Qt environment
-  std::string QtMajorVersion;
-  std::string QtMinorVersion;
+  unsigned long QtVersionMajor;
   std::string MocExecutable;
   std::string UicExecutable;
-  std::string RccExecutable;
   // -- File lists
   std::map<std::string, SourceJob> HeaderJobs;
   std::map<std::string, SourceJob> SourceJobs;
@@ -240,9 +190,6 @@
   std::vector<std::string> UicSearchPaths;
   cmsys::RegularExpression UicRegExpInclude;
   std::vector<std::unique_ptr<UicJob>> UicJobs;
-  // -- Rcc
-  bool RccSettingsChanged;
-  std::vector<RccJob> RccJobs;
 };
 
 #endif
diff --git a/Source/cmQtAutoGeneratorRcc.cxx b/Source/cmQtAutoGeneratorRcc.cxx
new file mode 100644
index 0000000..3c9f1a8
--- /dev/null
+++ b/Source/cmQtAutoGeneratorRcc.cxx
@@ -0,0 +1,425 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmQtAutoGen.h"
+#include "cmQtAutoGeneratorRcc.h"
+
+#include "cmAlgorithms.h"
+#include "cmCryptoHash.h"
+#include "cmMakefile.h"
+#include "cmOutputConverter.h"
+#include "cmSystemTools.h"
+
+// -- Static variables
+
+static const char* SettingsKeyRcc = "ARCC_SETTINGS_HASH";
+
+// -- Class methods
+
+cmQtAutoGeneratorRcc::cmQtAutoGeneratorRcc()
+  : MultiConfig(cmQtAutoGen::WRAP)
+  , SettingsChanged(false)
+{
+}
+
+bool cmQtAutoGeneratorRcc::InfoFileRead(cmMakefile* makefile)
+{
+  // Utility lambdas
+  auto InfoGet = [makefile](const char* key) {
+    return makefile->GetSafeDefinition(key);
+  };
+  auto InfoGetList = [makefile](const char* key) -> std::vector<std::string> {
+    std::vector<std::string> list;
+    cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list);
+    return list;
+  };
+  auto InfoGetConfig = [makefile, this](const char* key) -> std::string {
+    const char* valueConf = nullptr;
+    {
+      std::string keyConf = key;
+      keyConf += '_';
+      keyConf += this->GetInfoConfig();
+      valueConf = makefile->GetDefinition(keyConf);
+    }
+    if (valueConf == nullptr) {
+      valueConf = makefile->GetSafeDefinition(key);
+    }
+    return std::string(valueConf);
+  };
+  auto InfoGetConfigList =
+    [&InfoGetConfig](const char* key) -> std::vector<std::string> {
+    std::vector<std::string> list;
+    cmSystemTools::ExpandListArgument(InfoGetConfig(key), list);
+    return list;
+  };
+
+  // -- Read info file
+  if (!makefile->ReadListFile(this->GetInfoFile().c_str())) {
+    this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
+                       "File processing failed");
+    return false;
+  }
+
+  // -- Meta
+  this->MultiConfig =
+    cmQtAutoGen::MultiConfigType(InfoGet("ARCC_MULTI_CONFIG"));
+  this->ConfigSuffix = InfoGetConfig("ARCC_CONFIG_SUFFIX");
+  if (this->ConfigSuffix.empty()) {
+    this->ConfigSuffix = "_";
+    this->ConfigSuffix += this->GetInfoConfig();
+  }
+
+  this->SettingsFile = InfoGetConfig("ARCC_SETTINGS_FILE");
+
+  // - Files and directories
+  this->ProjectSourceDir = InfoGet("ARCC_CMAKE_SOURCE_DIR");
+  this->ProjectBinaryDir = InfoGet("ARCC_CMAKE_BINARY_DIR");
+  this->CurrentSourceDir = InfoGet("ARCC_CMAKE_CURRENT_SOURCE_DIR");
+  this->CurrentBinaryDir = InfoGet("ARCC_CMAKE_CURRENT_BINARY_DIR");
+  this->AutogenBuildDir = InfoGet("ARCC_BUILD_DIR");
+
+  // - Qt environment
+  this->RccExecutable = InfoGet("ARCC_RCC_EXECUTABLE");
+  this->RccListOptions = InfoGetList("ARCC_RCC_LIST_OPTIONS");
+
+  // - Job
+  this->QrcFile = InfoGet("ARCC_SOURCE");
+  this->RccFile = InfoGet("ARCC_OUTPUT");
+  this->Options = InfoGetConfigList("ARCC_OPTIONS");
+  this->Inputs = InfoGetList("ARCC_INPUTS");
+
+  // - Validity checks
+  if (this->SettingsFile.empty()) {
+    this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
+                       "Settings file name missing");
+    return false;
+  }
+  if (this->AutogenBuildDir.empty()) {
+    this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
+                       "Autogen build directory missing");
+    return false;
+  }
+  if (this->RccExecutable.empty()) {
+    this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
+                       "rcc executable missing");
+    return false;
+  }
+  if (this->QrcFile.empty()) {
+    this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
+                       "rcc input file missing");
+    return false;
+  }
+  if (this->RccFile.empty()) {
+    this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(),
+                       "rcc output file missing");
+    return false;
+  }
+
+  // Init derived information
+  // ------------------------
+
+  // Init file path checksum generator
+  this->FilePathChecksum.setupParentDirs(
+    this->CurrentSourceDir, this->CurrentBinaryDir, this->ProjectSourceDir,
+    this->ProjectBinaryDir);
+
+  return true;
+}
+
+void cmQtAutoGeneratorRcc::SettingsFileRead(cmMakefile* makefile)
+{
+  // Compose current settings strings
+  {
+    cmCryptoHash crypt(cmCryptoHash::AlgoSHA256);
+    std::string const sep(" ~~~ ");
+    {
+      std::string str;
+      str += this->RccExecutable;
+      str += sep;
+      str += cmJoin(this->RccListOptions, ";");
+      str += sep;
+      str += this->QrcFile;
+      str += sep;
+      str += this->RccFile;
+      str += sep;
+      str += cmJoin(this->Options, ";");
+      str += sep;
+      str += cmJoin(this->Inputs, ";");
+      str += sep;
+      this->SettingsString = crypt.HashString(str);
+    }
+  }
+
+  // Read old settings
+  if (makefile->ReadListFile(this->SettingsFile.c_str())) {
+    {
+      auto SMatch = [makefile](const char* key, std::string const& value) {
+        return (value == makefile->GetSafeDefinition(key));
+      };
+      if (!SMatch(SettingsKeyRcc, this->SettingsString)) {
+        this->SettingsChanged = true;
+      }
+    }
+    // In case any setting changed remove the old settings file.
+    // This triggers a full rebuild on the next run if the current
+    // build is aborted before writing the current settings in the end.
+    if (this->SettingsChanged) {
+      cmSystemTools::RemoveFile(this->SettingsFile);
+    }
+  } else {
+    // If the file could not be read re-generate everythiung.
+    this->SettingsChanged = true;
+  }
+}
+
+bool cmQtAutoGeneratorRcc::SettingsFileWrite()
+{
+  bool success = true;
+  // Only write if any setting changed
+  if (this->SettingsChanged) {
+    if (this->GetVerbose()) {
+      this->LogInfo(cmQtAutoGen::RCC, "Writing settings file " +
+                      cmQtAutoGen::Quoted(this->SettingsFile));
+    }
+    // Compose settings file content
+    std::string settings;
+    {
+      auto SettingAppend = [&settings](const char* key,
+                                       std::string const& value) {
+        settings += "set(";
+        settings += key;
+        settings += " ";
+        settings += cmOutputConverter::EscapeForCMake(value);
+        settings += ")\n";
+      };
+      SettingAppend(SettingsKeyRcc, this->SettingsString);
+    }
+    // Write settings file
+    if (!this->FileWrite(cmQtAutoGen::RCC, this->SettingsFile, settings)) {
+      this->LogFileError(cmQtAutoGen::RCC, this->SettingsFile,
+                         "Settings file writing failed");
+      // Remove old settings file to trigger a full rebuild on the next run
+      cmSystemTools::RemoveFile(this->SettingsFile);
+      success = false;
+    }
+  }
+  return success;
+}
+
+bool cmQtAutoGeneratorRcc::Process(cmMakefile* makefile)
+{
+  // Read info file
+  if (!this->InfoFileRead(makefile)) {
+    return false;
+  }
+  // Read latest settings
+  this->SettingsFileRead(makefile);
+  // Generate rcc file
+  if (!this->RccGenerate()) {
+    return false;
+  }
+  // Write latest settings
+  if (!this->SettingsFileWrite()) {
+    return false;
+  }
+  return true;
+}
+
+/**
+ * @return True on success
+ */
+bool cmQtAutoGeneratorRcc::RccGenerate()
+{
+  bool success = true;
+  bool rccGenerated = false;
+
+  std::string rccFileAbs;
+  {
+    std::string suffix;
+    switch (this->MultiConfig) {
+      case cmQtAutoGen::SINGLE:
+        break;
+      case cmQtAutoGen::WRAP:
+        suffix = "_CMAKE";
+        suffix += this->ConfigSuffix;
+        suffix += "_";
+        break;
+      case cmQtAutoGen::FULL:
+        suffix = this->ConfigSuffix;
+        break;
+    }
+    rccFileAbs = cmQtAutoGen::AppendFilenameSuffix(this->RccFile, suffix);
+  }
+  std::string const rccFileRel = cmSystemTools::RelativePath(
+    this->AutogenBuildDir.c_str(), rccFileAbs.c_str());
+
+  // Check if regeneration is required
+  bool generate = false;
+  std::string generateReason;
+  if (!cmSystemTools::FileExists(this->QrcFile)) {
+    {
+      std::string error = "Could not find the file\n  ";
+      error += cmQtAutoGen::Quoted(this->QrcFile);
+      this->LogError(cmQtAutoGen::RCC, error);
+    }
+    success = false;
+  }
+  if (success && !generate && !cmSystemTools::FileExists(rccFileAbs.c_str())) {
+    if (this->GetVerbose()) {
+      generateReason = "Generating ";
+      generateReason += cmQtAutoGen::Quoted(rccFileAbs);
+      generateReason += " from its source file ";
+      generateReason += cmQtAutoGen::Quoted(this->QrcFile);
+      generateReason += " because it doesn't exist";
+    }
+    generate = true;
+  }
+  if (success && !generate && this->SettingsChanged) {
+    if (this->GetVerbose()) {
+      generateReason = "Generating ";
+      generateReason += cmQtAutoGen::Quoted(rccFileAbs);
+      generateReason += " from ";
+      generateReason += cmQtAutoGen::Quoted(this->QrcFile);
+      generateReason += " because the RCC settings changed";
+    }
+    generate = true;
+  }
+  if (success && !generate) {
+    std::string error;
+    if (FileIsOlderThan(rccFileAbs, this->QrcFile, &error)) {
+      if (this->GetVerbose()) {
+        generateReason = "Generating ";
+        generateReason += cmQtAutoGen::Quoted(rccFileAbs);
+        generateReason += " because it is older than ";
+        generateReason += cmQtAutoGen::Quoted(this->QrcFile);
+      }
+      generate = true;
+    } else {
+      if (!error.empty()) {
+        this->LogError(cmQtAutoGen::RCC, error);
+        success = false;
+      }
+    }
+  }
+  if (success && !generate) {
+    // Acquire input file list
+    std::vector<std::string> readFiles;
+    std::vector<std::string> const* files = nullptr;
+    if (!this->Inputs.empty()) {
+      files = &this->Inputs;
+    } else {
+      // Read input file list from qrc file
+      std::string error;
+      if (cmQtAutoGen::RccListInputs(this->RccExecutable, this->RccListOptions,
+                                     this->QrcFile, readFiles, &error)) {
+        files = &readFiles;
+      } else {
+        this->LogFileError(cmQtAutoGen::RCC, this->QrcFile, error);
+        success = false;
+      }
+    }
+    // Test if any input file is newer than the build file
+    if (files != nullptr) {
+      std::string error;
+      for (std::string const& resFile : *files) {
+        if (!cmSystemTools::FileExists(resFile.c_str())) {
+          error = "Could not find the file\n  ";
+          error += cmQtAutoGen::Quoted(resFile);
+          error += "\nwhich is listed in\n  ";
+          error += cmQtAutoGen::Quoted(this->QrcFile);
+          break;
+        }
+        if (FileIsOlderThan(rccFileAbs, resFile, &error)) {
+          if (this->GetVerbose()) {
+            generateReason = "Generating ";
+            generateReason += cmQtAutoGen::Quoted(rccFileAbs);
+            generateReason += " from ";
+            generateReason += cmQtAutoGen::Quoted(this->QrcFile);
+            generateReason += " because it is older than ";
+            generateReason += cmQtAutoGen::Quoted(resFile);
+          }
+          generate = true;
+          break;
+        }
+        if (!error.empty()) {
+          break;
+        }
+      }
+      // Print error
+      if (!error.empty()) {
+        this->LogError(cmQtAutoGen::RCC, error);
+        success = false;
+      }
+    }
+  }
+  // Regenerate on demand
+  if (generate) {
+    // Log
+    if (this->GetVerbose()) {
+      this->LogBold("Generating RCC source " + rccFileRel);
+      this->LogInfo(cmQtAutoGen::RCC, generateReason);
+    }
+
+    // Make sure the parent directory exists
+    if (this->MakeParentDirectory(cmQtAutoGen::RCC, rccFileAbs)) {
+      // Compose rcc command
+      std::vector<std::string> cmd;
+      cmd.push_back(this->RccExecutable);
+      cmd.insert(cmd.end(), this->Options.begin(), this->Options.end());
+      cmd.push_back("-o");
+      cmd.push_back(rccFileAbs);
+      cmd.push_back(this->QrcFile);
+
+      std::string output;
+      if (this->RunCommand(cmd, output)) {
+        // Success
+        rccGenerated = true;
+      } else {
+        {
+          std::string emsg = "rcc failed for\n  ";
+          emsg += cmQtAutoGen::Quoted(this->QrcFile);
+          this->LogCommandError(cmQtAutoGen::RCC, emsg, cmd, output);
+        }
+        cmSystemTools::RemoveFile(rccFileAbs);
+        success = false;
+      }
+    } else {
+      // Parent directory creation failed
+      success = false;
+    }
+  }
+
+  // Generate a wrapper source file on demand
+  if (success && (this->MultiConfig == cmQtAutoGen::WRAP)) {
+    // Wrapper file name
+    std::string const& wrapperFileAbs = this->RccFile;
+    std::string const wrapperFileRel = cmSystemTools::RelativePath(
+      this->AutogenBuildDir.c_str(), wrapperFileAbs.c_str());
+    // Wrapper file content
+    std::string content = "// This is an autogenerated configuration "
+                          "wrapper file. Changes will be overwritten.\n"
+                          "#include \"";
+    content += cmSystemTools::GetFilenameName(rccFileRel);
+    content += "\"\n";
+    // Write content to file
+    if (this->FileDiffers(wrapperFileAbs, content)) {
+      // Write new wrapper file
+      if (this->GetVerbose()) {
+        this->LogBold("Generating RCC wrapper " + wrapperFileRel);
+      }
+      if (!this->FileWrite(cmQtAutoGen::RCC, wrapperFileAbs, content)) {
+        this->LogFileError(cmQtAutoGen::RCC, wrapperFileAbs,
+                           "rcc wrapper file writing failed");
+        success = false;
+      }
+    } else if (rccGenerated) {
+      // Just touch the wrapper file
+      if (this->GetVerbose()) {
+        this->LogInfo(cmQtAutoGen::RCC,
+                      "Touching RCC wrapper " + wrapperFileRel);
+      }
+      cmSystemTools::Touch(wrapperFileAbs, false);
+    }
+  }
+
+  return success;
+}
diff --git a/Source/cmQtAutoGeneratorRcc.h b/Source/cmQtAutoGeneratorRcc.h
new file mode 100644
index 0000000..0e3f690
--- /dev/null
+++ b/Source/cmQtAutoGeneratorRcc.h
@@ -0,0 +1,56 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmQtAutoGeneratorRcc_h
+#define cmQtAutoGeneratorRcc_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmFilePathChecksum.h"
+#include "cmQtAutoGen.h"
+#include "cmQtAutoGenerator.h"
+
+#include <string>
+#include <vector>
+
+class cmMakefile;
+
+class cmQtAutoGeneratorRcc : public cmQtAutoGenerator
+{
+  CM_DISABLE_COPY(cmQtAutoGeneratorRcc)
+public:
+  cmQtAutoGeneratorRcc();
+
+private:
+  // -- Initialization & settings
+  bool InfoFileRead(cmMakefile* makefile);
+  void SettingsFileRead(cmMakefile* makefile);
+  bool SettingsFileWrite();
+  // -- Central processing
+  bool Process(cmMakefile* makefile) override;
+  bool RccGenerate();
+
+  // -- Config settings
+  std::string ConfigSuffix;
+  cmQtAutoGen::MultiConfig MultiConfig;
+  // -- Settings
+  bool SettingsChanged;
+  std::string SettingsFile;
+  std::string SettingsString;
+  // -- Directories
+  std::string ProjectSourceDir;
+  std::string ProjectBinaryDir;
+  std::string CurrentSourceDir;
+  std::string CurrentBinaryDir;
+  std::string AutogenBuildDir;
+  cmFilePathChecksum FilePathChecksum;
+  // -- Qt environment
+  std::string RccExecutable;
+  std::vector<std::string> RccListOptions;
+  // -- Job
+  std::string QrcFile;
+  std::string RccFile;
+  std::vector<std::string> Options;
+  std::vector<std::string> Inputs;
+};
+
+#endif
diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx
index e923c22..9af4c0a 100644
--- a/Source/cmServer.cxx
+++ b/Source/cmServer.cxx
@@ -245,11 +245,10 @@
 void cmServer::WriteJsonObject(const Json::Value& jsonValue,
                                const DebugInfo* debug) const
 {
-  uv_rwlock_rdlock(&ConnectionsMutex);
+  cm::shared_lock<cm::shared_mutex> lock(ConnectionsMutex);
   for (auto& connection : this->Connections) {
     WriteJsonObject(connection.get(), jsonValue, debug);
   }
-  uv_rwlock_rdunlock(&ConnectionsMutex);
 }
 
 void cmServer::WriteJsonObject(cmConnection* connection,
@@ -456,14 +455,12 @@
   OnServeStart();
 
   {
-    uv_rwlock_rdlock(&ConnectionsMutex);
+    cm::shared_lock<cm::shared_mutex> lock(ConnectionsMutex);
     for (auto& connection : Connections) {
       if (!connection->OnServeStart(errorMessage)) {
-        uv_rwlock_rdunlock(&ConnectionsMutex);
         return false;
       }
     }
-    uv_rwlock_rdunlock(&ConnectionsMutex);
   }
 
   if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) {
@@ -501,12 +498,11 @@
   }
 
   {
-    uv_rwlock_wrlock(&ConnectionsMutex);
+    cm::unique_lock<cm::shared_mutex> lock(ConnectionsMutex);
     for (auto& connection : Connections) {
       connection->OnConnectionShuttingDown();
     }
     Connections.clear();
-    uv_rwlock_wrunlock(&ConnectionsMutex);
   }
 
   uv_walk(&Loop, on_walk_to_shutdown, nullptr);
@@ -525,9 +521,6 @@
   (void)err;
   assert(err == 0);
 
-  err = uv_rwlock_init(&ConnectionsMutex);
-  assert(err == 0);
-
   AddNewConnection(connection);
 }
 
@@ -540,14 +533,14 @@
   }
 
   uv_loop_close(&Loop);
-  uv_rwlock_destroy(&ConnectionsMutex);
 }
 
 void cmServerBase::AddNewConnection(cmConnection* ownedConnection)
 {
-  uv_rwlock_wrlock(&ConnectionsMutex);
-  Connections.emplace_back(ownedConnection);
-  uv_rwlock_wrunlock(&ConnectionsMutex);
+  {
+    cm::unique_lock<cm::shared_mutex> lock(ConnectionsMutex);
+    Connections.emplace_back(ownedConnection);
+  }
   ownedConnection->SetServer(this);
 }
 
@@ -561,11 +554,13 @@
   auto pred = [pConnection](const std::unique_ptr<cmConnection>& m) {
     return m.get() == pConnection;
   };
-  uv_rwlock_wrlock(&ConnectionsMutex);
-  Connections.erase(
-    std::remove_if(Connections.begin(), Connections.end(), pred),
-    Connections.end());
-  uv_rwlock_wrunlock(&ConnectionsMutex);
+  {
+    cm::unique_lock<cm::shared_mutex> lock(ConnectionsMutex);
+    Connections.erase(
+      std::remove_if(Connections.begin(), Connections.end(), pred),
+      Connections.end());
+  }
+
   if (Connections.empty()) {
     StartShutDown();
   }
diff --git a/Source/cmServer.h b/Source/cmServer.h
index 15fd2ba..6e46f8c 100644
--- a/Source/cmServer.h
+++ b/Source/cmServer.h
@@ -5,6 +5,7 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include "cm_jsoncpp_value.h"
+#include "cm_thread.hxx"
 #include "cm_uv.h"
 
 #include <memory> // IWYU pragma: keep
@@ -61,7 +62,7 @@
   void OnDisconnect(cmConnection* pConnection);
 
 protected:
-  mutable uv_rwlock_t ConnectionsMutex;
+  mutable cm::shared_mutex ConnectionsMutex;
   std::vector<std::unique_ptr<cmConnection>> Connections;
 
   bool ServeThreadRunning = false;
diff --git a/Source/cmServerDictionary.h b/Source/cmServerDictionary.h
index 405ff6b..8cd5e14 100644
--- a/Source/cmServerDictionary.h
+++ b/Source/cmServerDictionary.h
@@ -23,6 +23,7 @@
 static const std::string kREPLY_TYPE = "reply";
 static const std::string kSET_GLOBAL_SETTINGS_TYPE = "setGlobalSettings";
 static const std::string kSIGNAL_TYPE = "signal";
+static const std::string kCTEST_INFO_TYPE = "ctestInfo";
 
 static const std::string kARTIFACTS_KEY = "artifacts";
 static const std::string kBUILD_DIRECTORY_KEY = "buildDirectory";
@@ -88,6 +89,13 @@
 static const std::string kWARN_UNUSED_KEY = "warnUnused";
 static const std::string kWATCHED_DIRECTORIES_KEY = "watchedDirectories";
 static const std::string kWATCHED_FILES_KEY = "watchedFiles";
+static const std::string kHAS_INSTALL_RULE = "hasInstallRule";
+static const std::string kINSTALL_PATHS = "installPaths";
+static const std::string kHAS_ENABLED_TESTS = "hasEnabledTests";
+static const std::string kCTEST_NAME = "ctestName";
+static const std::string kCTEST_COMMAND = "ctestCommand";
+static const std::string kCTEST_INFO = "ctestInfo";
+static const std::string kMINIMUM_CMAKE_VERSION = "minimumCMakeVersion";
 
 static const std::string kTARGET_CROSS_REFERENCES_KEY = "crossReferences";
 static const std::string kLINE_NUMBER_KEY = "line";
diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx
index e835b7a..aae0a9d 100644
--- a/Source/cmServerProtocol.cxx
+++ b/Source/cmServerProtocol.cxx
@@ -8,10 +8,13 @@
 #include "cmGeneratorExpression.h"
 #include "cmGeneratorTarget.h"
 #include "cmGlobalGenerator.h"
+#include "cmInstallGenerator.h"
+#include "cmInstallTargetGenerator.h"
 #include "cmLinkLineComputer.h"
 #include "cmListFileCache.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
+#include "cmProperty.h"
 #include "cmServer.h"
 #include "cmServerDictionary.h"
 #include "cmSourceFile.h"
@@ -21,6 +24,7 @@
 #include "cmStateTypes.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
+#include "cmTest.h"
 #include "cm_uv.h"
 #include "cmake.h"
 
@@ -30,6 +34,7 @@
 #include <functional>
 #include <limits>
 #include <map>
+#include <memory>
 #include <set>
 #include <string>
 #include <unordered_map>
@@ -252,7 +257,7 @@
 
 std::pair<int, int> cmServerProtocol1::ProtocolVersion() const
 {
-  return std::make_pair(1, 1);
+  return std::make_pair(1, 2);
 }
 
 static void setErrorMessage(std::string* errorMessage, const std::string& text)
@@ -476,6 +481,9 @@
   if (request.Type == kSET_GLOBAL_SETTINGS_TYPE) {
     return this->ProcessSetGlobalSettings(request);
   }
+  if (request.Type == kCTEST_INFO_TYPE) {
+    return this->ProcessCTests(request);
+  }
 
   return request.ReportError("Unknown command!");
 }
@@ -763,6 +771,153 @@
   }
 }
 
+static Json::Value DumpCTestInfo(const std::string& name, cmTest* testInfo)
+{
+  Json::Value result = Json::objectValue;
+  result[kCTEST_NAME] = name;
+
+  // Concat command entries together. After the first should be the arguments
+  // for the command
+  std::string command;
+  for (auto const& cmd : testInfo->GetCommand()) {
+    command.append(cmd);
+    command.append(" ");
+  }
+  result[kCTEST_COMMAND] = command;
+
+  // Build up the list of properties that may have been specified
+  Json::Value properties = Json::arrayValue;
+  for (auto& prop : testInfo->GetProperties()) {
+    Json::Value entry = Json::objectValue;
+    entry[kKEY_KEY] = prop.first;
+    entry[kVALUE_KEY] = prop.second.GetValue();
+    properties.append(entry);
+  }
+  result[kPROPERTIES_KEY] = properties;
+
+  // Need backtrace to figure out where this test was originally added
+  result[kBACKTRACE_KEY] = DumpBacktrace(testInfo->GetBacktrace());
+
+  return result;
+}
+
+static Json::Value DumpCTestTarget(cmGeneratorTarget* target,
+                                   const std::string& config)
+{
+  cmLocalGenerator* lg = target->GetLocalGenerator();
+  const cmState* state = lg->GetState();
+
+  const cmStateEnums::TargetType type = target->GetType();
+  const std::string typeName = state->GetTargetTypeName(type);
+
+  Json::Value ttl = Json::arrayValue;
+  ttl.append("EXECUTABLE");
+  ttl.append("STATIC_LIBRARY");
+  ttl.append("SHARED_LIBRARY");
+  ttl.append("MODULE_LIBRARY");
+  ttl.append("OBJECT_LIBRARY");
+  ttl.append("UTILITY");
+  ttl.append("INTERFACE_LIBRARY");
+
+  if (!hasString(ttl, typeName) || target->IsImported()) {
+    return Json::Value();
+  }
+
+  Json::Value result = Json::objectValue;
+  result[kNAME_KEY] = target->GetName();
+  result[kTYPE_KEY] = typeName;
+
+  if (type == cmStateEnums::INTERFACE_LIBRARY) {
+    return result;
+  }
+  result[kFULL_NAME_KEY] = target->GetFullName(config);
+
+  if (target->Makefile->IsOn("CMAKE_TESTING_ENABLED")) {
+    result[kHAS_ENABLED_TESTS] = true;
+    std::vector<std::string> CTestNames;
+
+    Json::Value testInfo = Json::arrayValue;
+    std::vector<std::string> testNames;
+    target->Makefile->GetTestNames(testNames);
+    for (auto& name : testNames) {
+      auto test = target->Makefile->GetTest(name);
+      if (test != nullptr) {
+        testInfo.append(DumpCTestInfo(name, test));
+      }
+    }
+    result[kCTEST_INFO] = testInfo;
+  }
+
+  return result;
+}
+
+static Json::Value DumpCTestTargetsList(
+  const std::vector<cmLocalGenerator*>& generators, const std::string& config)
+{
+  Json::Value result = Json::arrayValue;
+
+  std::vector<cmGeneratorTarget*> targetList;
+  for (const auto& lgIt : generators) {
+    auto list = lgIt->GetGeneratorTargets();
+    targetList.insert(targetList.end(), list.begin(), list.end());
+  }
+  std::sort(targetList.begin(), targetList.end());
+
+  for (cmGeneratorTarget* target : targetList) {
+    Json::Value tmp = DumpCTestTarget(target, config);
+    if (!tmp.isNull()) {
+      result.append(tmp);
+    }
+  }
+
+  return result;
+}
+
+static Json::Value DumpCTestProjectList(const cmake* cm,
+                                        std::string const& config)
+{
+  Json::Value result = Json::arrayValue;
+
+  auto globalGen = cm->GetGlobalGenerator();
+
+  for (const auto& projectIt : globalGen->GetProjectMap()) {
+    Json::Value pObj = Json::objectValue;
+    pObj[kNAME_KEY] = projectIt.first;
+
+    // All Projects must have at least one local generator
+    assert(!projectIt.second.empty());
+
+    // Project structure information:
+    pObj[kTARGETS_KEY] = DumpCTestTargetsList(projectIt.second, config);
+
+    result.append(pObj);
+  }
+
+  return result;
+}
+
+static Json::Value DumpCTestConfiguration(const cmake* cm,
+                                          const std::string& config)
+{
+  Json::Value result = Json::objectValue;
+  result[kNAME_KEY] = config;
+
+  result[kPROJECTS_KEY] = DumpCTestProjectList(cm, config);
+
+  return result;
+}
+
+static Json::Value DumpCTestConfigurationsList(const cmake* cm)
+{
+  Json::Value result = Json::arrayValue;
+
+  for (const std::string& c : getConfigurations(cm)) {
+    result.append(DumpCTestConfiguration(cm, c));
+  }
+
+  return result;
+}
+
 static Json::Value DumpTarget(cmGeneratorTarget* target,
                               const std::string& config)
 {
@@ -797,6 +952,34 @@
 
   result[kFULL_NAME_KEY] = target->GetFullName(config);
 
+  if (target->Target->GetHaveInstallRule()) {
+    result[kHAS_INSTALL_RULE] = true;
+
+    Json::Value installPaths = Json::arrayValue;
+    auto targetGenerators = target->Makefile->GetInstallGenerators();
+    for (auto installGenerator : targetGenerators) {
+      auto installTargetGenerator =
+        dynamic_cast<cmInstallTargetGenerator*>(installGenerator);
+      if (installTargetGenerator != nullptr &&
+          installTargetGenerator->GetTarget()->Target == target->Target) {
+        auto dest = installTargetGenerator->GetDestination(config);
+
+        std::string installPath;
+        if (!dest.empty() && cmSystemTools::FileIsFullPath(dest.c_str())) {
+          installPath = dest;
+        } else {
+          std::string installPrefix =
+            target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
+          installPath = installPrefix + '/' + dest;
+        }
+
+        installPaths.append(installPath);
+      }
+    }
+
+    result[kINSTALL_PATHS] = installPaths;
+  }
+
   Json::Value crossRefs = Json::objectValue;
   crossRefs[kBACKTRACE_KEY] = DumpBacktrace(target->Target->GetBacktrace());
 
@@ -933,10 +1116,26 @@
 
     // Project structure information:
     const cmMakefile* mf = lg->GetMakefile();
+    pObj[kMINIMUM_CMAKE_VERSION] =
+      mf->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
     pObj[kSOURCE_DIRECTORY_KEY] = mf->GetCurrentSourceDirectory();
     pObj[kBUILD_DIRECTORY_KEY] = mf->GetCurrentBinaryDirectory();
     pObj[kTARGETS_KEY] = DumpTargetsList(projectIt.second, config);
 
+    // For a project-level install rule it might be defined in any of its
+    // associated generators.
+    bool hasInstallRule = false;
+    for (const auto generator : projectIt.second) {
+      hasInstallRule =
+        generator->GetMakefile()->GetInstallGenerators().empty() == false;
+
+      if (hasInstallRule) {
+        break;
+      }
+    }
+
+    pObj[kHAS_INSTALL_RULE] = hasInstallRule;
+
     result.append(pObj);
   }
 
@@ -1190,6 +1389,19 @@
   return request.Reply(result);
 }
 
+cmServerResponse cmServerProtocol1::ProcessCTests(
+  const cmServerRequest& request)
+{
+  if (this->m_State < STATE_COMPUTED) {
+    return request.ReportError("This instance was not yet computed.");
+  }
+
+  Json::Value result = Json::objectValue;
+  result[kCONFIGURATIONS_KEY] =
+    DumpCTestConfigurationsList(this->CMakeInstance());
+  return request.Reply(result);
+}
+
 cmServerProtocol1::GeneratorInformation::GeneratorInformation(
   const std::string& generatorName, const std::string& extraGeneratorName,
   const std::string& toolset, const std::string& platform,
diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h
index 124ac7f..df71cff 100644
--- a/Source/cmServerProtocol.h
+++ b/Source/cmServerProtocol.h
@@ -123,6 +123,7 @@
   cmServerResponse ProcessGlobalSettings(const cmServerRequest& request);
   cmServerResponse ProcessSetGlobalSettings(const cmServerRequest& request);
   cmServerResponse ProcessFileSystemWatchers(const cmServerRequest& request);
+  cmServerResponse ProcessCTests(const cmServerRequest& request);
 
   enum State
   {
diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx
index b32cda3..985aac8 100644
--- a/Source/cmSetCommand.cxx
+++ b/Source/cmSetCommand.cxx
@@ -2,8 +2,6 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmSetCommand.h"
 
-#include <string.h>
-
 #include "cmAlgorithms.h"
 #include "cmMakefile.h"
 #include "cmState.h"
@@ -22,19 +20,15 @@
   }
 
   // watch for ENV signatures
-  const char* variable = args[0].c_str(); // VAR is always first
-  if (cmHasLiteralPrefix(variable, "ENV{") && strlen(variable) > 5) {
+  auto const& variable = args[0]; // VAR is always first
+  if (cmHasLiteralPrefix(variable, "ENV{") && variable.size() > 5) {
     // what is the variable name
-    char* varName = new char[strlen(variable)];
-    strncpy(varName, variable + 4, strlen(variable) - 5);
-    varName[strlen(variable) - 5] = '\0';
-    std::string putEnvArg = varName;
-    putEnvArg += "=";
+    auto const& varName = variable.substr(4, variable.size() - 5);
+    std::string putEnvArg = varName + "=";
 
     // what is the current value if any
     std::string currValue;
     const bool currValueSet = cmSystemTools::GetEnv(varName, currValue);
-    delete[] varName;
 
     // will it be set to something, then set it
     if (args.size() > 1 && !args[1].empty()) {
diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx
index 4f337f2..6add7b3 100644
--- a/Source/cmSourceFileLocation.cxx
+++ b/Source/cmSourceFileLocation.cxx
@@ -8,9 +8,7 @@
 #include "cmSystemTools.h"
 #include "cmake.h"
 
-#include <algorithm>
 #include <assert.h>
-#include <vector>
 
 cmSourceFileLocation::cmSourceFileLocation()
   : Makefile(nullptr)
@@ -86,13 +84,9 @@
   // The global generator checks extensions of enabled languages.
   cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
   cmMakefile const* mf = this->Makefile;
-  const std::vector<std::string>& srcExts =
-    mf->GetCMakeInstance()->GetSourceExtensions();
-  const std::vector<std::string>& hdrExts =
-    mf->GetCMakeInstance()->GetHeaderExtensions();
+  auto cm = mf->GetCMakeInstance();
   if (!gg->GetLanguageFromExtension(ext.c_str()).empty() ||
-      std::find(srcExts.begin(), srcExts.end(), ext) != srcExts.end() ||
-      std::find(hdrExts.begin(), hdrExts.end(), ext) != hdrExts.end()) {
+      cm->IsSourceExtension(ext) || cm->IsHeaderExtension(ext)) {
     // This is a known extension.  Use the given filename with extension.
     this->Name = cmSystemTools::GetFilenameName(name);
     this->AmbiguousExtension = false;
@@ -149,14 +143,8 @@
   // disk.  One of these must match if loc refers to this source file.
   std::string const& ext = this->Name.substr(loc.Name.size() + 1);
   cmMakefile const* mf = this->Makefile;
-  const std::vector<std::string>& srcExts =
-    mf->GetCMakeInstance()->GetSourceExtensions();
-  if (std::find(srcExts.begin(), srcExts.end(), ext) != srcExts.end()) {
-    return true;
-  }
-  std::vector<std::string> hdrExts =
-    mf->GetCMakeInstance()->GetHeaderExtensions();
-  return std::find(hdrExts.begin(), hdrExts.end(), ext) != hdrExts.end();
+  auto cm = mf->GetCMakeInstance();
+  return cm->IsSourceExtension(ext) || cm->IsHeaderExtension(ext);
 }
 
 bool cmSourceFileLocation::Matches(cmSourceFileLocation const& loc)
diff --git a/Source/cmSourceGroup.cxx b/Source/cmSourceGroup.cxx
index fba4c31..18bcb49 100644
--- a/Source/cmSourceGroup.cxx
+++ b/Source/cmSourceGroup.cxx
@@ -60,14 +60,14 @@
   this->GroupFiles.insert(name);
 }
 
-const char* cmSourceGroup::GetName() const
+std::string const& cmSourceGroup::GetName() const
 {
-  return this->Name.c_str();
+  return this->Name;
 }
 
-const char* cmSourceGroup::GetFullName() const
+std::string const& cmSourceGroup::GetFullName() const
 {
-  return this->FullName.c_str();
+  return this->FullName;
 }
 
 bool cmSourceGroup::MatchesRegex(const char* name)
@@ -105,7 +105,7 @@
 
   // st
   for (; iter != end; ++iter) {
-    std::string sgName = iter->GetName();
+    std::string const& sgName = iter->GetName();
 
     // look if descenened is the one were looking for
     if (sgName == name) {
diff --git a/Source/cmSourceGroup.h b/Source/cmSourceGroup.h
index e8bd697..7c7c35f 100644
--- a/Source/cmSourceGroup.h
+++ b/Source/cmSourceGroup.h
@@ -55,12 +55,12 @@
   /**
    * Get the name of this group.
    */
-  const char* GetName() const;
+  std::string const& GetName() const;
 
   /**
    * Get the full path name for group.
    */
-  const char* GetFullName() const;
+  std::string const& GetFullName() const;
 
   /**
    * Check if the given name matches this group's regex.
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 63c1452..5d1f5f7 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -50,6 +50,8 @@
 #include <windows.h>
 // include wincrypt.h after windows.h
 #include <wincrypt.h>
+
+#include "cm_uv.h"
 #else
 #include <sys/time.h>
 #include <unistd.h>
@@ -943,6 +945,39 @@
   }
   return retry;
 }
+
+std::string cmSystemTools::GetRealPath(const std::string& path,
+                                       std::string* errorMessage)
+{
+  // uv_fs_realpath uses Windows Vista API so fallback to kwsys if not found
+  std::string resolved_path;
+  uv_fs_t req;
+  int err = uv_fs_realpath(NULL, &req, path.c_str(), NULL);
+  if (!err) {
+    resolved_path = std::string((char*)req.ptr);
+    cmSystemTools::ConvertToUnixSlashes(resolved_path);
+    // Normalize to upper-case drive letter as GetActualCaseForPath does.
+    if (resolved_path.size() > 1 && resolved_path[1] == ':') {
+      resolved_path[0] = toupper(resolved_path[0]);
+    }
+  } else if (err == UV_ENOSYS) {
+    resolved_path = cmsys::SystemTools::GetRealPath(path, errorMessage);
+  } else if (errorMessage) {
+    LPSTR message = NULL;
+    DWORD size = FormatMessageA(
+      FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+        FORMAT_MESSAGE_IGNORE_INSERTS,
+      NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&message, 0,
+      NULL);
+    *errorMessage = std::string(message, size);
+    LocalFree(message);
+
+    resolved_path = "";
+  } else {
+    resolved_path = path;
+  }
+  return resolved_path;
+}
 #endif
 
 bool cmSystemTools::RenameFile(const char* oldname, const char* newname)
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index e7082e6..2646df9 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -497,6 +497,10 @@
     unsigned int Delay;
   };
   static WindowsFileRetry GetWindowsFileRetry();
+
+  /** Get the real path for a given path, removing all symlinks. */
+  static std::string GetRealPath(const std::string& path,
+                                 std::string* errorMessage = 0);
 #endif
 private:
   static bool s_ForceUnixPaths;
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index c6cd502..bf36074 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -279,6 +279,7 @@
     this->SetPropertyDefault("CUDA_STANDARD_REQUIRED", nullptr);
     this->SetPropertyDefault("CUDA_EXTENSIONS", nullptr);
     this->SetPropertyDefault("CUDA_COMPILER_LAUNCHER", nullptr);
+    this->SetPropertyDefault("CUDA_SEPARABLE_COMPILATION", nullptr);
     this->SetPropertyDefault("LINK_SEARCH_START_STATIC", nullptr);
     this->SetPropertyDefault("LINK_SEARCH_END_STATIC", nullptr);
   }
@@ -884,6 +885,13 @@
     this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
     return;
   }
+  if (prop == "IMPORTED_GLOBAL" && !this->IsImported()) {
+    std::ostringstream e;
+    e << "IMPORTED_GLOBAL property can't be set on non-imported targets (\""
+      << this->Name << "\")\n";
+    this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+    return;
+  }
 
   if (prop == "INCLUDE_DIRECTORIES") {
     this->Internal->IncludeDirectoriesEntries.clear();
@@ -933,6 +941,19 @@
       this->Internal->SourceEntries.push_back(value);
       this->Internal->SourceBacktraces.push_back(lfbt);
     }
+  } else if (prop == "IMPORTED_GLOBAL") {
+    if (!cmSystemTools::IsOn(value)) {
+      std::ostringstream e;
+      e << "IMPORTED_GLOBAL property can't be set to FALSE on targets (\""
+        << this->Name << "\")\n";
+      this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+      return;
+    }
+    /* no need to change anything if value does not change */
+    if (!this->ImportedGloballyVisible) {
+      this->ImportedGloballyVisible = true;
+      this->GetGlobalGenerator()->IndexTarget(this);
+    }
   } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME") &&
              !this->CheckImportedLibName(prop, value ? value : "")) {
     /* error was reported by check method */
@@ -977,6 +998,14 @@
     this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
     return;
   }
+  if (prop == "IMPORTED_GLOBAL") {
+    std::ostringstream e;
+    e << "IMPORTED_GLOBAL property can't be appended, only set on imported "
+         "targets (\""
+      << this->Name << "\")\n";
+    this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+    return;
+  }
   if (prop == "INCLUDE_DIRECTORIES") {
     if (value && *value) {
       this->Internal->IncludeDirectoriesEntries.push_back(value);
@@ -1143,6 +1172,21 @@
   context->IssueMessage(cmake::FATAL_ERROR, e.str());
 }
 
+static void cmTargetCheckIMPORTED_GLOBAL(const cmTarget* target,
+                                         cmMakefile* context)
+{
+  std::vector<cmTarget*> targets = context->GetOwnedImportedTargets();
+  std::vector<cmTarget*>::const_iterator it =
+    std::find(targets.begin(), targets.end(), target);
+  if (it == targets.end()) {
+    std::ostringstream e;
+    e << "Attempt to promote imported target \"" << target->GetName()
+      << "\" to global scope (by setting IMPORTED_GLOBAL) "
+         "which is not built in this directory.";
+    context->IssueMessage(cmake::FATAL_ERROR, e.str());
+  }
+}
+
 void cmTarget::CheckProperty(const std::string& prop,
                              cmMakefile* context) const
 {
@@ -1157,11 +1201,16 @@
       cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, value, context, true);
     }
   }
-  if (cmHasLiteralPrefix(prop, "INTERFACE_LINK_LIBRARIES")) {
+  if (prop == "INTERFACE_LINK_LIBRARIES") {
     if (const char* value = this->GetProperty(prop)) {
       cmTargetCheckINTERFACE_LINK_LIBRARIES(value, context);
     }
   }
+  if (prop == "IMPORTED_GLOBAL") {
+    if (this->IsImported()) {
+      cmTargetCheckIMPORTED_GLOBAL(this, context);
+    }
+  }
 }
 
 const char* cmTarget::GetComputedProperty(
@@ -1182,6 +1231,7 @@
   MAKE_STATIC_PROP(COMPILE_OPTIONS);
   MAKE_STATIC_PROP(COMPILE_DEFINITIONS);
   MAKE_STATIC_PROP(IMPORTED);
+  MAKE_STATIC_PROP(IMPORTED_GLOBAL);
   MAKE_STATIC_PROP(MANUALLY_ADDED_DEPENDENCIES);
   MAKE_STATIC_PROP(NAME);
   MAKE_STATIC_PROP(BINARY_DIR);
@@ -1196,6 +1246,7 @@
     specialProps.insert(propCOMPILE_OPTIONS);
     specialProps.insert(propCOMPILE_DEFINITIONS);
     specialProps.insert(propIMPORTED);
+    specialProps.insert(propIMPORTED_GLOBAL);
     specialProps.insert(propMANUALLY_ADDED_DEPENDENCIES);
     specialProps.insert(propNAME);
     specialProps.insert(propBINARY_DIR);
@@ -1264,6 +1315,9 @@
     if (prop == propIMPORTED) {
       return this->IsImported() ? "TRUE" : "FALSE";
     }
+    if (prop == propIMPORTED_GLOBAL) {
+      return this->IsImportedGloballyVisible() ? "TRUE" : "FALSE";
+    }
     if (prop == propNAME) {
       return this->GetName().c_str();
     }
diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx
index d159d41..bd4121d 100644
--- a/Source/cmTargetCompileDefinitionsCommand.cxx
+++ b/Source/cmTargetCompileDefinitionsCommand.cxx
@@ -17,15 +17,6 @@
   return this->HandleArguments(args, "COMPILE_DEFINITIONS");
 }
 
-void cmTargetCompileDefinitionsCommand::HandleImportedTarget(
-  const std::string& tgt)
-{
-  std::ostringstream e;
-  e << "Cannot specify compile definitions for imported target \"" << tgt
-    << "\".";
-  this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
-
 void cmTargetCompileDefinitionsCommand::HandleMissingTarget(
   const std::string& name)
 {
@@ -56,5 +47,5 @@
   cmTarget* tgt, const std::vector<std::string>& content, bool, bool)
 {
   tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content).c_str());
-  return true;
+  return true; // Successfully handled.
 }
diff --git a/Source/cmTargetCompileDefinitionsCommand.h b/Source/cmTargetCompileDefinitionsCommand.h
index f910452..d41483a 100644
--- a/Source/cmTargetCompileDefinitionsCommand.h
+++ b/Source/cmTargetCompileDefinitionsCommand.h
@@ -30,7 +30,6 @@
                    cmExecutionStatus& status) override;
 
 private:
-  void HandleImportedTarget(const std::string& tgt) override;
   void HandleMissingTarget(const std::string& name) override;
 
   bool HandleDirectContent(cmTarget* tgt,
diff --git a/Source/cmTargetCompileFeaturesCommand.cxx b/Source/cmTargetCompileFeaturesCommand.cxx
index 722bbe5..f58e404 100644
--- a/Source/cmTargetCompileFeaturesCommand.cxx
+++ b/Source/cmTargetCompileFeaturesCommand.cxx
@@ -17,15 +17,6 @@
   return this->HandleArguments(args, "COMPILE_FEATURES", NO_FLAGS);
 }
 
-void cmTargetCompileFeaturesCommand::HandleImportedTarget(
-  const std::string& tgt)
-{
-  std::ostringstream e;
-  e << "Cannot specify compile features for imported target \"" << tgt
-    << "\".";
-  this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
-
 void cmTargetCompileFeaturesCommand::HandleMissingTarget(
   const std::string& name)
 {
@@ -49,8 +40,8 @@
     std::string error;
     if (!this->Makefile->AddRequiredTargetFeature(tgt, it, &error)) {
       this->SetError(error);
-      return false;
+      return false; // Not (successfully) handled.
     }
   }
-  return true;
+  return true; // Successfully handled.
 }
diff --git a/Source/cmTargetCompileFeaturesCommand.h b/Source/cmTargetCompileFeaturesCommand.h
index 444d260..45240a5 100644
--- a/Source/cmTargetCompileFeaturesCommand.h
+++ b/Source/cmTargetCompileFeaturesCommand.h
@@ -22,7 +22,6 @@
                    cmExecutionStatus& status) override;
 
 private:
-  void HandleImportedTarget(const std::string& tgt) override;
   void HandleMissingTarget(const std::string& name) override;
 
   bool HandleDirectContent(cmTarget* tgt,
diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx
index 1b4056d..4df3630 100644
--- a/Source/cmTargetCompileOptionsCommand.cxx
+++ b/Source/cmTargetCompileOptionsCommand.cxx
@@ -18,21 +18,12 @@
   return this->HandleArguments(args, "COMPILE_OPTIONS", PROCESS_BEFORE);
 }
 
-void cmTargetCompileOptionsCommand::HandleImportedTarget(
-  const std::string& tgt)
-{
-  std::ostringstream e;
-  e << "Cannot specify compile options for imported target \"" << tgt << "\".";
-  this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
-
 void cmTargetCompileOptionsCommand::HandleMissingTarget(
   const std::string& name)
 {
   std::ostringstream e;
   e << "Cannot specify compile options for target \"" << name
-    << "\" "
-       "which is not built by this project.";
+    << "\" which is not built by this project.";
   this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
 }
 
@@ -47,5 +38,5 @@
 {
   cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
   tgt->InsertCompileOption(this->Join(content), lfbt);
-  return true;
+  return true; // Successfully handled.
 }
diff --git a/Source/cmTargetCompileOptionsCommand.h b/Source/cmTargetCompileOptionsCommand.h
index 3fab238..6fb151a 100644
--- a/Source/cmTargetCompileOptionsCommand.h
+++ b/Source/cmTargetCompileOptionsCommand.h
@@ -30,7 +30,6 @@
                    cmExecutionStatus& status) override;
 
 private:
-  void HandleImportedTarget(const std::string& tgt) override;
   void HandleMissingTarget(const std::string& name) override;
 
   bool HandleDirectContent(cmTarget* tgt,
diff --git a/Source/cmTargetDepend.h b/Source/cmTargetDepend.h
index daa902e..b698db6 100644
--- a/Source/cmTargetDepend.h
+++ b/Source/cmTargetDepend.h
@@ -16,7 +16,7 @@
   cmGeneratorTarget const* Target;
 
   // The set order depends only on the Target, so we use
-  // mutable members to acheive a map with set syntax.
+  // mutable members to achieve a map with set syntax.
   mutable bool Link;
   mutable bool Util;
 
diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx
index 4646c7e..dcec830 100644
--- a/Source/cmTargetIncludeDirectoriesCommand.cxx
+++ b/Source/cmTargetIncludeDirectoriesCommand.cxx
@@ -21,22 +21,12 @@
                                ArgumentFlags(PROCESS_BEFORE | PROCESS_SYSTEM));
 }
 
-void cmTargetIncludeDirectoriesCommand::HandleImportedTarget(
-  const std::string& tgt)
-{
-  std::ostringstream e;
-  e << "Cannot specify include directories for imported target \"" << tgt
-    << "\".";
-  this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
-
 void cmTargetIncludeDirectoriesCommand::HandleMissingTarget(
   const std::string& name)
 {
   std::ostringstream e;
   e << "Cannot specify include directories for target \"" << name
-    << "\" "
-       "which is not built by this project.";
+    << "\" which is not built by this project.";
   this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
 }
 
@@ -79,7 +69,7 @@
     }
     tgt->AddSystemIncludeDirectories(sdirs);
   }
-  return true;
+  return true; // Successfully handled.
 }
 
 void cmTargetIncludeDirectoriesCommand::HandleInterfaceContent(
diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h
index 27a2f43..57bf8fc 100644
--- a/Source/cmTargetIncludeDirectoriesCommand.h
+++ b/Source/cmTargetIncludeDirectoriesCommand.h
@@ -30,7 +30,6 @@
                    cmExecutionStatus& status) override;
 
 private:
-  void HandleImportedTarget(const std::string& tgt) override;
   void HandleMissingTarget(const std::string& name) override;
 
   bool HandleDirectContent(cmTarget* tgt,
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index dda0464..37bcb70 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -40,6 +40,16 @@
     this->Makefile->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(
       args[0]);
   if (!this->Target) {
+    const std::vector<cmTarget*>& importedTargets =
+      this->Makefile->GetOwnedImportedTargets();
+    for (cmTarget* importedTarget : importedTargets) {
+      if (importedTarget->GetName() == args[0]) {
+        this->Target = importedTarget;
+        break;
+      }
+    }
+  }
+  if (!this->Target) {
     cmake::MessageType t = cmake::FATAL_ERROR; // fail by default
     std::ostringstream e;
     e << "Cannot specify link libraries for target \"" << args[0] << "\" "
@@ -228,7 +238,7 @@
     } else {
       // Lookup old-style cache entry if type is unspecified.  So if you
       // do a target_link_libraries(foo optimized bar) it will stay optimized
-      // and not use the lookup.  As there maybe the case where someone has
+      // and not use the lookup.  As there may be the case where someone has
       // specifed that a library is both debug and optimized.  (this check is
       // only there for backwards compatibility when mixing projects built
       // with old versions of CMake and new)
@@ -299,6 +309,14 @@
       "target_link_libraries");
     return false;
   }
+  if (this->Target->IsImported() &&
+      this->CurrentProcessingState != ProcessingKeywordLinkInterface) {
+    this->Makefile->IssueMessage(
+      cmake::FATAL_ERROR,
+      "IMPORTED library can only be used with the INTERFACE keyword of "
+      "target_link_libraries");
+    return false;
+  }
 
   cmTarget::TLLSignature sig =
     (this->CurrentProcessingState == ProcessingPlainPrivateInterface ||
@@ -355,6 +373,16 @@
     cmTarget* t =
       this->Makefile->FindLocalNonAliasTarget(this->Target->GetName());
     if (!t) {
+      const std::vector<cmTarget*>& importedTargets =
+        this->Makefile->GetOwnedImportedTargets();
+      for (cmTarget* importedTarget : importedTargets) {
+        if (importedTarget->GetName() == this->Target->GetName()) {
+          t = importedTarget;
+          break;
+        }
+      }
+    }
+    if (!t) {
       std::ostringstream e;
       e << "Attempt to add link library \"" << lib << "\" to target \""
         << this->Target->GetName()
diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx
index 45fe430..9a8fd96 100644
--- a/Source/cmTargetPropCommandBase.cxx
+++ b/Source/cmTargetPropCommandBase.cxx
@@ -17,11 +17,11 @@
     return false;
   }
 
-  // Lookup the target for which libraries are specified.
   if (this->Makefile->IsAlias(args[0])) {
     this->SetError("can not be used on an ALIAS target.");
     return false;
   }
+  // Lookup the target for which property-values are specified.
   this->Target =
     this->Makefile->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(
       args[0]);
@@ -84,16 +84,13 @@
     this->SetError("called with invalid arguments");
     return false;
   }
-
-  if (this->Target->IsImported()) {
-    this->HandleImportedTarget(args[0]);
-    return false;
-  }
-
   if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
       scope != "INTERFACE") {
-    this->SetError("may only be set INTERFACE properties on INTERFACE "
-                   "targets");
+    this->SetError("may only set INTERFACE properties on INTERFACE targets");
+    return false;
+  }
+  if (this->Target->IsImported() && scope != "INTERFACE") {
+    this->SetError("may only set INTERFACE properties on IMPORTED targets");
     return false;
   }
 
diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h
index 46a2f6b..3c736fc 100644
--- a/Source/cmTargetPropCommandBase.h
+++ b/Source/cmTargetPropCommandBase.h
@@ -35,7 +35,6 @@
                                       bool prepend, bool system);
 
 private:
-  virtual void HandleImportedTarget(const std::string& tgt) = 0;
   virtual void HandleMissingTarget(const std::string& name) = 0;
 
   virtual bool HandleDirectContent(cmTarget* tgt,
diff --git a/Source/cmTargetPropertyComputer.cxx b/Source/cmTargetPropertyComputer.cxx
index 1d2520d..ed9026e 100644
--- a/Source/cmTargetPropertyComputer.cxx
+++ b/Source/cmTargetPropertyComputer.cxx
@@ -57,6 +57,7 @@
     builtIns.insert("COMPATIBLE_INTERFACE_STRING");
     builtIns.insert("EXPORT_NAME");
     builtIns.insert("IMPORTED");
+    builtIns.insert("IMPORTED_GLOBAL");
     builtIns.insert("NAME");
     builtIns.insert("TYPE");
   }
diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx
index 058659a..3dd3748 100644
--- a/Source/cmTargetSourcesCommand.cxx
+++ b/Source/cmTargetSourcesCommand.cxx
@@ -17,13 +17,6 @@
   return this->HandleArguments(args, "SOURCES");
 }
 
-void cmTargetSourcesCommand::HandleImportedTarget(const std::string& tgt)
-{
-  std::ostringstream e;
-  e << "Cannot specify sources for imported target \"" << tgt << "\".";
-  this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
-
 void cmTargetSourcesCommand::HandleMissingTarget(const std::string& name)
 {
   std::ostringstream e;
@@ -43,5 +36,5 @@
   cmTarget* tgt, const std::vector<std::string>& content, bool, bool)
 {
   tgt->AppendProperty("SOURCES", this->Join(content).c_str());
-  return true;
+  return true; // Successfully handled.
 }
diff --git a/Source/cmTargetSourcesCommand.h b/Source/cmTargetSourcesCommand.h
index 0639e98..ea8776a 100644
--- a/Source/cmTargetSourcesCommand.h
+++ b/Source/cmTargetSourcesCommand.h
@@ -30,7 +30,6 @@
                    cmExecutionStatus& status) override;
 
 private:
-  void HandleImportedTarget(const std::string& tgt) override;
   void HandleMissingTarget(const std::string& name) override;
 
   bool HandleDirectContent(cmTarget* tgt,
diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx
index 9fb79d9..f1e9283 100644
--- a/Source/cmTimestamp.cxx
+++ b/Source/cmTimestamp.cxx
@@ -33,11 +33,13 @@
                                               const std::string& formatString,
                                               bool utcFlag)
 {
-  if (!cmsys::SystemTools::FileExists(path)) {
+  std::string real_path = cmSystemTools::GetRealPath(path);
+
+  if (!cmsys::SystemTools::FileExists(real_path)) {
     return std::string();
   }
 
-  time_t mtime = cmsys::SystemTools::ModifiedTime(path);
+  time_t mtime = cmsys::SystemTools::ModifiedTime(real_path);
   return CreateTimestampFromTimeT(mtime, formatString, utcFlag);
 }
 
@@ -151,7 +153,7 @@
       if (unixEpoch == -1) {
         cmSystemTools::Error(
           "Error generating UNIX epoch in "
-          "STRING(TIMESTAMP ...). Please, file a bug report aginst CMake");
+          "STRING(TIMESTAMP ...). Please, file a bug report against CMake");
         return std::string();
       }
 
diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx
index dcaa493..932b976 100644
--- a/Source/cmTryRunCommand.cxx
+++ b/Source/cmTryRunCommand.cxx
@@ -4,7 +4,6 @@
 
 #include "cmsys/FStream.hxx"
 #include <stdio.h>
-#include <string.h>
 
 #include "cmMakefile.h"
 #include "cmState.h"
@@ -191,13 +190,15 @@
     finalCommand.c_str(), out, out, &retVal, nullptr,
     cmSystemTools::OUTPUT_NONE, timeout);
   // set the run var
-  char retChar[1000];
+  char retChar[16];
+  const char* retStr;
   if (worked) {
     sprintf(retChar, "%i", retVal);
+    retStr = retChar;
   } else {
-    strcpy(retChar, "FAILED_TO_RUN");
+    retStr = "FAILED_TO_RUN";
   }
-  this->Makefile->AddCacheDefinition(this->RunResultVariable, retChar,
+  this->Makefile->AddCacheDefinition(this->RunResultVariable, retStr,
                                      "Result of TRY_RUN",
                                      cmStateEnums::INTERNAL);
 }
diff --git a/Source/cmUnsetCommand.cxx b/Source/cmUnsetCommand.cxx
index 18bbdd7..cfaa1fd2 100644
--- a/Source/cmUnsetCommand.cxx
+++ b/Source/cmUnsetCommand.cxx
@@ -2,8 +2,6 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmUnsetCommand.h"
 
-#include <string.h>
-
 #include "cmAlgorithms.h"
 #include "cmMakefile.h"
 #include "cmSystemTools.h"
@@ -19,19 +17,16 @@
     return false;
   }
 
-  const char* variable = args[0].c_str();
+  auto const& variable = args[0];
 
   // unset(ENV{VAR})
-  if (cmHasLiteralPrefix(variable, "ENV{") && strlen(variable) > 5) {
+  if (cmHasLiteralPrefix(variable, "ENV{") && variable.size() > 5) {
     // what is the variable name
-    char* envVarName = new char[strlen(variable)];
-    strncpy(envVarName, variable + 4, strlen(variable) - 5);
-    envVarName[strlen(variable) - 5] = '\0';
+    auto const& envVarName = variable.substr(4, variable.size() - 5);
 
 #ifdef CMAKE_BUILD_WITH_CMAKE
-    cmSystemTools::UnsetEnv(envVarName);
+    cmSystemTools::UnsetEnv(envVarName.c_str());
 #endif
-    delete[] envVarName;
     return true;
   }
   // unset(VAR)
diff --git a/Source/cmUseMangledMesaCommand.cxx b/Source/cmUseMangledMesaCommand.cxx
index c04a683..8d4b018 100644
--- a/Source/cmUseMangledMesaCommand.cxx
+++ b/Source/cmUseMangledMesaCommand.cxx
@@ -13,8 +13,8 @@
                                           cmExecutionStatus&)
 {
   // expected two arguments:
-  // arguement one: the full path to gl_mangle.h
-  // arguement two : directory for output of edited headers
+  // argument one: the full path to gl_mangle.h
+  // argument two : directory for output of edited headers
   if (args.size() != 2) {
     this->SetError("called with incorrect number of arguments");
     return false;
diff --git a/Source/cmVS141CLFlagTable.h b/Source/cmVS141CLFlagTable.h
index c780d46..7d3e356 100644
--- a/Source/cmVS141CLFlagTable.h
+++ b/Source/cmVS141CLFlagTable.h
@@ -1,6 +1,10 @@
 static cmVS7FlagTable cmVS141CLFlagTable[] = {
 
   // Enum Properties
+  { "DiagnosticsFormat", "diagnostics:classic", "Classic", "Classic", 0 },
+  { "DiagnosticsFormat", "diagnostics:column", "Column", "Column", 0 },
+  { "DiagnosticsFormat", "diagnostics:caret", "Caret", "Caret", 0 },
+
   { "DebugInformationFormat", "", "None", "None", 0 },
   { "DebugInformationFormat", "Z7", "C7 compatible", "OldStyle", 0 },
   { "DebugInformationFormat", "Zi", "Program Database", "ProgramDatabase", 0 },
diff --git a/Source/cmVSSetupHelper.cxx b/Source/cmVSSetupHelper.cxx
index ea13649..c2f8deb 100644
--- a/Source/cmVSSetupHelper.cxx
+++ b/Source/cmVSSetupHelper.cxx
@@ -80,6 +80,14 @@
     CoUninitialize();
 }
 
+bool cmVSSetupAPIHelper::SetVSInstance(std::string const& vsInstallLocation)
+{
+  this->SpecifiedVSInstallLocation = vsInstallLocation;
+  cmSystemTools::ConvertToUnixSlashes(this->SpecifiedVSInstallLocation);
+  chosenInstanceInfo = VSInstanceInfo();
+  return this->EnumerateAndChooseVSInstance();
+}
+
 bool cmVSSetupAPIHelper::IsVS2017Installed()
 {
   return this->EnumerateAndChooseVSInstance();
@@ -265,13 +273,6 @@
   if (cmSystemTools::GetEnv("VS150COMNTOOLS", envVSCommonToolsDir)) {
     cmSystemTools::ConvertToUnixSlashes(envVSCommonToolsDir);
   }
-  // FIXME: If the environment variable value changes between runs
-  // of CMake within a given build tree the results are not defined.
-  // Instead we should save a CMAKE_GENERATOR_INSTANCE value in the cache
-  // (similar to CMAKE_GENERATOR_TOOLSET) to hold it persistently.
-  // Unfortunately doing so will require refactoring elsewhere in
-  // order to make sure the value is available in time to create
-  // the generator.
 
   std::vector<VSInstanceInfo> vecVSInstances;
   SmartCOMPtr<IEnumSetupInstances> enumInstances = NULL;
@@ -296,16 +297,29 @@
     instance = instance2 = NULL;
 
     if (isInstalled) {
-      if (!envVSCommonToolsDir.empty()) {
+      if (!this->SpecifiedVSInstallLocation.empty()) {
+        // We are looking for a specific instance.
         std::string currentVSLocation = instanceInfo.GetInstallLocation();
-        currentVSLocation += "/Common7/Tools";
         if (cmSystemTools::ComparePath(currentVSLocation,
-                                       envVSCommonToolsDir)) {
+                                       this->SpecifiedVSInstallLocation)) {
           chosenInstanceInfo = instanceInfo;
           return true;
         }
+      } else {
+        // We are not looking for a specific instance.
+        // If we've been given a hint then use it.
+        if (!envVSCommonToolsDir.empty()) {
+          std::string currentVSLocation = instanceInfo.GetInstallLocation();
+          currentVSLocation += "/Common7/Tools";
+          if (cmSystemTools::ComparePath(currentVSLocation,
+                                         envVSCommonToolsDir)) {
+            chosenInstanceInfo = instanceInfo;
+            return true;
+          }
+        }
+        // Otherwise, add this to the list of candidates.
+        vecVSInstances.push_back(instanceInfo);
       }
-      vecVSInstances.push_back(instanceInfo);
     }
   }
 
diff --git a/Source/cmVSSetupHelper.h b/Source/cmVSSetupHelper.h
index 74a7ec0..c07cfaf 100644
--- a/Source/cmVSSetupHelper.h
+++ b/Source/cmVSSetupHelper.h
@@ -126,6 +126,8 @@
   cmVSSetupAPIHelper();
   ~cmVSSetupAPIHelper();
 
+  bool SetVSInstance(std::string const& vsInstallLocation);
+
   bool IsVS2017Installed();
   bool GetVSInstanceInfo(std::string& vsInstallLocation);
   bool IsWin10SDKInstalled();
@@ -150,6 +152,8 @@
   HRESULT comInitialized;
   // current best instance of VS selected
   VSInstanceInfo chosenInstanceInfo;
+
+  std::string SpecifiedVSInstallLocation;
 };
 
 #endif
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index c61902a..caeeeb9 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -15,6 +15,7 @@
 #include "cmVisualStudioGeneratorOptions.h"
 #include "windows.h"
 
+#include <iterator>
 #include <memory> // IWYU pragma: keep
 
 static std::string cmVS10EscapeXML(std::string arg)
@@ -1174,6 +1175,15 @@
        si != customCommands.end(); ++si) {
     this->WriteCustomCommand(*si);
   }
+
+  // Add CMakeLists.txt file with rule to re-run CMake for user convenience.
+  if (this->GeneratorTarget->GetType() != cmStateEnums::GLOBAL_TARGET &&
+      this->GeneratorTarget->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
+    if (cmSourceFile const* sf =
+          this->LocalGenerator->CreateVCProjBuildRule()) {
+      this->WriteCustomCommand(sf);
+    }
+  }
 }
 
 void cmVisualStudio10TargetGenerator::WriteCustomCommand(
@@ -1459,11 +1469,14 @@
   }
 
   this->WriteString("<ItemGroup>\n", 1);
-  for (std::set<cmSourceGroup*>::iterator g = groupsUsed.begin();
-       g != groupsUsed.end(); ++g) {
-    cmSourceGroup* sg = *g;
-    const char* name = sg->GetFullName();
-    if (strlen(name) != 0) {
+  std::vector<cmSourceGroup*> groupsVec(groupsUsed.begin(), groupsUsed.end());
+  std::sort(groupsVec.begin(), groupsVec.end(),
+            [](cmSourceGroup* l, cmSourceGroup* r) {
+              return l->GetFullName() < r->GetFullName();
+            });
+  for (cmSourceGroup* sg : groupsVec) {
+    std::string const& name = sg->GetFullName();
+    if (!name.empty()) {
       this->WriteString("<Filter Include=\"", 2);
       (*this->BuildFileStream) << name << "\">\n";
       std::string guidName = "SG_Filter_";
@@ -1548,12 +1561,12 @@
     std::string const& source = sf->GetFullPath();
     cmSourceGroup* sourceGroup =
       this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
-    const char* filter = sourceGroup->GetFullName();
+    std::string const& filter = sourceGroup->GetFullName();
     this->WriteString("<", 2);
     std::string path = this->ConvertPath(source, s->RelativePath);
     this->ConvertToWindowsSlash(path);
     (*this->BuildFileStream) << name << " Include=\"" << cmVS10EscapeXML(path);
-    if (strlen(filter)) {
+    if (!filter.empty()) {
       (*this->BuildFileStream) << "\">\n";
       this->WriteString("<Filter>", 3);
       (*this->BuildFileStream) << filter << "</Filter>\n";
@@ -1592,6 +1605,8 @@
   std::string shaderEntryPoint;
   std::string shaderModel;
   std::string shaderAdditionalFlags;
+  std::string shaderDisableOptimizations;
+  std::string shaderEnableDebug;
   std::string outputHeaderFile;
   std::string variableName;
   std::string settingsGenerator;
@@ -1658,6 +1673,16 @@
       shaderAdditionalFlags = saf;
       toolHasSettings = true;
     }
+    // Figure out if debug information should be generated
+    if (const char* sed = sf->GetProperty("VS_SHADER_ENABLE_DEBUG")) {
+      shaderEnableDebug = cmSystemTools::IsOn(sed) ? "true" : "false";
+      toolHasSettings = true;
+    }
+    // Figure out if optimizations should be disabled
+    if (const char* sdo = sf->GetProperty("VS_SHADER_DISABLE_OPTIMIZATIONS")) {
+      shaderDisableOptimizations = cmSystemTools::IsOn(sdo) ? "true" : "false";
+      toolHasSettings = true;
+    }
   } else if (ext == "jpg" || ext == "png") {
     tool = "Image";
   } else if (ext == "resw") {
@@ -1667,12 +1692,8 @@
   } else if (ext == "natvis") {
     tool = "Natvis";
   } else if (ext == "settings") {
-    // remove path to current source dir (if files are in current source dir)
-    if (!sourceLink.empty()) {
-      settingsLastGenOutput = sourceLink;
-    } else {
-      settingsLastGenOutput = sf->GetFullPath();
-    }
+    settingsLastGenOutput =
+      cmsys::SystemTools::GetFilenameName(sf->GetFullPath());
     std::size_t pos = settingsLastGenOutput.find(".settings");
     settingsLastGenOutput.replace(pos, 9, ".Designer.cs");
     settingsGenerator = "SettingsSingleFileGenerator";
@@ -1800,6 +1821,16 @@
         this->WriteString("</VariableName>\n", 0);
       }
     }
+    if (!shaderEnableDebug.empty()) {
+      this->WriteString("<EnableDebuggingInformation>", 3);
+      (*this->BuildFileStream) << cmVS10EscapeXML(shaderEnableDebug)
+                               << "</EnableDebuggingInformation>\n";
+    }
+    if (!shaderDisableOptimizations.empty()) {
+      this->WriteString("<DisableOptimizations>", 3);
+      (*this->BuildFileStream) << cmVS10EscapeXML(shaderDisableOptimizations)
+                               << "</DisableOptimizations>\n";
+    }
     if (!shaderAdditionalFlags.empty()) {
       this->WriteString("<AdditionalOptions>", 3);
       (*this->BuildFileStream) << cmVS10EscapeXML(shaderAdditionalFlags)
@@ -2359,14 +2390,14 @@
   // Choose a language whose flags to use for ClCompile.
   static const char* clLangs[] = { "CXX", "C", "Fortran", "CSharp" };
   std::string langForClCompile;
-  if (std::find(cmArrayBegin(clLangs), cmArrayEnd(clLangs), linkLanguage) !=
-      cmArrayEnd(clLangs)) {
+  if (std::find(cm::cbegin(clLangs), cm::cend(clLangs), linkLanguage) !=
+      cm::cend(clLangs)) {
     langForClCompile = linkLanguage;
   } else {
     std::set<std::string> languages;
     this->GeneratorTarget->GetLanguages(languages, configName);
-    for (const char* const* l = cmArrayBegin(clLangs);
-         l != cmArrayEnd(clLangs); ++l) {
+    for (const char* const* l = cm::cbegin(clLangs); l != cm::cend(clLangs);
+         ++l) {
       if (languages.find(*l) != languages.end()) {
         langForClCompile = *l;
         break;
diff --git a/Source/cmXCodeObject.cxx b/Source/cmXCodeObject.cxx
index e54f1f3..1747c9c 100644
--- a/Source/cmXCodeObject.cxx
+++ b/Source/cmXCodeObject.cxx
@@ -115,16 +115,15 @@
   if (separator == "\n") {
     out << separator;
   }
-  std::map<std::string, cmXCodeObject*>::iterator i;
   cmXCodeObject::Indent(3 * indentFactor, out);
   out << "isa = " << PBXTypeNames[this->IsA] << ";" << separator;
-  for (i = this->ObjectAttributes.begin(); i != this->ObjectAttributes.end();
-       ++i) {
-    if (i->first == "isa") {
+  for (const auto& keyVal : this->ObjectAttributes) {
+    if (keyVal.first == "isa") {
       continue;
     }
 
-    PrintAttribute(out, 3, separator, indentFactor, i->first, i->second, this);
+    PrintAttribute(out, 3, separator, indentFactor, keyVal.first,
+                   keyVal.second, this);
   }
   cmXCodeObject::Indent(2 * indentFactor, out);
   out << "};\n";
@@ -167,11 +166,9 @@
       if (separator == "\n") {
         out << separator;
       }
-      std::map<std::string, cmXCodeObject*>::const_iterator i;
-      for (i = object->ObjectAttributes.begin();
-           i != object->ObjectAttributes.end(); ++i) {
-        PrintAttribute(out, (level + 1) * factor, separator, factor, i->first,
-                       i->second, object);
+      for (const auto& keyVal : object->ObjectAttributes) {
+        PrintAttribute(out, (level + 1) * factor, separator, factor,
+                       keyVal.first, keyVal.second, object);
       }
       cmXCodeObject::Indent(level * factor, out);
       out << "};" << separator;
@@ -221,7 +218,7 @@
   this->Object = copy->Object;
 }
 
-void cmXCodeObject::PrintString(std::ostream& os, std::string String)
+void cmXCodeObject::PrintString(std::ostream& os, const std::string& String)
 {
   // The string needs to be quoted if it contains any characters
   // considered special by the Xcode project file parser.
@@ -234,13 +231,12 @@
 
   // Print the string, quoted and escaped as necessary.
   os << quote;
-  for (std::string::const_iterator i = String.begin(); i != String.end();
-       ++i) {
-    if (*i == '"' || *i == '\\') {
+  for (auto c : String) {
+    if (c == '"' || c == '\\') {
       // Escape double-quotes and backslashes.
       os << '\\';
     }
-    os << *i;
+    os << c;
   }
   os << quote;
 }
diff --git a/Source/cmXCodeObject.h b/Source/cmXCodeObject.h
index b0f1d31..51e5d36 100644
--- a/Source/cmXCodeObject.h
+++ b/Source/cmXCodeObject.h
@@ -150,7 +150,7 @@
     return this->List;
   }
   void SetComment(const std::string& c) { this->Comment = c; }
-  static void PrintString(std::ostream& os, std::string String);
+  static void PrintString(std::ostream& os, const std::string& String);
 
 protected:
   void PrintString(std::ostream& os) const;
diff --git a/Source/cmXMLWriter.h b/Source/cmXMLWriter.h
index 981255d..c890acf 100644
--- a/Source/cmXMLWriter.h
+++ b/Source/cmXMLWriter.h
@@ -7,6 +7,8 @@
 
 #include "cmXMLSafe.h"
 
+#include <chrono>
+#include <ctime>
 #include <ostream>
 #include <stack>
 #include <string>
@@ -99,6 +101,22 @@
     return cmXMLSafe(value).Quotes(false);
   }
 
+  /*
+   * Convert a std::chrono::system::time_point to the number of seconds since
+   * the UN*X epoch.
+   *
+   * It would be tempting to convert a time_point to number of seconds by
+   * using time_since_epoch(). Unfortunately the C++11 standard does not
+   * specify what the epoch of the system_clock must be.
+   * Therefore we must assume it is an arbitary point in time. Instead of this
+   * method, it is recommended to convert it by means of the to_time_t method.
+   */
+  static std::time_t SafeContent(
+    std::chrono::system_clock::time_point const& value)
+  {
+    return std::chrono::system_clock::to_time_t(value);
+  }
+
   template <typename T>
   static T SafeContent(T value)
   {
diff --git a/Source/cm_codecvt.cxx b/Source/cm_codecvt.cxx
index cf55741..6705851 100644
--- a/Source/cm_codecvt.cxx
+++ b/Source/cm_codecvt.cxx
@@ -38,12 +38,14 @@
   }
 }
 
-codecvt::~codecvt(){};
+codecvt::~codecvt()
+{
+}
 
 bool codecvt::do_always_noconv() const throw()
 {
   return m_noconv;
-};
+}
 
 std::codecvt_base::result codecvt::do_out(mbstate_t& state, const char* from,
                                           const char* from_end,
@@ -122,7 +124,7 @@
   static_cast<void>(to_next);
   return std::codecvt_base::noconv;
 #endif
-};
+}
 
 std::codecvt_base::result codecvt::do_unshift(mbstate_t& state, char* to,
                                               char* to_end,
@@ -143,7 +145,7 @@
   static_cast<void>(to_end);
   return std::codecvt_base::ok;
 #endif
-};
+}
 
 #if defined(_WIN32)
 std::codecvt_base::result codecvt::Decode(mbstate_t& state, int size,
@@ -235,9 +237,9 @@
 int codecvt::do_max_length() const throw()
 {
   return 4;
-};
+}
 
 int codecvt::do_encoding() const throw()
 {
   return 0;
-};
+}
diff --git a/Source/cm_thread.hxx b/Source/cm_thread.hxx
new file mode 100644
index 0000000..b8c25c7
--- /dev/null
+++ b/Source/cm_thread.hxx
@@ -0,0 +1,78 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef CM_THREAD_HXX
+#define CM_THREAD_HXX
+
+#include "cmConfigure.h" // IWYU pragma: keep
+#include "cm_uv.h"
+
+namespace cm {
+class mutex
+{
+  uv_mutex_t _M_;
+
+public:
+  mutex() { uv_mutex_init(&_M_); }
+  ~mutex() { uv_mutex_destroy(&_M_); }
+
+  void lock() { uv_mutex_lock(&_M_); }
+
+  void unlock() { uv_mutex_unlock(&_M_); }
+};
+
+template <typename T>
+class lock_guard
+{
+  T& _mutex;
+
+public:
+  lock_guard(T& m)
+    : _mutex(m)
+  {
+    _mutex.lock();
+  }
+  ~lock_guard() { _mutex.unlock(); }
+};
+
+class shared_mutex
+{
+  uv_rwlock_t _M_;
+
+public:
+  shared_mutex() { uv_rwlock_init(&_M_); }
+  ~shared_mutex() { uv_rwlock_destroy(&_M_); }
+
+  void lock() { uv_rwlock_wrlock(&_M_); }
+
+  void unlock() { uv_rwlock_wrunlock(&_M_); }
+
+  void lock_shared() { uv_rwlock_rdlock(&_M_); }
+
+  void unlock_shared() { uv_rwlock_rdunlock(&_M_); }
+};
+
+template <typename T>
+class shared_lock
+{
+  T& _mutex;
+
+public:
+  shared_lock(T& m)
+    : _mutex(m)
+  {
+    _mutex.lock_shared();
+  }
+  ~shared_lock() { _mutex.unlock_shared(); }
+};
+
+template <typename T>
+class unique_lock : public lock_guard<T>
+{
+public:
+  unique_lock(T& m)
+    : lock_guard<T>(m)
+  {
+  }
+};
+}
+#endif
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index fd7151f..2a5bb6c 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -110,6 +110,7 @@
 #include "cmsys/RegularExpression.hxx"
 #include <algorithm>
 #include <iostream>
+#include <iterator>
 #include <memory> // IWYU pragma: keep
 #include <sstream>
 #include <stdio.h>
@@ -199,6 +200,11 @@
   this->SourceFileExtensions.push_back("M");
   this->SourceFileExtensions.push_back("mm");
 
+  std::copy(this->SourceFileExtensions.begin(),
+            this->SourceFileExtensions.end(),
+            std::inserter(this->SourceFileExtensionsSet,
+                          this->SourceFileExtensionsSet.end()));
+
   this->HeaderFileExtensions.push_back("h");
   this->HeaderFileExtensions.push_back("hh");
   this->HeaderFileExtensions.push_back("h++");
@@ -207,6 +213,11 @@
   this->HeaderFileExtensions.push_back("hxx");
   this->HeaderFileExtensions.push_back("in");
   this->HeaderFileExtensions.push_back("txx");
+
+  std::copy(this->HeaderFileExtensions.begin(),
+            this->HeaderFileExtensions.end(),
+            std::inserter(this->HeaderFileExtensionsSet,
+                          this->HeaderFileExtensionsSet.end()));
 }
 
 cmake::~cmake()
@@ -1326,6 +1337,25 @@
                         cmStateEnums::INTERNAL);
   }
 
+  if (const char* instance =
+        this->State->GetInitializedCacheValue("CMAKE_GENERATOR_INSTANCE")) {
+    if (!this->GeneratorInstance.empty() &&
+        this->GeneratorInstance != instance) {
+      std::string message = "Error: generator instance: ";
+      message += this->GeneratorInstance;
+      message += "\nDoes not match the instance used previously: ";
+      message += instance;
+      message += "\nEither remove the CMakeCache.txt file and CMakeFiles "
+                 "directory or choose a different binary directory.";
+      cmSystemTools::Error(message.c_str());
+      return -2;
+    }
+  } else {
+    this->AddCacheEntry(
+      "CMAKE_GENERATOR_INSTANCE", this->GeneratorInstance.c_str(),
+      "Generator instance identifier.", cmStateEnums::INTERNAL);
+  }
+
   if (const char* platformName =
         this->State->GetInitializedCacheValue("CMAKE_GENERATOR_PLATFORM")) {
     if (!this->GeneratorPlatform.empty() &&
@@ -1453,12 +1483,12 @@
   if (vsSetupAPIHelper.IsVS2017Installed()) {
     found = "Visual Studio 15 2017";
   } else {
-    for (VSVersionedGenerator const* g = cmArrayBegin(vsGenerators);
-         found.empty() && g != cmArrayEnd(vsGenerators); ++g) {
-      for (const char* const* v = cmArrayBegin(vsVariants);
-           found.empty() && v != cmArrayEnd(vsVariants); ++v) {
-        for (const char* const* e = cmArrayBegin(vsEntries);
-             found.empty() && e != cmArrayEnd(vsEntries); ++e) {
+    for (VSVersionedGenerator const* g = cm::cbegin(vsGenerators);
+         found.empty() && g != cm::cend(vsGenerators); ++g) {
+      for (const char* const* v = cm::cbegin(vsVariants);
+           found.empty() && v != cm::cend(vsVariants); ++v) {
+        for (const char* const* e = cm::cbegin(vsEntries);
+             found.empty() && e != cm::cend(vsEntries); ++e) {
           std::string const reg = vsregBase + *v + g->MSVersion + *e;
           std::string dir;
           if (cmSystemTools::ReadRegistryValue(reg, dir,
@@ -1627,6 +1657,21 @@
   this->UnwatchUnusedCli(key);
 }
 
+std::string cmake::StripExtension(const std::string& file) const
+{
+  auto dotpos = file.rfind('.');
+  if (dotpos != std::string::npos) {
+    auto ext = file.substr(dotpos + 1);
+#if defined(_WIN32) || defined(__APPLE__)
+    ext = cmSystemTools::LowerCase(ext);
+#endif
+    if (this->IsSourceExtension(ext) || this->IsHeaderExtension(ext)) {
+      return file.substr(0, dotpos);
+    }
+  }
+  return file;
+}
+
 const char* cmake::GetCacheDefinition(const std::string& name) const
 {
   return this->State->GetInitializedCacheValue(name);
@@ -1716,8 +1761,8 @@
   bool result = this->State->LoadCache(path, internal, excludes, includes);
   static const char* entries[] = { "CMAKE_CACHE_MAJOR_VERSION",
                                    "CMAKE_CACHE_MINOR_VERSION" };
-  for (const char* const* nameIt = cmArrayBegin(entries);
-       nameIt != cmArrayEnd(entries); ++nameIt) {
+  for (const char* const* nameIt = cm::cbegin(entries);
+       nameIt != cm::cend(entries); ++nameIt) {
     this->UnwatchUnusedCli(*nameIt);
   }
   return result;
@@ -1730,8 +1775,8 @@
                                    "CMAKE_CACHE_MINOR_VERSION",
                                    "CMAKE_CACHE_PATCH_VERSION",
                                    "CMAKE_CACHEFILE_DIR" };
-  for (const char* const* nameIt = cmArrayBegin(entries);
-       nameIt != cmArrayEnd(entries); ++nameIt) {
+  for (const char* const* nameIt = cm::cbegin(entries);
+       nameIt != cm::cend(entries); ++nameIt) {
     this->UnwatchUnusedCli(*nameIt);
   }
   return result;
@@ -2360,6 +2405,14 @@
               << "\"\n";
     return 1;
   }
+  const char* cachedGeneratorInstance =
+    this->State->GetCacheEntryValue("CMAKE_GENERATOR_INSTANCE");
+  if (cachedGeneratorInstance) {
+    cmMakefile mf(gen.get(), this->GetCurrentSnapshot());
+    if (!gen->SetGeneratorInstance(cachedGeneratorInstance, &mf)) {
+      return 1;
+    }
+  }
   std::string output;
   std::string projName;
   const char* cachedProjectName =
@@ -2425,6 +2478,49 @@
                     nativeOptions);
 }
 
+bool cmake::Open(const std::string& dir, bool dryRun)
+{
+  this->SetHomeDirectory("");
+  this->SetHomeOutputDirectory("");
+  if (!cmSystemTools::FileIsDirectory(dir)) {
+    std::cerr << "Error: " << dir << " is not a directory\n";
+    return false;
+  }
+
+  std::string cachePath = FindCacheFile(dir);
+  if (!this->LoadCache(cachePath)) {
+    std::cerr << "Error: could not load cache\n";
+    return false;
+  }
+  const char* genName = this->State->GetCacheEntryValue("CMAKE_GENERATOR");
+  if (!genName) {
+    std::cerr << "Error: could not find CMAKE_GENERATOR in Cache\n";
+    return false;
+  }
+  const char* extraGenName =
+    this->State->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR");
+  std::string fullName =
+    cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
+      genName, extraGenName ? extraGenName : "");
+
+  std::unique_ptr<cmGlobalGenerator> gen(
+    this->CreateGlobalGenerator(fullName));
+  if (!gen.get()) {
+    std::cerr << "Error: could create CMAKE_GENERATOR \"" << fullName
+              << "\"\n";
+    return false;
+  }
+
+  const char* cachedProjectName =
+    this->State->GetCacheEntryValue("CMAKE_PROJECT_NAME");
+  if (!cachedProjectName) {
+    std::cerr << "Error: could not find CMAKE_PROJECT_NAME in Cache\n";
+    return false;
+  }
+
+  return gen->Open(dir, cachedProjectName, dryRun);
+}
+
 void cmake::WatchUnusedCli(const std::string& var)
 {
 #ifdef CMAKE_BUILD_WITH_CMAKE
diff --git a/Source/cmake.h b/Source/cmake.h
index b31b6f5..02c6cdb 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -8,6 +8,7 @@
 #include <map>
 #include <set>
 #include <string>
+#include <unordered_set>
 #include <vector>
 
 #include "cmInstalledFile.h"
@@ -203,6 +204,12 @@
   ///! Get the names of the current registered generators
   void GetRegisteredGenerators(std::vector<GeneratorInfo>& generators) const;
 
+  ///! Set the name of the selected generator-specific instance.
+  void SetGeneratorInstance(std::string const& instance)
+  {
+    this->GeneratorInstance = instance;
+  }
+
   ///! Set the name of the selected generator-specific platform.
   void SetGeneratorPlatform(std::string const& ts)
   {
@@ -219,11 +226,27 @@
   {
     return this->SourceFileExtensions;
   }
+
+  bool IsSourceExtension(const std::string& ext) const
+  {
+    return this->SourceFileExtensionsSet.find(ext) !=
+      this->SourceFileExtensionsSet.end();
+  }
+
   const std::vector<std::string>& GetHeaderExtensions() const
   {
     return this->HeaderFileExtensions;
   }
 
+  bool IsHeaderExtension(const std::string& ext) const
+  {
+    return this->HeaderFileExtensionsSet.find(ext) !=
+      this->HeaderFileExtensionsSet.end();
+  }
+
+  // Strips the extension (if present and known) from a filename
+  std::string StripExtension(const std::string& file) const;
+
   /**
    * Given a variable name, return its value (as a string).
    */
@@ -401,6 +424,9 @@
             const std::string& config,
             const std::vector<std::string>& nativeOptions, bool clean);
 
+  ///! run the --open option
+  bool Open(const std::string& dir, bool dryRun);
+
   void UnwatchUnusedCli(const std::string& var);
   void WatchUnusedCli(const std::string& var);
 
@@ -428,6 +454,7 @@
 
   cmGlobalGenerator* GlobalGenerator;
   std::map<std::string, DiagLevel> DiagLevels;
+  std::string GeneratorInstance;
   std::string GeneratorPlatform;
   std::string GeneratorToolset;
 
@@ -476,7 +503,9 @@
   std::string CheckStampList;
   std::string VSSolutionFile;
   std::vector<std::string> SourceFileExtensions;
+  std::unordered_set<std::string> SourceFileExtensionsSet;
   std::vector<std::string> HeaderFileExtensions;
+  std::unordered_set<std::string> HeaderFileExtensionsSet;
   bool ClearBuildSystem;
   bool DebugTryCompile;
   cmFileTimeComparison* FileComparison;
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index a1dfc3e..59b908a 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -66,6 +66,7 @@
   { "-E", "CMake command mode." },
   { "-L[A][H]", "List non-advanced cached variables." },
   { "--build <dir>", "Build a CMake-generated project binary tree." },
+  { "--open <dir>", "Open generated project in the associated application." },
   { "-N", "View mode only." },
   { "-P <file>", "Process script mode." },
   { "--find-package", "Run in pkg-config like mode." },
@@ -100,6 +101,7 @@
 
 int do_cmake(int ac, char const* const* av);
 static int do_build(int ac, char const* const* av);
+static int do_open(int ac, char const* const* av);
 
 static cmMakefile* cmakemainGetMakefile(void* clientdata)
 {
@@ -186,6 +188,9 @@
     if (strcmp(av[1], "--build") == 0) {
       return do_build(ac, av);
     }
+    if (strcmp(av[1], "--open") == 0) {
+      return do_open(ac, av);
+    }
     if (strcmp(av[1], "-E") == 0) {
       return do_command(ac, av);
     }
@@ -423,3 +428,41 @@
   return cm.Build(dir, target, config, nativeOptions, clean);
 #endif
 }
+
+static int do_open(int ac, char const* const* av)
+{
+#ifndef CMAKE_BUILD_WITH_CMAKE
+  std::cerr << "This cmake does not support --open\n";
+  return -1;
+#else
+  std::string dir;
+
+  enum Doing
+  {
+    DoingNone,
+    DoingDir,
+  };
+  Doing doing = DoingDir;
+  for (int i = 2; i < ac; ++i) {
+    switch (doing) {
+      case DoingDir:
+        dir = cmSystemTools::CollapseFullPath(av[i]);
+        doing = DoingNone;
+        break;
+      default:
+        std::cerr << "Unknown argument " << av[i] << std::endl;
+        dir.clear();
+        break;
+    }
+  }
+  if (dir.empty()) {
+    std::cerr << "Usage: cmake --open <dir>\n";
+    return 1;
+  }
+
+  cmake cm(cmake::RoleInternal);
+  cmSystemTools::SetMessageCallback(cmakemainMessageCallback, &cm);
+  cm.SetProgressCallback(cmakemainProgressCallback, &cm);
+  return cm.Open(dir, false) ? 0 : 1;
+#endif
+}
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 69339b4..3d9f65a 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -6,7 +6,8 @@
 #include "cmGlobalGenerator.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
-#include "cmQtAutoGenerators.h"
+#include "cmQtAutoGeneratorMocUic.h"
+#include "cmQtAutoGeneratorRcc.h"
 #include "cmStateDirectory.h"
 #include "cmStateSnapshot.h"
 #include "cmSystemTools.h"
@@ -34,6 +35,7 @@
 #include "cmsys/Terminal.h"
 #include <algorithm>
 #include <iostream>
+#include <iterator>
 #include <memory> // IWYU pragma: keep
 #include <sstream>
 #include <stdio.h>
@@ -371,8 +373,8 @@
       doing_options = false;
     } else if (doing_options) {
       bool optionFound = false;
-      for (CoCompiler const* cc = cmArrayBegin(CoCompilers);
-           cc != cmArrayEnd(CoCompilers); ++cc) {
+      for (CoCompiler const* cc = cm::cbegin(CoCompilers);
+           cc != cm::cend(CoCompilers); ++cc) {
         size_t optionLen = strlen(cc->Option);
         if (arg.compare(0, optionLen, cc->Option) == 0) {
           optionFound = true;
@@ -402,8 +404,8 @@
   if (jobs.empty()) {
     std::cerr << "__run_co_compile missing command to run. "
                  "Looking for one or more of the following:\n";
-    for (CoCompiler const* cc = cmArrayBegin(CoCompilers);
-         cc != cmArrayEnd(CoCompilers); ++cc) {
+    for (CoCompiler const* cc = cm::cbegin(CoCompilers);
+         cc != cm::cend(CoCompilers); ++cc) {
       std::cerr << cc->Option << "\n";
     }
     return 1;
@@ -991,11 +993,20 @@
     }
 
 #ifdef CMAKE_BUILD_WITH_CMAKE
-    if (args[1] == "cmake_autogen" && args.size() >= 4) {
-      cmQtAutoGenerators autogen;
+    if ((args[1] == "cmake_autogen") && (args.size() >= 4)) {
+      cmQtAutoGeneratorMocUic autoGen;
+      std::string const& infoDir = args[2];
       std::string const& config = args[3];
-      bool autogenSuccess = autogen.Run(args[2], config);
-      return autogenSuccess ? 0 : 1;
+      return autoGen.Run(infoDir, config) ? 0 : 1;
+    }
+    if ((args[1] == "cmake_autorcc") && (args.size() >= 3)) {
+      cmQtAutoGeneratorRcc autoGen;
+      std::string const& infoFile = args[2];
+      std::string config;
+      if (args.size() > 3) {
+        config = args[3];
+      };
+      return autoGen.Run(infoFile, config) ? 0 : 1;
     }
 #endif
 
@@ -1024,8 +1035,8 @@
           } else if (cmHasLiteralPrefix(arg, "--format=")) {
             format = arg.substr(9);
             bool isKnown =
-              std::find(cmArrayBegin(knownFormats), cmArrayEnd(knownFormats),
-                        format) != cmArrayEnd(knownFormats);
+              std::find(cm::cbegin(knownFormats), cm::cend(knownFormats),
+                        format) != cm::cend(knownFormats);
 
             if (!isKnown) {
               cmSystemTools::Error("Unknown -E tar --format= argument: ",
diff --git a/Source/ctest.cxx b/Source/ctest.cxx
index f6466fa..ad5fec0 100644
--- a/Source/ctest.cxx
+++ b/Source/ctest.cxx
@@ -104,8 +104,6 @@
   { "--test-timeout", "The time limit in seconds, internal use only." },
   { "--test-load", "CPU load threshold for starting new parallel tests." },
   { "--tomorrow-tag", "Nightly or experimental starts with next day tag." },
-  { "--ctest-config", "The configuration file used to initialize CTest state "
-                      "when submitting dashboards." },
   { "--overwrite", "Overwrite CTest configuration option." },
   { "--extra-submit <file>[;<file>]", "Submit extra files to the dashboard." },
   { "--force-new-ctest-process",
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index 21568bb..51f4088 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -445,8 +445,13 @@
   "Checking whether C compiler has ptrdiff_t in stddef.h" DIRECT)
 KWSYS_PLATFORM_C_TEST(KWSYS_C_HAS_SSIZE_T
   "Checking whether C compiler has ssize_t in unistd.h" DIRECT)
+IF(KWSYS_USE_Process)
+  KWSYS_PLATFORM_C_TEST(KWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC
+    "Checking whether C compiler has clock_gettime" DIRECT)
+ENDIF()
+
 SET_SOURCE_FILES_PROPERTIES(ProcessUNIX.c System.c PROPERTIES
-  COMPILE_FLAGS "-DKWSYS_C_HAS_PTRDIFF_T=${KWSYS_C_HAS_PTRDIFF_T} -DKWSYS_C_HAS_SSIZE_T=${KWSYS_C_HAS_SSIZE_T}"
+  COMPILE_FLAGS "-DKWSYS_C_HAS_PTRDIFF_T=${KWSYS_C_HAS_PTRDIFF_T} -DKWSYS_C_HAS_SSIZE_T=${KWSYS_C_HAS_SSIZE_T} -DKWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC=${KWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC}"
   )
 
 IF(DEFINED KWSYS_PROCESS_USE_SELECT)
@@ -1142,17 +1147,22 @@
       SET_TESTS_PROPERTIES(kwsys.testProcess-${n} PROPERTIES TIMEOUT 120)
     ENDFOREACH()
 
+    SET(testProcess_COMPILE_FLAGS "")
     # Some Apple compilers produce bad optimizations in this source.
     IF(APPLE AND CMAKE_C_COMPILER_ID MATCHES "^(GNU|LLVM)$")
-      SET_SOURCE_FILES_PROPERTIES(testProcess.c PROPERTIES COMPILE_FLAGS -O0)
+      SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -O0")
     ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "XL" AND
            NOT (CMAKE_SYSTEM MATCHES "Linux.*ppc64le" AND
                 NOT CMAKE_C_COMPILER_VERSION VERSION_LESS "13.1.1"))
       # Tell IBM XL not to warn about our test infinite loop
       # v13.1.1 and newer on Linux ppc64le is clang based and does not accept
       # the -qsuppress option
-      SET_PROPERTY(SOURCE testProcess.c PROPERTY COMPILE_FLAGS -qsuppress=1500-010)
+      SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -qsuppress=1500-010")
     ENDIF()
+    IF(CMAKE_C_FLAGS MATCHES "-fsanitize=")
+      SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -DCRASH_USING_ABORT")
+    ENDIF()
+    SET_PROPERTY(SOURCE testProcess.c PROPERTY COMPILE_FLAGS "${testProcess_COMPILE_FLAGS}")
 
     # Test SharedForward
     CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/testSharedForward.c.in
diff --git a/Source/kwsys/CommandLineArguments.cxx b/Source/kwsys/CommandLineArguments.cxx
index 5613bd7..5792da9 100644
--- a/Source/kwsys/CommandLineArguments.cxx
+++ b/Source/kwsys/CommandLineArguments.cxx
@@ -529,10 +529,7 @@
     }
   }
 
-  // Create format for that string
-  char format[80];
-  sprintf(format, "  %%-%us  ", static_cast<unsigned int>(maxlen));
-
+  CommandLineArguments::Internal::String::size_type maxstrlen = maxlen;
   maxlen += 4; // For the space before and after the option
 
   // Print help for each option
@@ -540,27 +537,24 @@
     CommandLineArguments::Internal::SetOfStrings::iterator sit;
     for (sit = mpit->second.begin(); sit != mpit->second.end(); sit++) {
       str << std::endl;
-      char argument[100];
-      sprintf(argument, "%s", sit->c_str());
+      std::string argument = *sit;
       switch (this->Internals->Callbacks[*sit].ArgumentType) {
         case CommandLineArguments::NO_ARGUMENT:
           break;
         case CommandLineArguments::CONCAT_ARGUMENT:
-          strcat(argument, "opt");
+          argument += "opt";
           break;
         case CommandLineArguments::SPACE_ARGUMENT:
-          strcat(argument, " opt");
+          argument += " opt";
           break;
         case CommandLineArguments::EQUAL_ARGUMENT:
-          strcat(argument, "=opt");
+          argument += "=opt";
           break;
         case CommandLineArguments::MULTI_ARGUMENT:
-          strcat(argument, " opt opt ...");
+          argument += " opt opt ...";
           break;
       }
-      char buffer[80];
-      sprintf(buffer, format, argument);
-      str << buffer;
+      str << "  " << argument.substr(0, maxstrlen) << "  ";
     }
     const char* ptr = this->Internals->Callbacks[mpit->first].Help;
     size_t len = strlen(ptr);
@@ -649,10 +643,7 @@
 void CommandLineArguments::PopulateVariable(char** variable,
                                             const std::string& value)
 {
-  if (*variable) {
-    delete[] * variable;
-    *variable = 0;
-  }
+  delete[] * variable;
   *variable = new char[value.size() + 1];
   strcpy(*variable, value.c_str());
 }
diff --git a/Source/kwsys/Configure.h.in b/Source/kwsys/Configure.h.in
index 0afcae7..224047a 100644
--- a/Source/kwsys/Configure.h.in
+++ b/Source/kwsys/Configure.h.in
@@ -62,9 +62,6 @@
   !defined(@KWSYS_NAMESPACE@_LFS_NO_DEFINE_FILE_OFFSET_BITS)
 #define _FILE_OFFSET_BITS 64
 #endif
-#if 0 && (defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS < 64)
-#error "_FILE_OFFSET_BITS must be defined to at least 64"
-#endif
 #endif
 #endif
 
diff --git a/Source/kwsys/DynamicLoader.cxx b/Source/kwsys/DynamicLoader.cxx
index 1b4596a..664f183 100644
--- a/Source/kwsys/DynamicLoader.cxx
+++ b/Source/kwsys/DynamicLoader.cxx
@@ -163,17 +163,13 @@
 {
   void* result = 0;
   // Need to prepend symbols with '_' on Apple-gcc compilers
-  size_t len = sym.size();
-  char* rsym = new char[len + 1 + 1];
-  strcpy(rsym, "_");
-  strcat(rsym + 1, sym.c_str());
+  std::string rsym = '_' + sym;
 
-  NSSymbol symbol = NSLookupSymbolInModule(lib, rsym);
+  NSSymbol symbol = NSLookupSymbolInModule(lib, rsym.c_str());
   if (symbol) {
     result = NSAddressOfSymbol(symbol);
   }
 
-  delete[] rsym;
   // Hack to cast pointer-to-data to pointer-to-function.
   return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result);
 }
@@ -237,17 +233,12 @@
   void* result;
 #if defined(__BORLANDC__) || defined(__WATCOMC__)
   // Need to prepend symbols with '_'
-  size_t len = sym.size();
-  char* rsym = new char[len + 1 + 1];
-  strcpy(rsym, "_");
-  strcat(rsym, sym.c_str());
+  std::string ssym = '_' + sym;
+  const char* rsym = ssym.c_str();
 #else
   const char* rsym = sym.c_str();
 #endif
   result = (void*)GetProcAddress(lib, rsym);
-#if defined(__BORLANDC__) || defined(__WATCOMC__)
-  delete[] rsym;
-#endif
 // Hack to cast pointer-to-data to pointer-to-function.
 #ifdef __WATCOMC__
   return *(DynamicLoader::SymbolPointer*)(&result);
diff --git a/Source/kwsys/DynamicLoader.hxx.in b/Source/kwsys/DynamicLoader.hxx.in
index 7e71a45..dc34692 100644
--- a/Source/kwsys/DynamicLoader.hxx.in
+++ b/Source/kwsys/DynamicLoader.hxx.in
@@ -35,7 +35,7 @@
  * or absolute) pathname.  Otherwise, the dynamic linker searches for the
  * library as follows : see ld.so(8) for further details):
  * Whereas this distinction does not exist on Win32. Therefore ideally you
- * should be doing full path to garantee to have a consistent way of dealing
+ * should be doing full path to guarantee to have a consistent way of dealing
  * with dynamic loading of shared library.
  *
  * \warning the Cygwin implementation do not use the Win32 HMODULE. Put extra
@@ -72,7 +72,7 @@
   static LibraryHandle OpenLibrary(const std::string&);
 
   /** Attempt to detach a dynamic library from the
-   * process.  A value of true is returned if it is sucessful. */
+   * process.  A value of true is returned if it is successful. */
   static int CloseLibrary(LibraryHandle);
 
   /** Find the address of the symbol in the given library. */
diff --git a/Source/kwsys/Process.h.in b/Source/kwsys/Process.h.in
index 237001c..daf334a 100644
--- a/Source/kwsys/Process.h.in
+++ b/Source/kwsys/Process.h.in
@@ -77,6 +77,7 @@
 #define kwsysProcess_WaitForExit kwsys_ns(Process_WaitForExit)
 #define kwsysProcess_Interrupt kwsys_ns(Process_Interrupt)
 #define kwsysProcess_Kill kwsys_ns(Process_Kill)
+#define kwsysProcess_KillPID kwsys_ns(Process_KillPID)
 #define kwsysProcess_ResetStartTime kwsys_ns(Process_ResetStartTime)
 #endif
 
@@ -420,7 +421,7 @@
 
 /**
  * Block until the child process terminates or the given timeout
- * expires.  If no process is running, returns immediatly.  The
+ * expires.  If no process is running, returns immediately.  The
  * argument is:
  *
  *  timeout = Specifies the maximum time this call may block.  Upon
@@ -457,6 +458,13 @@
 kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp);
 
 /**
+ * Same as kwsysProcess_Kill using process ID to locate process to
+ * terminate.
+ * @see kwsysProcess_Kill(kwsysProcess* cp)
+ */
+kwsysEXPORT void kwsysProcess_KillPID(unsigned long);
+
+/**
  * Reset the start time of the child process to the current time.
  */
 kwsysEXPORT void kwsysProcess_ResetStartTime(kwsysProcess* cp);
diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c
index 3b32ca7..718a1aa 100644
--- a/Source/kwsys/ProcessUNIX.c
+++ b/Source/kwsys/ProcessUNIX.c
@@ -359,9 +359,7 @@
   kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDIN, 0);
   kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDOUT, 0);
   kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDERR, 0);
-  if (cp->CommandExitCodes) {
-    free(cp->CommandExitCodes);
-  }
+  free(cp->CommandExitCodes);
   free(cp->ProcessResults);
   free(cp);
 }
@@ -498,11 +496,10 @@
     cp->WorkingDirectory = 0;
   }
   if (dir) {
-    cp->WorkingDirectory = (char*)malloc(strlen(dir) + 1);
+    cp->WorkingDirectory = strdup(dir);
     if (!cp->WorkingDirectory) {
       return 0;
     }
-    strcpy(cp->WorkingDirectory, dir);
   }
   return 1;
 }
@@ -531,11 +528,10 @@
     *pfile = 0;
   }
   if (file) {
-    *pfile = (char*)malloc(strlen(file) + 1);
+    *pfile = strdup(file);
     if (!*pfile) {
       return 0;
     }
-    strcpy(*pfile, file);
   }
 
   /* If we are redirecting the pipe, do not share it or use a native
@@ -1514,9 +1510,7 @@
   oldForkPIDs = cp->ForkPIDs;
   cp->ForkPIDs = (volatile pid_t*)malloc(sizeof(volatile pid_t) *
                                          (size_t)(cp->NumberOfCommands));
-  if (oldForkPIDs) {
-    kwsysProcessVolatileFree(oldForkPIDs);
-  }
+  kwsysProcessVolatileFree(oldForkPIDs);
   if (!cp->ForkPIDs) {
     return 0;
   }
@@ -1524,9 +1518,7 @@
     cp->ForkPIDs[i] = 0; /* can't use memset due to volatile */
   }
 
-  if (cp->CommandExitCodes) {
-    free(cp->CommandExitCodes);
-  }
+  free(cp->CommandExitCodes);
   cp->CommandExitCodes =
     (int*)malloc(sizeof(int) * (size_t)(cp->NumberOfCommands));
   if (!cp->CommandExitCodes) {
@@ -1938,6 +1930,7 @@
 
   /* Set close-on-exec flag on the pipe's end.  */
   if (fcntl(fout, F_SETFD, FD_CLOEXEC) < 0) {
+    close(fout);
     return 0;
   }
 
@@ -2033,7 +2026,15 @@
 {
   kwsysProcessTime current;
   kwsysProcessTimeNative current_native;
+#if KWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC
+  struct timespec current_timespec;
+  clock_gettime(CLOCK_MONOTONIC, &current_timespec);
+
+  current_native.tv_sec = current_timespec.tv_sec;
+  current_native.tv_usec = current_timespec.tv_nsec / 1000;
+#else
   gettimeofday(&current_native, 0);
+#endif
   current.tv_sec = (long)current_native.tv_sec;
   current.tv_usec = (long)current_native.tv_usec;
   return current;
@@ -2290,6 +2291,7 @@
   char buffer[KWSYSPE_PIPE_BUFFER_SIZE];
   kwsysProcess_ssize_t result;
   strncpy(buffer, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE);
+  buffer[KWSYSPE_PIPE_BUFFER_SIZE - 1] = '\0';
 
   /* Report the error to the parent through the special pipe.  */
   result = write(errorPipe, buffer, strlen(buffer));
@@ -2483,6 +2485,11 @@
 #define KWSYSPE_PS_FORMAT "%d %d %*[^\n]\n"
 #endif
 
+void kwsysProcess_KillPID(unsigned long process_id)
+{
+  kwsysProcessKill((pid_t)process_id);
+}
+
 static void kwsysProcessKill(pid_t process_id)
 {
 #if defined(__linux__) || defined(__CYGWIN__)
diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c
index 5183e3d..82fdc74 100644
--- a/Source/kwsys/ProcessWin32.c
+++ b/Source/kwsys/ProcessWin32.c
@@ -523,9 +523,7 @@
   kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDIN, 0);
   kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDOUT, 0);
   kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDERR, 0);
-  if (cp->CommandExitCodes) {
-    free(cp->CommandExitCodes);
-  }
+  free(cp->CommandExitCodes);
   free(cp->ProcessResults);
   free(cp);
 }
@@ -713,11 +711,10 @@
     *pfile = 0;
   }
   if (file) {
-    *pfile = (char*)malloc(strlen(file) + 1);
+    *pfile = strdup(file);
     if (!*pfile) {
       return 0;
     }
-    strcpy(*pfile, file);
   }
 
   /* If we are redirecting the pipe, do not share it or use a native
@@ -1469,6 +1466,11 @@
      for them to exit.  */
 }
 
+void kwsysProcess_KillPID(unsigned long process_id)
+{
+  kwsysProcessKillTree((DWORD)process_id);
+}
+
 /*
   Function executed for each pipe's thread.  Argument is a pointer to
   the kwsysProcessPipeData instance for this thread.
@@ -1607,9 +1609,7 @@
   }
   ZeroMemory(cp->ProcessInformation,
              sizeof(PROCESS_INFORMATION) * cp->NumberOfCommands);
-  if (cp->CommandExitCodes) {
-    free(cp->CommandExitCodes);
-  }
+  free(cp->CommandExitCodes);
   cp->CommandExitCodes = (DWORD*)malloc(sizeof(DWORD) * cp->NumberOfCommands);
   if (!cp->CommandExitCodes) {
     return 0;
@@ -2362,9 +2362,7 @@
 static void kwsysProcess_List__Delete_NT4(kwsysProcess_List* self)
 {
   /* Free the process information buffer.  */
-  if (self->Buffer) {
-    free(self->Buffer);
-  }
+  free(self->Buffer);
 }
 
 static int kwsysProcess_List__Update_NT4(kwsysProcess_List* self)
diff --git a/Source/kwsys/RegularExpression.hxx.in b/Source/kwsys/RegularExpression.hxx.in
index 606e3da..763fdab 100644
--- a/Source/kwsys/RegularExpression.hxx.in
+++ b/Source/kwsys/RegularExpression.hxx.in
@@ -109,12 +109,12 @@
  * object as an argument and creates an object initialized with the
  * information from the given RegularExpression object.
  *
- * The  find  member function  finds   the  first  occurence   of  the regualr
+ * The  find  member function  finds   the  first  occurrence   of  the regular
  * expression of that object in the string given to find as an argument.  Find
  * returns a boolean, and  if true,  mutates  the private  data appropriately.
  * Find sets pointers to the beginning and end of  the thing last  found, they
  * are pointers into the actual string  that was searched.   The start and end
- * member functions return indicies  into the searched string that  correspond
+ * member functions return indices  into the searched string that  correspond
  * to the beginning   and  end pointers  respectively.   The    compile member
  * function takes a char* and puts the  compiled version of the char* argument
  * into the object's private data fields.  The == and  != operators only check
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index 86fdccd..ab1f40a 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -1346,7 +1346,7 @@
     std::string binary;
     char buf[1024] = { '\0' };
     ssize_t ll = 0;
-    if ((ll = readlink("/proc/self/exe", buf, 1024)) > 0) {
+    if ((ll = readlink("/proc/self/exe", buf, 1024)) > 0 && ll < 1024) {
       buf[ll] = '\0';
       binary = buf;
     } else {
@@ -3633,7 +3633,7 @@
   // apply resource limits across groups of processes.
   // this is of use on certain SMP systems (eg. SGI UV)
   // where the host has a large amount of ram but a given user's
-  // access to it is severly restricted. The system will
+  // access to it is severely restricted. The system will
   // apply a limit across a set of processes. Units are in KiB.
   if (hostLimitEnvVarName) {
     const char* hostLimitEnvVarValue = getenv(hostLimitEnvVarName);
diff --git a/Source/kwsys/SystemInformation.hxx.in b/Source/kwsys/SystemInformation.hxx.in
index 516c505..5678e8a 100644
--- a/Source/kwsys/SystemInformation.hxx.in
+++ b/Source/kwsys/SystemInformation.hxx.in
@@ -124,7 +124,7 @@
   // are the processes comprising an mpi program which is running in
   // parallel. The amount of memory reported may differ from the host
   // total if a host wide resource limit is applied. Such reource limits
-  // are reported to us via an applicaiton specified environment variable.
+  // are reported to us via an application specified environment variable.
   LongLong GetHostMemoryAvailable(const char* hostLimitEnvVarName = NULL);
 
   // Get total system RAM in units of KiB available to this process.
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index ecfa331..50aa857 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -20,12 +20,14 @@
 #include KWSYS_HEADER(SystemTools.hxx)
 #include KWSYS_HEADER(Directory.hxx)
 #include KWSYS_HEADER(FStream.hxx)
+#include KWSYS_HEADER(Encoding.h)
 #include KWSYS_HEADER(Encoding.hxx)
 
 #include <fstream>
 #include <iostream>
 #include <set>
 #include <sstream>
+#include <utility>
 #include <vector>
 
 // Work-around CMake dependency scanning limitation.  This must
@@ -227,13 +229,17 @@
 {
   std::vector<wchar_t> w_buf(len);
   if (_wgetcwd(&w_buf[0], len)) {
-    // make sure the drive letter is capital
-    if (wcslen(&w_buf[0]) > 1 && w_buf[1] == L':') {
-      w_buf[0] = towupper(w_buf[0]);
+    size_t nlen = kwsysEncoding_wcstombs(buf, &w_buf[0], len);
+    if (nlen == static_cast<size_t>(-1)) {
+      return 0;
     }
-    std::string tmp = KWSYS_NAMESPACE::Encoding::ToNarrow(&w_buf[0]);
-    strcpy(buf, tmp.c_str());
-    return buf;
+    if (nlen < len) {
+      // make sure the drive letter is capital
+      if (nlen > 1 && buf[1] == ':') {
+        buf[0] = toupper(buf[0]);
+      }
+      return buf;
+    }
   }
   return 0;
 }
@@ -746,15 +752,15 @@
 #endif
 }
 
-bool SystemTools::MakeDirectory(const char* path)
+bool SystemTools::MakeDirectory(const char* path, const mode_t* mode)
 {
   if (!path) {
     return false;
   }
-  return SystemTools::MakeDirectory(std::string(path));
+  return SystemTools::MakeDirectory(std::string(path), mode);
 }
 
-bool SystemTools::MakeDirectory(const std::string& path)
+bool SystemTools::MakeDirectory(const std::string& path, const mode_t* mode)
 {
   if (SystemTools::PathExists(path)) {
     return SystemTools::FileIsDirectory(path);
@@ -769,8 +775,12 @@
   std::string topdir;
   while ((pos = dir.find('/', pos)) != std::string::npos) {
     topdir = dir.substr(0, pos);
-    Mkdir(topdir);
-    pos++;
+
+    if (Mkdir(topdir) == 0 && mode != 0) {
+      SystemTools::SetPermissions(topdir, *mode);
+    }
+
+    ++pos;
   }
   topdir = dir;
   if (Mkdir(topdir) != 0) {
@@ -785,7 +795,10 @@
           ) {
       return false;
     }
+  } else if (mode != 0) {
+    SystemTools::SetPermissions(topdir, *mode);
   }
+
   return true;
 }
 
@@ -1679,7 +1692,7 @@
     : false;
 }
 
-// Returns a pointer to the last occurence of str2 in str1
+// Returns a pointer to the last occurrence of str2 in str1
 const char* SystemTools::FindLastString(const char* str1, const char* str2)
 {
   if (!str1 || !str2) {
@@ -3360,7 +3373,7 @@
 }
 
 #ifdef _WIN32
-static std::string GetCasePathName(std::string const& pathIn)
+static std::pair<std::string, bool> GetCasePathName(std::string const& pathIn)
 {
   std::string casePath;
   std::vector<std::string> path_components;
@@ -3369,7 +3382,7 @@
   {
     // Relative paths cannot be converted.
     casePath = pathIn;
-    return casePath;
+    return std::make_pair(casePath, false);
   }
 
   // Start with root component.
@@ -3421,7 +3434,7 @@
 
     casePath += path_components[idx];
   }
-  return casePath;
+  return std::make_pair(casePath, converting);
 }
 #endif
 
@@ -3436,12 +3449,14 @@
   if (i != SystemTools::PathCaseMap->end()) {
     return i->second;
   }
-  std::string casePath = GetCasePathName(p);
-  if (casePath.size() > MAX_PATH) {
-    return casePath;
+  std::pair<std::string, bool> casePath = GetCasePathName(p);
+  if (casePath.first.size() > MAX_PATH) {
+    return casePath.first;
   }
-  (*SystemTools::PathCaseMap)[p] = casePath;
-  return casePath;
+  if (casePath.second) {
+    (*SystemTools::PathCaseMap)[p] = casePath.first;
+  }
+  return casePath.first;
 #endif
 }
 
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
index 35bc1b1..8a02b75 100644
--- a/Source/kwsys/SystemTools.hxx.in
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -107,7 +107,7 @@
   }
 
   /**
-   * Replace replace all occurences of the string in the source string.
+   * Replace replace all occurrences of the string in the source string.
    */
   static void ReplaceString(std::string& source, const char* replace,
                             const char* with);
@@ -175,7 +175,7 @@
   static bool StringEndsWith(const std::string& str1, const char* str2);
 
   /**
-   * Returns a pointer to the last occurence of str2 in str1
+   * Returns a pointer to the last occurrence of str2 in str1
    */
   static const char* FindLastString(const char* str1, const char* str2);
 
@@ -553,13 +553,20 @@
    */
   static FILE* Fopen(const std::string& file, const char* mode);
 
+/**
+ * Visual C++ does not define mode_t (note that Borland does, however).
+ */
+#if defined(_MSC_VER)
+  typedef unsigned short mode_t;
+#endif
+
   /**
    * Make a new directory if it is not there.  This function
    * can make a full path even if none of the directories existed
    * prior to calling this function.
    */
-  static bool MakeDirectory(const char* path);
-  static bool MakeDirectory(const std::string& path);
+  static bool MakeDirectory(const char* path, const mode_t* mode = 0);
+  static bool MakeDirectory(const std::string& path, const mode_t* mode = 0);
 
   /**
    * Copy the source file to the destination file only
@@ -749,13 +756,6 @@
    */
   static long int CreationTime(const std::string& filename);
 
-/**
- * Visual C++ does not define mode_t (note that Borland does, however).
- */
-#if defined(_MSC_VER)
-  typedef unsigned short mode_t;
-#endif
-
   /**
    * Get and set permissions of the file.  If honor_umask is set, the umask
    * is queried and applied to the given permissions.  Returns false if
@@ -905,7 +905,7 @@
 
   /**
    * Delay the execution for a specified amount of time specified
-   * in miliseconds
+   * in milliseconds
    */
   static void Delay(unsigned int msec);
 
diff --git a/Source/kwsys/kwsysPlatformTestsC.c b/Source/kwsys/kwsysPlatformTestsC.c
index 64a361b..5432633 100644
--- a/Source/kwsys/kwsysPlatformTestsC.c
+++ b/Source/kwsys/kwsysPlatformTestsC.c
@@ -55,6 +55,21 @@
 }
 #endif
 
+#ifdef TEST_KWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC
+#if defined(__APPLE__)
+#include <AvailabilityMacros.h>
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 101200
+#error "clock_gettime not available on macOS < 10.12"
+#endif
+#endif
+#include <time.h>
+int KWSYS_PLATFORM_TEST_C_MAIN()
+{
+  struct timespec ts;
+  return clock_gettime(CLOCK_MONOTONIC, &ts);
+}
+#endif
+
 #ifdef TEST_KWSYS_C_TYPE_MACROS
 char* info_macros =
 #if defined(__SIZEOF_SHORT__)
diff --git a/Source/kwsys/kwsysPlatformTestsCXX.cxx b/Source/kwsys/kwsysPlatformTestsCXX.cxx
index e67d436..f1f9ed3 100644
--- a/Source/kwsys/kwsysPlatformTestsCXX.cxx
+++ b/Source/kwsys/kwsysPlatformTestsCXX.cxx
@@ -281,7 +281,7 @@
 #ifdef TEST_KWSYS_CXX_HAS_BACKTRACE
 #if defined(__PATHSCALE__) || defined(__PATHCC__) ||                          \
   (defined(__LSB_VERSION__) && (__LSB_VERSION__ < 41))
-backtrace doesnt work with this compiler or os
+backtrace does not work with this compiler or os
 #endif
 #if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
 #define _GNU_SOURCE
diff --git a/Source/kwsys/testEncoding.cxx b/Source/kwsys/testEncoding.cxx
index 2c5ef46..2742fe4 100644
--- a/Source/kwsys/testEncoding.cxx
+++ b/Source/kwsys/testEncoding.cxx
@@ -75,6 +75,10 @@
   // test that the conversion functions handle invalid
   // unicode correctly/gracefully
 
+  // we manipulate the format flags of stdout, remember
+  // the original state here to restore before return
+  std::ios::fmtflags const& flags = std::cout.flags();
+
   int ret = 0;
   char cstr[] = { (char)-1, 0 };
   // this conversion could fail
@@ -120,6 +124,7 @@
     ret++;
   }
 
+  std::cout.flags(flags);
   return ret;
 }
 
diff --git a/Source/kwsys/testProcess.c b/Source/kwsys/testProcess.c
index 092dd03..4b4978d 100644
--- a/Source/kwsys/testProcess.c
+++ b/Source/kwsys/testProcess.c
@@ -107,6 +107,7 @@
 
 static int test4(int argc, const char* argv[])
 {
+#ifndef CRASH_USING_ABORT
   /* Prepare a pointer to an invalid address.  Don't use null, because
   dereferencing null is undefined behaviour and compilers are free to
   do whatever they want. ex: Clang will warn at compile time, or even
@@ -114,6 +115,7 @@
   'volatile' and a slightly larger address, based on a runtime value. */
   volatile int* invalidAddress = 0;
   invalidAddress += argc ? 1 : 2;
+#endif
 
 #if defined(_WIN32)
   /* Avoid error diagnostic popups since we are crashing on purpose.  */
@@ -128,9 +130,13 @@
   fprintf(stderr, "Output before crash on stderr from crash test.\n");
   fflush(stdout);
   fflush(stderr);
+#ifdef CRASH_USING_ABORT
+  abort();
+#else
   assert(invalidAddress); /* Quiet Clang scan-build. */
   /* Provoke deliberate crash by writing to the invalid address. */
   *invalidAddress = 0;
+#endif
   fprintf(stdout, "Output after crash on stdout from crash test.\n");
   fprintf(stderr, "Output after crash on stderr from crash test.\n");
   return 0;
@@ -149,7 +155,12 @@
   fprintf(stderr, "Output on stderr before recursive test.\n");
   fflush(stdout);
   fflush(stderr);
-  r = runChild(cmd, kwsysProcess_State_Exception, kwsysProcess_Exception_Fault,
+  r = runChild(cmd, kwsysProcess_State_Exception,
+#ifdef CRASH_USING_ABORT
+               kwsysProcess_Exception_Other,
+#else
+               kwsysProcess_Exception_Fault,
+#endif
                1, 1, 1, 0, 15, 0, 1, 0, 0, 0);
   fprintf(stdout, "Output on stdout after recursive test.\n");
   fprintf(stderr, "Output on stderr after recursive test.\n");
@@ -628,11 +639,16 @@
       kwsysProcess_State_Exception /* Process group test */
     };
     int exceptions[10] = {
-      kwsysProcess_Exception_None, kwsysProcess_Exception_None,
-      kwsysProcess_Exception_None, kwsysProcess_Exception_Fault,
-      kwsysProcess_Exception_None, kwsysProcess_Exception_None,
-      kwsysProcess_Exception_None, kwsysProcess_Exception_None,
-      kwsysProcess_Exception_None, kwsysProcess_Exception_Interrupt
+      kwsysProcess_Exception_None,  kwsysProcess_Exception_None,
+      kwsysProcess_Exception_None,
+#ifdef CRASH_USING_ABORT
+      kwsysProcess_Exception_Other,
+#else
+      kwsysProcess_Exception_Fault,
+#endif
+      kwsysProcess_Exception_None,  kwsysProcess_Exception_None,
+      kwsysProcess_Exception_None,  kwsysProcess_Exception_None,
+      kwsysProcess_Exception_None,  kwsysProcess_Exception_Interrupt
     };
     int values[10] = { 0, 123, 1, 1, 0, 0, 0, 0, 1, 1 };
     int shares[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 };
@@ -687,9 +703,7 @@
     fflush(stdout);
     fflush(stderr);
 #if defined(_WIN32)
-    if (argv0) {
-      free(argv0);
-    }
+    free(argv0);
 #endif
     return r;
   } else if (argc > 2 && strcmp(argv[1], "0") == 0) {
diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx
index 768eb4d..3b694c9 100644
--- a/Source/kwsys/testSystemTools.cxx
+++ b/Source/kwsys/testSystemTools.cxx
@@ -254,22 +254,22 @@
   }
   // should work, was created as new file before
   if (!kwsys::SystemTools::FileExists(testNewFile)) {
-    std::cerr << "Problem with FileExists for: " << testNewDir << std::endl;
+    std::cerr << "Problem with FileExists for: " << testNewFile << std::endl;
     res = false;
   }
   if (!kwsys::SystemTools::FileExists(testNewFile.c_str())) {
-    std::cerr << "Problem with FileExists as C string for: " << testNewDir
+    std::cerr << "Problem with FileExists as C string for: " << testNewFile
               << std::endl;
     res = false;
   }
   if (!kwsys::SystemTools::FileExists(testNewFile, true)) {
-    std::cerr << "Problem with FileExists as file for: " << testNewDir
+    std::cerr << "Problem with FileExists as file for: " << testNewFile
               << std::endl;
     res = false;
   }
   if (!kwsys::SystemTools::FileExists(testNewFile.c_str(), true)) {
     std::cerr << "Problem with FileExists as C string and file for: "
-              << testNewDir << std::endl;
+              << testNewFile << std::endl;
     res = false;
   }
 
@@ -285,7 +285,7 @@
   }
   // should work, was created as new file before
   if (!kwsys::SystemTools::PathExists(testNewFile)) {
-    std::cerr << "Problem with PathExists for: " << testNewDir << std::endl;
+    std::cerr << "Problem with PathExists for: " << testNewFile << std::endl;
     res = false;
   }
 
diff --git a/Tests/CFBundleTest/np_macmain.cpp b/Tests/CFBundleTest/np_macmain.cpp
index b5a4226..e5fd0d7 100644
--- a/Tests/CFBundleTest/np_macmain.cpp
+++ b/Tests/CFBundleTest/np_macmain.cpp
@@ -4,7 +4,7 @@
   Based on the default np_macmain.cpp from FireBreath
   http://firebreath.googlecode.com
 
-  This file has been stripped to prevent it from accidently
+  This file has been stripped to prevent it from accidentally
   doing anything useful.
 \***********************************************************/
 
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index ce53454..4a7b8c9 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -31,7 +31,9 @@
   set(TEST_HOME_ENV_CODE "# Fake a user home directory to avoid polluting the real one.
 # But provide original ENV{HOME} value in ENV{CTEST_REAL_HOME} for tests that
 # need access to the real HOME directory.
-set(ENV{CTEST_REAL_HOME} \"\$ENV{HOME}\")
+if(NOT DEFINED ENV{CTEST_REAL_HOME})
+  set(ENV{CTEST_REAL_HOME} \"\$ENV{HOME}\")
+endif()
 set(ENV{HOME} \"${TEST_HOME}\")
 ")
 endif()
@@ -407,11 +409,14 @@
 
   list(APPEND TEST_BUILD_DIRS ${CMake_TEST_INSTALL_PREFIX})
 
-  if(NOT QT4_FOUND)
+  if(NOT DEFINED CMake_TEST_Qt4)
+    set(CMake_TEST_Qt4 1)
+  endif()
+  if(CMake_TEST_Qt4 AND NOT QT4_FOUND)
     find_package(Qt4 QUIET)
   endif()
 
-  if(QT4_FOUND)
+  if(CMake_TEST_Qt4 AND QT4_FOUND)
     # test whether the Qt4 which has been found works, on some machines
     # which run nightly builds there were errors like "wrong file format"
     # for libQtCore.so. So first check it works, and only if it does add
@@ -1253,8 +1258,13 @@
     set(QtAutogen_BUILD_OPTIONS -DCMAKE_BUILD_TYPE=$<CONFIGURATION>)
   endif()
 
-  find_package(Qt5Widgets QUIET NO_MODULE)
-  if(Qt5Widgets_FOUND)
+  if(NOT DEFINED CMake_TEST_Qt5)
+    set(CMake_TEST_Qt5 1)
+  endif()
+  if(CMake_TEST_Qt5)
+    find_package(Qt5Widgets QUIET NO_MODULE)
+  endif()
+  if(CMake_TEST_Qt5 AND Qt5Widgets_FOUND)
     add_test(NAME Qt5Autogen COMMAND ${CMAKE_CTEST_COMMAND}
       --build-and-test
       "${CMake_SOURCE_DIR}/Tests/QtAutogen"
@@ -2830,7 +2840,7 @@
       PASS_REGULAR_EXPRESSION "Failed")
   else()
     set_tests_properties(CTestTestCrash PROPERTIES
-      PASS_REGULAR_EXPRESSION "(Illegal|SegFault)")
+      PASS_REGULAR_EXPRESSION "(Illegal|SegFault|Child aborted)")
   endif()
 
   configure_file(
@@ -3261,6 +3271,18 @@
           --build-options ${build_options}
           --test-command ${JAVA_RUNTIME} -classpath hello2.jar HelloWorld)
         list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJarSourceList")
+        add_test(Java.JarSourceListAndOutput ${CMAKE_CTEST_COMMAND}
+          --build-and-test
+          "${CMake_SOURCE_DIR}/Tests/Java"
+          "${CMake_BINARY_DIR}/Tests/JavaJarSourceListAndOutput"
+          ${build_generator_args}
+          --build-project hello
+          --build-target hello3
+          --build-two-config
+          --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJarSourceListAndOutput/hello3"
+          --build-options ${build_options}
+          --test-command ${JAVA_RUNTIME} -classpath hello3.jar HelloWorld)
+        list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJarSourceListAndOutput")
 
         # For next test, java tool must have same architecture as toolchain
         math(EXPR _object_mode "${CMAKE_SIZEOF_VOID_P} * 8")
@@ -3374,31 +3396,31 @@
   set_property(TEST CMakeWizardTest PROPERTY PASS_REGULAR_EXPRESSION
     "The \"cmake -i\" wizard mode is no longer supported.")
 
-  # If the cache variable CMAKE_CONTRACT_PROJECTS is set
-  # then the dashboard will run a contract with CMake test of that
-  # name.  For example CMAKE_CONTRACT_PROJECTS = vtk542 would run
-  # the vtk542 contract test.
-  # For each Contract test, the project should provide a directory
-  # with at least one CMakeLists.txt file that uses ExternalProject
-  # to download and configure the project. The directory should also
-  # contain a RunTest.cmake file that has a single set of the format:
-  # set(project_RUN_TEST testToRun)
-  # The testToRun should be a test executable that can be run to
-  # smoke test the build.
-  foreach(project ${CMAKE_CONTRACT_PROJECTS})
-    include(Contracts/${project}/RunTest.cmake)
-    ADD_TEST_MACRO(Contracts.${project}
-      ${${project}_RUN_TEST})
-    # Contract test timeout in seconds.
-    # Default to 6 hours.
-    if(DEFINED ${project}_TEST_TIMEOUT)
-      set(timeout ${${project}_TEST_TIMEOUT})
-    elseif(CMAKE_CONTRACT_TEST_TIMEOUT_DEFAULT)
-      set(timeout ${CMAKE_CONTRACT_TEST_TIMEOUT_DEFAULT})
-    else()
-      set(timeout 21600)
+  # Define a set of "contract" tests, each activated by a cache entry
+  # named "CMake_TEST_CONTRACT_<project>".  For each Contract test,
+  # the project should provide a directory with a CMakeLists.txt file
+  # that uses ExternalProject to download and configure the project.
+  # The directory should also contain a Configure.cmake file that
+  # sets "CMake_TEST_CONTRACT_<project>_<var>" variables to configure
+  # the code below.
+  foreach(project
+      PLplot
+      Trilinos
+      VTK
+      )
+    if(CMake_TEST_CONTRACT_${project})
+      include(Contracts/${project}/Configure.cmake)
+      ADD_TEST_MACRO(Contracts.${project} ${CMake_TEST_CONTRACT_${project}_RUN_TEST})
+      # The external projects may take a long time to build.
+      if(DEFINED CMake_TEST_CONTRACT_${project}_TIMEOUT)
+        set(timeout ${CMake_TEST_CONTRACT_${project}_TIMEOUT})
+      elseif(CMake_TEST_CONTRACT_DEFAULT_TIMEOUT)
+        set(timeout ${CMake_TEST_CONTRACT_DEFAULT_TIMEOUT})
+      else()
+        set(timeout 21600)
+      endif()
+      set_property(TEST Contracts.${project} PROPERTY TIMEOUT "${timeout}")
     endif()
-    set_tests_properties(Contracts.${project} PROPERTIES TIMEOUT ${timeout})
   endforeach()
 
   if(TEST_CompileCommandOutput)
diff --git a/Tests/CTestTest2/test.cmake.in b/Tests/CTestTest2/test.cmake.in
index 825b957..a9bbc52 100644
--- a/Tests/CTestTest2/test.cmake.in
+++ b/Tests/CTestTest2/test.cmake.in
@@ -34,6 +34,7 @@
 CMAKE_CXX_COMPILER:STRING=@CMAKE_CXX_COMPILER@
 CMAKE_C_COMPILER_ARG1:STRING=@CMAKE_C_COMPILER_ARG1@
 CMAKE_CXX_COMPILER_ARG1:STRING=@CMAKE_CXX_COMPILER_ARG1@
+KWSYS_ENCODING_DEFAULT_CODEPAGE:STRING=CP_UTF8
 
 # This one is needed for testing advanced ctest features
 CTEST_TEST_KWSYS:BOOL=ON
diff --git a/Tests/CTestTestStopTime/GetDate.cmake b/Tests/CTestTestStopTime/GetDate.cmake
index 46ab2fb..64a4fb9 100644
--- a/Tests/CTestTestStopTime/GetDate.cmake
+++ b/Tests/CTestTestStopTime/GetDate.cmake
@@ -68,7 +68,7 @@
 
   #
   # Extract six individual components by matching a regex with paren groupings.
-  # Use the replace functionality and \\1 thru \\6 to extract components.
+  # Use the replace functionality and \\1 through \\6 to extract components.
   #
   set(${GD_PREFIX}REGEX "([^/]+)/([^/]+)/([^ ]+) +([^:]+):([^:]+):([^\\.]+)")
 
diff --git a/Tests/CheckFortran.cmake b/Tests/CheckFortran.cmake
index b1652ba..16a8ed2 100644
--- a/Tests/CheckFortran.cmake
+++ b/Tests/CheckFortran.cmake
@@ -15,11 +15,18 @@
   \"set(CMAKE_Fortran_COMPILER_SUPPORTS_F90 \\\"\${CMAKE_Fortran_COMPILER_SUPPORTS_F90}\\\")\\n\"
   )
 ")
+  if(CMAKE_GENERATOR_INSTANCE)
+    set(_D_CMAKE_GENERATOR_INSTANCE "-DCMAKE_GENERATOR_INSTANCE:INTERNAL=${CMAKE_GENERATOR_INSTANCE}")
+  else()
+    set(_D_CMAKE_GENERATOR_INSTANCE "")
+  endif()
   execute_process(
     WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CheckFortran
     COMMAND ${CMAKE_COMMAND} . -G ${CMAKE_GENERATOR}
                                -A "${CMAKE_GENERATOR_PLATFORM}"
                                -T "${CMAKE_GENERATOR_TOOLSET}"
+                               ${_D_CMAKE_GENERATOR_INSTANCE}
+    TIMEOUT 60
     OUTPUT_VARIABLE output
     ERROR_VARIABLE output
     RESULT_VARIABLE result
diff --git a/Tests/Contracts/Home.cmake b/Tests/Contracts/Home.cmake
new file mode 100644
index 0000000..8b05e81
--- /dev/null
+++ b/Tests/Contracts/Home.cmake
@@ -0,0 +1,19 @@
+# Find a home in which to build.
+if(NOT DEFINED HOME)
+  if(DEFINED ENV{CTEST_REAL_HOME})
+    set(HOME "$ENV{CTEST_REAL_HOME}")
+  else()
+    set(HOME "$ENV{HOME}")
+  endif()
+
+  if(NOT HOME AND WIN32)
+    # Try for USERPROFILE as HOME equivalent:
+    string(REPLACE "\\" "/" HOME "$ENV{USERPROFILE}")
+
+    # But just use root of SystemDrive if USERPROFILE contains any spaces:
+    # (Default on XP and earlier...)
+    if(HOME MATCHES " ")
+      string(REPLACE "\\" "/" HOME "$ENV{SystemDrive}")
+    endif()
+  endif()
+endif()
diff --git a/Tests/Contracts/PLplot/CMakeLists.txt b/Tests/Contracts/PLplot/CMakeLists.txt
new file mode 100644
index 0000000..b87b4c3
--- /dev/null
+++ b/Tests/Contracts/PLplot/CMakeLists.txt
@@ -0,0 +1,18 @@
+cmake_minimum_required(VERSION 3.9)
+project(PLplotDriver NONE)
+include(ExternalProject)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../Home.cmake)
+set(PLplot_PREFIX "${HOME}/.cmake/Contracts/PLplot")
+file(REMOVE_RECURSE "${PLplot_PREFIX}")
+separate_arguments(PLplot_CMAKE_ARGS UNIX_COMMAND "${PLplot_CMAKE_FLAGS}")
+if(NOT PLplot_GIT_TAG)
+  set(PLplot_GIT_TAG "plplot-5.13.0")
+endif()
+ExternalProject_Add(PLplot
+  GIT_REPOSITORY "https://git.code.sf.net/p/plplot/plplot.git"
+  GIT_TAG "${PLplot_GIT_TAG}"
+  PREFIX "${PLplot_PREFIX}"
+  CMAKE_ARGS
+    -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
+    ${PLplot_CMAKE_ARGS}
+  )
diff --git a/Tests/Contracts/PLplot/Configure.cmake b/Tests/Contracts/PLplot/Configure.cmake
new file mode 100644
index 0000000..83591d4
--- /dev/null
+++ b/Tests/Contracts/PLplot/Configure.cmake
@@ -0,0 +1,4 @@
+set(Contracts.PLplot_BUILD_OPTIONS
+  -DPLplot_CMAKE_FLAGS=${CMake_TEST_CONTRACT_PLplot_CMAKE_FLAGS}
+  -DPLplot_GIT_TAG=${CMake_TEST_CONTRACT_PLplot_GIT_TAG}
+  )
diff --git a/Tests/Contracts/Trilinos/CMakeLists.txt b/Tests/Contracts/Trilinos/CMakeLists.txt
index 8d74ca5..4d7062b 100644
--- a/Tests/Contracts/Trilinos/CMakeLists.txt
+++ b/Tests/Contracts/Trilinos/CMakeLists.txt
@@ -6,24 +6,7 @@
 include("${CMAKE_CURRENT_SOURCE_DIR}/LocalOverrides.cmake" OPTIONAL)
 include("${CMAKE_CURRENT_BINARY_DIR}/LocalOverrides.cmake" OPTIONAL)
 
-if(NOT DEFINED HOME)
-  if(DEFINED ENV{CTEST_REAL_HOME})
-    set(HOME "$ENV{CTEST_REAL_HOME}")
-  else()
-    set(HOME "$ENV{HOME}")
-  endif()
-
-  if(NOT HOME AND WIN32)
-    # Try for USERPROFILE as HOME equivalent:
-    string(REPLACE "\\" "/" HOME "$ENV{USERPROFILE}")
-
-    # But just use root of SystemDrive if USERPROFILE contains any spaces:
-    # (Default on XP and earlier...)
-    if(HOME MATCHES " ")
-      string(REPLACE "\\" "/" HOME "$ENV{SystemDrive}")
-    endif()
-  endif()
-endif()
+include(${CMAKE_CURRENT_SOURCE_DIR}/../Home.cmake)
 message(STATUS "HOME='${HOME}'")
 
 if(NOT DEFINED url)
diff --git a/Tests/Contracts/Trilinos/RunTest.cmake b/Tests/Contracts/Trilinos/Configure.cmake
similarity index 78%
rename from Tests/Contracts/Trilinos/RunTest.cmake
rename to Tests/Contracts/Trilinos/Configure.cmake
index d661a4c..d62eb79 100644
--- a/Tests/Contracts/Trilinos/RunTest.cmake
+++ b/Tests/Contracts/Trilinos/Configure.cmake
@@ -4,4 +4,4 @@
 set(exe "${CMAKE_COMMAND}")
 set(args -P "${dir}/ValidateBuild.cmake")
 
-set(Trilinos_RUN_TEST ${exe} ${args})
+set(CMake_TEST_CONTRACT_Trilinos_RUN_TEST ${exe} ${args})
diff --git a/Tests/Contracts/Trilinos/EnvScript.cmake b/Tests/Contracts/Trilinos/EnvScript.cmake
deleted file mode 100644
index dacb704..0000000
--- a/Tests/Contracts/Trilinos/EnvScript.cmake
+++ /dev/null
@@ -1,32 +0,0 @@
-# Site specific settings:
-#
-if(CTEST_SITE MATCHES "faraway")
-  set(CTEST_SITE "faraway.kitware")
-  set(ENV{CTEST_SITE} "${CTEST_SITE}")
-endif()
-
-if(CTEST_SITE STREQUAL "HUT11")
-  set(CTEST_SITE "hut11.kitware")
-  set(ENV{CTEST_SITE} "${CTEST_SITE}")
-
-  set(ENV{CLAPACK_DIR} "C:/T/clapack/b/clapack-prefix/src/clapack-build")
-endif()
-
-if(CTEST_SITE MATCHES "qwghlm")
-  set(CTEST_SITE "qwghlm.kitware")
-  set(ENV{CTEST_SITE} "${CTEST_SITE}")
-
-  set(ENV{PATH} "/opt/local/bin:$ENV{PATH}")
-  set(ENV{CC} "gcc-mp-4.3")
-  set(ENV{CXX} "g++-mp-4.3")
-  set(ENV{FC} "gfortran-mp-4.3")
-endif()
-
-# Submit to alternate CDash server:
-#
-#set(ENV{CTEST_DROP_SITE} "localhost")
-#set(ENV{CTEST_DROP_LOCATION} "/CDash/submit.php?project=Trilinos")
-
-# Limit packages built:
-#
-set(ENV{Trilinos_PACKAGES} "Teuchos;Kokkos")
diff --git a/Tests/Contracts/VTK/CMakeLists.txt b/Tests/Contracts/VTK/CMakeLists.txt
index ef19325..c946499 100644
--- a/Tests/Contracts/VTK/CMakeLists.txt
+++ b/Tests/Contracts/VTK/CMakeLists.txt
@@ -5,24 +5,7 @@
 include(ExternalProject)
 
 # find "HOME".  VTK will be downloaded & built within a subdirectory.
-if(NOT DEFINED HOME)
-  if(DEFINED ENV{CTEST_REAL_HOME})
-    set(HOME "$ENV{CTEST_REAL_HOME}")
-  else()
-    set(HOME "$ENV{HOME}")
-  endif()
-
-  if(NOT HOME AND WIN32)
-    # Try for USERPROFILE as HOME equivalent:
-    string(REPLACE "\\" "/" HOME "$ENV{USERPROFILE}")
-
-    # But just use root of SystemDrive if USERPROFILE contains any spaces:
-    # (Default on XP and earlier...)
-    if(HOME MATCHES " ")
-      string(REPLACE "\\" "/" HOME "$ENV{SystemDrive}")
-    endif()
-  endif()
-endif()
+include(${CMAKE_CURRENT_SOURCE_DIR}/../Home.cmake)
 
 set(base_dir "${HOME}/.cmake/Contracts/VTK")
 
diff --git a/Tests/Contracts/VTK/RunTest.cmake b/Tests/Contracts/VTK/Configure.cmake
similarity index 65%
rename from Tests/Contracts/VTK/RunTest.cmake
rename to Tests/Contracts/VTK/Configure.cmake
index 65285cf..037d75a 100644
--- a/Tests/Contracts/VTK/RunTest.cmake
+++ b/Tests/Contracts/VTK/Configure.cmake
@@ -1,3 +1,3 @@
 set(exe "$ENV{HOME}/.cmake/Contracts/VTK/VTK-build/bin/vtkCommonCoreCxxTests")
 set(args otherArrays)
-set(VTK_RUN_TEST ${exe} ${args})
+set(CMake_TEST_CONTRACT_VTK_RUN_TEST ${exe} ${args})
diff --git a/Tests/Contracts/cse-snapshot/CMakeLists.txt b/Tests/Contracts/cse-snapshot/CMakeLists.txt
deleted file mode 100644
index 9134210..0000000
--- a/Tests/Contracts/cse-snapshot/CMakeLists.txt
+++ /dev/null
@@ -1,114 +0,0 @@
-cmake_minimum_required(VERSION 2.8)
-project(cse-snapshot)
-
-include(ExternalProject)
-
-include("${CMAKE_CURRENT_SOURCE_DIR}/LocalOverrides.cmake" OPTIONAL)
-include("${CMAKE_CURRENT_BINARY_DIR}/LocalOverrides.cmake" OPTIONAL)
-
-if(NOT DEFINED HOME)
-  if(DEFINED ENV{CTEST_REAL_HOME})
-    set(HOME "$ENV{CTEST_REAL_HOME}")
-  else()
-    set(HOME "$ENV{HOME}")
-  endif()
-endif()
-message(STATUS "HOME='${HOME}'")
-
-if(NOT DEFINED repo)
-  set(repo "git://public.kitware.com/cse.git")
-endif()
-message(STATUS "repo='${repo}'")
-
-if(NOT DEFINED tag)
-  set(tag "cc1dcb95439a21ab1d58f444d93481598414196e")
-endif()
-message(STATUS "tag='${tag}'")
-
-string(SUBSTRING "${tag}" 0 8 shorttag)
-
-set(base_dir "${HOME}/.cmake/Contracts/${PROJECT_NAME}/${shorttag}")
-set(binary_dir "${base_dir}/build")
-set(script_dir "${base_dir}")
-set(source_dir "${base_dir}/src")
-
-if(NOT DEFINED BUILDNAME)
-  set(BUILDNAME "CMakeContract-${shorttag}")
-endif()
-message(STATUS "BUILDNAME='${BUILDNAME}'")
-
-if(NOT DEFINED SITE)
-  site_name(SITE)
-endif()
-message(STATUS "SITE='${SITE}'")
-
-if(NOT DEFINED PROCESSOR_COUNT)
-  # Unknown:
-  set(PROCESSOR_COUNT 0)
-
-  # Linux:
-  set(cpuinfo_file "/proc/cpuinfo")
-  if(EXISTS "${cpuinfo_file}")
-    file(STRINGS "${cpuinfo_file}" procs REGEX "^processor.: [0-9]+$")
-    list(LENGTH procs PROCESSOR_COUNT)
-  endif()
-
-  # Mac:
-  if(APPLE)
-    find_program(cmd_sysctl "sysctl")
-    if(cmd_sysctl)
-      execute_process(COMMAND ${cmd_sysctl} -n hw.ncpu
-        OUTPUT_VARIABLE PROCESSOR_COUNT
-        OUTPUT_STRIP_TRAILING_WHITESPACE)
-    endif()
-  endif()
-
-  # Windows:
-  if(WIN32)
-    set(PROCESSOR_COUNT "$ENV{NUMBER_OF_PROCESSORS}")
-  endif()
-endif()
-message(STATUS "PROCESSOR_COUNT='${PROCESSOR_COUNT}'")
-
-find_package(Git)
-if(NOT GIT_EXECUTABLE)
-  message(FATAL_ERROR "error: could not find git")
-  # adjust PATH to find git, or set GIT_EXECUTABLE in LocalOverrides.cmake
-endif()
-message(STATUS "GIT_EXECUTABLE='${GIT_EXECUTABLE}'")
-
-configure_file(
-  "${CMAKE_CURRENT_SOURCE_DIR}/Dashboard.cmake.in"
-  "${script_dir}/Dashboard.cmake"
-  @ONLY)
-
-# Source dir for this project exists outside the CMake build tree because it
-# is absolutely huge.
-#
-if(EXISTS "${source_dir}/.git")
-  # If it exists already, download is a complete no-op:
-  ExternalProject_Add(download-${PROJECT_NAME}
-    DOWNLOAD_COMMAND ""
-    CONFIGURE_COMMAND ""
-    BUILD_COMMAND ""
-    INSTALL_COMMAND ""
-  )
-else()
-  # If it does not yet exist, download clones the git repository:
-  ExternalProject_Add(download-${PROJECT_NAME}
-    SOURCE_DIR "${source_dir}"
-    GIT_REPOSITORY "${repo}"
-    GIT_TAG "${tag}"
-    CONFIGURE_COMMAND ""
-    BUILD_COMMAND ""
-    INSTALL_COMMAND ""
-  )
-endif()
-
-ExternalProject_Add(build-${PROJECT_NAME}
-  DOWNLOAD_COMMAND ""
-  CONFIGURE_COMMAND ""
-  BUILD_COMMAND ${CMAKE_CTEST_COMMAND} -S "${script_dir}/Dashboard.cmake"
-  INSTALL_COMMAND ""
-  DEPENDS download-${PROJECT_NAME}
-  )
diff --git a/Tests/Contracts/cse-snapshot/Dashboard.cmake.in b/Tests/Contracts/cse-snapshot/Dashboard.cmake.in
deleted file mode 100644
index 138eb3f..0000000
--- a/Tests/Contracts/cse-snapshot/Dashboard.cmake.in
+++ /dev/null
@@ -1,76 +0,0 @@
-# This "ctest -S" script may be configured to drive a nightly dashboard on any
-# Linux machine.
-#
-set(CTEST_BINARY_DIRECTORY "@binary_dir@")
-set(CTEST_BUILD_NAME "@BUILDNAME@")
-set(CTEST_SITE "@SITE@")
-set(CTEST_SOURCE_DIRECTORY "@source_dir@")
-set(PROCESSOR_COUNT "@PROCESSOR_COUNT@")
-
-# Assume a Linux build, with a make that supports -j. Modify this script if
-# assumption is ever invalid.
-#
-if(PROCESSOR_COUNT)
-  set(CTEST_BUILD_FLAGS "-j${PROCESSOR_COUNT}")
-endif()
-
-set(CTEST_CMAKE_GENERATOR "Unix Makefiles")
-set(CTEST_NOTES_FILES "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}")
-
-message("Cleaning binary dir '${CTEST_BINARY_DIRECTORY}'")
-ctest_empty_binary_directory("${CTEST_BINARY_DIRECTORY}")
-
-# Intentionally no ctest_update step in this script. This script is run as a
-# "Contract" test on a CMake dashboard submission using the just-built ctest
-# as the driver. The download step in the Contract CMakeLists file takes care
-# of setting up the source tree before calling this ctest -S script. The idea
-# is that the source tree will be the same every day, so there should not be
-# an "update" step for this build.
-
-message("Configuring CSE in binary dir '${CTEST_BINARY_DIRECTORY}'")
-set_property(GLOBAL PROPERTY SubProject "CSE-toplevel")
-set_property(GLOBAL PROPERTY Label "CSE-toplevel")
-
-ctest_start("Experimental")
-
-set(CSE_TOPLEVEL_OPTIONS
-  -DEXTERNAL_PROJECT_DASHBOARD_BUILD:BOOL=ON
-  -DEXTERNAL_PROJECT_TESTS:BOOL=ON
-  -DCSE_INSTALL_PREFIX:PATH=${CTEST_BINARY_DIRECTORY}/built
-  -DCSE_SUBSET:STRING=ALL
-  -DCTEST_SITE:STRING=${CTEST_SITE}
-)
-
-ctest_configure(OPTIONS "${CSE_TOPLEVEL_OPTIONS}")
-
-# The configure step produces a file listing the CSE packages and dependencies.
-# This file also generates Project.xml and stores it in ${PROJECT_XML}.
-#
-set(subprojects "")
-if(EXISTS "${CTEST_BINARY_DIRECTORY}/CSEBuildtimeDepends.cmake")
-  message("Including CSEBuildtimeDepends.cmake")
-  include("${CTEST_BINARY_DIRECTORY}/CSEBuildtimeDepends.cmake")
-  set(subprojects ${CSE_ALL_SORTED})
-  message("Submitting Project.xml")
-  ctest_submit(FILES ${PROJECT_XML})
-endif()
-
-message("Submitting CSE configure results")
-ctest_submit()
-
-if(subprojects)
-  message("Building by looping over subprojects...")
-  foreach(subproject ${subprojects})
-    message("##########  ${subproject}  ##########")
-    set_property(GLOBAL PROPERTY SubProject "${subproject}")
-    set_property(GLOBAL PROPERTY Label "${subproject}")
-    ctest_build(TARGET "${subproject}" APPEND)
-    message("Submitting ${subproject} build results")
-    ctest_submit(PARTS build)
-  endforeach()
-else()
-  message("Building all...")
-  ctest_build(APPEND)
-  message("Submitting build results")
-  ctest_submit(PARTS build)
-endif()
diff --git a/Tests/Contracts/cse-snapshot/RunTest.cmake b/Tests/Contracts/cse-snapshot/RunTest.cmake
deleted file mode 100644
index 7eb6301..0000000
--- a/Tests/Contracts/cse-snapshot/RunTest.cmake
+++ /dev/null
@@ -1,3 +0,0 @@
-set(exe "$ENV{HOME}/.cmake/Contracts/cse-snapshot/510345e4/build/built/Release/git-1.6.5.2/bin/git")
-set(args help clone)
-set(cse-snapshot_RUN_TEST ${exe} ${args})
diff --git a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt
index 7ef626f..cfca823 100644
--- a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt
+++ b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt
@@ -13,7 +13,13 @@
 set(CMAKE_CXX_STANDARD 11)
 set(CMAKE_CUDA_STANDARD 11)
 
+set(CMAKE_CUDA_SEPARABLE_COMPILATION ON)
 add_library(CUDASeparateLibA STATIC file1.cu file2.cu file3.cu)
+get_property(sep_comp TARGET CUDASeparateLibA PROPERTY CUDA_SEPARABLE_COMPILATION)
+if(NOT sep_comp)
+  message(FATAL_ERROR "CUDA_SEPARABLE_COMPILATION not initialized")
+endif()
+unset(CMAKE_CUDA_SEPARABLE_COMPILATION)
 
 if(CMAKE_CUDA_SIMULATE_ID STREQUAL "MSVC")
   # Test adding a flag that is not in our CUDA flag table for VS.
diff --git a/Tests/FindOpenGL/Test/CMakeLists.txt b/Tests/FindOpenGL/Test/CMakeLists.txt
index 3b5ffee..9004a98 100644
--- a/Tests/FindOpenGL/Test/CMakeLists.txt
+++ b/Tests/FindOpenGL/Test/CMakeLists.txt
@@ -1,4 +1,5 @@
-cmake_minimum_required(VERSION 3.9)
+cmake_minimum_required(VERSION 3.10)
+cmake_policy(SET CMP0072 NEW)
 project(TestFindOpenGL C)
 include(CTest)
 
diff --git a/Tests/FindPatch/Test/CMakeLists.txt b/Tests/FindPatch/Test/CMakeLists.txt
index f4cd621..66c672c 100644
--- a/Tests/FindPatch/Test/CMakeLists.txt
+++ b/Tests/FindPatch/Test/CMakeLists.txt
@@ -70,8 +70,8 @@
 )
 
 add_custom_target(TestPatch ALL
-  COMMAND ${Patch_EXECUTABLE} -p1 -i quote-add-author.patch
-  COMMAND Patch::patch -p1 -i quote-add-date.patch
+  COMMAND ${Patch_EXECUTABLE} -p1 -i quote-add-author.patch --binary
+  COMMAND Patch::patch -p1 -i quote-add-date.patch --binary
   COMMAND ${CMAKE_COMMAND} -E compare_files QUOTE.txt QUOTE.txt.baseline
   WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
   )
diff --git a/Tests/FortranModules/test_preprocess.F90 b/Tests/FortranModules/test_preprocess.F90
index 3a09976..c5a5ec3 100644
--- a/Tests/FortranModules/test_preprocess.F90
+++ b/Tests/FortranModules/test_preprocess.F90
@@ -1,5 +1,5 @@
 MODULE Available
-! no conent
+! no content
 END MODULE
 
 PROGRAM PPTEST
diff --git a/Tests/FortranModules/test_preprocess_module.F90 b/Tests/FortranModules/test_preprocess_module.F90
index 5849b62..fdbc051 100644
--- a/Tests/FortranModules/test_preprocess_module.F90
+++ b/Tests/FortranModules/test_preprocess_module.F90
@@ -1,5 +1,5 @@
 #ifdef FOO
 MODULE PPAvailable
-! no conent
+! no content
 END MODULE
 #endif
diff --git a/Tests/Java/CMakeLists.txt b/Tests/Java/CMakeLists.txt
index e1bcf3c..0b8269b 100644
--- a/Tests/Java/CMakeLists.txt
+++ b/Tests/Java/CMakeLists.txt
@@ -11,3 +11,6 @@
 # use listing file to specify sources
 file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/java_fileslist "A.java\nHelloWorld.java\n")
 add_jar(hello2 @${CMAKE_CURRENT_BINARY_DIR}/java_fileslist)
+
+# use listing file to specify sources and specify output directory (issue #17316)
+add_jar(hello3 @${CMAKE_CURRENT_BINARY_DIR}/java_fileslist OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/hello3")
diff --git a/Tests/OutOfSource/CMakeLists.txt b/Tests/OutOfSource/CMakeLists.txt
index de1603a..4687882 100644
--- a/Tests/OutOfSource/CMakeLists.txt
+++ b/Tests/OutOfSource/CMakeLists.txt
@@ -1,4 +1,4 @@
-# a simple test cas
+# a simple test case
 cmake_minimum_required (VERSION 2.6)
 project (OutOfSource)
 
diff --git a/Tests/RunCMake/CMP0037/CMP0037-NEW-colon.cmake b/Tests/RunCMake/CMP0037/CMP0037-NEW-colon.cmake
index f4c070d..fd56e75 100644
--- a/Tests/RunCMake/CMP0037/CMP0037-NEW-colon.cmake
+++ b/Tests/RunCMake/CMP0037/CMP0037-NEW-colon.cmake
@@ -1,4 +1,4 @@
-
+enable_language(CXX)
 cmake_policy(SET CMP0037 NEW)
 
 add_library("lib:colon" empty.cpp)
diff --git a/Tests/RunCMake/CMP0037/CMP0037-NEW-reserved.cmake b/Tests/RunCMake/CMP0037/CMP0037-NEW-reserved.cmake
index e9f6404..83a7119 100644
--- a/Tests/RunCMake/CMP0037/CMP0037-NEW-reserved.cmake
+++ b/Tests/RunCMake/CMP0037/CMP0037-NEW-reserved.cmake
@@ -1,4 +1,4 @@
-
+enable_language(CXX)
 cmake_policy(SET CMP0037 NEW)
 
 add_library(all empty.cpp)
diff --git a/Tests/RunCMake/CMP0037/CMP0037-NEW-space.cmake b/Tests/RunCMake/CMP0037/CMP0037-NEW-space.cmake
index 9227986..2a288cc 100644
--- a/Tests/RunCMake/CMP0037/CMP0037-NEW-space.cmake
+++ b/Tests/RunCMake/CMP0037/CMP0037-NEW-space.cmake
@@ -1,4 +1,4 @@
-
+enable_language(CXX)
 cmake_policy(SET CMP0037 NEW)
 
 add_library("lib with spaces" empty.cpp)
diff --git a/Tests/RunCMake/CMP0037/CMP0037-OLD-reserved-result.txt b/Tests/RunCMake/CMP0037/CMP0037-OLD-reserved-result.txt
deleted file mode 100644
index 573541a..0000000
--- a/Tests/RunCMake/CMP0037/CMP0037-OLD-reserved-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/Tests/RunCMake/CMP0037/CMP0037-OLD-reserved-stderr.txt b/Tests/RunCMake/CMP0037/CMP0037-OLD-reserved-stderr.txt
new file mode 100644
index 0000000..de09351
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/CMP0037-OLD-reserved-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0037-OLD-reserved.cmake:2 \(cmake_policy\):
+  The OLD behavior for policy CMP0037 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0037/CMP0037-OLD-reserved.cmake b/Tests/RunCMake/CMP0037/CMP0037-OLD-reserved.cmake
index 870a286..f52e4d2 100644
--- a/Tests/RunCMake/CMP0037/CMP0037-OLD-reserved.cmake
+++ b/Tests/RunCMake/CMP0037/CMP0037-OLD-reserved.cmake
@@ -1,4 +1,4 @@
-
+enable_language(CXX)
 cmake_policy(SET CMP0037 OLD)
 
 add_library(all empty.cpp)
diff --git a/Tests/RunCMake/CMP0037/CMP0037-OLD-space-result.txt b/Tests/RunCMake/CMP0037/CMP0037-OLD-space-result.txt
deleted file mode 100644
index 573541a..0000000
--- a/Tests/RunCMake/CMP0037/CMP0037-OLD-space-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/Tests/RunCMake/CMP0037/CMP0037-OLD-space-stderr.txt b/Tests/RunCMake/CMP0037/CMP0037-OLD-space-stderr.txt
new file mode 100644
index 0000000..4d13e59
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/CMP0037-OLD-space-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0037-OLD-space.cmake:2 \(cmake_policy\):
+  The OLD behavior for policy CMP0037 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0037/CMP0037-OLD-space.cmake b/Tests/RunCMake/CMP0037/CMP0037-OLD-space.cmake
index 46193a1..c9fb6c8 100644
--- a/Tests/RunCMake/CMP0037/CMP0037-OLD-space.cmake
+++ b/Tests/RunCMake/CMP0037/CMP0037-OLD-space.cmake
@@ -1,4 +1,4 @@
-
+enable_language(CXX)
 cmake_policy(SET CMP0037 OLD)
 
 add_library("lib with spaces" empty.cpp)
diff --git a/Tests/RunCMake/CMP0037/CMP0037-WARN-colon.cmake b/Tests/RunCMake/CMP0037/CMP0037-WARN-colon.cmake
index 445e3b2..1b1a405 100644
--- a/Tests/RunCMake/CMP0037/CMP0037-WARN-colon.cmake
+++ b/Tests/RunCMake/CMP0037/CMP0037-WARN-colon.cmake
@@ -1,4 +1,4 @@
-
+enable_language(CXX)
 add_library("lib:colon" empty.cpp)
 add_executable("exe:colon" empty.cpp)
 add_custom_target("custom:colon")
diff --git a/Tests/RunCMake/CMP0037/CMP0037-WARN-reserved-stderr.txt b/Tests/RunCMake/CMP0037/CMP0037-WARN-reserved-stderr.txt
new file mode 100644
index 0000000..2d556a7
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/CMP0037-WARN-reserved-stderr.txt
@@ -0,0 +1,36 @@
+CMake Warning \(dev\) at CMP0037-WARN-reserved.cmake:2 \(add_library\):
+  Policy CMP0037 is not set: Target names should not be reserved and should
+  match a validity pattern.  Run "cmake --help-policy CMP0037" for policy
+  details.  Use the cmake_policy command to set the policy and suppress this
+  warning.
+
+  The target name "all" is reserved or not valid for certain CMake features,
+  such as generator expressions, and may result in undefined behavior.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+This warning is for project developers.  Use -Wno-dev to suppress it.
++
+CMake Warning \(dev\) at CMP0037-WARN-reserved.cmake:3 \(add_executable\):
+  Policy CMP0037 is not set: Target names should not be reserved and should
+  match a validity pattern.  Run "cmake --help-policy CMP0037" for policy
+  details.  Use the cmake_policy command to set the policy and suppress this
+  warning.
+
+  The target name "clean" is reserved or not valid for certain CMake
+  features, such as generator expressions, and may result in undefined
+  behavior.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+This warning is for project developers.  Use -Wno-dev to suppress it.
++
+CMake Warning \(dev\) at CMP0037-WARN-reserved.cmake:4 \(add_custom_target\):
+  Policy CMP0037 is not set: Target names should not be reserved and should
+  match a validity pattern.  Run "cmake --help-policy CMP0037" for policy
+  details.  Use the cmake_policy command to set the policy and suppress this
+  warning.
+
+  The target name "help" is reserved or not valid for certain CMake features,
+  such as generator expressions, and may result in undefined behavior.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+This warning is for project developers.  Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CMP0037/CMP0037-WARN-reserved.cmake b/Tests/RunCMake/CMP0037/CMP0037-WARN-reserved.cmake
new file mode 100644
index 0000000..a5e0f10
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/CMP0037-WARN-reserved.cmake
@@ -0,0 +1,4 @@
+enable_language(CXX)
+add_library(all empty.cpp)
+add_executable(clean empty.cpp)
+add_custom_target(help)
diff --git a/Tests/RunCMake/CMP0037/CMP0037-WARN-space.cmake b/Tests/RunCMake/CMP0037/CMP0037-WARN-space.cmake
index e50a64d..e01b8e5 100644
--- a/Tests/RunCMake/CMP0037/CMP0037-WARN-space.cmake
+++ b/Tests/RunCMake/CMP0037/CMP0037-WARN-space.cmake
@@ -1,4 +1,4 @@
-
+enable_language(CXX)
 add_library("lib with spaces" empty.cpp)
 add_executable("exe with spaces" empty.cpp)
 add_custom_target("custom with spaces")
diff --git a/Tests/RunCMake/CMP0037/CMakeLists.txt b/Tests/RunCMake/CMP0037/CMakeLists.txt
index f452db1..12cd3c7 100644
--- a/Tests/RunCMake/CMP0037/CMakeLists.txt
+++ b/Tests/RunCMake/CMP0037/CMakeLists.txt
@@ -1,3 +1,3 @@
 cmake_minimum_required(VERSION 2.8.4)
-project(${RunCMake_TEST} CXX)
+project(${RunCMake_TEST} NONE)
 include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/add_executable/OnlyObjectSources-result.txt b/Tests/RunCMake/CMP0037/NEW-cond-package-result.txt
similarity index 100%
copy from Tests/RunCMake/add_executable/OnlyObjectSources-result.txt
copy to Tests/RunCMake/CMP0037/NEW-cond-package-result.txt
diff --git a/Tests/RunCMake/CMP0037/NEW-cond-package-stderr.txt b/Tests/RunCMake/CMP0037/NEW-cond-package-stderr.txt
new file mode 100644
index 0000000..270fa6d
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/NEW-cond-package-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at NEW-cond-package.cmake:4 \(add_custom_target\):
+  The target name "package" is reserved when CPack packaging is enabled.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0037/NEW-cond-package.cmake b/Tests/RunCMake/CMP0037/NEW-cond-package.cmake
new file mode 100644
index 0000000..ceea907
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/NEW-cond-package.cmake
@@ -0,0 +1,5 @@
+cmake_policy(SET CMP0037 NEW)
+file(WRITE "${CMAKE_BINARY_DIR}/CPackConfig.cmake" "")
+add_custom_target(test)
+add_custom_target(package)
+add_custom_target(package_source)
diff --git a/Tests/RunCMake/add_executable/OnlyObjectSources-result.txt b/Tests/RunCMake/CMP0037/NEW-cond-package_source-result.txt
similarity index 100%
copy from Tests/RunCMake/add_executable/OnlyObjectSources-result.txt
copy to Tests/RunCMake/CMP0037/NEW-cond-package_source-result.txt
diff --git a/Tests/RunCMake/CMP0037/NEW-cond-package_source-stderr.txt b/Tests/RunCMake/CMP0037/NEW-cond-package_source-stderr.txt
new file mode 100644
index 0000000..2d32147
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/NEW-cond-package_source-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at NEW-cond-package_source.cmake:5 \(add_custom_target\):
+  The target name "package_source" is reserved when CPack source packaging is
+  enabled.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0037/NEW-cond-package_source.cmake b/Tests/RunCMake/CMP0037/NEW-cond-package_source.cmake
new file mode 100644
index 0000000..3f8883b
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/NEW-cond-package_source.cmake
@@ -0,0 +1,5 @@
+cmake_policy(SET CMP0037 NEW)
+file(WRITE "${CMAKE_BINARY_DIR}/CPackSourceConfig.cmake" "")
+add_custom_target(test)
+add_custom_target(package)
+add_custom_target(package_source)
diff --git a/Tests/RunCMake/add_executable/OnlyObjectSources-result.txt b/Tests/RunCMake/CMP0037/NEW-cond-test-result.txt
similarity index 100%
copy from Tests/RunCMake/add_executable/OnlyObjectSources-result.txt
copy to Tests/RunCMake/CMP0037/NEW-cond-test-result.txt
diff --git a/Tests/RunCMake/CMP0037/NEW-cond-test-stderr.txt b/Tests/RunCMake/CMP0037/NEW-cond-test-stderr.txt
new file mode 100644
index 0000000..44b4741
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/NEW-cond-test-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at NEW-cond-test.cmake:3 \(add_custom_target\):
+  The target name "test" is reserved when CTest testing is enabled.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0037/NEW-cond-test.cmake b/Tests/RunCMake/CMP0037/NEW-cond-test.cmake
new file mode 100644
index 0000000..7eeaffc
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/NEW-cond-test.cmake
@@ -0,0 +1,5 @@
+cmake_policy(SET CMP0037 NEW)
+enable_testing()
+add_custom_target(test)
+add_custom_target(package)
+add_custom_target(package_source)
diff --git a/Tests/RunCMake/CMP0037/NEW-cond.cmake b/Tests/RunCMake/CMP0037/NEW-cond.cmake
new file mode 100644
index 0000000..d0dc77af
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/NEW-cond.cmake
@@ -0,0 +1,4 @@
+cmake_policy(SET CMP0037 NEW)
+add_custom_target(test)
+add_custom_target(package)
+add_custom_target(package_source)
diff --git a/Tests/RunCMake/CMP0037/OLD-cond-package-stderr.txt b/Tests/RunCMake/CMP0037/OLD-cond-package-stderr.txt
new file mode 100644
index 0000000..5a29a49
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/OLD-cond-package-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at OLD-cond-package.cmake:1 \(cmake_policy\):
+  The OLD behavior for policy CMP0037 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0037/OLD-cond-package.cmake b/Tests/RunCMake/CMP0037/OLD-cond-package.cmake
new file mode 100644
index 0000000..7a0afbe
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/OLD-cond-package.cmake
@@ -0,0 +1,5 @@
+cmake_policy(SET CMP0037 OLD)
+file(WRITE "${CMAKE_BINARY_DIR}/CPackConfig.cmake" "")
+add_custom_target(test)
+add_custom_target(package)
+add_custom_target(package_source)
diff --git a/Tests/RunCMake/CMP0037/OLD-cond-package_source-stderr.txt b/Tests/RunCMake/CMP0037/OLD-cond-package_source-stderr.txt
new file mode 100644
index 0000000..5f72e16
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/OLD-cond-package_source-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at OLD-cond-package_source.cmake:1 \(cmake_policy\):
+  The OLD behavior for policy CMP0037 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0037/OLD-cond-package_source.cmake b/Tests/RunCMake/CMP0037/OLD-cond-package_source.cmake
new file mode 100644
index 0000000..95616b6
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/OLD-cond-package_source.cmake
@@ -0,0 +1,5 @@
+cmake_policy(SET CMP0037 OLD)
+file(WRITE "${CMAKE_BINARY_DIR}/CPackSourceConfig.cmake" "")
+add_custom_target(test)
+add_custom_target(package)
+add_custom_target(package_source)
diff --git a/Tests/RunCMake/CMP0037/OLD-cond-stderr.txt b/Tests/RunCMake/CMP0037/OLD-cond-stderr.txt
new file mode 100644
index 0000000..94e4575
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/OLD-cond-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at OLD-cond.cmake:1 \(cmake_policy\):
+  The OLD behavior for policy CMP0037 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0037/OLD-cond-test-stderr.txt b/Tests/RunCMake/CMP0037/OLD-cond-test-stderr.txt
new file mode 100644
index 0000000..81e10ce
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/OLD-cond-test-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at OLD-cond-test.cmake:1 \(cmake_policy\):
+  The OLD behavior for policy CMP0037 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0037/OLD-cond-test.cmake b/Tests/RunCMake/CMP0037/OLD-cond-test.cmake
new file mode 100644
index 0000000..bfa32a9
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/OLD-cond-test.cmake
@@ -0,0 +1,5 @@
+cmake_policy(SET CMP0037 OLD)
+enable_testing()
+add_custom_target(test)
+add_custom_target(package)
+add_custom_target(package_source)
diff --git a/Tests/RunCMake/CMP0037/OLD-cond.cmake b/Tests/RunCMake/CMP0037/OLD-cond.cmake
new file mode 100644
index 0000000..abad680
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/OLD-cond.cmake
@@ -0,0 +1,5 @@
+cmake_policy(SET CMP0037 OLD)
+
+add_custom_target(test)
+add_custom_target(package)
+add_custom_target(package_source)
diff --git a/Tests/RunCMake/CMP0037/RunCMakeTest.cmake b/Tests/RunCMake/CMP0037/RunCMakeTest.cmake
index b7d8d7b..98274f0 100644
--- a/Tests/RunCMake/CMP0037/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMP0037/RunCMakeTest.cmake
@@ -9,5 +9,22 @@
   run_cmake(CMP0037-WARN-colon)
 endif()
 
+run_cmake(CMP0037-WARN-reserved)
 run_cmake(CMP0037-OLD-reserved)
 run_cmake(CMP0037-NEW-reserved)
+
+run_cmake(NEW-cond)
+run_cmake(NEW-cond-test)
+run_cmake(NEW-cond-package)
+run_cmake(OLD-cond)
+run_cmake(OLD-cond-test)
+run_cmake(OLD-cond-package)
+run_cmake(WARN-cond)
+run_cmake(WARN-cond-test)
+run_cmake(WARN-cond-package)
+
+if(RunCMake_GENERATOR MATCHES "Make|Ninja")
+  run_cmake(NEW-cond-package_source)
+  run_cmake(OLD-cond-package_source)
+  run_cmake(WARN-cond-package_source)
+endif()
diff --git a/Tests/RunCMake/CMP0037/WARN-cond-package-stderr.txt b/Tests/RunCMake/CMP0037/WARN-cond-package-stderr.txt
new file mode 100644
index 0000000..5960e51
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/WARN-cond-package-stderr.txt
@@ -0,0 +1,11 @@
+^CMake Warning \(dev\) at WARN-cond-package.cmake:4 \(add_custom_target\):
+  Policy CMP0037 is not set: Target names should not be reserved and should
+  match a validity pattern.  Run "cmake --help-policy CMP0037" for policy
+  details.  Use the cmake_policy command to set the policy and suppress this
+  warning.
+
+  The target name "package" is reserved when CPack packaging is enabled.  It
+  may result in undefined behavior.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+This warning is for project developers.  Use -Wno-dev to suppress it.$
diff --git a/Tests/RunCMake/CMP0037/WARN-cond-package.cmake b/Tests/RunCMake/CMP0037/WARN-cond-package.cmake
new file mode 100644
index 0000000..61cdc68
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/WARN-cond-package.cmake
@@ -0,0 +1,5 @@
+
+file(WRITE "${CMAKE_BINARY_DIR}/CPackConfig.cmake" "")
+add_custom_target(test)
+add_custom_target(package)
+add_custom_target(package_source)
diff --git a/Tests/RunCMake/CMP0037/WARN-cond-package_source-stderr.txt b/Tests/RunCMake/CMP0037/WARN-cond-package_source-stderr.txt
new file mode 100644
index 0000000..ae72909
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/WARN-cond-package_source-stderr.txt
@@ -0,0 +1,11 @@
+^CMake Warning \(dev\) at WARN-cond-package_source.cmake:5 \(add_custom_target\):
+  Policy CMP0037 is not set: Target names should not be reserved and should
+  match a validity pattern.  Run "cmake --help-policy CMP0037" for policy
+  details.  Use the cmake_policy command to set the policy and suppress this
+  warning.
+
+  The target name "package_source" is reserved when CPack source packaging is
+  enabled.  It may result in undefined behavior.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+This warning is for project developers.  Use -Wno-dev to suppress it.$
diff --git a/Tests/RunCMake/CMP0037/WARN-cond-package_source.cmake b/Tests/RunCMake/CMP0037/WARN-cond-package_source.cmake
new file mode 100644
index 0000000..468380c
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/WARN-cond-package_source.cmake
@@ -0,0 +1,5 @@
+
+file(WRITE "${CMAKE_BINARY_DIR}/CPackSourceConfig.cmake" "")
+add_custom_target(test)
+add_custom_target(package)
+add_custom_target(package_source)
diff --git a/Tests/RunCMake/CMP0037/WARN-cond-test-stderr.txt b/Tests/RunCMake/CMP0037/WARN-cond-test-stderr.txt
new file mode 100644
index 0000000..e7a3ee5
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/WARN-cond-test-stderr.txt
@@ -0,0 +1,11 @@
+^CMake Warning \(dev\) at WARN-cond-test.cmake:3 \(add_custom_target\):
+  Policy CMP0037 is not set: Target names should not be reserved and should
+  match a validity pattern.  Run "cmake --help-policy CMP0037" for policy
+  details.  Use the cmake_policy command to set the policy and suppress this
+  warning.
+
+  The target name "test" is reserved when CTest testing is enabled.  It may
+  result in undefined behavior.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+This warning is for project developers.  Use -Wno-dev to suppress it.$
diff --git a/Tests/RunCMake/CMP0037/WARN-cond-test.cmake b/Tests/RunCMake/CMP0037/WARN-cond-test.cmake
new file mode 100644
index 0000000..982af36
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/WARN-cond-test.cmake
@@ -0,0 +1,5 @@
+
+enable_testing()
+add_custom_target(test)
+add_custom_target(package)
+add_custom_target(package_source)
diff --git a/Tests/RunCMake/CMP0037/WARN-cond.cmake b/Tests/RunCMake/CMP0037/WARN-cond.cmake
new file mode 100644
index 0000000..04a7f9d
--- /dev/null
+++ b/Tests/RunCMake/CMP0037/WARN-cond.cmake
@@ -0,0 +1,4 @@
+
+add_custom_target(test)
+add_custom_target(package)
+add_custom_target(package_source)
diff --git a/Tests/RunCMake/CMP0038/CMP0038-OLD-result.txt b/Tests/RunCMake/CMP0038/CMP0038-OLD-result.txt
deleted file mode 100644
index 573541a..0000000
--- a/Tests/RunCMake/CMP0038/CMP0038-OLD-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/Tests/RunCMake/CMP0038/CMP0038-OLD-stderr.txt b/Tests/RunCMake/CMP0038/CMP0038-OLD-stderr.txt
new file mode 100644
index 0000000..c754128
--- /dev/null
+++ b/Tests/RunCMake/CMP0038/CMP0038-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0038-OLD.cmake:2 \(cmake_policy\):
+  The OLD behavior for policy CMP0038 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0039/CMP0039-OLD-result.txt b/Tests/RunCMake/CMP0039/CMP0039-OLD-result.txt
deleted file mode 100644
index 573541a..0000000
--- a/Tests/RunCMake/CMP0039/CMP0039-OLD-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/Tests/RunCMake/CMP0039/CMP0039-OLD-stderr.txt b/Tests/RunCMake/CMP0039/CMP0039-OLD-stderr.txt
new file mode 100644
index 0000000..d7863fd
--- /dev/null
+++ b/Tests/RunCMake/CMP0039/CMP0039-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0039-OLD.cmake:2 \(cmake_policy\):
+  The OLD behavior for policy CMP0039 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0040/CMP0040-OLD-existing-target-result.txt b/Tests/RunCMake/CMP0040/CMP0040-OLD-existing-target-result.txt
deleted file mode 100644
index 573541a..0000000
--- a/Tests/RunCMake/CMP0040/CMP0040-OLD-existing-target-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/Tests/RunCMake/CMP0040/CMP0040-OLD-existing-target-stderr.txt b/Tests/RunCMake/CMP0040/CMP0040-OLD-existing-target-stderr.txt
new file mode 100644
index 0000000..f38c03d
--- /dev/null
+++ b/Tests/RunCMake/CMP0040/CMP0040-OLD-existing-target-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0040-OLD-existing-target.cmake:1 \(cmake_policy\):
+  The OLD behavior for policy CMP0040 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0040/CMP0040-OLD-missing-target-result.txt b/Tests/RunCMake/CMP0040/CMP0040-OLD-missing-target-result.txt
deleted file mode 100644
index 573541a..0000000
--- a/Tests/RunCMake/CMP0040/CMP0040-OLD-missing-target-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/Tests/RunCMake/CMP0040/CMP0040-OLD-missing-target-stderr.txt b/Tests/RunCMake/CMP0040/CMP0040-OLD-missing-target-stderr.txt
new file mode 100644
index 0000000..61f4f03
--- /dev/null
+++ b/Tests/RunCMake/CMP0040/CMP0040-OLD-missing-target-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0040-OLD-missing-target.cmake:1 \(cmake_policy\):
+  The OLD behavior for policy CMP0040 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0041/CMP0041-OLD-result.txt b/Tests/RunCMake/CMP0041/CMP0041-OLD-result.txt
deleted file mode 100644
index 573541a..0000000
--- a/Tests/RunCMake/CMP0041/CMP0041-OLD-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/Tests/RunCMake/CMP0041/CMP0041-OLD-stderr.txt b/Tests/RunCMake/CMP0041/CMP0041-OLD-stderr.txt
new file mode 100644
index 0000000..1b736da
--- /dev/null
+++ b/Tests/RunCMake/CMP0041/CMP0041-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0041-OLD.cmake:2 \(cmake_policy\):
+  The OLD behavior for policy CMP0041 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0041/CMP0041-tid-OLD-result.txt b/Tests/RunCMake/CMP0041/CMP0041-tid-OLD-result.txt
deleted file mode 100644
index 573541a..0000000
--- a/Tests/RunCMake/CMP0041/CMP0041-tid-OLD-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/Tests/RunCMake/CMP0041/CMP0041-tid-OLD-stderr.txt b/Tests/RunCMake/CMP0041/CMP0041-tid-OLD-stderr.txt
new file mode 100644
index 0000000..dbc5167
--- /dev/null
+++ b/Tests/RunCMake/CMP0041/CMP0041-tid-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0041-tid-OLD.cmake:2 \(cmake_policy\):
+  The OLD behavior for policy CMP0041 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0042/CMP0042-OLD-result.txt b/Tests/RunCMake/CMP0042/CMP0042-OLD-result.txt
deleted file mode 100644
index 573541a..0000000
--- a/Tests/RunCMake/CMP0042/CMP0042-OLD-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/Tests/RunCMake/CMP0042/CMP0042-OLD-stderr.txt b/Tests/RunCMake/CMP0042/CMP0042-OLD-stderr.txt
new file mode 100644
index 0000000..9d1488d
--- /dev/null
+++ b/Tests/RunCMake/CMP0042/CMP0042-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0042-OLD.cmake:2 \(cmake_policy\):
+  The OLD behavior for policy CMP0042 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0043/CMP0043-OLD-result.txt b/Tests/RunCMake/CMP0043/CMP0043-OLD-result.txt
deleted file mode 100644
index 573541a..0000000
--- a/Tests/RunCMake/CMP0043/CMP0043-OLD-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/Tests/RunCMake/CMP0043/CMP0043-OLD-stderr.txt b/Tests/RunCMake/CMP0043/CMP0043-OLD-stderr.txt
new file mode 100644
index 0000000..ebbb361
--- /dev/null
+++ b/Tests/RunCMake/CMP0043/CMP0043-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0043-OLD.cmake:2 \(cmake_policy\):
+  The OLD behavior for policy CMP0043 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0045/CMP0045-OLD-result.txt b/Tests/RunCMake/CMP0045/CMP0045-OLD-result.txt
deleted file mode 100644
index 573541a..0000000
--- a/Tests/RunCMake/CMP0045/CMP0045-OLD-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/Tests/RunCMake/CMP0045/CMP0045-OLD-stderr.txt b/Tests/RunCMake/CMP0045/CMP0045-OLD-stderr.txt
new file mode 100644
index 0000000..0dac20f
--- /dev/null
+++ b/Tests/RunCMake/CMP0045/CMP0045-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0045-OLD.cmake:2 \(cmake_policy\):
+  The OLD behavior for policy CMP0045 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0046/CMP0046-OLD-existing-dependency-stderr.txt b/Tests/RunCMake/CMP0046/CMP0046-OLD-existing-dependency-stderr.txt
new file mode 100644
index 0000000..4444118
--- /dev/null
+++ b/Tests/RunCMake/CMP0046/CMP0046-OLD-existing-dependency-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0046-OLD-existing-dependency.cmake:1 \(cmake_policy\):
+  The OLD behavior for policy CMP0046 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0046/CMP0046-OLD-missing-dependency-stderr.txt b/Tests/RunCMake/CMP0046/CMP0046-OLD-missing-dependency-stderr.txt
new file mode 100644
index 0000000..525954f
--- /dev/null
+++ b/Tests/RunCMake/CMP0046/CMP0046-OLD-missing-dependency-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0046-OLD-missing-dependency.cmake:1 \(cmake_policy\):
+  The OLD behavior for policy CMP0046 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0049/CMP0049-OLD-result.txt b/Tests/RunCMake/CMP0049/CMP0049-OLD-result.txt
deleted file mode 100644
index 573541a..0000000
--- a/Tests/RunCMake/CMP0049/CMP0049-OLD-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/Tests/RunCMake/CMP0049/CMP0049-OLD-stderr.txt b/Tests/RunCMake/CMP0049/CMP0049-OLD-stderr.txt
new file mode 100644
index 0000000..b373970
--- /dev/null
+++ b/Tests/RunCMake/CMP0049/CMP0049-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0049-OLD.cmake:2 \(cmake_policy\):
+  The OLD behavior for policy CMP0049 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0050/CMP0050-OLD-result.txt b/Tests/RunCMake/CMP0050/CMP0050-OLD-result.txt
deleted file mode 100644
index 573541a..0000000
--- a/Tests/RunCMake/CMP0050/CMP0050-OLD-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/Tests/RunCMake/CMP0050/CMP0050-OLD-stderr.txt b/Tests/RunCMake/CMP0050/CMP0050-OLD-stderr.txt
new file mode 100644
index 0000000..3e7fa97
--- /dev/null
+++ b/Tests/RunCMake/CMP0050/CMP0050-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0050-OLD.cmake:2 \(cmake_policy\):
+  The OLD behavior for policy CMP0050 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0051/CMP0051-OLD-result.txt b/Tests/RunCMake/CMP0051/CMP0051-OLD-result.txt
deleted file mode 100644
index 573541a..0000000
--- a/Tests/RunCMake/CMP0051/CMP0051-OLD-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/Tests/RunCMake/CMP0051/CMP0051-OLD-stderr.txt b/Tests/RunCMake/CMP0051/CMP0051-OLD-stderr.txt
index cc17f33..697265e 100644
--- a/Tests/RunCMake/CMP0051/CMP0051-OLD-stderr.txt
+++ b/Tests/RunCMake/CMP0051/CMP0051-OLD-stderr.txt
@@ -1 +1,12 @@
-^Sources: "empty.cpp"$
+^CMake Deprecation Warning at CMP0051-OLD.cmake:2 \(cmake_policy\):
+  The OLD behavior for policy CMP0051 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+Sources: "empty.cpp"$
diff --git a/Tests/RunCMake/CMP0053/CMP0053-OLD-stderr.txt b/Tests/RunCMake/CMP0053/CMP0053-OLD-stderr.txt
index 836b0ff..2a0ddbaa 100644
--- a/Tests/RunCMake/CMP0053/CMP0053-OLD-stderr.txt
+++ b/Tests/RunCMake/CMP0053/CMP0053-OLD-stderr.txt
@@ -1,2 +1,13 @@
-^called
+^CMake Deprecation Warning at CMP0053-OLD.cmake:1 \(cmake_policy\):
+  The OLD behavior for policy CMP0053 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+called
 --><--$
diff --git a/Tests/RunCMake/CMP0054/CMP0054-OLD-stderr.txt b/Tests/RunCMake/CMP0054/CMP0054-OLD-stderr.txt
index f5a8fbe..0500280 100644
--- a/Tests/RunCMake/CMP0054/CMP0054-OLD-stderr.txt
+++ b/Tests/RunCMake/CMP0054/CMP0054-OLD-stderr.txt
@@ -1 +1,10 @@
-$^
+^CMake Deprecation Warning at CMP0054-OLD.cmake:1 \(cmake_policy\):
+  The OLD behavior for policy CMP0054 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0054/CMP0054-keywords-OLD-stderr.txt b/Tests/RunCMake/CMP0054/CMP0054-keywords-OLD-stderr.txt
index f5a8fbe..60303cd 100644
--- a/Tests/RunCMake/CMP0054/CMP0054-keywords-OLD-stderr.txt
+++ b/Tests/RunCMake/CMP0054/CMP0054-keywords-OLD-stderr.txt
@@ -1 +1,10 @@
-$^
+^CMake Deprecation Warning at CMP0054-keywords-OLD.cmake:1 \(cmake_policy\):
+  The OLD behavior for policy CMP0054 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0054/CMP0054-policy-command-scope-stderr.txt b/Tests/RunCMake/CMP0054/CMP0054-policy-command-scope-stderr.txt
index f5a8fbe..1b35472 100644
--- a/Tests/RunCMake/CMP0054/CMP0054-policy-command-scope-stderr.txt
+++ b/Tests/RunCMake/CMP0054/CMP0054-policy-command-scope-stderr.txt
@@ -1 +1,10 @@
-$^
+^CMake Deprecation Warning at CMP0054-policy-command-scope.cmake:25 \(cmake_policy\):
+  The OLD behavior for policy CMP0054 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0054/CMP0054-policy-foreach-scope-stderr.txt b/Tests/RunCMake/CMP0054/CMP0054-policy-foreach-scope-stderr.txt
index f5a8fbe..4eac90e 100644
--- a/Tests/RunCMake/CMP0054/CMP0054-policy-foreach-scope-stderr.txt
+++ b/Tests/RunCMake/CMP0054/CMP0054-policy-foreach-scope-stderr.txt
@@ -1 +1,54 @@
-$^
+^CMake Deprecation Warning at CMP0054-policy-foreach-scope.cmake:14 \(cmake_policy\):
+  The OLD behavior for policy CMP0054 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+CMake Deprecation Warning at CMP0054-policy-foreach-scope.cmake:14 \(cmake_policy\):
+  The OLD behavior for policy CMP0054 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+CMake Deprecation Warning at CMP0054-policy-foreach-scope.cmake:27 \(cmake_policy\):
+  The OLD behavior for policy CMP0054 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+CMake Deprecation Warning at CMP0054-policy-foreach-scope.cmake:48 \(cmake_policy\):
+  The OLD behavior for policy CMP0054 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+CMake Deprecation Warning at CMP0054-policy-foreach-scope.cmake:48 \(cmake_policy\):
+  The OLD behavior for policy CMP0054 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0054/CMP0054-policy-nested-if-stderr.txt b/Tests/RunCMake/CMP0054/CMP0054-policy-nested-if-stderr.txt
index f5a8fbe..a2dd62e 100644
--- a/Tests/RunCMake/CMP0054/CMP0054-policy-nested-if-stderr.txt
+++ b/Tests/RunCMake/CMP0054/CMP0054-policy-nested-if-stderr.txt
@@ -1 +1,10 @@
-$^
+^CMake Deprecation Warning at CMP0054-policy-nested-if.cmake:23 \(cmake_policy\):
+  The OLD behavior for policy CMP0054 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMP0054/CMP0054-policy-while-scope-stderr.txt b/Tests/RunCMake/CMP0054/CMP0054-policy-while-scope-stderr.txt
index f5a8fbe..718904d 100644
--- a/Tests/RunCMake/CMP0054/CMP0054-policy-while-scope-stderr.txt
+++ b/Tests/RunCMake/CMP0054/CMP0054-policy-while-scope-stderr.txt
@@ -1 +1,54 @@
-$^
+^CMake Deprecation Warning at CMP0054-policy-while-scope.cmake:16 \(cmake_policy\):
+  The OLD behavior for policy CMP0054 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+CMake Deprecation Warning at CMP0054-policy-while-scope.cmake:16 \(cmake_policy\):
+  The OLD behavior for policy CMP0054 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+CMake Deprecation Warning at CMP0054-policy-while-scope.cmake:37 \(cmake_policy\):
+  The OLD behavior for policy CMP0054 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+CMake Deprecation Warning at CMP0054-policy-while-scope.cmake:58 \(cmake_policy\):
+  The OLD behavior for policy CMP0054 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+CMake Deprecation Warning at CMP0054-policy-while-scope.cmake:58 \(cmake_policy\):
+  The OLD behavior for policy CMP0054 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 29325ff..f306200 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -15,6 +15,7 @@
   add_test(NAME RunCMake.${test} COMMAND ${CMAKE_CMAKE_COMMAND}
     -DCMAKE_MODULE_PATH=${CMAKE_CURRENT_SOURCE_DIR}
     -DRunCMake_GENERATOR=${CMAKE_GENERATOR}
+    -DRunCMake_GENERATOR_INSTANCE=${CMAKE_GENERATOR_INSTANCE}
     -DRunCMake_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
     -DRunCMake_GENERATOR_TOOLSET=${CMAKE_GENERATOR_TOOLSET}
     -DRunCMake_MAKE_PROGRAM=${CMake_TEST_EXPLICIT_MAKE_PROGRAM}
@@ -47,6 +48,7 @@
         -DTEST_TYPE=${type}
         -DCMAKE_MODULE_PATH=${CMAKE_CURRENT_SOURCE_DIR}
         -DRunCMake_GENERATOR=${CMAKE_GENERATOR}
+        -DRunCMake_GENERATOR_INSTANCE=${CMAKE_GENERATOR_INSTANCE}
         -DRunCMake_GENERATOR_PLATFORM=${CMAKE_GENERATOR_PLATFORM}
         -DRunCMake_GENERATOR_TOOLSET=${CMAKE_GENERATOR_TOOLSET}
         -DRunCMake_MAKE_PROGRAM=${CMake_TEST_EXPLICIT_MAKE_PROGRAM}
@@ -142,10 +144,12 @@
 add_RunCMake_test(FeatureSummary)
 add_RunCMake_test(FPHSA)
 add_RunCMake_test(FindBoost)
+add_RunCMake_test(FindOpenGL)
 if(NOT CMAKE_C_COMPILER_ID MATCHES "Watcom")
   add_RunCMake_test(GenerateExportHeader)
 endif()
 add_RunCMake_test(GeneratorExpression)
+add_RunCMake_test(GeneratorInstance)
 add_RunCMake_test(GeneratorPlatform)
 add_RunCMake_test(GeneratorToolset)
 add_RunCMake_test(GetPrerequisites)
@@ -215,6 +219,7 @@
 add_RunCMake_test(find_package)
 add_RunCMake_test(find_path)
 add_RunCMake_test(find_program -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME})
+add_RunCMake_test(foreach)
 add_RunCMake_test(get_filename_component)
 add_RunCMake_test(get_property)
 add_RunCMake_test(if)
@@ -327,6 +332,7 @@
 add_RunCMake_test(CPackConfig)
 add_RunCMake_test(CPackInstallProperties)
 add_RunCMake_test(ExternalProject)
+add_RunCMake_test(FetchContent)
 add_RunCMake_test(CTestCommandLine)
 # Only run this test on unix platforms that support
 # symbolic links
diff --git a/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake b/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake
index 99d3155..948c6ab 100644
--- a/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake
+++ b/Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake
@@ -45,13 +45,22 @@
     unset(prefix_)
   endif()
 
-  if(NOT DEFINED TEST_MAIN_INSTALL_PREFIX_PATH)
-    set(TEST_MAIN_INSTALL_PREFIX_PATH "/usr")
+  # add install prefix to expected paths
+  if(DEFINED EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX)
+    set(EXPECTED_FILE_PACKAGING_PREFIX
+      "${EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX}")
+  elseif(NOT DEFINED EXPECTED_FILE_PACKAGING_PREFIX)
+    # default CPack Archive packaging install prefix
+    set(EXPECTED_FILE_PACKAGING_PREFIX "/")
   endif()
+  set(prepared_ "${EXPECTED_FILE_PACKAGING_PREFIX}")
+  foreach(part_ IN LISTS ${CONTENT_VAR})
+    list(APPEND prepared_ "${EXPECTED_FILE_PACKAGING_PREFIX}${part_}")
+  endforeach()
 
   unset(filtered_)
-  foreach(part_ IN LISTS ${CONTENT_VAR})
-    string(REGEX REPLACE "^${TEST_MAIN_INSTALL_PREFIX_PATH}(/|$)" "" part_ "${part_}")
+  foreach(part_ IN LISTS prepared_)
+    string(REGEX REPLACE "^/" "" part_ "${part_}")
 
     if(part_)
       list(APPEND filtered_ "${prefix_}${part_}")
diff --git a/Tests/RunCMake/CPack/CPackTestHelpers.cmake b/Tests/RunCMake/CPack/CPackTestHelpers.cmake
index f883c69..447b08b 100644
--- a/Tests/RunCMake/CPack/CPackTestHelpers.cmake
+++ b/Tests/RunCMake/CPack/CPackTestHelpers.cmake
@@ -35,10 +35,27 @@
       "-DRunCMake_TEST_FILE_PREFIX=${TEST_NAME}"
       "-DRunCMake_SUBTEST_SUFFIX=${SUBTEST_SUFFIX}"
       "-DPACKAGING_TYPE=${PACKAGING_TYPE}")
+
+    foreach(o out err)
+      if(SUBTEST_SUFFIX AND EXISTS ${RunCMake_SOURCE_DIR}/tests/${TEST_NAME}/configure-${PACKAGING_TYPE}-${SUBTEST_SUFFIX}-std${o}.txt)
+        set(RunCMake-std${o}-file "tests/${TEST_NAME}/configure-${PACKAGING_TYPE}-${SUBTEST_SUFFIX}-std${o}.txt")
+      elseif(SUBTEST_SUFFIX AND EXISTS ${RunCMake_SOURCE_DIR}/tests/${TEST_NAME}/configure-${SUBTEST_SUFFIX}-std${o}.txt)
+        set(RunCMake-std${o}-file "tests/${TEST_NAME}/configure-${SUBTEST_SUFFIX}-std${o}.txt")
+      elseif(EXISTS ${RunCMake_SOURCE_DIR}/tests/${TEST_NAME}/configure-${PACKAGING_TYPE}-std${o}.txt)
+        set(RunCMake-std${o}-file "tests/${TEST_NAME}/configure-${PACKAGING_TYPE}-std${o}.txt")
+      elseif(EXISTS ${RunCMake_SOURCE_DIR}/tests/${TEST_NAME}/configure-std${o}.txt)
+        set(RunCMake-std${o}-file "tests/${TEST_NAME}/configure-std${o}.txt")
+      else()
+        unset(RunCMake-std${o}-file)
+      endif()
+    endforeach()
+
     run_cmake(${full_test_name_})
 
     # execute optional build step
     if(build)
+      unset(RunCMake-stdout-file)
+      unset(RunCMake-stderr-file)
       run_cmake_command(${full_test_name_}-Build "${CMAKE_COMMAND}" --build "${RunCMake_TEST_BINARY_DIR}")
     endif()
 
@@ -68,8 +85,12 @@
         set(RunCMake-std${o}-file "tests/${TEST_NAME}/${TEST_TYPE}-${SUBTEST_SUFFIX}-std${o}.txt")
       elseif(EXISTS ${RunCMake_SOURCE_DIR}/tests/${TEST_NAME}/${TEST_TYPE}-std${o}.txt)
         set(RunCMake-std${o}-file "tests/${TEST_NAME}/${TEST_TYPE}-std${o}.txt")
+      elseif(SUBTEST_SUFFIX AND EXISTS ${RunCMake_SOURCE_DIR}/tests/${TEST_NAME}/${SUBTEST_SUFFIX}-std${o}.txt)
+        set(RunCMake-std${o}-file "tests/${TEST_NAME}/${SUBTEST_SUFFIX}-std${o}.txt")
       elseif(EXISTS ${RunCMake_SOURCE_DIR}/${TEST_TYPE}/default_expected_std${o}.txt)
         set(RunCMake-std${o}-file "${TEST_TYPE}/default_expected_std${o}.txt")
+      else()
+        unset(RunCMake-std${o}-file)
       endif()
     endforeach()
 
diff --git a/Tests/RunCMake/CPack/DEB/Helpers.cmake b/Tests/RunCMake/CPack/DEB/Helpers.cmake
index 6d8e84a..f7c5c84 100644
--- a/Tests/RunCMake/CPack/DEB/Helpers.cmake
+++ b/Tests/RunCMake/CPack/DEB/Helpers.cmake
@@ -47,7 +47,20 @@
 endfunction()
 
 function(toExpectedContentList FILE_NO CONTENT_VAR)
-  # no need to do anything
+  # add install prefix to expected paths
+  if(DEFINED EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX)
+    set(EXPECTED_FILE_PACKAGING_PREFIX
+      "${EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX}")
+  elseif(NOT DEFINED EXPECTED_FILE_PACKAGING_PREFIX)
+    # default CPackDeb packaging install prefix
+    set(EXPECTED_FILE_PACKAGING_PREFIX "/usr")
+  endif()
+  set(prepared_ "${EXPECTED_FILE_PACKAGING_PREFIX}")
+  foreach(part_ IN LISTS ${CONTENT_VAR})
+    list(APPEND prepared_ "${EXPECTED_FILE_PACKAGING_PREFIX}${part_}")
+  endforeach()
+
+  set(${CONTENT_VAR} "${prepared_}" PARENT_SCOPE)
 endfunction()
 
 function(getMissingShlibsErrorExtra FILE RESULT_VAR)
diff --git a/Tests/RunCMake/CPack/README.txt b/Tests/RunCMake/CPack/README.txt
index cf7c02c..2e2abdf 100644
--- a/Tests/RunCMake/CPack/README.txt
+++ b/Tests/RunCMake/CPack/README.txt
@@ -96,6 +96,14 @@
 a function run_after_include_cpack can be declared in test.cmake file and that
 function will run after the inclusion of CPack.cmake.
 
+NOTE: During CMake configure stage developer warnings may be expected. In such
+cases an expected output regular expression can be provided by creating
+'<test_name>/configure-stdout.txt' and/or '<test_name>/configure-stderr.txt'
+file. There are also more specialized versions of the file available:
+- configure-${PACKAGING_TYPE}-${SUBTEST_SUFFIX}-std${o}.txt
+- configure-${SUBTEST_SUFFIX}-std${o}.txt
+- configure-${PACKAGING_TYPE}-std${o}.txt
+
 build phase (optional and not available for source package tests)
 -----------------------------------------------------------------
 
@@ -149,17 +157,23 @@
   NOTE: This variable should be used only as last resort as it sets generator
         specific regular expression.
         EXPECTED_FILE_CONTENT_<file_number_starting_with_1>_LIST should be
-        prefered as it requires a list of expected files and directories that
+        preferred as it requires a list of expected files and directories that
         is later changed automatically depending on the generator so expected
         package content can be written only once per test for all generators.
 
+- EXPECTED_FILE_PACKAGING_PREFIX and
+  EXPECTED_FILE_<file_number_starting_with_1>_PACKAGING_PREFIX variables can be
+  set to explicitly specified CPACK_PACKAGING_PREFIX value. By default this
+  variable does not need to be set as it is implicitly set to package generator
+  specific prefix.
+
 Optional verification phase is generator specific and is optionaly executed.
 This phase is executed if '<test_name>/VerifyResult.cmake' script exists.
 
 VerifyResult.cmake script also automatically prints out standard output and
 standard error from CPack execution phase that is compared with
 '<test_name>/<generator_name>-stdout.txt' regular expression and
-and '<test_name>/<generator_name>-stderr.txt' regular expresson respectively.
+'<test_name>/<generator_name>-stderr.txt' regular expresson respectively.
 NOTE: For subtests generator name can also be suffixed with subtest name and/or
       packaging type (MONOLITHIC, COMPONENT, GROUP) and in such cases the
       preferences of which file will be used are as follows:
@@ -167,6 +181,7 @@
         - generator name + packaging type
         - generator name + subtest name
         - generator name
+        - subtest name
         - default generator
       File name format: '<generator_name>-<packaging_type>-<subtest_name>-std<type>.txt'
                         where <type> can either be 'out' or 'err'.
@@ -209,7 +224,7 @@
       + FILE that will contain the package file for which the package content
         should be returned.
       + RESULT_VAR that will tell the function which variable in parent scope
-        should contain the result (list of pacakge content)
+        should contain the result (list of package content)
     - toExpectedContentList: This function should convert an expected package
                              content list into one that is expected for the
                              generator (e.g. rpm packages have install/relocate
diff --git a/Tests/RunCMake/CPack/RPM/Helpers.cmake b/Tests/RunCMake/CPack/RPM/Helpers.cmake
index 88fc231..a29c020 100644
--- a/Tests/RunCMake/CPack/RPM/Helpers.cmake
+++ b/Tests/RunCMake/CPack/RPM/Helpers.cmake
@@ -47,14 +47,29 @@
 endfunction()
 
 function(toExpectedContentList FILE_NO CONTENT_VAR)
-  if(NOT DEFINED TEST_INSTALL_PREFIX_PATHS)
-    set(TEST_INSTALL_PREFIX_PATHS "/usr")
+  # add install prefix to expected paths
+  if(DEFINED EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX)
+    set(EXPECTED_FILE_PACKAGING_PREFIX
+      "${EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX}")
+  elseif(NOT DEFINED EXPECTED_FILE_PACKAGING_PREFIX)
+    # default CPackRPM packaging install prefix
+    set(EXPECTED_FILE_PACKAGING_PREFIX "/usr")
   endif()
-
-  unset(filtered_)
+  set(prepared_ "${EXPECTED_FILE_PACKAGING_PREFIX}")
   foreach(part_ IN LISTS ${CONTENT_VAR})
+    list(APPEND prepared_ "${EXPECTED_FILE_PACKAGING_PREFIX}${part_}")
+  endforeach()
+
+  # remove paths that are excluded from auto packaging
+  if(NOT DEFINED CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST)
+    set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST
+      /etc /etc/init.d /usr /usr/bin /usr/include /usr/lib
+      /usr/libx32 /usr/lib64 /usr/share /usr/share/aclocal /usr/share/doc)
+  endif()
+  unset(filtered_)
+  foreach(part_ IN LISTS prepared_)
     unset(dont_add_)
-    foreach(for_removal_ IN LISTS TEST_INSTALL_PREFIX_PATHS)
+    foreach(for_removal_ IN LISTS CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST)
       if(part_ STREQUAL for_removal_)
         set(dont_add_ TRUE)
         break()
diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake
index aa55c44..4b7f146 100644
--- a/Tests/RunCMake/CPack/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake
@@ -7,12 +7,13 @@
 run_cpack_test(CUSTOM_BINARY_SPEC_FILE "RPM" false "MONOLITHIC;COMPONENT")
 run_cpack_test(CUSTOM_NAMES "RPM;DEB;TGZ" true "COMPONENT")
 run_cpack_test(DEBUGINFO "RPM" true "COMPONENT")
+run_cpack_test_subtests(DEFAULT_PERMISSIONS "CMAKE_var_set;CPACK_var_set;both_set;invalid_CMAKE_var;invalid_CPACK_var" "RPM;DEB" false "MONOLITHIC;COMPONENT")
 run_cpack_test(DEPENDENCIES "RPM;DEB" true "COMPONENT")
 run_cpack_test(DIST "RPM" false "MONOLITHIC")
 run_cpack_test(EMPTY_DIR "RPM;DEB;TGZ" true "MONOLITHIC;COMPONENT")
 run_cpack_test(VERSION "RPM;DEB" false "MONOLITHIC;COMPONENT")
 run_cpack_test(EXTRA "DEB" false "COMPONENT")
-run_cpack_test(GENERATE_SHLIBS "DEB" true "COMPONENT")
+run_cpack_test_subtests(GENERATE_SHLIBS "soversion_not_zero;soversion_zero" "DEB" true "COMPONENT")
 run_cpack_test(GENERATE_SHLIBS_LDCONFIG "DEB" true "COMPONENT")
 run_cpack_test(INSTALL_SCRIPTS "RPM" false "COMPONENT")
 run_cpack_test(LONG_FILENAMES "DEB" false "MONOLITHIC")
diff --git a/Tests/RunCMake/CPack/STGZ/Helpers.cmake b/Tests/RunCMake/CPack/STGZ/Helpers.cmake
index 68b1eab..1756645 100644
--- a/Tests/RunCMake/CPack/STGZ/Helpers.cmake
+++ b/Tests/RunCMake/CPack/STGZ/Helpers.cmake
@@ -47,18 +47,29 @@
     string(SUBSTRING "${prefix_}" 0 ${pos_} prefix_)
   endif()
 
-  if(NOT DEFINED TEST_MAIN_INSTALL_PREFIX_PATH)
-    set(TEST_MAIN_INSTALL_PREFIX_PATH "/usr")
+    # add install prefix to expected paths
+  if(DEFINED EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX)
+    set(EXPECTED_FILE_PACKAGING_PREFIX
+      "${EXPECTED_FILE_${FILE_NO}_PACKAGING_PREFIX}")
+  elseif(NOT DEFINED EXPECTED_FILE_PACKAGING_PREFIX)
+    # default CPack Archive packaging install prefix
+    set(EXPECTED_FILE_PACKAGING_PREFIX "/")
   endif()
 
-  set(filtered_ "${prefix_}")
-  foreach(part_ IN LISTS ${CONTENT_VAR})
-    string(REGEX REPLACE "^${TEST_MAIN_INSTALL_PREFIX_PATH}(/|$)" "" part_ "${part_}")
+  # remove trailing slash otherwise path concatenation will cause double slashes
+  string(REGEX REPLACE "/$" "" EXPECTED_FILE_PACKAGING_PREFIX
+    "${EXPECTED_FILE_PACKAGING_PREFIX}")
 
-    if(part_)
-      list(APPEND filtered_ "${prefix_}/${part_}")
-    endif()
+  if(EXPECTED_FILE_PACKAGING_PREFIX)
+    set(prepared_ "${prefix_}")
+  else()
+    unset(prepared_)
+  endif()
+
+  list(APPEND prepared_ "${prefix_}${EXPECTED_FILE_PACKAGING_PREFIX}")
+  foreach(part_ IN LISTS ${CONTENT_VAR})
+    list(APPEND prepared_ "${prefix_}${EXPECTED_FILE_PACKAGING_PREFIX}${part_}")
   endforeach()
 
-  set(${CONTENT_VAR} "${filtered_}" PARENT_SCOPE)
+  set(${CONTENT_VAR} "${prepared_}" PARENT_SCOPE)
 endfunction()
diff --git a/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/ExpectedFiles.cmake
index 5cb12c3..02a7821 100644
--- a/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/CPACK_INSTALL_SCRIPT/ExpectedFiles.cmake
@@ -1,3 +1,3 @@
 set(EXPECTED_FILES_COUNT "1")
 
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/abc.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/abc.txt")
diff --git a/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/ExpectedFiles.cmake
index 694dc00..6d895ec 100644
--- a/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/ExpectedFiles.cmake
@@ -1,9 +1,9 @@
 set(EXPECTED_FILES_COUNT "1")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
 
 if(PACKAGING_TYPE STREQUAL "COMPONENT")
   set(EXPECTED_FILES_COUNT "2")
   set(EXPECTED_FILE_1_COMPONENT "test")
   set(EXPECTED_FILE_2_COMPONENT "test2")
-  set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt")
+  set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt")
 endif()
diff --git a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake
index 5cb280c..07226df 100644
--- a/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake
@@ -1,10 +1,10 @@
 set(EXPECTED_FILES_COUNT "3")
 set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE)
 set(EXPECTED_FILE_1_COMPONENT "pkg_1")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
 set(EXPECTED_FILE_2_NAME "second")
-set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
-set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_2_LIST "/foo;/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_3_LIST "/foo;/foo/CMakeLists.txt")
 
 if(GENERATOR_TYPE STREQUAL "DEB" OR GENERATOR_TYPE STREQUAL "RPM")
   string(TOLOWER "${GENERATOR_TYPE}" file_extension_)
diff --git a/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake
index 3d8de74..b26c6c7 100644
--- a/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake
@@ -5,11 +5,11 @@
 
 set(EXPECTED_FILE_1_NAME "Debuginfo")
 set(EXPECTED_FILE_1_COMPONENT "applications")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/test_prog")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog")
 set(EXPECTED_FILE_2 "TestDinfo-pkg*-headers.rpm")
-set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt")
 set(EXPECTED_FILE_3 "TestDinfo-pkg*-libs.rpm")
-set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/bas;/usr/bas/libtest_lib.so")
+set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/libtest_lib.so")
 
 set(EXPECTED_FILE_4_NAME "Debuginfo")
 set(EXPECTED_FILE_4_COMPONENT "applications-debuginfo")
diff --git a/Tests/RunCMake/CPack/tests/DEB_PACKAGE_VERSION_BACK_COMPATIBILITY/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/DEB_PACKAGE_VERSION_BACK_COMPATIBILITY/ExpectedFiles.cmake
index 6142eb3..d1a3a5f 100644
--- a/Tests/RunCMake/CPack/tests/DEB_PACKAGE_VERSION_BACK_COMPATIBILITY/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/DEB_PACKAGE_VERSION_BACK_COMPATIBILITY/ExpectedFiles.cmake
@@ -1,2 +1,2 @@
 set(EXPECTED_FILES_COUNT "1")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
diff --git a/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/ExpectedFiles.cmake
new file mode 100644
index 0000000..b6fcc17
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/ExpectedFiles.cmake
@@ -0,0 +1,6 @@
+if(${RunCMake_SUBTEST_SUFFIX} MATCHES "invalid_.*_var")
+  set(EXPECTED_FILES_COUNT "0")
+else()
+  set(EXPECTED_FILES_COUNT "1")
+  set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
+endif()
diff --git a/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/VerifyResult.cmake
new file mode 100644
index 0000000..16ebcdc
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/VerifyResult.cmake
@@ -0,0 +1,39 @@
+if(NOT ${RunCMake_SUBTEST_SUFFIX} MATCHES "invalid_.*_var")
+  if(GENERATOR_TYPE STREQUAL "RPM")
+    function(checkContentPermissions_ FILE REGEX)
+      execute_process(COMMAND ${RPM_EXECUTABLE} -qp --dump ${FILE}
+                  WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
+                  OUTPUT_VARIABLE PERMISSIONS_
+                  ERROR_QUIET
+                  OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+      if(NOT PERMISSIONS_ MATCHES "${REGEX}")
+        message(FATAL_ERROR "Permissions in '${FILE}'. Permissions: '${PERMISSIONS_}'")
+      endif()
+    endfunction()
+
+    if(${RunCMake_SUBTEST_SUFFIX} MATCHES "CMAKE_var_set")
+      checkContentPermissions_("${FOUND_FILE_1}"
+        "/usr/foo .*740 root root.*")
+    else()
+      checkContentPermissions_("${FOUND_FILE_1}"
+        "/usr/foo .*700 root root.*")
+    endif()
+  else() # DEB
+    function(checkContentPermissions_ FILE REGEX)
+      getPackageContent("${FILE}" PERMISSIONS_)
+
+      if(NOT PERMISSIONS_ MATCHES "${REGEX}")
+        message(FATAL_ERROR "Permissions in '${FILE}'. Permissions: '${PERMISSIONS_}'")
+      endif()
+    endfunction()
+
+    if(${RunCMake_SUBTEST_SUFFIX} MATCHES "CMAKE_var_set")
+      checkContentPermissions_("${FOUND_FILE_1}"
+        "drwxr----- root/root .* ./usr/\ndrwxr----- root/root .* ./usr/foo/\n.*")
+    else()
+      checkContentPermissions_("${FOUND_FILE_1}"
+        "drwx------ root/root .* ./usr/\ndrwx------ root/root .* ./usr/foo/\n.*")
+    endif()
+  endif()
+endif()
diff --git a/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/invalid_CMAKE_var-stderr.txt b/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/invalid_CMAKE_var-stderr.txt
new file mode 100644
index 0000000..541763a
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/invalid_CMAKE_var-stderr.txt
@@ -0,0 +1 @@
+.*CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS value is invalid.*
diff --git a/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/invalid_CPACK_var-stderr.txt b/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/invalid_CPACK_var-stderr.txt
new file mode 100644
index 0000000..541763a
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/invalid_CPACK_var-stderr.txt
@@ -0,0 +1 @@
+.*CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS value is invalid.*
diff --git a/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/test.cmake b/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/test.cmake
new file mode 100644
index 0000000..afe9390
--- /dev/null
+++ b/Tests/RunCMake/CPack/tests/DEFAULT_PERMISSIONS/test.cmake
@@ -0,0 +1,34 @@
+if(${RunCMake_SUBTEST_SUFFIX} MATCHES "CMAKE_var_set" OR
+  ${RunCMake_SUBTEST_SUFFIX} MATCHES "both_set")
+
+  set(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
+      OWNER_READ
+      OWNER_WRITE
+      OWNER_EXECUTE
+      GROUP_READ
+    )
+endif()
+
+if(${RunCMake_SUBTEST_SUFFIX} MATCHES "invalid_CMAKE_var")
+  list(APPEND CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS "INVALID")
+endif()
+
+if(${RunCMake_SUBTEST_SUFFIX} MATCHES "CPACK_var_set" OR
+  ${RunCMake_SUBTEST_SUFFIX} MATCHES "both_set")
+
+  set(CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
+      OWNER_READ
+      OWNER_WRITE
+      OWNER_EXECUTE
+    )
+endif()
+
+if(${RunCMake_SUBTEST_SUFFIX} MATCHES "invalid_CPACK_var")
+  list(APPEND CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS "INVALID")
+endif()
+
+install(FILES CMakeLists.txt DESTINATION foo COMPONENT test)
+
+if(PACKAGING_TYPE STREQUAL "COMPONENT")
+  set(CPACK_COMPONENTS_ALL test)
+endif()
diff --git a/Tests/RunCMake/CPack/tests/DEPENDENCIES/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/DEPENDENCIES/ExpectedFiles.cmake
index 3b280ba..be7ba07 100644
--- a/Tests/RunCMake/CPack/tests/DEPENDENCIES/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/DEPENDENCIES/ExpectedFiles.cmake
@@ -1,14 +1,14 @@
 set(EXPECTED_FILES_COUNT "5")
 set(EXPECTED_FILE_1_COMPONENT "applications")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/test_prog")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog")
 set(EXPECTED_FILE_2_COMPONENT "applications_auto")
-set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/foo_auto;/usr/foo_auto/test_prog")
+set(EXPECTED_FILE_CONTENT_2_LIST "/foo_auto;/foo_auto/test_prog")
 set(EXPECTED_FILE_3_COMPONENT "headers")
-set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_3_LIST "/bar;/bar/CMakeLists.txt")
 set(EXPECTED_FILE_4_COMPONENT "libs")
-set(EXPECTED_FILE_CONTENT_4_LIST "/usr/bas;/usr/bas/libtest_lib.so")
+set(EXPECTED_FILE_CONTENT_4_LIST "/bas;/bas/libtest_lib.so")
 set(EXPECTED_FILE_5_COMPONENT "libs_auto")
-set(EXPECTED_FILE_CONTENT_5_LIST "/usr;/usr/bas_auto;/usr/bas_auto/libtest_lib.so")
+set(EXPECTED_FILE_CONTENT_5_LIST "/bas_auto;/bas_auto/libtest_lib.so")
 
 if(GENERATOR_TYPE STREQUAL "DEB")
   set(whitespaces_ "[\t\n\r ]*")
diff --git a/Tests/RunCMake/CPack/tests/DIST/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/DIST/ExpectedFiles.cmake
index 6142eb3..d1a3a5f 100644
--- a/Tests/RunCMake/CPack/tests/DIST/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/DIST/ExpectedFiles.cmake
@@ -1,2 +1,2 @@
 set(EXPECTED_FILES_COUNT "1")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
diff --git a/Tests/RunCMake/CPack/tests/EMPTY_DIR/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/EMPTY_DIR/ExpectedFiles.cmake
index 650687c..8df6831 100644
--- a/Tests/RunCMake/CPack/tests/EMPTY_DIR/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/EMPTY_DIR/ExpectedFiles.cmake
@@ -1,6 +1,6 @@
 set(EXPECTED_FILES_COUNT "1")
 set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE)
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/empty")
+set(EXPECTED_FILE_CONTENT_1_LIST "/empty")
 
 if(PACKAGING_TYPE STREQUAL "COMPONENT")
   set(EXPECTED_FILE_1_COMPONENT "test")
diff --git a/Tests/RunCMake/CPack/tests/EXTRA/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/EXTRA/ExpectedFiles.cmake
index ded2923..407cbe6 100644
--- a/Tests/RunCMake/CPack/tests/EXTRA/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/EXTRA/ExpectedFiles.cmake
@@ -1,8 +1,8 @@
 set(EXPECTED_FILES_COUNT "3")
 set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE)
 set(EXPECTED_FILE_1_COMPONENT "foo")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
 set(EXPECTED_FILE_2_COMPONENT "bar")
-set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt")
 set(EXPECTED_FILE_3_COMPONENT "bas")
-set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/bas;/usr/bas/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/CMakeLists.txt")
diff --git a/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake
index a45b38d..974df22 100644
--- a/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/EXTRA_SLASH_IN_PATH/ExpectedFiles.cmake
@@ -2,6 +2,7 @@
 
 set(EXPECTED_FILES_COUNT "5")
 set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE)
+set(EXPECTED_FILE_PACKAGING_PREFIX "")
 
 set(EXPECTED_FILE_1_COMPONENT "applications")
 set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog")
diff --git a/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/VerifyResult.cmake b/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/VerifyResult.cmake
index b1952ef..8cefeea 100644
--- a/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/VerifyResult.cmake
+++ b/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/VerifyResult.cmake
@@ -1,4 +1,9 @@
-set(shlibs_shlibs "^libtest_lib 0\\.8 generate_shlibs \\(\\= 0\\.1\\.1\\)\n$")
+if(RunCMake_SUBTEST_SUFFIX STREQUAL "soversion_not_zero")
+  set(shlibs_shlibs "^libtest_lib 0\\.8 generate_shlibs \\(\\= 0\\.1\\.1\\)\n$")
+else() # soversion_zero
+  set(shlibs_shlibs "^libtest_lib 0 generate_shlibs \\(\\= 0\\.1\\.1\\)\n$")
+endif()
+
 # optional dot at the end of permissions regex is for SELinux enabled systems
 set(shlibs_shlibs_permissions_regex "-rw-r--r--\.? .*")
 verifyDebControl("${FOUND_FILE_1}" "shlibs" "shlibs")
diff --git a/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/test.cmake b/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/test.cmake
index 90351ba..e0eb67b 100644
--- a/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/test.cmake
+++ b/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/test.cmake
@@ -9,6 +9,11 @@
 file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test_lib.cpp"
     "#include \"test_lib.hpp\"\nint test_lib() {return 0;}\n")
 add_library(test_lib SHARED "${CMAKE_CURRENT_BINARY_DIR}/test_lib.cpp")
-set_target_properties(test_lib PROPERTIES SOVERSION "0.8")
+
+if(RunCMake_SUBTEST_SUFFIX STREQUAL "soversion_not_zero")
+  set_target_properties(test_lib PROPERTIES SOVERSION "0.8")
+else() # soversion_zero
+  set_target_properties(test_lib PROPERTIES SOVERSION "0")
+endif()
 
 install(TARGETS test_lib DESTINATION foo COMPONENT libs)
diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake
index 44346ab..de38df9 100644
--- a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake
@@ -1,5 +1,5 @@
 set(EXPECTED_FILES_COUNT "2")
 set(EXPECTED_FILE_1_COMPONENT "foo")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
 set(EXPECTED_FILE_2_COMPONENT "bar")
-set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt")
diff --git a/Tests/RunCMake/CPack/tests/LONG_FILENAMES/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/LONG_FILENAMES/ExpectedFiles.cmake
index 631d957..4cb8dd0 100644
--- a/Tests/RunCMake/CPack/tests/LONG_FILENAMES/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/LONG_FILENAMES/ExpectedFiles.cmake
@@ -1,3 +1,3 @@
 set(EXPECTED_FILES_COUNT "1")
 set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE)
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/llllllllll_oooooooooo_nnnnnnnnnn_gggggggggg_ffffffffff_iiiiiiiiii_llllllllll_eeeeeeeeee_nnnnnnnnnn_aaaaaaaaaa_mmmmmmmmmm_eeeeeeeeee.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/llllllllll_oooooooooo_nnnnnnnnnn_gggggggggg_ffffffffff_iiiiiiiiii_llllllllll_eeeeeeeeee_nnnnnnnnnn_aaaaaaaaaa_mmmmmmmmmm_eeeeeeeeee.txt")
diff --git a/Tests/RunCMake/CPack/tests/MAIN_COMPONENT/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/MAIN_COMPONENT/ExpectedFiles.cmake
index 6bfb0c1..629be9e 100644
--- a/Tests/RunCMake/CPack/tests/MAIN_COMPONENT/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/MAIN_COMPONENT/ExpectedFiles.cmake
@@ -3,9 +3,9 @@
 if(NOT RunCMake_SUBTEST_SUFFIX STREQUAL "invalid")
   set(EXPECTED_FILES_COUNT "3")
   set(EXPECTED_FILE_1 "main_component-0.1.1-1.*.rpm")
-  set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+  set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
   set(EXPECTED_FILE_2_COMPONENT "headers")
-  set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt")
+  set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt")
   set(EXPECTED_FILE_3_COMPONENT "libs")
-  set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/bas;/usr/bas/CMakeLists.txt")
+  set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/CMakeLists.txt")
 endif()
diff --git a/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake
index 6142eb3..d1a3a5f 100644
--- a/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake
@@ -1,2 +1,2 @@
 set(EXPECTED_FILES_COUNT "1")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
diff --git a/Tests/RunCMake/CPack/tests/MINIMAL/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/MINIMAL/ExpectedFiles.cmake
index 6142eb3..d1a3a5f 100644
--- a/Tests/RunCMake/CPack/tests/MINIMAL/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/MINIMAL/ExpectedFiles.cmake
@@ -1,2 +1,2 @@
 set(EXPECTED_FILES_COUNT "1")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
diff --git a/Tests/RunCMake/CPack/tests/PACKAGE_CHECKSUM/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/PACKAGE_CHECKSUM/ExpectedFiles.cmake
index eed5b92..c375aca 100644
--- a/Tests/RunCMake/CPack/tests/PACKAGE_CHECKSUM/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/PACKAGE_CHECKSUM/ExpectedFiles.cmake
@@ -2,5 +2,5 @@
 
 if(NOT ${RunCMake_SUBTEST_SUFFIX} MATCHES "invalid")
   set(EXPECTED_FILES_COUNT "1")
-  set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+  set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
 endif()
diff --git a/Tests/RunCMake/CPack/tests/PARTIALLY_RELOCATABLE_WARNING/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/PARTIALLY_RELOCATABLE_WARNING/ExpectedFiles.cmake
index ae58c4b..137da47 100644
--- a/Tests/RunCMake/CPack/tests/PARTIALLY_RELOCATABLE_WARNING/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/PARTIALLY_RELOCATABLE_WARNING/ExpectedFiles.cmake
@@ -1,2 +1,4 @@
 set(EXPECTED_FILES_COUNT "1")
+# don't set the prefix here as we have absolute paths that should not be prefixed
+set(EXPECTED_FILE_PACKAGING_PREFIX "")
 set(EXPECTED_FILE_CONTENT_1_LIST "/not_relocatable;/not_relocatable/CMakeLists.txt;/opt")
diff --git a/Tests/RunCMake/CPack/tests/PER_COMPONENT_FIELDS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/PER_COMPONENT_FIELDS/ExpectedFiles.cmake
index 9bdb176..26fa1df 100644
--- a/Tests/RunCMake/CPack/tests/PER_COMPONENT_FIELDS/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/PER_COMPONENT_FIELDS/ExpectedFiles.cmake
@@ -1,8 +1,8 @@
 set(EXPECTED_FILES_COUNT "3")
 set(EXPECTED_FILES_NAME_GENERATOR_SPECIFIC_FORMAT TRUE)
 set(EXPECTED_FILE_1_COMPONENT "pkg_1")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
 set(EXPECTED_FILE_2_NAME "second")
-set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_2_LIST "/foo;/foo/CMakeLists.txt")
 set(EXPECTED_FILE_3_COMPONENT "pkg_3")
-set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_3_LIST "/foo;/foo/CMakeLists.txt")
diff --git a/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake
index ca866ea..8170d39 100644
--- a/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake
@@ -5,25 +5,25 @@
 if(RunCMake_SUBTEST_SUFFIX STREQUAL "valid" OR RunCMake_SUBTEST_SUFFIX STREQUAL "no_debuginfo")
   set(EXPECTED_FILES_COUNT "4")
   set(EXPECTED_FILE_1 "single_debuginfo-0.1.1-1.*.rpm")
-  set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/test_prog")
+  set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog")
   set(EXPECTED_FILE_2 "single_debuginfo*-headers.rpm")
-  set(EXPECTED_FILE_CONTENT_2_LIST "/usr;/usr/bar;/usr/bar/CMakeLists.txt")
+  set(EXPECTED_FILE_CONTENT_2_LIST "/bar;/bar/CMakeLists.txt")
   set(EXPECTED_FILE_3 "single_debuginfo*-libs.rpm")
-  set(EXPECTED_FILE_CONTENT_3_LIST "/usr;/usr/bas;/usr/bas/libtest_lib.so")
+  set(EXPECTED_FILE_CONTENT_3_LIST "/bas;/bas/libtest_lib.so")
 
   set(EXPECTED_FILE_4_COMPONENT "debuginfo")
   set(EXPECTED_FILE_CONTENT_4 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp${whitespaces_}/src/src_1/test_lib.cpp.*")
 elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "one_component" OR RunCMake_SUBTEST_SUFFIX STREQUAL "one_component_no_debuginfo")
   set(EXPECTED_FILES_COUNT "2")
   set(EXPECTED_FILE_1 "single_debuginfo-0*-applications.rpm")
-  set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/test_prog")
+  set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog")
 
   set(EXPECTED_FILE_2 "single_debuginfo-applications-debuginfo*.rpm")
   set(EXPECTED_FILE_CONTENT_2 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp.*")
 elseif(RunCMake_SUBTEST_SUFFIX STREQUAL "one_component_main" OR RunCMake_SUBTEST_SUFFIX STREQUAL "no_components")
   set(EXPECTED_FILES_COUNT "2")
   set(EXPECTED_FILE_1 "single_debuginfo-0*.rpm")
-  set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/test_prog")
+  set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/test_prog")
 
   set(EXPECTED_FILE_2 "single_debuginfo-debuginfo*.rpm")
   set(EXPECTED_FILE_CONTENT_2 ".*/src${whitespaces_}/src/src_1${whitespaces_}/src/src_1/main.cpp.*")
diff --git a/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/ExpectedFiles.cmake
index 0a3e426..d78f222 100644
--- a/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/ExpectedFiles.cmake
@@ -1,2 +1,3 @@
 set(EXPECTED_FILES_COUNT "1")
+set(EXPECTED_FILE_PACKAGING_PREFIX "")
 set(EXPECTED_FILE_CONTENT_1_LIST "source_package-0.1.1.tar.gz;source_package.spec")
diff --git a/Tests/RunCMake/CPack/tests/SUGGESTS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/SUGGESTS/ExpectedFiles.cmake
index 6142eb3..d1a3a5f 100644
--- a/Tests/RunCMake/CPack/tests/SUGGESTS/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/SUGGESTS/ExpectedFiles.cmake
@@ -1,2 +1,2 @@
 set(EXPECTED_FILES_COUNT "1")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
diff --git a/Tests/RunCMake/CPack/tests/SYMLINKS/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/SYMLINKS/ExpectedFiles.cmake
index 05be748..e8281a8 100644
--- a/Tests/RunCMake/CPack/tests/SYMLINKS/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/SYMLINKS/ExpectedFiles.cmake
@@ -1,12 +1,11 @@
 set(EXPECTED_FILES_COUNT "1")
 
 set(EXPECTED_FILE_CONTENT_1_LIST
-  "/usr"
-  "/usr/empty_dir"
-  "/usr/non_empty_dir"
-  "/usr/non_empty_dir/CMakeLists.txt"
-  "/usr/symlink_to_empty_dir"
-  "/usr/symlink_to_non_empty_dir")
+  "/empty_dir"
+  "/non_empty_dir"
+  "/non_empty_dir/CMakeLists.txt"
+  "/symlink_to_empty_dir"
+  "/symlink_to_non_empty_dir")
 
 if(PACKAGING_TYPE STREQUAL "COMPONENT")
   set(EXPECTED_FILE_1_COMPONENT "links")
diff --git a/Tests/RunCMake/CPack/tests/USER_FILELIST/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/USER_FILELIST/ExpectedFiles.cmake
index aabe537..8420986 100644
--- a/Tests/RunCMake/CPack/tests/USER_FILELIST/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/USER_FILELIST/ExpectedFiles.cmake
@@ -1,2 +1,2 @@
 set(EXPECTED_FILES_COUNT "1")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr/one;/usr/one/foo.txt;/usr/one/two;/usr/one/two/bar.txt;/usr/three;/usr/three/baz.txt;/usr/three/qux.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/one;/one/foo.txt;/one/two;/one/two/bar.txt;/three;/three/baz.txt;/three/qux.txt")
diff --git a/Tests/RunCMake/CPack/tests/VERSION/ExpectedFiles.cmake b/Tests/RunCMake/CPack/tests/VERSION/ExpectedFiles.cmake
index 85c571c..372f71b 100644
--- a/Tests/RunCMake/CPack/tests/VERSION/ExpectedFiles.cmake
+++ b/Tests/RunCMake/CPack/tests/VERSION/ExpectedFiles.cmake
@@ -1,3 +1,3 @@
 set(EXPECTED_FILES_COUNT "1")
-set(EXPECTED_FILE_CONTENT_1_LIST "/usr;/usr/foo;/usr/foo/CMakeLists.txt")
+set(EXPECTED_FILE_CONTENT_1_LIST "/foo;/foo/CMakeLists.txt")
 set(EXPECTED_FILE_1_REVISION "1")
diff --git a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
index e936dab..0fafea5 100644
--- a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
@@ -102,7 +102,7 @@
   add_test(TestLoad1 \"${CMAKE_COMMAND}\" -E echo \"test of --test-load\")
   add_test(TestLoad2 \"${CMAKE_COMMAND}\" -E echo \"test of --test-load\")
 ")
-  run_cmake_command(${name} ${CMAKE_CTEST_COMMAND} -j2 --test-load ${load} --test-timeout 5)
+  run_cmake_command(${name} ${CMAKE_CTEST_COMMAND} -j2 --test-load ${load})
 endfunction()
 
 # Tests for the --test-load feature of ctest
diff --git a/Tests/RunCMake/FetchContent/CMakeLists.txt b/Tests/RunCMake/FetchContent/CMakeLists.txt
new file mode 100644
index 0000000..d3137f6
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.9)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/FetchContent/DirOverrides.cmake b/Tests/RunCMake/FetchContent/DirOverrides.cmake
new file mode 100644
index 0000000..50eef16
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/DirOverrides.cmake
@@ -0,0 +1,46 @@
+include(FetchContent)
+
+# Test using saved details
+FetchContent_Declare(
+  t1
+  SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/savedSrc
+  DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E make_directory <SOURCE_DIR>
+)
+FetchContent_Populate(t1)
+if(NOT IS_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/savedSrc)
+  message(FATAL_ERROR "Saved details SOURCE_DIR override failed")
+endif()
+
+# Test direct population
+FetchContent_Populate(
+  t2
+  SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/directSrc
+  DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E make_directory <SOURCE_DIR>
+)
+if(NOT IS_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/directSrc)
+  message(FATAL_ERROR "Direct details SOURCE_DIR override failed")
+endif()
+
+# Ensure setting BINARY_DIR to SOURCE_DIR works (a technique to
+# prevent an unwanted separate BINARY_DIR from being created, which
+# ExternalProject_Add() does whether we like it or not)
+FetchContent_Declare(
+  t3
+  SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/savedNoBuildDir
+  BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/savedNoBuildDir
+  DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E make_directory <SOURCE_DIR>
+)
+FetchContent_Populate(t3)
+if(IS_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/savedNobuildDir-build)
+  message(FATAL_ERROR "Saved details BINARY_DIR override failed")
+endif()
+
+FetchContent_Populate(
+  t4
+  SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/directNoBuildDir
+  BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/directNoBuildDir
+  DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E make_directory <SOURCE_DIR>
+)
+if(IS_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/savedNobuildDir-build)
+  message(FATAL_ERROR "Direct details BINARY_DIR override failed")
+endif()
diff --git a/Tests/RunCMake/FetchContent/DirectIgnoresDetails-stdout.txt b/Tests/RunCMake/FetchContent/DirectIgnoresDetails-stdout.txt
new file mode 100644
index 0000000..6fa5a57
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/DirectIgnoresDetails-stdout.txt
@@ -0,0 +1 @@
+Local details used
diff --git a/Tests/RunCMake/FetchContent/DirectIgnoresDetails.cmake b/Tests/RunCMake/FetchContent/DirectIgnoresDetails.cmake
new file mode 100644
index 0000000..0731b43
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/DirectIgnoresDetails.cmake
@@ -0,0 +1,12 @@
+include(FetchContent)
+
+FetchContent_Declare(
+  t1
+  DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E echo "Saved details used"
+)
+
+# No QUIET option given, so command output will be shown
+FetchContent_Populate(
+  t1
+  DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E echo "Local details used"
+)
diff --git a/Tests/RunCMake/add_executable/OnlyObjectSources-result.txt b/Tests/RunCMake/FetchContent/DownloadTwice-result.txt
similarity index 100%
copy from Tests/RunCMake/add_executable/OnlyObjectSources-result.txt
copy to Tests/RunCMake/FetchContent/DownloadTwice-result.txt
diff --git a/Tests/RunCMake/FetchContent/DownloadTwice-stderr.txt b/Tests/RunCMake/FetchContent/DownloadTwice-stderr.txt
new file mode 100644
index 0000000..96fed48
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/DownloadTwice-stderr.txt
@@ -0,0 +1 @@
+Content t1 already populated in
diff --git a/Tests/RunCMake/FetchContent/DownloadTwice.cmake b/Tests/RunCMake/FetchContent/DownloadTwice.cmake
new file mode 100644
index 0000000..6863c30
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/DownloadTwice.cmake
@@ -0,0 +1,9 @@
+include(FetchContent)
+
+FetchContent_Declare(
+  t1
+  DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E echo "Download command executed"
+)
+
+FetchContent_Populate(t1)
+FetchContent_Populate(t1) # Triggers error
diff --git a/Tests/RunCMake/FetchContent/FirstDetailsWin-stdout.txt b/Tests/RunCMake/FetchContent/FirstDetailsWin-stdout.txt
new file mode 100644
index 0000000..7a8bf18
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/FirstDetailsWin-stdout.txt
@@ -0,0 +1 @@
+First details used
diff --git a/Tests/RunCMake/FetchContent/FirstDetailsWin.cmake b/Tests/RunCMake/FetchContent/FirstDetailsWin.cmake
new file mode 100644
index 0000000..208b12d
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/FirstDetailsWin.cmake
@@ -0,0 +1,16 @@
+include(FetchContent)
+
+# Need to see the download command output
+set(FETCHCONTENT_QUIET OFF)
+
+FetchContent_Declare(
+  t1
+  DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E echo "First details used"
+)
+
+FetchContent_Declare(
+  t1
+  DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E echo "Second details used"
+)
+
+FetchContent_Populate(t1)
diff --git a/Tests/RunCMake/FetchContent/GetProperties.cmake b/Tests/RunCMake/FetchContent/GetProperties.cmake
new file mode 100644
index 0000000..61c99fe
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/GetProperties.cmake
@@ -0,0 +1,67 @@
+include(FetchContent)
+
+# First confirm properties are empty even before declare
+FetchContent_GetProperties(t1)
+if(t1_POPULATED)
+    message(FATAL_ERROR "Property says populated before doing anything")
+endif()
+if(t1_SOURCE_DIR)
+    message(FATAL_ERROR "SOURCE_DIR property not initially empty")
+endif()
+if(t1_BINARY_DIR)
+    message(FATAL_ERROR "BINARY_DIR property not initially empty")
+endif()
+
+# Declare, but no properties should change yet
+FetchContent_Declare(
+  t1
+  SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/savedSrc
+  BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/savedBin
+  DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E echo "Do nothing"
+)
+
+FetchContent_GetProperties(t1)
+if(t1_POPULATED)
+    message(FATAL_ERROR "Property says populated after only declaring details")
+endif()
+if(t1_SOURCE_DIR)
+    message(FATAL_ERROR "SOURCE_DIR property not empty after declare")
+endif()
+if(t1_BINARY_DIR)
+    message(FATAL_ERROR "BINARY_DIR property not empty after declare")
+endif()
+
+# Populate should make all properties non-empty/set
+FetchContent_Populate(t1)
+
+FetchContent_GetProperties(t1)
+if(NOT t1_POPULATED)
+    message(FATAL_ERROR "Population did not set POPULATED property")
+endif()
+if(NOT "${t1_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/savedSrc")
+    message(FATAL_ERROR "SOURCE_DIR property not correct after population: "
+            "${t1_SOURCE_DIR}\n"
+            "    Expected: ${CMAKE_CURRENT_BINARY_DIR}/savedSrc")
+endif()
+if(NOT "${t1_BINARY_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/savedBin")
+    message(FATAL_ERROR "BINARY_DIR property not correct after population: "
+            "${t1_BINARY_DIR}\n"
+            "    Expected: ${CMAKE_CURRENT_BINARY_DIR}/savedBin")
+endif()
+
+# Verify we can retrieve properties individually too
+FetchContent_GetProperties(t1 POPULATED  varPop)
+FetchContent_GetProperties(t1 SOURCE_DIR varSrc)
+FetchContent_GetProperties(t1 BINARY_DIR varBin)
+
+if(NOT varPop)
+    message(FATAL_ERROR "Failed to retrieve POPULATED property")
+endif()
+if(NOT "${varSrc}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/savedSrc")
+    message(FATAL_ERROR "SOURCE_DIR property not retrieved correctly: ${varSrc}\n"
+            "    Expected: ${CMAKE_CURRENT_BINARY_DIR}/savedSrc")
+endif()
+if(NOT "${varBin}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/savedBin")
+    message(FATAL_ERROR "BINARY_DIR property not retrieved correctly: ${varBin}\n"
+            "    Expected: ${CMAKE_CURRENT_BINARY_DIR}/savedBin")
+endif()
diff --git a/Tests/RunCMake/add_executable/OnlyObjectSources-result.txt b/Tests/RunCMake/FetchContent/MissingDetails-result.txt
similarity index 100%
rename from Tests/RunCMake/add_executable/OnlyObjectSources-result.txt
rename to Tests/RunCMake/FetchContent/MissingDetails-result.txt
diff --git a/Tests/RunCMake/FetchContent/MissingDetails-stderr.txt b/Tests/RunCMake/FetchContent/MissingDetails-stderr.txt
new file mode 100644
index 0000000..c4f1daf
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/MissingDetails-stderr.txt
@@ -0,0 +1 @@
+No content details recorded for t1
diff --git a/Tests/RunCMake/FetchContent/MissingDetails.cmake b/Tests/RunCMake/FetchContent/MissingDetails.cmake
new file mode 100644
index 0000000..ba8d121
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/MissingDetails.cmake
@@ -0,0 +1,3 @@
+include(FetchContent)
+
+FetchContent_Populate(t1)
diff --git a/Tests/RunCMake/FetchContent/RunCMakeTest.cmake b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake
new file mode 100644
index 0000000..621fb8b
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake
@@ -0,0 +1,28 @@
+include(RunCMake)
+
+unset(RunCMake_TEST_NO_CLEAN)
+
+run_cmake(MissingDetails)
+run_cmake(DirectIgnoresDetails)
+run_cmake(FirstDetailsWin)
+run_cmake(DownloadTwice)
+run_cmake(SameGenerator)
+run_cmake(VarDefinitions)
+run_cmake(GetProperties)
+run_cmake(DirOverrides)
+
+# We need to pass through CMAKE_GENERATOR and CMAKE_MAKE_PROGRAM
+# to ensure the test can run on machines where the build tool
+# isn't on the PATH. Some build slaves explicitly test with such
+# an arrangement (e.g. to test with spaces in the path). We also
+# pass through the platform and toolset for completeness, even
+# though we don't build anything, just in case this somehow affects
+# the way the build tool is invoked.
+run_cmake_command(ScriptMode
+    ${CMAKE_COMMAND}
+    -DCMAKE_GENERATOR=${RunCMake_GENERATOR}
+    -DCMAKE_GENERATOR_PLATFORM=${RunCMake_GENERATOR_PLATFORM}
+    -DCMAKE_GENERATOR_TOOLSET=${RunCMake_GENERATOR_TOOLSET}
+    -DCMAKE_MAKE_PROGRAM=${RunCMake_MAKE_PROGRAM}
+    -P ${CMAKE_CURRENT_LIST_DIR}/ScriptMode.cmake
+)
diff --git a/Tests/RunCMake/FetchContent/SameGenerator.cmake b/Tests/RunCMake/FetchContent/SameGenerator.cmake
new file mode 100644
index 0000000..58204ef
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/SameGenerator.cmake
@@ -0,0 +1,17 @@
+include(FetchContent)
+
+FetchContent_Declare(
+  t1
+  DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E echo "Download command executed"
+)
+
+FetchContent_Populate(t1)
+
+file(STRINGS "${FETCHCONTENT_BASE_DIR}/t1-subbuild/CMakeCache.txt"
+     matchLine REGEX "^CMAKE_GENERATOR:.*="
+     LIMIT_COUNT 1
+)
+if(NOT matchLine MATCHES "${CMAKE_GENERATOR}")
+  message(FATAL_ERROR "Generator line mismatch: ${matchLine}\n"
+                      "  Expected type: ${CMAKE_GENERATOR}")
+endif()
diff --git a/Tests/RunCMake/FetchContent/ScriptMode.cmake b/Tests/RunCMake/FetchContent/ScriptMode.cmake
new file mode 100644
index 0000000..0a93d62
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/ScriptMode.cmake
@@ -0,0 +1,35 @@
+include(FetchContent)
+
+file(WRITE tmpFile.txt "Generated contents, not important")
+
+FetchContent_Populate(
+  t1
+  DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E copy
+                   ${CMAKE_CURRENT_BINARY_DIR}/tmpFile.txt
+                   <SOURCE_DIR>/done1.txt
+)
+if(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/t1-src/done1.txt)
+  message(FATAL_ERROR "Default SOURCE_DIR doesn't contain done1.txt")
+endif()
+
+FetchContent_Populate(
+  t2
+  SOURCE_DIR       ${CMAKE_CURRENT_BINARY_DIR}/mysrc
+  DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E copy
+                   ${CMAKE_CURRENT_BINARY_DIR}/tmpFile.txt
+                   <SOURCE_DIR>/done2.txt
+)
+if(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/mysrc/done2.txt)
+  message(FATAL_ERROR "Specified SOURCE_DIR doesn't contain done2.txt")
+endif()
+
+FetchContent_Populate(
+  t3
+  SOURCE_DIR       myrelsrc
+  DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E copy
+                   ${CMAKE_CURRENT_BINARY_DIR}/tmpFile.txt
+                   <SOURCE_DIR>/done3.txt
+)
+if(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/myrelsrc/done3.txt)
+  message(FATAL_ERROR "Relative SOURCE_DIR doesn't contain done3.txt")
+endif()
diff --git a/Tests/RunCMake/FetchContent/VarDefinitions.cmake b/Tests/RunCMake/FetchContent/VarDefinitions.cmake
new file mode 100644
index 0000000..4d2a929
--- /dev/null
+++ b/Tests/RunCMake/FetchContent/VarDefinitions.cmake
@@ -0,0 +1,75 @@
+unset(FETCHCONTENT_FULLY_DISCONNECTED CACHE)
+unset(FETCHCONTENT_UPDATES_DISCONNECTED CACHE)
+unset(FETCHCONTENT_QUIET CACHE)
+unset(FETCHCONTENT_BASE_DIR CACHE)
+
+include(FetchContent)
+
+# Each of the cache entries should be defined and have the
+# expected value. Be careful to check unset separately from a
+# false value, since unset also equates to false.
+if(FETCHCONTENT_FULLY_DISCONNECTED STREQUAL "")
+  message(FATAL_ERROR "FETCHCONTENT_FULLY_DISCONNECTED not defined")
+elseif(FETCHCONTENT_FULLY_DISCONNECTED)
+  message(FATAL_ERROR "FETCHCONTENT_FULLY_DISCONNECTED not defaulted to OFF")
+endif()
+
+if(FETCHCONTENT_UPDATES_DISCONNECTED STREQUAL "")
+  message(FATAL_ERROR "FETCHCONTENT_UPDATES_DISCONNECTED not defined")
+elseif(FETCHCONTENT_UPDATES_DISCONNECTED)
+  message(FATAL_ERROR "FETCHCONTENT_UPDATES_DISCONNECTED not defaulted to OFF")
+endif()
+
+if(FETCHCONTENT_QUIET STREQUAL "")
+  message(FATAL_ERROR "FETCHCONTENT_QUIET not defined")
+elseif(NOT FETCHCONTENT_QUIET)
+  message(FATAL_ERROR "FETCHCONTENT_QUIET not defaulted to ON")
+endif()
+
+if(NOT FETCHCONTENT_BASE_DIR STREQUAL "${CMAKE_BINARY_DIR}/_deps")
+  message(FATAL_ERROR "FETCHCONTENT_BASE_DIR has default value: "
+          "${FETCHCONTENT_BASE_DIR}\n  Expected: ${CMAKE_BINARY_DIR}/_deps")
+endif()
+
+file(REMOVE_RECURSE ${FETCHCONTENT_BASE_DIR}/t1-subbuild)
+
+# Use uppercase T1 test name to confirm conversion to lowercase
+# for the t1_... variable names that get set
+FetchContent_Declare(
+  T1
+  DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E echo "Download command executed"
+)
+FetchContent_Populate(T1)
+
+# Be careful to check both regular and cache variables. Since they have
+# the same name, we can only confirm them separately by using get_property().
+get_property(srcRegVarSet VARIABLE PROPERTY t1_SOURCE_DIR SET)
+get_property(bldRegVarSet VARIABLE PROPERTY t1_BINARY_DIR SET)
+
+get_property(srcCacheVarSet CACHE t1_SOURCE_DIR PROPERTY VALUE SET)
+get_property(bldCacheVarSet CACHE t1_BINARY_DIR PROPERTY VALUE SET)
+
+if(NOT srcRegVarSet)
+  message(FATAL_ERROR "t1_SOURCE_DIR regular variable not set")
+endif()
+if(NOT bldRegVarSet)
+  message(FATAL_ERROR "t1_BINARY_DIR regular variable not set")
+endif()
+if(srcCacheVarSet)
+  message(FATAL_ERROR "t1_SOURCE_DIR cache variable unexpectedly set")
+endif()
+if(bldCacheVarSet)
+  message(FATAL_ERROR "t1_BINARY_DIR cache variable unexpectedly set")
+endif()
+
+set(srcRegVar ${t1_SOURCE_DIR})
+set(bldRegVar ${t1_BINARY_DIR})
+
+if(NOT srcRegVar STREQUAL "${CMAKE_BINARY_DIR}/_deps/t1-src")
+  message(FATAL_ERROR "Unexpected t1_SOURCE_DIR value: ${srcRegVar}\n"
+                      "  Expected: ${CMAKE_BINARY_DIR}/_deps/t1-src")
+endif()
+if(NOT bldRegVar STREQUAL "${CMAKE_BINARY_DIR}/_deps/t1-build")
+  message(FATAL_ERROR "Unexpected t1_BINARY_DIR value: ${bldRegVar}\n"
+                      "  Expected: ${CMAKE_BINARY_DIR}/_deps/t1-build")
+endif()
diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-NEW-stdout.txt b/Tests/RunCMake/FindOpenGL/CMP0072-NEW-stdout.txt
new file mode 100644
index 0000000..f5ee220
--- /dev/null
+++ b/Tests/RunCMake/FindOpenGL/CMP0072-NEW-stdout.txt
@@ -0,0 +1,3 @@
+-- OpenGL_GL_PREFERENCE='GLVND'
+-- OPENGL_gl_LIBRARY=''
+-- OPENGL_LIBRARIES='OpenGL;GLX;GLU'
diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-NEW.cmake b/Tests/RunCMake/FindOpenGL/CMP0072-NEW.cmake
new file mode 100644
index 0000000..6cbbeec
--- /dev/null
+++ b/Tests/RunCMake/FindOpenGL/CMP0072-NEW.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0072 NEW)
+include(CMP0072-common.cmake)
diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-OLD-stdout.txt b/Tests/RunCMake/FindOpenGL/CMP0072-OLD-stdout.txt
new file mode 100644
index 0000000..22df1b1
--- /dev/null
+++ b/Tests/RunCMake/FindOpenGL/CMP0072-OLD-stdout.txt
@@ -0,0 +1,3 @@
+-- OpenGL_GL_PREFERENCE='LEGACY'
+-- OPENGL_gl_LIBRARY='GL'
+-- OPENGL_LIBRARIES='GL;GLU'
diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-OLD.cmake b/Tests/RunCMake/FindOpenGL/CMP0072-OLD.cmake
new file mode 100644
index 0000000..6d57004
--- /dev/null
+++ b/Tests/RunCMake/FindOpenGL/CMP0072-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0072 OLD)
+include(CMP0072-common.cmake)
diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-WARN-stderr.txt b/Tests/RunCMake/FindOpenGL/CMP0072-WARN-stderr.txt
new file mode 100644
index 0000000..f26f217
--- /dev/null
+++ b/Tests/RunCMake/FindOpenGL/CMP0072-WARN-stderr.txt
@@ -0,0 +1,21 @@
+^CMake Warning \(dev\) at .*/Modules/FindOpenGL.cmake:[0-9]+ \(message\):
+  Policy CMP0072 is not set: FindOpenGL prefers GLVND by default when
+  available.  Run "cmake --help-policy CMP0072" for policy details.  Use the
+  cmake_policy command to set the policy and suppress this warning.
+
+  FindOpenGL found both a legacy GL library:
+
+    OPENGL_gl_LIBRARY: GL
+
+  and GLVND libraries for OpenGL and GLX:
+
+    OPENGL_opengl_LIBRARY: OpenGL
+    OPENGL_glx_LIBRARY: GLX
+
+  OpenGL_GL_PREFERENCE has not been set to "GLVND" or "LEGACY", so for
+  compatibility with CMake 3.10 and below the legacy GL library will be used.
+Call Stack \(most recent call first\):
+  CMP0072-common.cmake:[0-9]+ \(find_package\)
+  CMP0072-WARN.cmake:[0-9]+ \(include\)
+  CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers.  Use -Wno-dev to suppress it.$
diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-WARN-stdout.txt b/Tests/RunCMake/FindOpenGL/CMP0072-WARN-stdout.txt
new file mode 100644
index 0000000..22df1b1
--- /dev/null
+++ b/Tests/RunCMake/FindOpenGL/CMP0072-WARN-stdout.txt
@@ -0,0 +1,3 @@
+-- OpenGL_GL_PREFERENCE='LEGACY'
+-- OPENGL_gl_LIBRARY='GL'
+-- OPENGL_LIBRARIES='GL;GLU'
diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-WARN.cmake b/Tests/RunCMake/FindOpenGL/CMP0072-WARN.cmake
new file mode 100644
index 0000000..459c458
--- /dev/null
+++ b/Tests/RunCMake/FindOpenGL/CMP0072-WARN.cmake
@@ -0,0 +1 @@
+include(CMP0072-common.cmake)
diff --git a/Tests/RunCMake/FindOpenGL/CMP0072-common.cmake b/Tests/RunCMake/FindOpenGL/CMP0072-common.cmake
new file mode 100644
index 0000000..3fe8030
--- /dev/null
+++ b/Tests/RunCMake/FindOpenGL/CMP0072-common.cmake
@@ -0,0 +1,13 @@
+set(CYGWIN 0)
+set(WIN32 0)
+set(APPLE 0)
+set(OPENGL_INCLUDE_DIR GL/include)
+set(OPENGL_GLX_INCLUDE_DIR GLX/include)
+set(OPENGL_gl_LIBRARY GL)
+set(OPENGL_opengl_LIBRARY OpenGL)
+set(OPENGL_glx_LIBRARY GLX)
+set(OPENGL_glu_LIBRARY GLU)
+find_package(OpenGL)
+message(STATUS "OpenGL_GL_PREFERENCE='${OpenGL_GL_PREFERENCE}'")
+message(STATUS "OPENGL_gl_LIBRARY='${OPENGL_gl_LIBRARY}'")
+message(STATUS "OPENGL_LIBRARIES='${OPENGL_LIBRARIES}'")
diff --git a/Tests/RunCMake/FindOpenGL/CMakeLists.txt b/Tests/RunCMake/FindOpenGL/CMakeLists.txt
new file mode 100644
index 0000000..bf2ef15
--- /dev/null
+++ b/Tests/RunCMake/FindOpenGL/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.10)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/FindOpenGL/RunCMakeTest.cmake b/Tests/RunCMake/FindOpenGL/RunCMakeTest.cmake
new file mode 100644
index 0000000..fcc130f
--- /dev/null
+++ b/Tests/RunCMake/FindOpenGL/RunCMakeTest.cmake
@@ -0,0 +1,5 @@
+include(RunCMake)
+
+run_cmake(CMP0072-WARN)
+run_cmake(CMP0072-OLD)
+run_cmake(CMP0072-NEW)
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_PROPERTY-SOURCES-check.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_PROPERTY-SOURCES-check.cmake
index f1452b5..c1a0f5b 100644
--- a/Tests/RunCMake/GeneratorExpression/TARGET_PROPERTY-SOURCES-check.cmake
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_PROPERTY-SOURCES-check.cmake
@@ -1,8 +1,5 @@
 file(READ ${RunCMake_TEST_BINARY_DIR}/foo.txt foo_sources)
 
-# VS generators inject CMakeLists.txt as a source.  Remove it.
-string(REGEX REPLACE ";[^;]*CMakeLists.txt$" "" foo_sources "${foo_sources}")
-
 set(foo_expected "empty.c;empty2.c;empty3.c")
 if(NOT foo_sources STREQUAL foo_expected)
   set(RunCMake_TEST_FAILED "foo SOURCES was:\n [[${foo_sources}]]\nbut expected:\n [[${foo_expected}]]")
diff --git a/Tests/RunCMake/add_executable/OnlyObjectSources-result.txt b/Tests/RunCMake/GeneratorInstance/BadInstance-result.txt
similarity index 100%
copy from Tests/RunCMake/add_executable/OnlyObjectSources-result.txt
copy to Tests/RunCMake/GeneratorInstance/BadInstance-result.txt
diff --git a/Tests/RunCMake/GeneratorInstance/BadInstance-stderr.txt b/Tests/RunCMake/GeneratorInstance/BadInstance-stderr.txt
new file mode 100644
index 0000000..5d01c4f
--- /dev/null
+++ b/Tests/RunCMake/GeneratorInstance/BadInstance-stderr.txt
@@ -0,0 +1,10 @@
+CMake Error at CMakeLists.txt:[0-9]+ \(project\):
+  Generator
+
+    .*
+
+  does not support instance specification, but instance
+
+    Bad Instance
+
+  was specified.$
diff --git a/Tests/RunCMake/GeneratorInstance/BadInstance-toolchain.cmake b/Tests/RunCMake/GeneratorInstance/BadInstance-toolchain.cmake
new file mode 100644
index 0000000..1d99259
--- /dev/null
+++ b/Tests/RunCMake/GeneratorInstance/BadInstance-toolchain.cmake
@@ -0,0 +1 @@
+set(CMAKE_GENERATOR_INSTANCE "Bad Instance")
diff --git a/Tests/RunCMake/GeneratorInstance/BadInstance.cmake b/Tests/RunCMake/GeneratorInstance/BadInstance.cmake
new file mode 100644
index 0000000..2fc38e5
--- /dev/null
+++ b/Tests/RunCMake/GeneratorInstance/BadInstance.cmake
@@ -0,0 +1 @@
+message(FATAL_ERROR "This should not be reached!")
diff --git a/Tests/RunCMake/add_executable/OnlyObjectSources-result.txt b/Tests/RunCMake/GeneratorInstance/BadInstanceToolchain-result.txt
similarity index 100%
copy from Tests/RunCMake/add_executable/OnlyObjectSources-result.txt
copy to Tests/RunCMake/GeneratorInstance/BadInstanceToolchain-result.txt
diff --git a/Tests/RunCMake/GeneratorInstance/BadInstanceToolchain-stderr.txt b/Tests/RunCMake/GeneratorInstance/BadInstanceToolchain-stderr.txt
new file mode 100644
index 0000000..5d01c4f
--- /dev/null
+++ b/Tests/RunCMake/GeneratorInstance/BadInstanceToolchain-stderr.txt
@@ -0,0 +1,10 @@
+CMake Error at CMakeLists.txt:[0-9]+ \(project\):
+  Generator
+
+    .*
+
+  does not support instance specification, but instance
+
+    Bad Instance
+
+  was specified.$
diff --git a/Tests/RunCMake/GeneratorInstance/BadInstanceToolchain.cmake b/Tests/RunCMake/GeneratorInstance/BadInstanceToolchain.cmake
new file mode 100644
index 0000000..2fc38e5
--- /dev/null
+++ b/Tests/RunCMake/GeneratorInstance/BadInstanceToolchain.cmake
@@ -0,0 +1 @@
+message(FATAL_ERROR "This should not be reached!")
diff --git a/Tests/RunCMake/GeneratorInstance/CMakeLists.txt b/Tests/RunCMake/GeneratorInstance/CMakeLists.txt
new file mode 100644
index 0000000..d3137f6
--- /dev/null
+++ b/Tests/RunCMake/GeneratorInstance/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.9)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/GeneratorInstance/DefaultInstance.cmake b/Tests/RunCMake/GeneratorInstance/DefaultInstance.cmake
new file mode 100644
index 0000000..7750c2e
--- /dev/null
+++ b/Tests/RunCMake/GeneratorInstance/DefaultInstance.cmake
@@ -0,0 +1,13 @@
+if("x${CMAKE_GENERATOR_INSTANCE}" STREQUAL "x")
+  message(FATAL_ERROR "CMAKE_GENERATOR_INSTANCE is empty but should have a value.")
+elseif("x${CMAKE_GENERATOR_INSTANCE}" MATCHES [[\\]])
+  message(FATAL_ERROR
+    "CMAKE_GENERATOR_INSTANCE is\n"
+    "  ${CMAKE_GENERATOR_INSTANCE}\n"
+    "which contains a backslash.")
+elseif(NOT IS_DIRECTORY "${CMAKE_GENERATOR_INSTANCE}")
+  message(FATAL_ERROR
+    "CMAKE_GENERATOR_INSTANCE is\n"
+    "  ${CMAKE_GENERATOR_INSTANCE}\n"
+    "which is not an existing directory.")
+endif()
diff --git a/Tests/RunCMake/add_executable/OnlyObjectSources-result.txt b/Tests/RunCMake/GeneratorInstance/MissingInstance-result.txt
similarity index 100%
copy from Tests/RunCMake/add_executable/OnlyObjectSources-result.txt
copy to Tests/RunCMake/GeneratorInstance/MissingInstance-result.txt
diff --git a/Tests/RunCMake/GeneratorInstance/MissingInstance-stderr.txt b/Tests/RunCMake/GeneratorInstance/MissingInstance-stderr.txt
new file mode 100644
index 0000000..623bf2e
--- /dev/null
+++ b/Tests/RunCMake/GeneratorInstance/MissingInstance-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at CMakeLists.txt:[0-9]+ \(project\):
+  Generator
+
+    .*
+
+  could not find specified instance of .*:
+
+    .*/Tests/RunCMake/GeneratorInstance/instance_does_not_exist$
diff --git a/Tests/RunCMake/GeneratorInstance/MissingInstance-toolchain.cmake b/Tests/RunCMake/GeneratorInstance/MissingInstance-toolchain.cmake
new file mode 100644
index 0000000..f803f14
--- /dev/null
+++ b/Tests/RunCMake/GeneratorInstance/MissingInstance-toolchain.cmake
@@ -0,0 +1 @@
+set(CMAKE_GENERATOR_INSTANCE "${CMAKE_CURRENT_LIST_DIR}/instance_does_not_exist")
diff --git a/Tests/RunCMake/GeneratorInstance/MissingInstance.cmake b/Tests/RunCMake/GeneratorInstance/MissingInstance.cmake
new file mode 100644
index 0000000..2fc38e5
--- /dev/null
+++ b/Tests/RunCMake/GeneratorInstance/MissingInstance.cmake
@@ -0,0 +1 @@
+message(FATAL_ERROR "This should not be reached!")
diff --git a/Tests/RunCMake/add_executable/OnlyObjectSources-result.txt b/Tests/RunCMake/GeneratorInstance/MissingInstanceToolchain-result.txt
similarity index 100%
copy from Tests/RunCMake/add_executable/OnlyObjectSources-result.txt
copy to Tests/RunCMake/GeneratorInstance/MissingInstanceToolchain-result.txt
diff --git a/Tests/RunCMake/GeneratorInstance/MissingInstanceToolchain-stderr.txt b/Tests/RunCMake/GeneratorInstance/MissingInstanceToolchain-stderr.txt
new file mode 100644
index 0000000..623bf2e
--- /dev/null
+++ b/Tests/RunCMake/GeneratorInstance/MissingInstanceToolchain-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at CMakeLists.txt:[0-9]+ \(project\):
+  Generator
+
+    .*
+
+  could not find specified instance of .*:
+
+    .*/Tests/RunCMake/GeneratorInstance/instance_does_not_exist$
diff --git a/Tests/RunCMake/GeneratorInstance/MissingInstanceToolchain.cmake b/Tests/RunCMake/GeneratorInstance/MissingInstanceToolchain.cmake
new file mode 100644
index 0000000..2fc38e5
--- /dev/null
+++ b/Tests/RunCMake/GeneratorInstance/MissingInstanceToolchain.cmake
@@ -0,0 +1 @@
+message(FATAL_ERROR "This should not be reached!")
diff --git a/Tests/RunCMake/add_executable/OnlyObjectSources-result.txt b/Tests/RunCMake/GeneratorInstance/NoInstance-result.txt
similarity index 100%
copy from Tests/RunCMake/add_executable/OnlyObjectSources-result.txt
copy to Tests/RunCMake/GeneratorInstance/NoInstance-result.txt
diff --git a/Tests/RunCMake/GeneratorInstance/NoInstance-stderr.txt b/Tests/RunCMake/GeneratorInstance/NoInstance-stderr.txt
new file mode 100644
index 0000000..e7b52fd
--- /dev/null
+++ b/Tests/RunCMake/GeneratorInstance/NoInstance-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at NoInstance.cmake:2 \(message\):
+  CMAKE_GENERATOR_INSTANCE is empty as expected.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/GeneratorInstance/NoInstance.cmake b/Tests/RunCMake/GeneratorInstance/NoInstance.cmake
new file mode 100644
index 0000000..2e6782e
--- /dev/null
+++ b/Tests/RunCMake/GeneratorInstance/NoInstance.cmake
@@ -0,0 +1,7 @@
+if("x${CMAKE_GENERATOR_INSTANCE}" STREQUAL "x")
+  message(FATAL_ERROR "CMAKE_GENERATOR_INSTANCE is empty as expected.")
+else()
+  message(FATAL_ERROR
+    "CMAKE_GENERATOR_INSTANCE is \"${CMAKE_GENERATOR_INSTANCE}\" "
+    "but should be empty!")
+endif()
diff --git a/Tests/RunCMake/GeneratorInstance/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorInstance/RunCMakeTest.cmake
new file mode 100644
index 0000000..e7f9ccb
--- /dev/null
+++ b/Tests/RunCMake/GeneratorInstance/RunCMakeTest.cmake
@@ -0,0 +1,22 @@
+include(RunCMake)
+
+if("${RunCMake_GENERATOR}" MATCHES "^Visual Studio 1[56789]")
+  set(RunCMake_GENERATOR_INSTANCE "")
+  run_cmake(DefaultInstance)
+
+  set(RunCMake_GENERATOR_INSTANCE "${RunCMake_SOURCE_DIR}/instance_does_not_exist")
+  run_cmake(MissingInstance)
+  set(RunCMake_TEST_OPTIONS -DCMAKE_TOOLCHAIN_FILE=${RunCMake_SOURCE_DIR}/MissingInstance-toolchain.cmake)
+  run_cmake(MissingInstanceToolchain)
+  unset(RunCMake_TEST_OPTIONS)
+else()
+  set(RunCMake_GENERATOR_INSTANCE "")
+  run_cmake(NoInstance)
+
+  set(RunCMake_GENERATOR_INSTANCE "Bad Instance")
+  run_cmake(BadInstance)
+
+  set(RunCMake_TEST_OPTIONS -DCMAKE_TOOLCHAIN_FILE=${RunCMake_SOURCE_DIR}/BadInstance-toolchain.cmake)
+  run_cmake(BadInstanceToolchain)
+  unset(RunCMake_TEST_OPTIONS)
+endif()
diff --git a/Tests/RunCMake/IfacePaths/BinInInstallPrefix-CMP0052-OLD-stderr.txt b/Tests/RunCMake/IfacePaths/BinInInstallPrefix-CMP0052-OLD-stderr.txt
new file mode 100644
index 0000000..37747a1
--- /dev/null
+++ b/Tests/RunCMake/IfacePaths/BinInInstallPrefix-CMP0052-OLD-stderr.txt
@@ -0,0 +1,8 @@
+^CMake Deprecation Warning at CMakeLists.txt:1 \(cmake_minimum_required\):
+  The OLD behavior for policy CMP0052 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.$
diff --git a/Tests/RunCMake/IfacePaths/SrcInInstallPrefix-CMP0052-OLD-stderr.txt b/Tests/RunCMake/IfacePaths/SrcInInstallPrefix-CMP0052-OLD-stderr.txt
new file mode 100644
index 0000000..37747a1
--- /dev/null
+++ b/Tests/RunCMake/IfacePaths/SrcInInstallPrefix-CMP0052-OLD-stderr.txt
@@ -0,0 +1,8 @@
+^CMake Deprecation Warning at CMakeLists.txt:1 \(cmake_minimum_required\):
+  The OLD behavior for policy CMP0052 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.$
diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake
index 26312c4..e688830 100644
--- a/Tests/RunCMake/RunCMake.cmake
+++ b/Tests/RunCMake/RunCMake.cmake
@@ -79,11 +79,17 @@
       ${maybe_timeout}
       )
   else()
+    if(RunCMake_GENERATOR_INSTANCE)
+      set(_D_CMAKE_GENERATOR_INSTANCE "-DCMAKE_GENERATOR_INSTANCE=${RunCMake_GENERATOR_INSTANCE}")
+    else()
+      set(_D_CMAKE_GENERATOR_INSTANCE "")
+    endif()
     execute_process(
       COMMAND ${CMAKE_COMMAND} "${RunCMake_TEST_SOURCE_DIR}"
                 -G "${RunCMake_GENERATOR}"
                 -A "${RunCMake_GENERATOR_PLATFORM}"
                 -T "${RunCMake_GENERATOR_TOOLSET}"
+                ${_D_CMAKE_GENERATOR_INSTANCE}
                 -DRunCMake_TEST=${test}
                 --no-warn-unused-cli
                 ${RunCMake_TEST_OPTIONS}
@@ -99,9 +105,21 @@
   if(NOT "${actual_result}" MATCHES "${expect_result}")
     string(APPEND msg "Result is [${actual_result}], not [${expect_result}].\n")
   endif()
+  string(CONCAT ignore_line_regex
+    "(^|\n)((==[0-9]+=="
+    "|BullseyeCoverage"
+    "|[a-z]+\\([0-9]+\\) malloc:"
+    "|clang[^:]*: warning: the object size sanitizer has no effect at -O0, but is explicitly enabled:"
+    "|Error kstat returned"
+    "|Hit xcodebuild bug"
+    "|[^\n]*is a member of multiple groups"
+    "|[^\n]*from Time Machine by path"
+    "|[^\n]*Bullseye Testing Technology"
+    ")[^\n]*\n)+"
+    )
   foreach(o out err)
     string(REGEX REPLACE "\r\n" "\n" actual_std${o} "${actual_std${o}}")
-    string(REGEX REPLACE "(^|\n)((==[0-9]+==|BullseyeCoverage|[a-z]+\\([0-9]+\\) malloc:|Error kstat returned|Hit xcodebuild bug|[^\n]*is a member of multiple groups|[^\n]*from Time Machine by path|[^\n]*Bullseye Testing Technology)[^\n]*\n)+" "\\1" actual_std${o} "${actual_std${o}}")
+    string(REGEX REPLACE "${ignore_line_regex}" "\\1" actual_std${o} "${actual_std${o}}")
     string(REGEX REPLACE "\n+$" "" actual_std${o} "${actual_std${o}}")
     set(expect_${o} "")
     if(DEFINED expect_std${o})
diff --git a/Tests/RunCMake/Syntax/CMP0053-At-OLD-stderr.txt b/Tests/RunCMake/Syntax/CMP0053-At-OLD-stderr.txt
index acfa30a..0dde1bc 100644
--- a/Tests/RunCMake/Syntax/CMP0053-At-OLD-stderr.txt
+++ b/Tests/RunCMake/Syntax/CMP0053-At-OLD-stderr.txt
@@ -1 +1,12 @@
-^-->wrong<--$
+^CMake Deprecation Warning at CMP0053-At-OLD.cmake:1 \(cmake_policy\):
+  The OLD behavior for policy CMP0053 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
++
+-->wrong<--$
diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
index 5f6be87..8d5139d 100644
--- a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
+++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
@@ -12,6 +12,7 @@
    \* CMP0021
    \* CMP0022
    \* CMP0027
+   \* CMP0037
    \* CMP0038
    \* CMP0041
    \* CMP0042
diff --git a/Tests/RunCMake/TargetSources/ConfigNotAllowed-stderr.txt b/Tests/RunCMake/TargetSources/ConfigNotAllowed-stderr.txt
index 1de5dd7..c6b75fc 100644
--- a/Tests/RunCMake/TargetSources/ConfigNotAllowed-stderr.txt
+++ b/Tests/RunCMake/TargetSources/ConfigNotAllowed-stderr.txt
@@ -6,9 +6,7 @@
 
     .*/Tests/RunCMake/TargetSources/empty_1.cpp
     .*/Tests/RunCMake/TargetSources/empty_2.cpp
-    .*/Tests/RunCMake/TargetSources/CMakeLists.txt
 
   Config "Release":
 
     .*/Tests/RunCMake/TargetSources/empty_1.cpp
-    .*/Tests/RunCMake/TargetSources/CMakeLists.txt
diff --git a/Tests/RunCMake/TargetSources/OriginDebugIDE-result.txt b/Tests/RunCMake/TargetSources/OriginDebugIDE-result.txt
deleted file mode 100644
index 573541a..0000000
--- a/Tests/RunCMake/TargetSources/OriginDebugIDE-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/Tests/RunCMake/TargetSources/OriginDebugIDE-stderr.txt b/Tests/RunCMake/TargetSources/OriginDebugIDE-stderr.txt
deleted file mode 100644
index 6fdcce7..0000000
--- a/Tests/RunCMake/TargetSources/OriginDebugIDE-stderr.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-CMake Debug Log at OriginDebug.cmake:13 \(add_library\):
-  Used sources for target OriginDebug:
-
-   \* .*Tests/RunCMake/TargetSources/empty_2.cpp
-
-Call Stack \(most recent call first\):
-  OriginDebugIDE.cmake:4 \(include\)
-  CMakeLists.txt:3 \(include\)
-+
-CMake Debug Log at OriginDebug.cmake:16 \(set_property\):
-  Used sources for target OriginDebug:
-
-   \* .*Tests/RunCMake/TargetSources/empty_3.cpp
-
-Call Stack \(most recent call first\):
-  OriginDebugIDE.cmake:4 \(include\)
-  CMakeLists.txt:3 \(include\)
-+
-CMake Debug Log at OriginDebug.cmake:20 \(target_sources\):
-  Used sources for target OriginDebug:
-
-   \* .*Tests/RunCMake/TargetSources/empty_4.cpp
-
-Call Stack \(most recent call first\):
-  OriginDebugIDE.cmake:4 \(include\)
-  CMakeLists.txt:3 \(include\)
-+
-CMake Debug Log in CMakeLists.txt:
-  Used sources for target OriginDebug:
-
-   * .*CMakeLists.txt
-+
-CMake Debug Log at OriginDebug.cmake:14 \(target_link_libraries\):
-  Used sources for target OriginDebug:
-
-   \* .*Tests/RunCMake/TargetSources/empty_1.cpp
-
-Call Stack \(most recent call first\):
-  OriginDebugIDE.cmake:4 \(include\)
-  CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/TargetSources/OriginDebugIDE.cmake b/Tests/RunCMake/TargetSources/OriginDebugIDE.cmake
deleted file mode 100644
index a3cc3a8..0000000
--- a/Tests/RunCMake/TargetSources/OriginDebugIDE.cmake
+++ /dev/null
@@ -1,4 +0,0 @@
-
-# Separate test for the IDEs, because they show the CMakeLists.txt file
-# as a source file.
-include(${CMAKE_CURRENT_LIST_DIR}/OriginDebug.cmake)
diff --git a/Tests/RunCMake/TargetSources/RunCMakeTest.cmake b/Tests/RunCMake/TargetSources/RunCMakeTest.cmake
index bb55a6e..36d01de 100644
--- a/Tests/RunCMake/TargetSources/RunCMakeTest.cmake
+++ b/Tests/RunCMake/TargetSources/RunCMakeTest.cmake
@@ -2,11 +2,9 @@
 
 if(RunCMake_GENERATOR MATCHES "Visual Studio|Xcode")
   run_cmake(ConfigNotAllowed)
-  run_cmake(OriginDebugIDE)
-else()
-  run_cmake(OriginDebug)
 endif()
 
+run_cmake(OriginDebug)
 run_cmake(CMP0026-LOCATION)
 run_cmake(RelativePathInInterface)
 run_cmake(ExportBuild)
diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake
index 7d436b6..f730b83 100644
--- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake
+++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake
@@ -8,6 +8,7 @@
 run_cmake(XcodeAttributeLocation)
 run_cmake(XcodeAttributeGenex)
 run_cmake(XcodeAttributeGenexError)
+run_cmake(XcodeGenerateTopLevelProjectOnly)
 run_cmake(XcodeObjectNeedsEscape)
 run_cmake(XcodeObjectNeedsQuote)
 run_cmake(XcodeOptimizationFlags)
diff --git a/Tests/RunCMake/XcodeProject/XcodeGenerateTopLevelProjectOnly-check.cmake b/Tests/RunCMake/XcodeProject/XcodeGenerateTopLevelProjectOnly-check.cmake
new file mode 100644
index 0000000..64654af
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/XcodeGenerateTopLevelProjectOnly-check.cmake
@@ -0,0 +1,3 @@
+if(EXISTS "${RunCMake_TEST_BINARY_DIR}/subproject/subproject.xcodeproj")
+  message(SEND_ERROR "Unexpected project file for subproject found.")
+endif()
diff --git a/Tests/RunCMake/XcodeProject/XcodeGenerateTopLevelProjectOnly.cmake b/Tests/RunCMake/XcodeProject/XcodeGenerateTopLevelProjectOnly.cmake
new file mode 100644
index 0000000..7e53c49
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/XcodeGenerateTopLevelProjectOnly.cmake
@@ -0,0 +1,3 @@
+set(CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY TRUE)
+project(XcodeGenerateTopLevelProjectOnly NONE)
+add_subdirectory(subproject)
diff --git a/Tests/RunCMake/XcodeProject/subproject/CMakeLists.txt b/Tests/RunCMake/XcodeProject/subproject/CMakeLists.txt
new file mode 100644
index 0000000..20e12b1
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/subproject/CMakeLists.txt
@@ -0,0 +1 @@
+project(subproject)
diff --git a/Tests/RunCMake/add_executable/NoSources-stderr.txt b/Tests/RunCMake/add_executable/NoSources-stderr.txt
index 5985905..4fcfd49 100644
--- a/Tests/RunCMake/add_executable/NoSources-stderr.txt
+++ b/Tests/RunCMake/add_executable/NoSources-stderr.txt
@@ -1,4 +1,4 @@
 ^CMake Error at NoSources.cmake:[0-9]+ \(add_executable\):
-  add_executable called with incorrect number of arguments
+  No SOURCES given to target: TestExeWithoutSources
 Call Stack \(most recent call first\):
   CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/add_executable/NoSourcesButLinkObjects-stderr.txt b/Tests/RunCMake/add_executable/NoSourcesButLinkObjects-stderr.txt
index c8afadb..5561daa 100644
--- a/Tests/RunCMake/add_executable/NoSourcesButLinkObjects-stderr.txt
+++ b/Tests/RunCMake/add_executable/NoSourcesButLinkObjects-stderr.txt
@@ -1,11 +1,4 @@
 ^CMake Error at NoSourcesButLinkObjects.cmake:[0-9]+ \(add_executable\):
-  add_executable called with incorrect number of arguments
-Call Stack \(most recent call first\):
-  CMakeLists.txt:[0-9]+ \(include\)
-
-
-CMake Error at NoSourcesButLinkObjects.cmake:[0-9]+ \(target_link_libraries\):
-  Cannot specify link libraries for target \"TestExeWithoutSources\" which is
-  not built by this project.
+  No SOURCES given to target: TestExeWithoutSources
 Call Stack \(most recent call first\):
   CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/add_executable/OnlyObjectSources-stderr.txt b/Tests/RunCMake/add_executable/OnlyObjectSources-stderr.txt
deleted file mode 100644
index ea72d5d..0000000
--- a/Tests/RunCMake/add_executable/OnlyObjectSources-stderr.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-^CMake Error at OnlyObjectSources.cmake:[0-9]+ \(add_executable\):
-  add_executable called with incorrect number of arguments
-Call Stack \(most recent call first\):
-  CMakeLists.txt:[0-9]+ \(include\)
-
-
-CMake Error at OnlyObjectSources.cmake:[0-9]+ \(target_sources\):
-  Cannot specify sources for target \"TestExeWithoutSources\" which is not
-  built by this project.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/add_executable/RunCMakeTest.cmake b/Tests/RunCMake/add_executable/RunCMakeTest.cmake
index 70a68f2..88916b7 100644
--- a/Tests/RunCMake/add_executable/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_executable/RunCMakeTest.cmake
@@ -2,4 +2,6 @@
 
 run_cmake(NoSources)
 run_cmake(OnlyObjectSources)
-run_cmake(NoSourcesButLinkObjects)
+if(NOT RunCMake_GENERATOR STREQUAL "Xcode" OR NOT "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]")
+  run_cmake(NoSourcesButLinkObjects)
+endif()
diff --git a/Tests/RunCMake/add_library/MODULEwithNoSources-stderr.txt b/Tests/RunCMake/add_library/MODULEwithNoSources-stderr.txt
index 5cf0b1e..41da381 100644
--- a/Tests/RunCMake/add_library/MODULEwithNoSources-stderr.txt
+++ b/Tests/RunCMake/add_library/MODULEwithNoSources-stderr.txt
@@ -1,3 +1,4 @@
-^You have called ADD_LIBRARY for library TestModuleLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file(
-CMake Error: CMake can not determine linker language for target: TestModuleLibWithoutSources)+(
-CMake Error: Cannot determine link language for target \"TestModuleLibWithoutSources\".)?$
+^CMake Error at MODULEwithNoSources.cmake:[0-9]+ \(add_library\):
+  No SOURCES given to target: TestModuleLibWithoutSources
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/add_library/MODULEwithNoSourcesButLinkObjects-stderr.txt b/Tests/RunCMake/add_library/MODULEwithNoSourcesButLinkObjects-stderr.txt
index 951594a..67dd87c 100644
--- a/Tests/RunCMake/add_library/MODULEwithNoSourcesButLinkObjects-stderr.txt
+++ b/Tests/RunCMake/add_library/MODULEwithNoSourcesButLinkObjects-stderr.txt
@@ -1,3 +1,4 @@
-^You have called ADD_LIBRARY for library TestModuleLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file(
-CMake Error: CMake can not determine linker language for target: TestModuleLibWithoutSources)+(
-CMake Error: Cannot determine link language for target \"TestModuleLibWithoutSources\".)*$
+^CMake Error at MODULEwithNoSourcesButLinkObjects.cmake:[0-9]+ \(add_library\):
+  No SOURCES given to target: TestModuleLibWithoutSources
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/add_library/MODULEwithOnlyObjectSources-stderr.txt b/Tests/RunCMake/add_library/MODULEwithOnlyObjectSources-stderr.txt
deleted file mode 100644
index de83755..0000000
--- a/Tests/RunCMake/add_library/MODULEwithOnlyObjectSources-stderr.txt
+++ /dev/null
@@ -1 +0,0 @@
-^You have called ADD_LIBRARY for library TestModuleLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file$
diff --git a/Tests/RunCMake/add_library/OBJECTwithNoSources-result.txt b/Tests/RunCMake/add_library/OBJECTwithNoSources-result.txt
index 9c558e3..d00491f 100644
--- a/Tests/RunCMake/add_library/OBJECTwithNoSources-result.txt
+++ b/Tests/RunCMake/add_library/OBJECTwithNoSources-result.txt
@@ -1 +1 @@
-.
+1
diff --git a/Tests/RunCMake/add_library/OBJECTwithNoSources-stderr.txt b/Tests/RunCMake/add_library/OBJECTwithNoSources-stderr.txt
index 099ec4f..20d3a8a 100644
--- a/Tests/RunCMake/add_library/OBJECTwithNoSources-stderr.txt
+++ b/Tests/RunCMake/add_library/OBJECTwithNoSources-stderr.txt
@@ -1,2 +1,4 @@
-^You have called ADD_LIBRARY for library TestObjectLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file(
-CMake Error: CMake can not determine linker language for target: TestObjectLibWithoutSources)*$
+^CMake Error at OBJECTwithNoSources.cmake:[0-9]+ \(add_library\):
+  No SOURCES given to target: TestObjectLibWithoutSources
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/add_library/OBJECTwithNoSourcesButLinkObjects-stderr.txt b/Tests/RunCMake/add_library/OBJECTwithNoSourcesButLinkObjects-stderr.txt
index 8f20096..cd6f1e0 100644
--- a/Tests/RunCMake/add_library/OBJECTwithNoSourcesButLinkObjects-stderr.txt
+++ b/Tests/RunCMake/add_library/OBJECTwithNoSourcesButLinkObjects-stderr.txt
@@ -1,5 +1,4 @@
-^You have called ADD_LIBRARY for library TestObjectLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file
-CMake Error at OBJECTwithNoSourcesButLinkObjects.cmake:[0-9]+ \(target_link_libraries\):
+^CMake Error at OBJECTwithNoSourcesButLinkObjects.cmake:[0-9]+ \(target_link_libraries\):
   Object library target \"TestObjectLibWithoutSources\" may not link to
   anything.
 Call Stack \(most recent call first\):
diff --git a/Tests/RunCMake/add_library/OBJECTwithOnlyObjectSources-stderr.txt b/Tests/RunCMake/add_library/OBJECTwithOnlyObjectSources-stderr.txt
index f9cbf6b..77a72f1 100644
--- a/Tests/RunCMake/add_library/OBJECTwithOnlyObjectSources-stderr.txt
+++ b/Tests/RunCMake/add_library/OBJECTwithOnlyObjectSources-stderr.txt
@@ -1,5 +1,4 @@
-^You have called ADD_LIBRARY for library TestObjectLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file
-CMake Error at OBJECTwithOnlyObjectSources.cmake:[0-9]+ \(add_library\):
+^CMake Error at OBJECTwithOnlyObjectSources.cmake:[0-9]+ \(add_library\):
   OBJECT library \"TestObjectLibWithoutSources\" contains:
 
     [^
diff --git a/Tests/RunCMake/add_library/SHAREDwithNoSources-stderr.txt b/Tests/RunCMake/add_library/SHAREDwithNoSources-stderr.txt
index 228d1cc..5cedd62 100644
--- a/Tests/RunCMake/add_library/SHAREDwithNoSources-stderr.txt
+++ b/Tests/RunCMake/add_library/SHAREDwithNoSources-stderr.txt
@@ -1,3 +1,4 @@
-^You have called ADD_LIBRARY for library TestSharedLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file(
-CMake Error: CMake can not determine linker language for target: TestSharedLibWithoutSources)+(
-CMake Error: Cannot determine link language for target \"TestSharedLibWithoutSources\".)*$
+^CMake Error at SHAREDwithNoSources.cmake:[0-9]+ \(add_library\):
+  No SOURCES given to target: TestSharedLibWithoutSources
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/add_library/SHAREDwithNoSourcesButLinkObjects-stderr.txt b/Tests/RunCMake/add_library/SHAREDwithNoSourcesButLinkObjects-stderr.txt
index 228d1cc..d621e76 100644
--- a/Tests/RunCMake/add_library/SHAREDwithNoSourcesButLinkObjects-stderr.txt
+++ b/Tests/RunCMake/add_library/SHAREDwithNoSourcesButLinkObjects-stderr.txt
@@ -1,3 +1,4 @@
-^You have called ADD_LIBRARY for library TestSharedLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file(
-CMake Error: CMake can not determine linker language for target: TestSharedLibWithoutSources)+(
-CMake Error: Cannot determine link language for target \"TestSharedLibWithoutSources\".)*$
+^CMake Error at SHAREDwithNoSourcesButLinkObjects.cmake:[0-9]+ \(add_library\):
+  No SOURCES given to target: TestSharedLibWithoutSources
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/add_library/SHAREDwithOnlyObjectSources-stderr.txt b/Tests/RunCMake/add_library/SHAREDwithOnlyObjectSources-stderr.txt
deleted file mode 100644
index ec350cd..0000000
--- a/Tests/RunCMake/add_library/SHAREDwithOnlyObjectSources-stderr.txt
+++ /dev/null
@@ -1 +0,0 @@
-^You have called ADD_LIBRARY for library TestSharedLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file$
diff --git a/Tests/RunCMake/add_library/STATICwithNoSources-stderr.txt b/Tests/RunCMake/add_library/STATICwithNoSources-stderr.txt
index 830eb22..10b2112 100644
--- a/Tests/RunCMake/add_library/STATICwithNoSources-stderr.txt
+++ b/Tests/RunCMake/add_library/STATICwithNoSources-stderr.txt
@@ -1,3 +1,4 @@
-^You have called ADD_LIBRARY for library TestStaticLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file(
-CMake Error: Cannot determine link language for target \"TestStaticLibWithoutSources\".)?(
-CMake Error: CMake can not determine linker language for target: TestStaticLibWithoutSources)+$
+^CMake Error at STATICwithNoSources.cmake:[0-9]+ \(add_library\):
+  No SOURCES given to target: TestStaticLibWithoutSources
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/add_library/STATICwithNoSourcesButLinkObjects-stderr.txt b/Tests/RunCMake/add_library/STATICwithNoSourcesButLinkObjects-stderr.txt
index 830eb22..33c23b2 100644
--- a/Tests/RunCMake/add_library/STATICwithNoSourcesButLinkObjects-stderr.txt
+++ b/Tests/RunCMake/add_library/STATICwithNoSourcesButLinkObjects-stderr.txt
@@ -1,3 +1,4 @@
-^You have called ADD_LIBRARY for library TestStaticLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file(
-CMake Error: Cannot determine link language for target \"TestStaticLibWithoutSources\".)?(
-CMake Error: CMake can not determine linker language for target: TestStaticLibWithoutSources)+$
+^CMake Error at STATICwithNoSourcesButLinkObjects.cmake:[0-9]+ \(add_library\):
+  No SOURCES given to target: TestStaticLibWithoutSources
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/add_library/STATICwithOnlyObjectSources-stderr.txt b/Tests/RunCMake/add_library/STATICwithOnlyObjectSources-stderr.txt
deleted file mode 100644
index 5cd10d4..0000000
--- a/Tests/RunCMake/add_library/STATICwithOnlyObjectSources-stderr.txt
+++ /dev/null
@@ -1 +0,0 @@
-^You have called ADD_LIBRARY for library TestStaticLibWithoutSources without any source files. This typically indicates a problem with your CMakeLists.txt file$
diff --git a/Tests/RunCMake/add_library/UNKNOWNwithNoSourcesButLinkObjects-result.txt b/Tests/RunCMake/add_library/UNKNOWNwithNoSourcesButLinkObjects-result.txt
deleted file mode 100644
index d00491f..0000000
--- a/Tests/RunCMake/add_library/UNKNOWNwithNoSourcesButLinkObjects-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/Tests/RunCMake/add_library/UNKNOWNwithNoSourcesButLinkObjects-stderr.txt b/Tests/RunCMake/add_library/UNKNOWNwithNoSourcesButLinkObjects-stderr.txt
deleted file mode 100644
index adcd3a2..0000000
--- a/Tests/RunCMake/add_library/UNKNOWNwithNoSourcesButLinkObjects-stderr.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-^CMake Error at UNKNOWNwithNoSourcesButLinkObjects.cmake:[0-9]+ \(target_link_libraries\):
-  Cannot specify link libraries for target \"TestUnknownLibWithoutSources\"
-  which is not built by this project.
-Call Stack \(most recent call first\):
-  CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/add_library/UNKNOWNwithNoSourcesButLinkObjects.cmake b/Tests/RunCMake/add_library/UNKNOWNwithNoSourcesButLinkObjects.cmake
index 8e014c2..a977d42 100644
--- a/Tests/RunCMake/add_library/UNKNOWNwithNoSourcesButLinkObjects.cmake
+++ b/Tests/RunCMake/add_library/UNKNOWNwithNoSourcesButLinkObjects.cmake
@@ -2,4 +2,4 @@
 add_library(ObjectLibDependency OBJECT test.cpp)
 
 add_library(TestUnknownLibWithoutSources UNKNOWN IMPORTED)
-target_link_libraries(TestUnknownLibWithoutSources PUBLIC $<TARGET_OBJECTS:ObjectLibDependency>)
+target_link_libraries(TestUnknownLibWithoutSources INTERFACE $<TARGET_OBJECTS:ObjectLibDependency>)
diff --git a/Tests/RunCMake/alias_targets/RunCMakeTest.cmake b/Tests/RunCMake/alias_targets/RunCMakeTest.cmake
index 9a5eaaf..dded248 100644
--- a/Tests/RunCMake/alias_targets/RunCMakeTest.cmake
+++ b/Tests/RunCMake/alias_targets/RunCMakeTest.cmake
@@ -6,6 +6,7 @@
 run_cmake(imported)
 run_cmake(invalid-name)
 run_cmake(invalid-target)
+run_cmake(imported-global-target)
 run_cmake(imported-target)
 run_cmake(alias-target)
 run_cmake(set_property)
diff --git a/Tests/RunCMake/alias_targets/imported-global-target-stderr.txt b/Tests/RunCMake/alias_targets/imported-global-target-stderr.txt
new file mode 100644
index 0000000..8259c80
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/imported-global-target-stderr.txt
@@ -0,0 +1,2 @@
+^'alias-test-exe' is an alias for 'test-exe' and its name-property contains 'test-exe'.
+'alias-test-lib' is an alias for 'test-lib' and its name-property contains 'test-lib'.$
diff --git a/Tests/RunCMake/alias_targets/imported-global-target.cmake b/Tests/RunCMake/alias_targets/imported-global-target.cmake
new file mode 100644
index 0000000..12c4e0a
--- /dev/null
+++ b/Tests/RunCMake/alias_targets/imported-global-target.cmake
@@ -0,0 +1,46 @@
+
+enable_language(CXX)
+
+
+add_executable(test-exe IMPORTED GLOBAL)
+add_executable(alias-test-exe ALIAS test-exe)
+
+if(TARGET alias-test-exe)
+  get_target_property(aliased-target alias-test-exe ALIASED_TARGET)
+  if("${aliased-target}" STREQUAL "test-exe")
+    get_target_property(aliased-name alias-test-exe NAME)
+    if("${aliased-name}" STREQUAL "test-exe")
+      message("'alias-test-exe' is an alias for '${aliased-target}'"
+              " and its name-property contains '${aliased-name}'.")
+    else()
+      message("'alias-test-exe' is an alias for '${aliased-target}'"
+              " but its name-property contains '${aliased-name}'!?")
+    endif()
+  else()
+    message("'alias-test-exe' is something but not a real target!?")
+  endif()
+else()
+    message("'alias-test-exe' does not exist!?")
+endif()
+
+
+add_library(test-lib SHARED IMPORTED GLOBAL)
+add_library(alias-test-lib ALIAS test-lib)
+
+if(TARGET alias-test-lib)
+  get_target_property(aliased-target alias-test-lib ALIASED_TARGET)
+  if("${aliased-target}" STREQUAL "test-lib")
+    get_target_property(aliased-name alias-test-lib NAME)
+    if("${aliased-name}" STREQUAL "test-lib")
+      message("'alias-test-lib' is an alias for '${aliased-target}'"
+              " and its name-property contains '${aliased-name}'.")
+    else()
+      message("'alias-test-lib' is an alias for '${aliased-target}'"
+              " but its name-property contains '${aliased-name}'!?")
+    endif()
+  else()
+    message("'alias-test-lib' is something but not a real target!?")
+  endif()
+else()
+    message("'alias-test-lib' does not exist!?")
+endif()
diff --git a/Tests/RunCMake/alias_targets/imported-target-stderr.txt b/Tests/RunCMake/alias_targets/imported-target-stderr.txt
index bbff29a..12ffbc2 100644
--- a/Tests/RunCMake/alias_targets/imported-target-stderr.txt
+++ b/Tests/RunCMake/alias_targets/imported-target-stderr.txt
@@ -1,5 +1,9 @@
-CMake Error at imported-target.cmake:6 \(add_library\):
-  add_library cannot create ALIAS target "alias" because target "foo" is
-  IMPORTED.
+^CMake Error at imported-target.cmake:[0-9]+ \(add_executable\):
+  add_executable cannot create ALIAS target \"alias-test-exe\" because target
+  \"test-exe\" is imported but not globally visible.
 Call Stack \(most recent call first\):
-  CMakeLists.txt:3 \(include\)
+  CMakeLists.txt:[0-9]+ \(include\)
+
+
+'alias-test-exe' does not exist![?]
+'alias-test-lib' does not exist![?]$
diff --git a/Tests/RunCMake/alias_targets/imported-target.cmake b/Tests/RunCMake/alias_targets/imported-target.cmake
index 7259ab0..bb682fe 100644
--- a/Tests/RunCMake/alias_targets/imported-target.cmake
+++ b/Tests/RunCMake/alias_targets/imported-target.cmake
@@ -1,6 +1,46 @@
 
 enable_language(CXX)
 
-add_library(foo SHARED IMPORTED)
 
-add_library(alias ALIAS foo)
+add_executable(test-exe IMPORTED)
+add_executable(alias-test-exe ALIAS test-exe)
+
+if(TARGET alias-test-exe)
+  get_target_property(aliased-target alias-test-exe ALIASED_TARGET)
+  if("${aliased-target}" STREQUAL "test-exe")
+    get_target_property(aliased-name alias-test-exe NAME)
+    if("${aliased-name}" STREQUAL "test-exe")
+      message("'alias-test-exe' is an alias for '${aliased-target}'"
+              " and its name-property contains '${aliased-name}'.")
+    else()
+      message("'alias-test-exe' is an alias for '${aliased-target}'"
+              " but its name-property contains '${aliased-name}'!?")
+    endif()
+  else()
+    message("'alias-test-exe' is something but not a real target!?")
+  endif()
+else()
+    message("'alias-test-exe' does not exist!?")
+endif()
+
+
+add_library(test-lib SHARED IMPORTED)
+add_library(alias-test-lib ALIAS test-lib)
+
+if(TARGET alias-test-lib)
+  get_target_property(aliased-target alias-test-lib ALIASED_TARGET)
+  if("${aliased-target}" STREQUAL "test-lib")
+    get_target_property(aliased-name alias-test-lib NAME)
+    if("${aliased-name}" STREQUAL "test-lib")
+      message("'alias-test-lib' is an alias for '${aliased-target}'"
+              " and its name-property contains '${aliased-name}'.")
+    else()
+      message("'alias-test-lib' is an alias for '${aliased-target}'"
+              " but its name-property contains '${aliased-name}'!?")
+    endif()
+  else()
+    message("'alias-test-lib' is something but not a real target!?")
+  endif()
+else()
+    message("'alias-test-lib' does not exist!?")
+endif()
diff --git a/Tests/RunCMake/add_executable/OnlyObjectSources-result.txt b/Tests/RunCMake/file/DOWNLOAD-netrc-bad-result.txt
similarity index 100%
copy from Tests/RunCMake/add_executable/OnlyObjectSources-result.txt
copy to Tests/RunCMake/file/DOWNLOAD-netrc-bad-result.txt
diff --git a/Tests/RunCMake/file/DOWNLOAD-netrc-bad-stderr.txt b/Tests/RunCMake/file/DOWNLOAD-netrc-bad-stderr.txt
new file mode 100644
index 0000000..96ce62a
--- /dev/null
+++ b/Tests/RunCMake/file/DOWNLOAD-netrc-bad-stderr.txt
@@ -0,0 +1,19 @@
+^CMake Error at DOWNLOAD-netrc-bad\.cmake:[0-9]+ \(file\):
+  file DOWNLOAD missing level value for NETRC\.
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at DOWNLOAD-netrc-bad\.cmake:[0-9]+ \(file\):
+  file DOWNLOAD missing file value for NETRC_FILE\.
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at DOWNLOAD-netrc-bad\.cmake:[0-9]+ \(file\):
+  file NETRC accepts OPTIONAL, IGNORED or REQUIRED but got: INVALID
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at DOWNLOAD-netrc-bad\.cmake:[0-9]+ \(file\):
+  file NETRC accepts OPTIONAL, IGNORED or REQUIRED but got: FALSE
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/file/DOWNLOAD-netrc-bad.cmake b/Tests/RunCMake/file/DOWNLOAD-netrc-bad.cmake
new file mode 100644
index 0000000..6a62df9
--- /dev/null
+++ b/Tests/RunCMake/file/DOWNLOAD-netrc-bad.cmake
@@ -0,0 +1,15 @@
+if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" MATCHES "^/")
+  set(slash /)
+endif()
+file(DOWNLOAD "" "" NETRC)
+file(DOWNLOAD "" "" NETRC_FILE)
+set(CMAKE_NETRC FALSE)
+file(DOWNLOAD
+  "file://${slash}${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-netrc-bad.txt"
+  "${CMAKE_CURRENT_BINARY_DIR}/netrc-bad.txt"
+  NETRC INVALID
+  )
+file(DOWNLOAD
+  "file://${slash}${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-netrc-bad.txt"
+  "${CMAKE_CURRENT_BINARY_DIR}/netrc-bad.txt"
+  )
diff --git a/Tests/RunCMake/file/DOWNLOAD-netrc-bad.txt b/Tests/RunCMake/file/DOWNLOAD-netrc-bad.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/file/DOWNLOAD-netrc-bad.txt
diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake
index 26051b4..3be4fb7 100644
--- a/Tests/RunCMake/file/RunCMakeTest.cmake
+++ b/Tests/RunCMake/file/RunCMakeTest.cmake
@@ -3,9 +3,11 @@
 run_cmake(DOWNLOAD-hash-mismatch)
 run_cmake(DOWNLOAD-unused-argument)
 run_cmake(DOWNLOAD-httpheader-not-set)
+run_cmake(DOWNLOAD-netrc-bad)
 run_cmake(DOWNLOAD-pass-not-set)
 run_cmake(UPLOAD-unused-argument)
 run_cmake(UPLOAD-httpheader-not-set)
+run_cmake(UPLOAD-netrc-bad)
 run_cmake(UPLOAD-pass-not-set)
 run_cmake(INSTALL-DIRECTORY)
 run_cmake(INSTALL-FILES_FROM_DIR)
diff --git a/Tests/RunCMake/add_executable/OnlyObjectSources-result.txt b/Tests/RunCMake/file/UPLOAD-netrc-bad-result.txt
similarity index 100%
copy from Tests/RunCMake/add_executable/OnlyObjectSources-result.txt
copy to Tests/RunCMake/file/UPLOAD-netrc-bad-result.txt
diff --git a/Tests/RunCMake/file/UPLOAD-netrc-bad-stderr.txt b/Tests/RunCMake/file/UPLOAD-netrc-bad-stderr.txt
new file mode 100644
index 0000000..d5752ea
--- /dev/null
+++ b/Tests/RunCMake/file/UPLOAD-netrc-bad-stderr.txt
@@ -0,0 +1,19 @@
+^CMake Error at UPLOAD-netrc-bad\.cmake:[0-9]+ \(file\):
+  file UPLOAD missing level value for NETRC\.
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at UPLOAD-netrc-bad\.cmake:[0-9]+ \(file\):
+  file UPLOAD missing file value for NETRC_FILE\.
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at UPLOAD-netrc-bad\.cmake:[0-9]+ \(file\):
+  file NETRC accepts OPTIONAL, IGNORED or REQUIRED but got: INVALID
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at UPLOAD-netrc-bad\.cmake:[0-9]+ \(file\):
+  file NETRC accepts OPTIONAL, IGNORED or REQUIRED but got: FALSE
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/file/UPLOAD-netrc-bad.cmake b/Tests/RunCMake/file/UPLOAD-netrc-bad.cmake
new file mode 100644
index 0000000..e59a2c4
--- /dev/null
+++ b/Tests/RunCMake/file/UPLOAD-netrc-bad.cmake
@@ -0,0 +1,15 @@
+if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" MATCHES "^/")
+  set(slash /)
+endif()
+file(UPLOAD "" "" NETRC)
+file(UPLOAD "" "" NETRC_FILE)
+set(CMAKE_NETRC FALSE)
+file(UPLOAD
+  "${CMAKE_CURRENT_SOURCE_DIR}/UPLOAD-netrc-bad.txt"
+  "file://${slash}${CMAKE_CURRENT_BINARY_DIR}/netrc-bad.txt"
+  NETRC INVALID
+  )
+file(UPLOAD
+  "${CMAKE_CURRENT_SOURCE_DIR}/UPLOAD-netrc-bad.txt"
+  "file://${slash}${CMAKE_CURRENT_BINARY_DIR}/netrc-bad.txt"
+  )
diff --git a/Tests/RunCMake/file/UPLOAD-netrc-bad.txt b/Tests/RunCMake/file/UPLOAD-netrc-bad.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/file/UPLOAD-netrc-bad.txt
diff --git a/Tests/RunCMake/add_executable/OnlyObjectSources-result.txt b/Tests/RunCMake/foreach/BadRangeInFunction-result.txt
similarity index 100%
copy from Tests/RunCMake/add_executable/OnlyObjectSources-result.txt
copy to Tests/RunCMake/foreach/BadRangeInFunction-result.txt
diff --git a/Tests/RunCMake/foreach/BadRangeInFunction-stderr.txt b/Tests/RunCMake/foreach/BadRangeInFunction-stderr.txt
new file mode 100644
index 0000000..e16a0f1
--- /dev/null
+++ b/Tests/RunCMake/foreach/BadRangeInFunction-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at BadRangeInFunction.cmake:2 \(foreach\):
+  foreach called with incorrect range specification: start 2, stop 1, step 1
+Call Stack \(most recent call first\):
+  BadRangeInFunction.cmake:5 \(func\)
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/foreach/BadRangeInFunction.cmake b/Tests/RunCMake/foreach/BadRangeInFunction.cmake
new file mode 100644
index 0000000..f51cbbf
--- /dev/null
+++ b/Tests/RunCMake/foreach/BadRangeInFunction.cmake
@@ -0,0 +1,5 @@
+function(func)
+  foreach(bad_range RANGE 2 1 1)
+  endforeach()
+endfunction()
+func()
diff --git a/Tests/RunCMake/foreach/CMakeLists.txt b/Tests/RunCMake/foreach/CMakeLists.txt
new file mode 100644
index 0000000..bf2ef15
--- /dev/null
+++ b/Tests/RunCMake/foreach/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.10)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/foreach/RunCMakeTest.cmake b/Tests/RunCMake/foreach/RunCMakeTest.cmake
new file mode 100644
index 0000000..4b74cfe
--- /dev/null
+++ b/Tests/RunCMake/foreach/RunCMakeTest.cmake
@@ -0,0 +1,3 @@
+include(RunCMake)
+
+run_cmake(BadRangeInFunction)
diff --git a/Tests/RunCMake/get_property/target_properties-stderr.txt b/Tests/RunCMake/get_property/target_properties-stderr.txt
index 6b3c6ca..df7a2f1 100644
--- a/Tests/RunCMake/get_property/target_properties-stderr.txt
+++ b/Tests/RunCMake/get_property/target_properties-stderr.txt
@@ -7,4 +7,10 @@
 get_target_property: -->(.*)/Tests/RunCMake/get_property<--
 get_property: -->(.*)/Tests/RunCMake/get_property<--
 get_target_property: -->(.*)/Tests/RunCMake/get_property/target_properties-build<--
-get_property: -->(.*)/Tests/RunCMake/get_property/target_properties-build<--$
+get_property: -->(.*)/Tests/RunCMake/get_property/target_properties-build<--
+get_target_property: -->FALSE<--
+get_property: -->FALSE<--
+get_target_property: -->FALSE<--
+get_property: -->FALSE<--
+get_target_property: -->TRUE<--
+get_property: -->TRUE<--$
diff --git a/Tests/RunCMake/get_property/target_properties.cmake b/Tests/RunCMake/get_property/target_properties.cmake
index 9ff833a..321d5b5 100644
--- a/Tests/RunCMake/get_property/target_properties.cmake
+++ b/Tests/RunCMake/get_property/target_properties.cmake
@@ -16,3 +16,10 @@
 check_target_property(tgt noexist)
 check_target_property(tgt SOURCE_DIR)
 check_target_property(tgt BINARY_DIR)
+
+add_library(imported_local_tgt SHARED IMPORTED)
+add_library(imported_global_tgt SHARED IMPORTED GLOBAL)
+
+check_target_property(tgt IMPORTED_GLOBAL)
+check_target_property(imported_local_tgt IMPORTED_GLOBAL)
+check_target_property(imported_global_tgt IMPORTED_GLOBAL)
diff --git a/Tests/RunCMake/interface_library/target_commands-stderr.txt b/Tests/RunCMake/interface_library/target_commands-stderr.txt
index be11b77..9362a75 100644
--- a/Tests/RunCMake/interface_library/target_commands-stderr.txt
+++ b/Tests/RunCMake/interface_library/target_commands-stderr.txt
@@ -23,25 +23,25 @@
   CMakeLists.txt:3 \(include\)
 +
 CMake Error at target_commands.cmake:9 \(target_include_directories\):
-  target_include_directories may only be set INTERFACE properties on
-  INTERFACE targets
+  target_include_directories may only set INTERFACE properties on INTERFACE
+  targets
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
 +
 CMake Error at target_commands.cmake:10 \(target_include_directories\):
-  target_include_directories may only be set INTERFACE properties on
-  INTERFACE targets
+  target_include_directories may only set INTERFACE properties on INTERFACE
+  targets
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
 +
 CMake Error at target_commands.cmake:12 \(target_compile_definitions\):
-  target_compile_definitions may only be set INTERFACE properties on
-  INTERFACE targets
+  target_compile_definitions may only set INTERFACE properties on INTERFACE
+  targets
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
 +
 CMake Error at target_commands.cmake:13 \(target_compile_definitions\):
-  target_compile_definitions may only be set INTERFACE properties on
-  INTERFACE targets
+  target_compile_definitions may only set INTERFACE properties on INTERFACE
+  targets
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/message/RunCMakeTest.cmake b/Tests/RunCMake/message/RunCMakeTest.cmake
index 2346c86..24dad03 100644
--- a/Tests/RunCMake/message/RunCMakeTest.cmake
+++ b/Tests/RunCMake/message/RunCMakeTest.cmake
@@ -7,6 +7,6 @@
 run_cmake(warnmessage)
 # message command sets fatal occurred flag, so check each type of error
 
-# seperately
+# separately
 run_cmake(errormessage_deprecated)
 run_cmake(errormessage_dev)
diff --git a/Tests/RunCMake/project/CMP0048-OLD-stderr.txt b/Tests/RunCMake/project/CMP0048-OLD-stderr.txt
new file mode 100644
index 0000000..1fa70f8
--- /dev/null
+++ b/Tests/RunCMake/project/CMP0048-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0048-OLD.cmake:1 \(cmake_policy\):
+  The OLD behavior for policy CMP0048 will be removed from a future version
+  of CMake.
+
+  The cmake-policies\(7\) manual explains that the OLD behaviors of all
+  policies are deprecated and that a policy should be set to OLD only under
+  specific short-term circumstances.  Projects should be ported to the NEW
+  behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/add_executable/OnlyObjectSources-result.txt b/Tests/RunCMake/set_property/IMPORTED_GLOBAL-result.txt
similarity index 100%
copy from Tests/RunCMake/add_executable/OnlyObjectSources-result.txt
copy to Tests/RunCMake/set_property/IMPORTED_GLOBAL-result.txt
diff --git a/Tests/RunCMake/set_property/IMPORTED_GLOBAL-stderr.txt b/Tests/RunCMake/set_property/IMPORTED_GLOBAL-stderr.txt
new file mode 100644
index 0000000..f21b1de
--- /dev/null
+++ b/Tests/RunCMake/set_property/IMPORTED_GLOBAL-stderr.txt
@@ -0,0 +1,61 @@
+^CMake Error at IMPORTED_GLOBAL.cmake:9 \(set_property\):
+  IMPORTED_GLOBAL property can't be set to FALSE on targets
+  \(\"ImportedGlobalTarget\"\)
+
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+
+
+CMake Error at IMPORTED_GLOBAL.cmake:16 \(set_property\):
+  IMPORTED_GLOBAL property can't be appended, only set on imported targets
+  \(\"ImportedGlobalTarget\"\)
+
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+
+
+CMake Error at IMPORTED_GLOBAL.cmake:26 \(set_property\):
+  IMPORTED_GLOBAL property can't be set to FALSE on targets
+  \(\"ImportedLocalTarget\"\)
+
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+
+
+CMake Error at IMPORTED_GLOBAL.cmake:32 \(set_property\):
+  IMPORTED_GLOBAL property can't be set on non-imported targets
+  \(\"NonImportedTarget\"\)
+
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+
+
+CMake Error at IMPORTED_GLOBAL/CMakeLists.txt:8 \(set_property\):
+  Attempt to promote imported target \"ImportedLocalTarget2\" to global scope
+  \(by setting IMPORTED_GLOBAL\) which is not built in this directory.
+
+
+CMake Error in IMPORTED_GLOBAL/CMakeLists.txt:
+  IMPORTED_GLOBAL property can't be set to FALSE on targets
+  \(\"ImportedSubdirTarget1\"\)
+
+
+
+CMake Error at IMPORTED_GLOBAL.cmake:50 \(set_property\):
+  Attempt to promote imported target \"ImportedSubdirTarget1\" to global scope
+  \(by setting IMPORTED_GLOBAL\) which is not built in this directory.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)
+
+
+CMake Error in IMPORTED_GLOBAL/CMakeLists.txt:
+  IMPORTED_GLOBAL property can't be set to FALSE on targets
+  \(\"ImportedSubdirTarget2\"\)
+
+
+
+CMake Error at IMPORTED_GLOBAL.cmake:52 \(set_property\):
+  Attempt to promote imported target \"ImportedSubdirTarget2\" to global scope
+  \(by setting IMPORTED_GLOBAL\) which is not built in this directory.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/set_property/IMPORTED_GLOBAL-stdout.txt b/Tests/RunCMake/set_property/IMPORTED_GLOBAL-stdout.txt
new file mode 100644
index 0000000..c5f1d11
--- /dev/null
+++ b/Tests/RunCMake/set_property/IMPORTED_GLOBAL-stdout.txt
@@ -0,0 +1,17 @@
+-- ImportedGlobalTarget: Target IMPORTED_GLOBAL is 'TRUE'
+-- ImportedGlobalTarget: Target IMPORTED_GLOBAL is 'TRUE'
+-- ImportedGlobalTarget: Target IMPORTED_GLOBAL is 'TRUE'
+-- ImportedGlobalTarget: Target IMPORTED_GLOBAL is 'TRUE'
+-- ImportedGlobalTarget: Target IMPORTED_GLOBAL is 'TRUE'
+-- ImportedLocalTarget: Target IMPORTED_GLOBAL is 'FALSE'
+-- ImportedLocalTarget: Target IMPORTED_GLOBAL is 'TRUE'
+-- ImportedLocalTarget: Target IMPORTED_GLOBAL is 'TRUE'
+-- ImportedLocalTarget: Target IMPORTED_GLOBAL is 'TRUE'
+-- NonImportedTarget: Target IMPORTED_GLOBAL is 'FALSE'
+-- NonImportedTarget: Target IMPORTED_GLOBAL is 'FALSE'
+-- ImportedLocalTarget2: Target IMPORTED_GLOBAL is 'FALSE'
+-- ImportedLocalTarget2: Target IMPORTED_GLOBAL is 'TRUE'
+-- ImportedSubdirTarget1: Target IMPORTED_GLOBAL is 'TRUE'
+-- ImportedSubdirTarget2: Target IMPORTED_GLOBAL is 'TRUE'
+-- ImportedSubdirTarget1: Target IMPORTED_GLOBAL is 'TRUE'
+-- ImportedSubdirTarget2: Target IMPORTED_GLOBAL is 'TRUE'
diff --git a/Tests/RunCMake/set_property/IMPORTED_GLOBAL.cmake b/Tests/RunCMake/set_property/IMPORTED_GLOBAL.cmake
new file mode 100644
index 0000000..08308eb
--- /dev/null
+++ b/Tests/RunCMake/set_property/IMPORTED_GLOBAL.cmake
@@ -0,0 +1,53 @@
+macro(print_property TARGET PROP)
+  get_property(val TARGET ${TARGET} PROPERTY ${PROP})
+  message(STATUS "${TARGET}: Target ${PROP} is '${val}'")
+endmacro()
+
+# Changing property on IMPORTED target created with `GLOBAL` option.
+add_library(ImportedGlobalTarget SHARED IMPORTED GLOBAL)
+print_property(ImportedGlobalTarget IMPORTED_GLOBAL)
+set_property(TARGET ImportedGlobalTarget PROPERTY IMPORTED_GLOBAL FALSE)
+print_property(ImportedGlobalTarget IMPORTED_GLOBAL)
+set_property(TARGET ImportedGlobalTarget PROPERTY IMPORTED_GLOBAL TRUE)
+print_property(ImportedGlobalTarget IMPORTED_GLOBAL)
+set_property(TARGET ImportedGlobalTarget PROPERTY IMPORTED_GLOBAL TRUE)
+print_property(ImportedGlobalTarget IMPORTED_GLOBAL)
+# Appending property is never allowed!
+set_property(TARGET ImportedGlobalTarget APPEND PROPERTY IMPORTED_GLOBAL TRUE)
+print_property(ImportedGlobalTarget IMPORTED_GLOBAL)
+
+# Changing property on IMPORTED target created without `GLOBAL` option.
+add_library(ImportedLocalTarget SHARED IMPORTED)
+print_property(ImportedLocalTarget IMPORTED_GLOBAL)
+set_property(TARGET ImportedLocalTarget PROPERTY IMPORTED_GLOBAL TRUE)
+print_property(ImportedLocalTarget IMPORTED_GLOBAL)
+set_property(TARGET ImportedLocalTarget PROPERTY IMPORTED_GLOBAL TRUE)
+print_property(ImportedLocalTarget IMPORTED_GLOBAL)
+set_property(TARGET ImportedLocalTarget PROPERTY IMPORTED_GLOBAL FALSE)
+print_property(ImportedLocalTarget IMPORTED_GLOBAL)
+
+# Setting property on non-IMPORTED target is never allowed!
+add_library(NonImportedTarget SHARED test.cpp)
+print_property(NonImportedTarget IMPORTED_GLOBAL)
+set_property(TARGET NonImportedTarget PROPERTY IMPORTED_GLOBAL TRUE)
+print_property(NonImportedTarget IMPORTED_GLOBAL)
+
+# Local IMPORTED targets can only be promoted from same directory!
+add_library(ImportedLocalTarget2 SHARED IMPORTED)
+print_property(ImportedLocalTarget2 IMPORTED_GLOBAL)
+add_subdirectory(IMPORTED_GLOBAL)
+# Note: The value should not have changed. However, it does change because the
+# check for the same directory comes after it was changed! (At least, that is
+# not really bad because the generation will fail due to this error.)
+print_property(ImportedLocalTarget2 IMPORTED_GLOBAL)
+
+# Global IMPORTED targets from subdir are always visible
+# no matter how they became global.
+print_property(ImportedSubdirTarget1 IMPORTED_GLOBAL)
+print_property(ImportedSubdirTarget2 IMPORTED_GLOBAL)
+
+# Changing property on IMPORTED target from subdir is never possible.
+set_property(TARGET ImportedSubdirTarget1 PROPERTY IMPORTED_GLOBAL FALSE)
+print_property(ImportedSubdirTarget1 IMPORTED_GLOBAL)
+set_property(TARGET ImportedSubdirTarget2 PROPERTY IMPORTED_GLOBAL FALSE)
+print_property(ImportedSubdirTarget2 IMPORTED_GLOBAL)
diff --git a/Tests/RunCMake/set_property/IMPORTED_GLOBAL/CMakeLists.txt b/Tests/RunCMake/set_property/IMPORTED_GLOBAL/CMakeLists.txt
new file mode 100644
index 0000000..468bf78
--- /dev/null
+++ b/Tests/RunCMake/set_property/IMPORTED_GLOBAL/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_library(ImportedSubdirTarget1 SHARED IMPORTED GLOBAL)
+add_library(ImportedSubdirTarget2 SHARED IMPORTED)
+
+# Extend visibility of ImportedSubdirTarget2 to global scope.
+set_property(TARGET ImportedSubdirTarget2 PROPERTY IMPORTED_GLOBAL TRUE)
+
+# Only targets from the same directory can be promoted.
+set_property(TARGET ImportedLocalTarget2 PROPERTY IMPORTED_GLOBAL TRUE)
diff --git a/Tests/RunCMake/set_property/RunCMakeTest.cmake b/Tests/RunCMake/set_property/RunCMakeTest.cmake
index 1ddacee..5b5327d 100644
--- a/Tests/RunCMake/set_property/RunCMakeTest.cmake
+++ b/Tests/RunCMake/set_property/RunCMakeTest.cmake
@@ -3,6 +3,7 @@
 run_cmake(COMPILE_DEFINITIONS)
 run_cmake(COMPILE_FEATURES)
 run_cmake(COMPILE_OPTIONS)
+run_cmake(IMPORTED_GLOBAL)
 run_cmake(INCLUDE_DIRECTORIES)
 run_cmake(LINK_LIBRARIES)
 run_cmake(SOURCES)
diff --git a/Tests/RunCMake/set_property/test.cpp b/Tests/RunCMake/set_property/test.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/set_property/test.cpp
diff --git a/Tests/RunCMake/target_compile_features/imported_target-stderr.txt b/Tests/RunCMake/target_compile_features/imported_target-stderr.txt
index 7a07427..afad537 100644
--- a/Tests/RunCMake/target_compile_features/imported_target-stderr.txt
+++ b/Tests/RunCMake/target_compile_features/imported_target-stderr.txt
@@ -1,4 +1,5 @@
-CMake Error at imported_target.cmake:[0-9]+ \(target_compile_features\):
-  Cannot specify compile features for imported target "main".
+^CMake Error at imported_target.cmake:[0-9]+ \(target_compile_features\):
+  target_compile_features may only set INTERFACE properties on INTERFACE
+  targets
 Call Stack \(most recent call first\):
-  CMakeLists.txt:3 \(include\)
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/target_compile_features/imported_target.cmake b/Tests/RunCMake/target_compile_features/imported_target.cmake
index e886ce9..e410ace 100644
--- a/Tests/RunCMake/target_compile_features/imported_target.cmake
+++ b/Tests/RunCMake/target_compile_features/imported_target.cmake
@@ -1,4 +1,10 @@
 enable_language(CXX)
 
-add_library(main INTERFACE IMPORTED)
-target_compile_features(main INTERFACE cxx_delegating_constructors)
+add_library(lib1-interface INTERFACE IMPORTED)
+target_compile_features(lib1-interface INTERFACE cxx_delegating_constructors)
+
+add_library(lib2-interface INTERFACE IMPORTED)
+target_compile_features(lib2-interface PUBLIC cxx_delegating_constructors)
+
+add_library(lib-shared SHARED IMPORTED)
+target_compile_features(lib-shared INTERFACE cxx_delegating_constructors)
diff --git a/Tests/RunCMake/target_compile_features/invalid_args_on_interface-stderr.txt b/Tests/RunCMake/target_compile_features/invalid_args_on_interface-stderr.txt
index 3708998..23a8eeb 100644
--- a/Tests/RunCMake/target_compile_features/invalid_args_on_interface-stderr.txt
+++ b/Tests/RunCMake/target_compile_features/invalid_args_on_interface-stderr.txt
@@ -1,5 +1,5 @@
 CMake Error at invalid_args_on_interface.cmake:[0-9]+ \(target_compile_features\):
-  target_compile_features may only be set INTERFACE properties on INTERFACE
+  target_compile_features may only set INTERFACE properties on INTERFACE
   targets
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/target_link_libraries/ImportedTarget.cmake b/Tests/RunCMake/target_link_libraries/ImportedTarget.cmake
new file mode 100644
index 0000000..e5ec3f6
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries/ImportedTarget.cmake
@@ -0,0 +1,2 @@
+add_library(UnknownImportedGlobal UNKNOWN IMPORTED GLOBAL)
+target_link_libraries(UnknownImportedGlobal INTERFACE z)
diff --git a/Tests/RunCMake/add_executable/OnlyObjectSources-result.txt b/Tests/RunCMake/target_link_libraries/ImportedTargetFailure-result.txt
similarity index 100%
copy from Tests/RunCMake/add_executable/OnlyObjectSources-result.txt
copy to Tests/RunCMake/target_link_libraries/ImportedTargetFailure-result.txt
diff --git a/Tests/RunCMake/target_link_libraries/ImportedTargetFailure-stderr.txt b/Tests/RunCMake/target_link_libraries/ImportedTargetFailure-stderr.txt
new file mode 100644
index 0000000..1cafa5b
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries/ImportedTargetFailure-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at ImportedTargetFailure.cmake:[0-9]+ \(target_link_libraries\):
+  IMPORTED library can only be used with the INTERFACE keyword of
+  target_link_libraries
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/target_link_libraries/ImportedTargetFailure.cmake b/Tests/RunCMake/target_link_libraries/ImportedTargetFailure.cmake
new file mode 100644
index 0000000..3ac0aa9
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries/ImportedTargetFailure.cmake
@@ -0,0 +1,2 @@
+add_library(UnknownImportedGlobal UNKNOWN IMPORTED GLOBAL)
+target_link_libraries(UnknownImportedGlobal PRIVATE z)
diff --git a/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake b/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake
index b1c9435..97b0888 100644
--- a/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake
@@ -4,6 +4,8 @@
 run_cmake(CMP0023-NEW)
 run_cmake(CMP0023-WARN-2)
 run_cmake(CMP0023-NEW-2)
+run_cmake(ImportedTarget)
+run_cmake(ImportedTargetFailure)
 run_cmake(MixedSignature)
 run_cmake(Separate-PRIVATE-LINK_PRIVATE-uses)
 run_cmake(SubDirTarget)
diff --git a/Tests/Server/CMakeLists.txt b/Tests/Server/CMakeLists.txt
index 08bef0c..41d1131 100644
--- a/Tests/Server/CMakeLists.txt
+++ b/Tests/Server/CMakeLists.txt
@@ -3,10 +3,10 @@
 
 find_package(PythonInterp REQUIRED)
 
-macro(do_test bsname file)
+macro(do_test bsname file type)
   execute_process(COMMAND ${PYTHON_EXECUTABLE}
     -B # no .pyc files
-    "${CMAKE_SOURCE_DIR}/server-test.py"
+    "${CMAKE_SOURCE_DIR}/${type}-test.py"
     "${CMAKE_COMMAND}"
     "${CMAKE_SOURCE_DIR}/${file}"
     "${CMAKE_SOURCE_DIR}"
@@ -20,9 +20,9 @@
   endif()
 endmacro()
 
-do_test("test_cache" "tc_cache.json")
-do_test("test_handshake" "tc_handshake.json")
-do_test("test_globalSettings" "tc_globalSettings.json")
-do_test("test_buildsystem1" "tc_buildsystem1.json")
+do_test("test_cache" "tc_cache.json" "server")
+do_test("test_handshake" "tc_handshake.json" "server")
+do_test("test_globalSettings" "tc_globalSettings.json" "server")
+do_test("test_buildsystem1" "tc_buildsystem1.json" "server")
 
 add_executable(Server empty.cpp)
diff --git a/Tests/Server/cmakelib.py b/Tests/Server/cmakelib.py
index 2218e02..39e3618 100644
--- a/Tests/Server/cmakelib.py
+++ b/Tests/Server/cmakelib.py
@@ -1,5 +1,5 @@
 from __future__ import print_function
-import sys, subprocess, json
+import sys, subprocess, json, os, select, shutil, time, socket
 
 termwidth = 150
 
@@ -38,11 +38,50 @@
   for index in range(numRows):
     print(indent + pad.join(item.ljust(maxitemwidth) for item in array[index::numRows]))
 
+filterPacket = lambda x: x
+
+STDIN = 0
+PIPE = 1
+
+communicationMethods = [STDIN]
+
+if hasattr(socket, 'AF_UNIX'):
+  communicationMethods.append(PIPE)
+
+def defaultExitWithError(proc):
+  data = ""
+  try:
+    while select.select([proc.outPipe], [], [], 3.)[0]:
+      data = data + proc.outPipe.read(1)
+    if len(data):
+      print("Rest of raw buffer from server:")
+      printServer(data)
+  except:
+    pass
+  proc.outPipe.close()
+  proc.inPipe.close()
+  proc.kill()
+  sys.exit(1)
+
+exitWithError = lambda proc: defaultExitWithError(proc)
+
+serverTag = "SERVER"
+
+def printServer(*args):
+    print(serverTag + ">", *args)
+    print()
+    sys.stdout.flush()
+
+def printClient(*args):
+    print("CLIENT>", *args)
+    print()
+    sys.stdout.flush()
+
 def waitForRawMessage(cmakeCommand):
   stdoutdata = ""
   payload = ""
   while not cmakeCommand.poll():
-    stdoutdataLine = cmakeCommand.stdout.readline()
+    stdoutdataLine = cmakeCommand.outPipe.readline()
     if stdoutdataLine:
       stdoutdata += stdoutdataLine.decode('utf-8')
     else:
@@ -50,12 +89,16 @@
     begin = stdoutdata.find('[== "CMake Server" ==[\n')
     end = stdoutdata.find(']== "CMake Server" ==]')
 
-    if (begin != -1 and end != -1):
+    if begin != -1 and end != -1:
       begin += len('[== "CMake Server" ==[\n')
       payload = stdoutdata[begin:end]
-      if print_communication:
-        print("\nSERVER>", json.loads(payload), "\n")
-      return json.loads(payload)
+      jsonPayload = json.loads(payload)
+      filteredPayload = filterPacket(jsonPayload)
+      if print_communication and filteredPayload:
+        printServer(filteredPayload)
+      if filteredPayload is not None or jsonPayload is None:
+          return jsonPayload
+      stdoutdata = stdoutdata[(end+len(']== "CMake Server" ==]')):]
 
 def writeRawData(cmakeCommand, content):
   writeRawData.counter += 1
@@ -71,27 +114,53 @@
     payload = payload.replace('\n', '\r\n')
 
   if print_communication:
-    print("\nCLIENT>", content, "(Use \\r\\n:", rn, ")\n")
-  cmakeCommand.stdin.write(payload.encode('utf-8'))
-  cmakeCommand.stdin.flush()
+    printClient(content, "(Use \\r\\n:", rn, ")")
+
+  cmakeCommand.write(payload.encode('utf-8'))
+
 writeRawData.counter = 0
 
 def writePayload(cmakeCommand, obj):
   writeRawData(cmakeCommand, json.dumps(obj))
 
-def initProc(cmakeCommand):
-  cmakeCommand = subprocess.Popen([cmakeCommand, "-E", "server", "--experimental", "--debug"],
-                                  stdin=subprocess.PIPE,
-                                  stdout=subprocess.PIPE)
+def getPipeName():
+  return "/tmp/server-test-socket"
+
+def attachPipe(cmakeCommand, pipeName):
+  time.sleep(1)
+  sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+  sock.connect(pipeName)
+  global serverTag
+  serverTag = "SERVER(PIPE)"
+  cmakeCommand.outPipe = sock.makefile()
+  cmakeCommand.inPipe = sock
+  cmakeCommand.write = cmakeCommand.inPipe.sendall
+
+def writeAndFlush(pipe, val):
+  pipe.write(val)
+  pipe.flush()
+
+def initServerProc(cmakeCommand, comm):
+  if comm == PIPE:
+    pipeName = getPipeName()
+    cmakeCommand = subprocess.Popen([cmakeCommand, "-E", "server", "--experimental", "--pipe=" + pipeName])
+    attachPipe(cmakeCommand, pipeName)
+  else:
+    cmakeCommand = subprocess.Popen([cmakeCommand, "-E", "server", "--experimental", "--debug"],
+                                    stdin=subprocess.PIPE,
+                                    stdout=subprocess.PIPE)
+    cmakeCommand.outPipe = cmakeCommand.stdout
+    cmakeCommand.inPipe = cmakeCommand.stdin
+    cmakeCommand.write = lambda val: writeAndFlush(cmakeCommand.inPipe, val)
 
   packet = waitForRawMessage(cmakeCommand)
   if packet == None:
     print("Not in server mode")
-    sys.exit(1)
+    sys.exit(2)
 
   if packet['type'] != 'hello':
     print("No hello message")
-    sys.exit(1)
+    sys.exit(3)
 
   return cmakeCommand
 
@@ -115,7 +184,8 @@
   packet = ordered(waitForRawMessage(cmakeCommand))
 
   if packet != data:
-    sys.exit(-1)
+    print ("Received unexpected message; test failed")
+    exitWithError(cmakeCommand)
   return packet
 
 def waitForReply(cmakeCommand, originalType, cookie, skipProgress):
@@ -124,25 +194,27 @@
     packet = waitForRawMessage(cmakeCommand)
     t = packet['type']
     if packet['cookie'] != cookie or packet['inReplyTo'] != originalType:
-      sys.exit(1)
+      print("cookie or inReplyTo mismatch")
+      sys.exit(4)
     if t == 'message' or t == 'progress':
       if skipProgress:
         continue
     if t == 'reply':
         break
-    sys.exit(1)
+    print("Unrecognized message", packet)
+    sys.exit(5)
 
   return packet
 
 def waitForError(cmakeCommand, originalType, cookie, message):
   packet = waitForRawMessage(cmakeCommand)
   if packet['cookie'] != cookie or packet['type'] != 'error' or packet['inReplyTo'] != originalType or packet['errorMessage'] != message:
-    sys.exit(1)
+    sys.exit(6)
 
 def waitForProgress(cmakeCommand, originalType, cookie, current, message):
   packet = waitForRawMessage(cmakeCommand)
   if packet['cookie'] != cookie or packet['type'] != 'progress' or packet['inReplyTo'] != originalType or packet['progressCurrent'] != current or packet['progressMessage'] != message:
-    sys.exit(1)
+    sys.exit(7)
 
 def handshake(cmakeCommand, major, minor, source, build, generator, extraGenerator):
   version = { 'major': major }
@@ -167,9 +239,9 @@
   versionString = version['string']
   vs = str(version['major']) + '.' + str(version['minor']) + '.' + str(version['patch'])
   if (versionString != vs and not versionString.startswith(vs + '-')):
-    sys.exit(1)
+    sys.exit(8)
   if (versionString != cmakeVersion):
-    sys.exit(1)
+    sys.exit(9)
 
   # validate generators:
   generatorObjects = capabilities['generators']
@@ -202,16 +274,16 @@
 
   for gen in cmakeGenerators:
     if (not gen in generators):
-        sys.exit(1)
+        sys.exit(10)
 
   gen = packet['generator']
   if (gen != '' and not (gen in generators)):
-    sys.exit(1)
+    sys.exit(11)
 
   for i in data:
     print("Validating", i)
     if (packet[i] != data[i]):
-      sys.exit(1)
+      sys.exit(12)
 
 def validateCache(cmakeCommand, data):
   packet = waitForReply(cmakeCommand, 'cache', '', False)
@@ -236,3 +308,43 @@
   if (not hadHomeDir):
     print('No CMAKE_HOME_DIRECTORY found in cache.')
     sys.exit(1)
+
+def handleBasicMessage(proc, obj, debug):
+  if 'sendRaw' in obj:
+    data = obj['sendRaw']
+    if debug: print("Sending raw:", data)
+    writeRawData(proc, data)
+    return True
+  elif 'send' in obj:
+    data = obj['send']
+    if debug: print("Sending:", json.dumps(data))
+    writePayload(proc, data)
+    return True
+  elif 'recv' in obj:
+    data = obj['recv']
+    if debug: print("Waiting for:", json.dumps(data))
+    waitForMessage(proc, data)
+    return True
+  elif 'message' in obj:
+    print("MESSAGE:", obj["message"])
+    sys.stdout.flush()
+    return True
+  return False
+
+def shutdownProc(proc):
+  # Tell the server to exit.
+  proc.inPipe.close()
+  proc.outPipe.close()
+
+  # Wait for the server to exit.
+  # If this version of python supports it, terminate the server after a timeout.
+  try:
+    proc.wait(timeout=5)
+  except TypeError:
+    proc.wait()
+  except:
+    proc.terminate()
+    raise
+
+  print('cmake-server exited: %d' % proc.returncode)
+  sys.exit(proc.returncode)
diff --git a/Tests/Server/server-test.py b/Tests/Server/server-test.py
index 9380910..701c6e9 100644
--- a/Tests/Server/server-test.py
+++ b/Tests/Server/server-test.py
@@ -9,7 +9,7 @@
 buildDir = sys.argv[4] + "/" + os.path.splitext(os.path.basename(testFile))[0]
 cmakeGenerator = sys.argv[5]
 
-print("Test:", testFile,
+print("Server Test:", testFile,
       "\n-- SourceDir:", sourceDir,
       "\n-- BuildDir:", buildDir,
       "\n-- Generator:", cmakeGenerator)
@@ -17,99 +17,89 @@
 if os.path.exists(buildDir):
     shutil.rmtree(buildDir)
 
-proc = cmakelib.initProc(cmakeCommand)
+cmakelib.filterBase = sourceDir
 
 with open(testFile) as f:
     testData = json.loads(f.read())
 
-for obj in testData:
-    if 'sendRaw' in obj:
-        data = obj['sendRaw']
-        if debug: print("Sending raw:", data)
-        cmakelib.writeRawData(proc, data)
-    elif 'send' in obj:
-        data = obj['send']
-        if debug: print("Sending:", json.dumps(data))
-        cmakelib.writePayload(proc, data)
-    elif 'recv' in obj:
-        data = obj['recv']
-        if debug: print("Waiting for:", json.dumps(data))
-        cmakelib.waitForMessage(proc, data)
-    elif 'reply' in obj:
-        data = obj['reply']
-        if debug: print("Waiting for reply:", json.dumps(data))
-        originalType = ""
-        cookie = ""
-        skipProgress = False;
-        if 'cookie' in data: cookie = data['cookie']
-        if 'type' in data: originalType = data['type']
-        if 'skipProgress' in data: skipProgress = data['skipProgress']
-        cmakelib.waitForReply(proc, originalType, cookie, skipProgress)
-    elif 'error' in obj:
-        data = obj['error']
-        if debug: print("Waiting for error:", json.dumps(data))
-        originalType = ""
-        cookie = ""
-        message = ""
-        if 'cookie' in data: cookie = data['cookie']
-        if 'type' in data: originalType = data['type']
-        if 'message' in data: message = data['message']
-        cmakelib.waitForError(proc, originalType, cookie, message)
-    elif 'progress' in obj:
-        data = obj['progress']
-        if debug: print("Waiting for progress:", json.dumps(data))
-        originalType = ''
-        cookie = ""
-        current = 0
-        message = ""
-        if 'cookie' in data: cookie = data['cookie']
-        if 'type' in data: originalType = data['type']
-        if 'current' in data: current = data['current']
-        if 'message' in data: message = data['message']
-        cmakelib.waitForProgress(proc, originalType, cookie, current, message)
-    elif 'handshake' in obj:
-        data = obj['handshake']
-        if debug: print("Doing handshake:", json.dumps(data))
-        major = -1
-        minor = -1
-        generator = cmakeGenerator
-        extraGenerator = ''
-        sourceDirectory = sourceDir
-        buildDirectory = buildDir
-        if 'major' in data: major = data['major']
-        if 'minor' in data: minor = data['minor']
-        if 'buildDirectory' in data: buildDirectory = data['buildDirectory']
-        if 'sourceDirectory' in data: sourceDirectory = data['sourceDirectory']
-        if 'generator' in data: generator = data['generator']
-        if 'extraGenerator' in data: extraGenerator = data['extraGenerator']
-        if not os.path.isabs(buildDirectory):
-            buildDirectory = buildDir + "/" + buildDirectory
-        if sourceDirectory != '' and not os.path.isabs(sourceDirectory):
-            sourceDirectory = sourceDir + "/" + sourceDirectory
-        cmakelib.handshake(proc, major, minor, sourceDirectory, buildDirectory,
-          generator, extraGenerator)
-    elif 'validateGlobalSettings' in obj:
-        data = obj['validateGlobalSettings']
-        if not 'buildDirectory' in data: data['buildDirectory'] = buildDir
-        if not 'sourceDirectory' in data: data['sourceDirectory'] = sourceDir
-        if not 'generator' in data: data['generator'] = cmakeGenerator
-        if not 'extraGenerator' in data: data['extraGenerator'] = ''
-        cmakelib.validateGlobalSettings(proc, cmakeCommand, data)
-    elif 'validateCache' in obj:
-        data = obj['validateCache']
-        if not 'isEmpty' in data: data['isEmpty'] = false
-        cmakelib.validateCache(proc, data)
-    elif 'message' in obj:
-        print("MESSAGE:", obj["message"])
-    elif 'reconnect' in obj:
-        cmakelib.exitProc(proc)
-        proc = cmakelib.initProc(cmakeCommand)
-    else:
-        print("Unknown command:", json.dumps(obj))
-        sys.exit(2)
+for communicationMethod in cmakelib.communicationMethods:
+    proc = cmakelib.initServerProc(cmakeCommand, communicationMethod)
+    if proc is None:
+        continue
 
+    for obj in testData:
+        if cmakelib.handleBasicMessage(proc, obj, debug):
+            pass
+        elif 'reply' in obj:
+            data = obj['reply']
+            if debug: print("Waiting for reply:", json.dumps(data))
+            originalType = ""
+            cookie = ""
+            skipProgress = False;
+            if 'cookie' in data: cookie = data['cookie']
+            if 'type' in data: originalType = data['type']
+            if 'skipProgress' in data: skipProgress = data['skipProgress']
+            cmakelib.waitForReply(proc, originalType, cookie, skipProgress)
+        elif 'error' in obj:
+            data = obj['error']
+            if debug: print("Waiting for error:", json.dumps(data))
+            originalType = ""
+            cookie = ""
+            message = ""
+            if 'cookie' in data: cookie = data['cookie']
+            if 'type' in data: originalType = data['type']
+            if 'message' in data: message = data['message']
+            cmakelib.waitForError(proc, originalType, cookie, message)
+        elif 'progress' in obj:
+            data = obj['progress']
+            if debug: print("Waiting for progress:", json.dumps(data))
+            originalType = ''
+            cookie = ""
+            current = 0
+            message = ""
+            if 'cookie' in data: cookie = data['cookie']
+            if 'type' in data: originalType = data['type']
+            if 'current' in data: current = data['current']
+            if 'message' in data: message = data['message']
+            cmakelib.waitForProgress(proc, originalType, cookie, current, message)
+        elif 'handshake' in obj:
+            data = obj['handshake']
+            if debug: print("Doing handshake:", json.dumps(data))
+            major = -1
+            minor = -1
+            generator = cmakeGenerator
+            extraGenerator = ''
+            sourceDirectory = sourceDir
+            buildDirectory = buildDir
+            if 'major' in data: major = data['major']
+            if 'minor' in data: minor = data['minor']
+            if 'buildDirectory' in data: buildDirectory = data['buildDirectory']
+            if 'sourceDirectory' in data: sourceDirectory = data['sourceDirectory']
+            if 'generator' in data: generator = data['generator']
+            if 'extraGenerator' in data: extraGenerator = data['extraGenerator']
+
+            if not os.path.isabs(buildDirectory):
+                buildDirectory = buildDir + "/" + buildDirectory
+            if sourceDirectory != '' and not os.path.isabs(sourceDirectory):
+                sourceDirectory = sourceDir + "/" + sourceDirectory
+            cmakelib.handshake(proc, major, minor, sourceDirectory, buildDirectory,
+                               generator, extraGenerator)
+        elif 'validateGlobalSettings' in obj:
+            data = obj['validateGlobalSettings']
+            if not 'buildDirectory' in data: data['buildDirectory'] = buildDir
+            if not 'sourceDirectory' in data: data['sourceDirectory'] = sourceDir
+            if not 'generator' in data: data['generator'] = cmakeGenerator
+            if not 'extraGenerator' in data: data['extraGenerator'] = ''
+            cmakelib.validateGlobalSettings(proc, cmakeCommand, data)
+        elif 'validateCache' in obj:
+            data = obj['validateCache']
+            if not 'isEmpty' in data: data['isEmpty'] = false
+            cmakelib.validateCache(proc, data)
+        elif 'reconnect' in obj:
+            cmakelib.exitProc(proc)
+            proc = cmakelib.initServerProc(cmakeCommand, communicationMethod)
+        else:
+            print("Unknown command:", json.dumps(obj))
+            sys.exit(2)
+    cmakelib.shutdownProc(proc)
     print("Completed")
-
-cmakelib.exitProc(proc)
-print('cmake-server exited: %d' % proc.returncode)
-sys.exit(proc.returncode)
diff --git a/Utilities/Release/linux64_release.cmake b/Utilities/Release/linux64_release.cmake
index 02742ad..97fc33c 100644
--- a/Utilities/Release/linux64_release.cmake
+++ b/Utilities/Release/linux64_release.cmake
@@ -29,15 +29,14 @@
 CURSES_INCLUDE_PATH:PATH=/home/kitware/ncurses-5.9/include
 FORM_LIBRARY:FILEPATH=/home/kitware/ncurses-5.9/lib/libform.a
 CMAKE_USE_OPENSSL:BOOL=ON
-OPENSSL_CRYPTO_LIBRARY:FILEPATH=/home/kitware/openssl-1.0.2j/lib/libcrypto.a
-OPENSSL_INCLUDE_DIR:PATH=/home/kitware/openssl-1.0.2j/include
-OPENSSL_SSL_LIBRARY:FILEPATH=/home/kitware/openssl-1.0.2j/lib/libssl.a
+OPENSSL_CRYPTO_LIBRARY:STRING=/home/kitware/openssl-1.1.0g/lib/libcrypto.a;-pthread
+OPENSSL_INCLUDE_DIR:PATH=/home/kitware/openssl-1.1.0g/include
+OPENSSL_SSL_LIBRARY:FILEPATH=/home/kitware/openssl-1.1.0g/lib/libssl.a
 PYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3
 CPACK_SYSTEM_NAME:STRING=Linux-x86_64
 BUILD_QtDialog:BOOL:=TRUE
 CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE
 CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL:STRING=3
-CMake_INSTALL_DEPENDENCIES:BOOL=ON
 CMAKE_PREFIX_PATH:STRING=${qt_prefix}
 CMake_QT_STATIC_QXcbIntegrationPlugin_LIBRARIES:STRING=${qt_xcb_libs}
 ")
diff --git a/Utilities/Release/win32_release.cmake b/Utilities/Release/win32_release.cmake
index f54a4ca..bdf002e 100644
--- a/Utilities/Release/win32_release.cmake
+++ b/Utilities/Release/win32_release.cmake
@@ -1,13 +1,20 @@
-set(CMAKE_RELEASE_DIRECTORY "c:/msys64/home/dashboard/CMakeReleaseDirectory")
+set(CMAKE_RELEASE_DIRECTORY "c:/msys64/home/dashboard/CMakeReleaseDirectory32")
 set(CONFIGURE_WITH_CMAKE TRUE)
 set(CMAKE_CONFIGURE_PATH "c:/Program\\ Files/CMake/bin/cmake.exe")
-set(PROCESSORS 8)
-set(HOST dash3win7)
+set(PROCESSORS 16)
+set(HOST win32)
 set(RUN_LAUNCHER ~/rel/run)
 set(CPACK_BINARY_GENERATORS "WIX ZIP")
 set(CPACK_SOURCE_GENERATORS "ZIP")
 set(MAKE_PROGRAM "ninja")
-set(MAKE "${MAKE_PROGRAM} -j8")
+set(MAKE "${MAKE_PROGRAM} -j16")
+set(qt_prefix "c:/Qt/5.6.3/msvc2017-32-xp-mt")
+set(qt_win_libs
+  ${qt_prefix}/plugins/platforms/qwindows.lib
+  ${qt_prefix}/lib/Qt5PlatformSupport.lib
+  ${qt_prefix}/lib/qtfreetype.lib
+  imm32.lib
+  )
 set(INITIAL_CACHE "CMAKE_BUILD_TYPE:STRING=Release
 CMAKE_DOC_DIR:STRING=doc/cmake
 CMAKE_USE_OPENSSL:BOOL=OFF
@@ -16,17 +23,22 @@
 CMAKE_GENERATOR:INTERNAL=Ninja
 BUILD_QtDialog:BOOL:=TRUE
 CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL:STRING=3
-CMake_INSTALL_DEPENDENCIES:BOOL=ON
+CMAKE_C_FLAGS_RELEASE:STRING=-MT -O2 -Ob2 -DNDEBUG
+CMAKE_CXX_FLAGS_RELEASE:STRING=-MT -O2 -Ob2 -DNDEBUG
 CMAKE_EXE_LINKER_FLAGS:STRING=-machine:x86 -subsystem:console,5.01
+CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES:STRING=${qt_win_libs}
+CMAKE_PREFIX_PATH:STRING=${qt_prefix}
+CMake_TEST_Qt4:BOOL=OFF
+CMake_TEST_Qt5:BOOL=OFF
 ")
 set(ppflags "-D_WIN32_WINNT=0x501 -DNTDDI_VERSION=0x05010000 -D_USING_V110_SDK71_")
 set(CFLAGS "${ppflags}")
 set(CXXFLAGS "${ppflags}")
-set(ENV ". ~/rel/env")
+set(ENV ". ~/rel/env32")
 get_filename_component(path "${CMAKE_CURRENT_LIST_FILE}" PATH)
 set(GIT_EXTRA "git config core.autocrlf true")
 if(CMAKE_CREATE_VERSION STREQUAL "nightly")
   # Some tests fail spuriously too often.
-  set(EXTRA_CTEST_ARGS "-E 'Qt5Autogen|ConsoleBuf'")
+  set(EXTRA_CTEST_ARGS "-E 'ConsoleBuf'")
 endif()
 include(${path}/release_cmake.cmake)
diff --git a/Utilities/Release/win64_release.cmake b/Utilities/Release/win64_release.cmake
index bd2690f..1c81f82 100644
--- a/Utilities/Release/win64_release.cmake
+++ b/Utilities/Release/win64_release.cmake
@@ -1,14 +1,20 @@
 set(CMAKE_RELEASE_DIRECTORY "c:/msys64/home/dashboard/CMakeReleaseDirectory64")
 set(CONFIGURE_WITH_CMAKE TRUE)
 set(CMAKE_CONFIGURE_PATH "c:/Program\\ Files/CMake/bin/cmake.exe")
-set(PROCESSORS 8)
-set(HOST dash3win7)
-set(SCRIPT_NAME dash3win7x64)
+set(PROCESSORS 16)
+set(HOST win64)
 set(RUN_LAUNCHER ~/rel/run)
 set(CPACK_BINARY_GENERATORS "WIX ZIP")
 set(CPACK_SOURCE_GENERATORS "")
 set(MAKE_PROGRAM "ninja")
-set(MAKE "${MAKE_PROGRAM} -j8")
+set(MAKE "${MAKE_PROGRAM} -j16")
+set(qt_prefix "c:/Qt/5.6.3/msvc2017-64-xp-mt")
+set(qt_win_libs
+  ${qt_prefix}/plugins/platforms/qwindows.lib
+  ${qt_prefix}/lib/Qt5PlatformSupport.lib
+  ${qt_prefix}/lib/qtfreetype.lib
+  imm32.lib
+  )
 set(INITIAL_CACHE "CMAKE_BUILD_TYPE:STRING=Release
 CMAKE_DOC_DIR:STRING=doc/cmake
 CMAKE_USE_OPENSSL:BOOL=OFF
@@ -17,8 +23,13 @@
 CMAKE_GENERATOR:INTERNAL=Ninja
 BUILD_QtDialog:BOOL:=TRUE
 CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL:STRING=3
-CMake_INSTALL_DEPENDENCIES:BOOL=ON
+CMAKE_C_FLAGS_RELEASE:STRING=-MT -O2 -Ob2 -DNDEBUG
+CMAKE_CXX_FLAGS_RELEASE:STRING=-MT -O2 -Ob2 -DNDEBUG
 CMAKE_EXE_LINKER_FLAGS:STRING=-machine:x64 -subsystem:console,5.02
+CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES:STRING=${qt_win_libs}
+CMAKE_PREFIX_PATH:STRING=${qt_prefix}
+CMake_TEST_Qt4:BOOL=OFF
+CMake_TEST_Qt5:BOOL=OFF
 ")
 set(ppflags "-D_WIN32_WINNT=0x502 -DNTDDI_VERSION=0x05020000 -D_USING_V110_SDK71_")
 set(CFLAGS "${ppflags}")
@@ -28,6 +39,6 @@
 set(GIT_EXTRA "git config core.autocrlf true")
 if(CMAKE_CREATE_VERSION STREQUAL "nightly")
   # Some tests fail spuriously too often.
-  set(EXTRA_CTEST_ARGS "-E 'Qt5Autogen|ConsoleBuf'")
+  set(EXTRA_CTEST_ARGS "-E 'ConsoleBuf'")
 endif()
 include(${path}/release_cmake.cmake)
diff --git a/Utilities/cmcurl/CMake/Utilities.cmake b/Utilities/cmcurl/CMake/Utilities.cmake
index 8b6276d..005b166 100644
--- a/Utilities/cmcurl/CMake/Utilities.cmake
+++ b/Utilities/cmcurl/CMake/Utilities.cmake
@@ -19,7 +19,7 @@
   set(${LIST_NAME} "${NEW_LIST_SPACE}" PARENT_SCOPE)
 endfunction()
 
-# Convinience function that does the same as LIST(FIND ...) but with a TRUE/FALSE return value.
+# Convenience function that does the same as LIST(FIND ...) but with a TRUE/FALSE return value.
 # Ex: IN_STR_LIST(MY_LIST "Searched item" WAS_FOUND)
 function(IN_STR_LIST LIST_NAME ITEM_SEARCHED RETVAL)
   list(FIND ${LIST_NAME} ${ITEM_SEARCHED} FIND_POS)
diff --git a/bootstrap b/bootstrap
index 47f7e76..d9e243d 100755
--- a/bootstrap
+++ b/bootstrap
@@ -311,6 +311,7 @@
   cmFindProgramCommand \
   cmForEachCommand \
   cmFunctionCommand \
+  cmFSPermissions \
   cmGeneratedFileStream \
   cmGeneratorExpression \
   cmGeneratorExpressionContext \