Merge topic '17870-effective-system-name'

4597396784 Apple: Use include_guard() within compiler config
e95b3fd9bb Apple: Use CMAKE_EFFECTIVE_SYSTEM_NAME to share compiler info
84f9f63fcc Modules: Introduce CMAKE_EFFECTIVE_SYSTEM_NAME to lookup compiler info
9fa0f2eb56 CMakeFindPackageMode: Perform platform-specific initialization

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !1964
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a27c662..3ee67cb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -546,7 +546,7 @@
   #---------------------------------------------------------------------
   # Build libuv library.
   if(CMAKE_USE_SYSTEM_LIBUV)
-    find_package(LibUV 1.0.0)
+    find_package(LibUV 1.10.0)
     if(NOT LIBUV_FOUND)
       message(FATAL_ERROR
         "CMAKE_USE_SYSTEM_LIBUV is ON but a libuv is not found!")
diff --git a/Help/command/list.rst b/Help/command/list.rst
index 6218a2a..e240b65 100644
--- a/Help/command/list.rst
+++ b/Help/command/list.rst
@@ -151,6 +151,79 @@
 
 Removes duplicated items in the list.
 
+TRANSFORM
+"""""""""
+
+::
+
+  list(TRANSFORM <list> <ACTION> [<SELECTOR>]
+                        [OUTPUT_VARIABLE <output variable>])
+
+Transforms the list by applying an action to all or, by specifying a
+``<SELECTOR>``, to the selected elements of the list, storing result in-place
+or in the specified output variable.
+
+.. note::
+
+   ``TRANSFORM`` sub-command does not change the number of elements of the
+   list. If a ``<SELECTOR>`` is specified, only some elements will be changed,
+   the other ones will remain same as before the transformation.
+
+``<ACTION>`` specify the action to apply to the elements of list.
+The actions have exactly the same semantics as sub-commands of
+:command:`string` command.
+
+The ``<ACTION>`` may be one of:
+
+``APPEND``, ``PREPEND``: Append, prepend specified value to each element of
+the list. ::
+
+  list(TRANSFORM <list> <APPEND|PREPEND> <value> ...)
+
+``TOUPPER``, ``TOLOWER``: Convert each element of the list to upper, lower
+characters. ::
+
+  list(TRANSFORM <list> <TOLOWER|TOUPPER> ...)
+
+``STRIP``: Remove leading and trailing spaces from each element of the
+list. ::
+
+  list(TRANSFORM <list> STRIP ...)
+
+``GENEX_STRIP``: Strip any
+:manual:`generator expressions <cmake-generator-expressions(7)>` from each
+element of the list. ::
+
+  list(TRANSFORM <list> GENEX_STRIP ...)
+
+``REPLACE``: Match the regular expression as many times as possible and
+substitute the replacement expression for the match for each element
+of the list
+(Same semantic as ``REGEX REPLACE`` from :command:`string` command). ::
+
+  list(TRANSFORM <list> REPLACE <regular_expression>
+                                <replace_expression> ...)
+
+``<SELECTOR>`` select which elements of the list will be transformed. Only one
+type of selector can be specified at a time.
+
+The ``<SELECTOR>`` may be one of:
+
+``AT``: Specify a list of indexes. ::
+
+  list(TRANSFORM <list> <ACTION> AT <index> [<index> ...] ...)
+
+``FOR``: Specify a range with, optionaly, an increment used to iterate over
+the range. ::
+
+  list(TRANSFORM <list> <ACTION> FOR <start> <stop> [<step>] ...)
+
+``REGEX``: Specify a regular expression. Only elements matching the regular
+expression will be transformed. ::
+
+  list(TRANSFORM <list> <ACTION> REGEX <regular_expression> ...)
+
+
 Sorting
 ^^^^^^^
 
diff --git a/Help/release/dev/list-transform.rst b/Help/release/dev/list-transform.rst
new file mode 100644
index 0000000..4a6dacc
--- /dev/null
+++ b/Help/release/dev/list-transform.rst
@@ -0,0 +1,5 @@
+list-transform
+--------------
+
+* The :command:`list` command learned a ``TRANSFORM`` sub-command
+  to apply various string transformation to list's elements.
diff --git a/Modules/CMakeCUDACompiler.cmake.in b/Modules/CMakeCUDACompiler.cmake.in
index f524e5f..9761d8c 100644
--- a/Modules/CMakeCUDACompiler.cmake.in
+++ b/Modules/CMakeCUDACompiler.cmake.in
@@ -11,6 +11,7 @@
 set(CMAKE_CUDA_COMPILER_ENV_VAR "CUDACXX")
 set(CMAKE_CUDA_HOST_COMPILER_ENV_VAR "CUDAHOSTCXX")
 
+set(CMAKE_CUDA_COMPILER_LOADED 1)
 set(CMAKE_CUDA_COMPILER_ID_RUN 1)
 set(CMAKE_CUDA_SOURCE_FILE_EXTENSIONS cu)
 set(CMAKE_CUDA_LINKER_PREFERENCE 15)
diff --git a/Modules/CMakeParseImplicitLinkInfo.cmake b/Modules/CMakeParseImplicitLinkInfo.cmake
index 63d18ab..935f92d 100644
--- a/Modules/CMakeParseImplicitLinkInfo.cmake
+++ b/Modules/CMakeParseImplicitLinkInfo.cmake
@@ -142,7 +142,7 @@
   # We remove items that are not language-specific.
   set(implicit_libs "")
   foreach(lib IN LISTS implicit_libs_tmp)
-    if("x${lib}" MATCHES "^x(crt.*\\.o|gcc_eh.*|System.*|.*libclang_rt.*|msvcrt.*|libvcruntime.*|libucrt.*|libcmt.*)$")
+    if("x${lib}" MATCHES "^x(crt.*\\.o|gcc_eh.*|.*libgcc_eh.*|System.*|.*libclang_rt.*|msvcrt.*|libvcruntime.*|libucrt.*|libcmt.*)$")
       string(APPEND log "  remove lib [${lib}]\n")
     elseif(IS_ABSOLUTE "${lib}")
       get_filename_component(abs "${lib}" ABSOLUTE)
diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake
index 4bfbf03..75c4441 100644
--- a/Modules/FindMPI.cmake
+++ b/Modules/FindMPI.cmake
@@ -352,6 +352,9 @@
   # Ensure that no error output might be passed upwards.
   if(NOT WRAPPER_RETURN EQUAL 0)
     unset(WRAPPER_OUTPUT)
+  else()
+    # Strip leading whitespace
+    string(REGEX REPLACE "^ +" "" WRAPPER_OUTPUT "${WRAPPER_OUTPUT}")
   endif()
   set(${OUTPUT_VARIABLE} "${WRAPPER_OUTPUT}" PARENT_SCOPE)
   set(${RESULT_VARIABLE} "${WRAPPER_RETURN}" PARENT_SCOPE)
@@ -715,20 +718,20 @@
   # or shared libraries if there aren't any import libraries in use on the system.
   # Note that we do not consider CMAKE_<TYPE>_LIBRARY_PREFIX intentionally here: The linker will for a given file
   # decide how to link it based on file type, not based on a prefix like 'lib'.
-  set(_MPI_LIB_NAME_REGEX "[^\" ]+${CMAKE_STATIC_LIBRARY_SUFFIX}|\"[^\"]+${CMAKE_STATIC_LIBRARY_SUFFIX}\"")
+  set(_MPI_LIB_SUFFIX_REGEX "${CMAKE_STATIC_LIBRARY_SUFFIX}")
   if(DEFINED CMAKE_IMPORT_LIBRARY_SUFFIX)
     if(NOT ("${CMAKE_IMPORT_LIBRARY_SUFFIX}" STREQUAL "${CMAKE_STATIC_LIBRARY_SUFFIX}"))
-      string(APPEND _MPI_LIB_NAME_REGEX "[^\" ]+${CMAKE_IMPORT_LIBRARY_SUFFIX}|\"[^\"]+${CMAKE_IMPORT_LIBRARY_SUFFIX}\"")
+      string(APPEND _MPI_SUFFIX_REGEX "|${CMAKE_IMPORT_LIBRARY_SUFFIX}")
     endif()
   else()
-    string(APPEND _MPI_LIB_NAME_REGEX "[^\" ]+${CMAKE_SHARED_LIBRARY_SUFFIX}|\"[^\"]+${CMAKE_SHARED_LIBRARY_SUFFIX}\"")
+    string(APPEND _MPI_LIB_SUFFIX_REGEX "|${CMAKE_SHARED_LIBRARY_SUFFIX}")
   endif()
+  set(_MPI_LIB_NAME_REGEX "(([^\" ]+(${_MPI_LIB_SUFFIX_REGEX}))|(\"[^\"]+(${_MPI_LIB_SUFFIX_REGEX})\"))( +|$)")
   string(REPLACE "." "\\." _MPI_LIB_NAME_REGEX "${_MPI_LIB_NAME_REGEX}")
 
-  string(REGEX MATCHALL "(^| )(${_MPI_LIB_NAME_REGEX})" MPI_LIBNAMES "${MPI_LINK_CMDLINE}")
+  string(REGEX MATCHALL "${_MPI_LIB_NAME_REGEX}" MPI_LIBNAMES "${MPI_LINK_CMDLINE}")
   foreach(_MPI_LIB_NAME IN LISTS MPI_LIBNAMES)
-    string(REGEX REPLACE "^ " "" _MPI_LIB_NAME "${_MPI_LIB_NAME}")
-    string(REPLACE "\"" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}")
+    string(REGEX REPLACE "^ +\"?|\"? +$" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}")
     get_filename_component(_MPI_LIB_PATH "${_MPI_LIB_NAME}" DIRECTORY)
     if(NOT "${_MPI_LIB_PATH}" STREQUAL "")
       list(APPEND MPI_LIB_FULLPATHS_WORK "${_MPI_LIB_NAME}")
diff --git a/Modules/FindOpenAL.cmake b/Modules/FindOpenAL.cmake
index c3d202e..7521d51 100644
--- a/Modules/FindOpenAL.cmake
+++ b/Modules/FindOpenAL.cmake
@@ -58,7 +58,7 @@
 find_path(OPENAL_INCLUDE_DIR al.h
   HINTS
     ENV OPENALDIR
-  PATH_SUFFIXES include/AL include/OpenAL include
+  PATH_SUFFIXES include/AL include/OpenAL include AL OpenAL
   PATHS
   ~/Library/Frameworks
   /Library/Frameworks
diff --git a/Modules/FindOpenMP.cmake b/Modules/FindOpenMP.cmake
index e252ba5..329ace1 100644
--- a/Modules/FindOpenMP.cmake
+++ b/Modules/FindOpenMP.cmake
@@ -242,19 +242,10 @@
         endforeach()
         set("${OPENMP_LIB_NAMES_VAR}" "${_OPENMP_LIB_NAMES}" PARENT_SCOPE)
       else()
-        # The Intel compiler on windows has no verbose mode, so we need to treat it explicitly
-        if("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "Intel" AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
-          set("${OPENMP_LIB_NAMES_VAR}" "libiomp5md" PARENT_SCOPE)
-          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()
-          set("${OPENMP_LIB_NAMES_VAR}" "" PARENT_SCOPE)
-        endif()
+        # We do not know how to extract implicit OpenMP libraries for this compiler.
+        # Assume that it handles them automatically, e.g. the Intel Compiler on
+        # Windows should put the dependency in its object files.
+        set("${OPENMP_LIB_NAMES_VAR}" "" PARENT_SCOPE)
       endif()
       break()
     elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "AppleClang"
diff --git a/Modules/FindOpenSSL.cmake b/Modules/FindOpenSSL.cmake
index c358ff1..d5cd8bc 100644
--- a/Modules/FindOpenSSL.cmake
+++ b/Modules/FindOpenSSL.cmake
@@ -7,6 +7,12 @@
 #
 # Find the OpenSSL encryption library.
 #
+# Optional COMPONENTS
+# ^^^^^^^^^^^^^^^^^^^
+#
+# This module supports two optional COMPONENTS: ``Crypto`` and ``SSL``.  Both
+# components have associated imported targets, as described below.
+#
 # Imported Targets
 # ^^^^^^^^^^^^^^^^
 #
@@ -23,7 +29,8 @@
 # This module will set the following variables in your project:
 #
 # ``OPENSSL_FOUND``
-#   System has the OpenSSL library.
+#   System has the OpenSSL library. If no components are requested it only
+#   requires the crypto library.
 # ``OPENSSL_INCLUDE_DIR``
 #   The OpenSSL include directory.
 # ``OPENSSL_CRYPTO_LIBRARY``
@@ -371,28 +378,47 @@
   endif ()
 endif ()
 
-include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
-
 set(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} )
 
-if (OPENSSL_VERSION)
-  find_package_handle_standard_args(OpenSSL
-    REQUIRED_VARS
-      #OPENSSL_SSL_LIBRARY # FIXME: require based on a component request?
-      OPENSSL_CRYPTO_LIBRARY
-      OPENSSL_INCLUDE_DIR
-    VERSION_VAR
-      OPENSSL_VERSION
-    FAIL_MESSAGE
-      "Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR"
-  )
-else ()
-  find_package_handle_standard_args(OpenSSL "Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR"
-    #OPENSSL_SSL_LIBRARY # FIXME: require based on a component request?
+foreach(_comp IN LISTS OpenSSL_FIND_COMPONENTS)
+  if(_comp STREQUAL "Crypto")
+    if(EXISTS "${OPENSSL_INCLUDE_DIR}" AND
+        (EXISTS "${OPENSSL_CRYPTO_LIBRARY}" OR
+        EXISTS "${LIB_EAY_LIBRARY_DEBUG}" OR
+        EXISTS "${LIB_EAY_LIBRARY_RELEASE}")
+    )
+      set(OpenSSL_${_comp}_FOUND TRUE)
+    else()
+      set(OpenSSL_${_comp}_FOUND FALSE)
+    endif()
+  elseif(_comp STREQUAL "SSL")
+    if(EXISTS "${OPENSSL_INCLUDE_DIR}" AND
+        (EXISTS "${OPENSSL_SSL_LIBRARY}" OR
+        EXISTS "${SSL_EAY_LIBRARY_DEBUG}" OR
+        EXISTS "${SSL_EAY_LIBRARY_RELEASE}")
+    )
+      set(OpenSSL_${_comp}_FOUND TRUE)
+    else()
+      set(OpenSSL_${_comp}_FOUND FALSE)
+    endif()
+  else()
+    message(WARNING "${_comp} is not a valid OpenSSL component")
+    set(OpenSSL_${_comp}_FOUND FALSE)
+  endif()
+endforeach()
+unset(_comp)
+
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+find_package_handle_standard_args(OpenSSL
+  REQUIRED_VARS
     OPENSSL_CRYPTO_LIBRARY
     OPENSSL_INCLUDE_DIR
-  )
-endif ()
+  VERSION_VAR
+    OPENSSL_VERSION
+  HANDLE_COMPONENTS
+  FAIL_MESSAGE
+    "Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR"
+)
 
 mark_as_advanced(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES)
 
@@ -425,6 +451,7 @@
         IMPORTED_LOCATION_DEBUG "${LIB_EAY_LIBRARY_DEBUG}")
     endif()
   endif()
+
   if(NOT TARGET OpenSSL::SSL AND
       (EXISTS "${OPENSSL_SSL_LIBRARY}" OR
         EXISTS "${SSL_EAY_LIBRARY_DEBUG}" OR
diff --git a/Modules/Platform/Android-Determine.cmake b/Modules/Platform/Android-Determine.cmake
index add1dc1..e623902 100644
--- a/Modules/Platform/Android-Determine.cmake
+++ b/Modules/Platform/Android-Determine.cmake
@@ -261,7 +261,40 @@
   else()
     # https://developer.android.com/ndk/guides/application_mk.html
     # Default is the oldest ARM ABI.
-    set(CMAKE_ANDROID_ARCH_ABI "armeabi")
+
+    # Lookup the available ABIs among all toolchains.
+    set(_ANDROID_ABIS "")
+    file(GLOB _ANDROID_CONFIG_MKS
+      "${CMAKE_ANDROID_NDK}/build/core/toolchains/*/config.mk"
+      "${CMAKE_ANDROID_NDK}/toolchains/*/config.mk"
+      )
+    foreach(config_mk IN LISTS _ANDROID_CONFIG_MKS)
+      file(STRINGS "${config_mk}" _ANDROID_TOOL_ABIS REGEX "^TOOLCHAIN_ABIS :=")
+      string(REPLACE "TOOLCHAIN_ABIS :=" "" _ANDROID_TOOL_ABIS "${_ANDROID_TOOL_ABIS}")
+      separate_arguments(_ANDROID_TOOL_ABIS UNIX_COMMAND "${_ANDROID_TOOL_ABIS}")
+      list(APPEND _ANDROID_ABIS ${_ANDROID_TOOL_ABIS})
+      unset(_ANDROID_TOOL_ABIS)
+    endforeach()
+    unset(_ANDROID_CONFIG_MKS)
+
+    # Choose the oldest among the available arm ABIs.
+    if(_ANDROID_ABIS)
+      list(REMOVE_DUPLICATES _ANDROID_ABIS)
+      cmake_policy(PUSH)
+      cmake_policy(SET CMP0057 NEW)
+      foreach(abi armeabi armeabi-v7a arm64-v8a)
+        if("${abi}" IN_LIST _ANDROID_ABIS)
+          set(CMAKE_ANDROID_ARCH_ABI "${abi}")
+          break()
+        endif()
+      endforeach()
+      cmake_policy(POP)
+    endif()
+    unset(_ANDROID_ABIS)
+
+    if(NOT CMAKE_ANDROID_ARCH_ABI)
+      set(CMAKE_ANDROID_ARCH_ABI "armeabi")
+    endif()
   endif()
 endif()
 set(CMAKE_ANDROID_ARCH "${_ANDROID_ABI_${CMAKE_ANDROID_ARCH_ABI}_ARCH}")
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index e23b070..a007098 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -557,6 +557,7 @@
   cmSiteNameCommand.h
   cmSourceGroupCommand.cxx
   cmSourceGroupCommand.h
+  cmStringReplaceHelper.cxx
   cmStringCommand.cxx
   cmStringCommand.h
   cmSubdirCommand.cxx
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 3d7c07a..f32f2ee 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 11)
-set(CMake_VERSION_PATCH 20180415)
+set(CMake_VERSION_PATCH 20180419)
 #set(CMake_VERSION_RC 1)
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index df671c2..4481bdc 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -841,6 +841,19 @@
   return buildFile;
 }
 
+void cmGlobalXCodeGenerator::AddXCodeProjBuildRule(
+  cmGeneratorTarget* target, std::vector<cmSourceFile*>& sources) const
+{
+  std::string listfile =
+    target->GetLocalGenerator()->GetCurrentSourceDirectory();
+  listfile += "/CMakeLists.txt";
+  cmSourceFile* srcCMakeLists = target->Makefile->GetOrCreateSource(listfile);
+  if (std::find(sources.begin(), sources.end(), srcCMakeLists) ==
+      sources.end()) {
+    sources.push_back(srcCMakeLists);
+  }
+}
+
 std::string GetSourcecodeValueFromFileExtension(const std::string& _ext,
                                                 const std::string& lang,
                                                 bool& keepLastKnownFileType)
@@ -1063,10 +1076,7 @@
     }
 
     // Add CMakeLists.txt file for user convenience.
-    std::string listfile =
-      gtgt->GetLocalGenerator()->GetCurrentSourceDirectory();
-    listfile += "/CMakeLists.txt";
-    classes.push_back(gtgt->Makefile->GetOrCreateSource(listfile));
+    this->AddXCodeProjBuildRule(gtgt, classes);
 
     std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare());
 
@@ -2359,10 +2369,7 @@
     }
 
     // Add CMakeLists.txt file for user convenience.
-    std::string listfile =
-      gtgt->GetLocalGenerator()->GetCurrentSourceDirectory();
-    listfile += "/CMakeLists.txt";
-    sources.push_back(gtgt->Makefile->GetOrCreateSource(listfile));
+    this->AddXCodeProjBuildRule(gtgt, sources);
 
     for (auto sourceFile : sources) {
       if (!sourceFile->GetPropertyAsBool("GENERATED")) {
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index b45887e..7c51177 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -198,6 +198,8 @@
                                           cmGeneratorTarget* target);
   cmXCodeObject* CreateXCodeSourceFile(cmLocalGenerator* gen, cmSourceFile* sf,
                                        cmGeneratorTarget* gtgt);
+  void AddXCodeProjBuildRule(cmGeneratorTarget* target,
+                             std::vector<cmSourceFile*>& sources) const;
   bool CreateXCodeTargets(cmLocalGenerator* gen, std::vector<cmXCodeObject*>&);
   bool IsHeaderFile(cmSourceFile*);
   void AddDependTarget(cmXCodeObject* target, cmXCodeObject* dependTarget);
diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx
index 821e6d1..31bc1c0 100644
--- a/Source/cmListCommand.cxx
+++ b/Source/cmListCommand.cxx
@@ -5,14 +5,19 @@
 #include "cmsys/RegularExpression.hxx"
 #include <algorithm>
 #include <assert.h>
+#include <functional>
 #include <iterator>
+#include <set>
 #include <sstream>
+#include <stdexcept>
 #include <stdio.h>
 #include <stdlib.h> // required for atoi
 
 #include "cmAlgorithms.h"
+#include "cmGeneratorExpression.h"
 #include "cmMakefile.h"
 #include "cmPolicies.h"
+#include "cmStringReplaceHelper.h"
 #include "cmSystemTools.h"
 #include "cmake.h"
 
@@ -54,6 +59,9 @@
   if (subCommand == "REMOVE_DUPLICATES") {
     return this->HandleRemoveDuplicatesCommand(args);
   }
+  if (subCommand == "TRANSFORM") {
+    return this->HandleTransformCommand(args);
+  }
   if (subCommand == "SORT") {
     return this->HandleSortCommand(args);
   }
@@ -407,6 +415,554 @@
   return true;
 }
 
+// Helpers for list(TRANSFORM <list> ...)
+namespace {
+using transform_type = std::function<std::string(const std::string&)>;
+
+class transform_error : public std::runtime_error
+{
+public:
+  transform_error(const std::string& error)
+    : std::runtime_error(error)
+  {
+  }
+};
+
+class TransformSelector
+{
+public:
+  virtual ~TransformSelector() {}
+
+  std::string Tag;
+
+  virtual bool Validate(std::size_t count = 0) = 0;
+
+  virtual bool InSelection(const std::string&) = 0;
+
+  virtual void Transform(std::vector<std::string>& list,
+                         const transform_type& transform)
+  {
+    std::transform(list.begin(), list.end(), list.begin(), transform);
+  }
+
+protected:
+  TransformSelector(std::string&& tag)
+    : Tag(std::move(tag))
+  {
+  }
+};
+class TransformNoSelector : public TransformSelector
+{
+public:
+  TransformNoSelector()
+    : TransformSelector("NO SELECTOR")
+  {
+  }
+
+  bool Validate(std::size_t) override { return true; }
+
+  bool InSelection(const std::string&) override { return true; }
+};
+class TransformSelectorRegex : public TransformSelector
+{
+public:
+  TransformSelectorRegex(const std::string& regex)
+    : TransformSelector("REGEX")
+    , Regex(regex)
+  {
+  }
+
+  bool Validate(std::size_t) override { return this->Regex.is_valid(); }
+
+  bool InSelection(const std::string& value) override
+  {
+    return this->Regex.find(value);
+  }
+
+  cmsys::RegularExpression Regex;
+};
+class TransformSelectorIndexes : public TransformSelector
+{
+public:
+  std::vector<int> Indexes;
+
+  bool InSelection(const std::string&) override { return true; }
+
+  void Transform(std::vector<std::string>& list,
+                 const transform_type& transform) override
+  {
+    this->Validate(list.size());
+
+    for (auto index : this->Indexes) {
+      list[index] = transform(list[index]);
+    }
+  }
+
+protected:
+  TransformSelectorIndexes(std::string&& tag)
+    : TransformSelector(std::move(tag))
+  {
+  }
+  TransformSelectorIndexes(std::string&& tag, std::vector<int>&& indexes)
+    : TransformSelector(std::move(tag))
+    , Indexes(indexes)
+  {
+  }
+
+  int NormalizeIndex(int index, std::size_t count)
+  {
+    if (index < 0) {
+      index = static_cast<int>(count) + index;
+    }
+    if (index < 0 || count <= static_cast<std::size_t>(index)) {
+      std::ostringstream str;
+      str << "sub-command TRANSFORM, selector " << this->Tag
+          << ", index: " << index << " out of range (-" << count << ", "
+          << count - 1 << ").";
+      throw transform_error(str.str());
+    }
+    return index;
+  }
+};
+class TransformSelectorAt : public TransformSelectorIndexes
+{
+public:
+  TransformSelectorAt(std::vector<int>&& indexes)
+    : TransformSelectorIndexes("AT", std::move(indexes))
+  {
+  }
+
+  bool Validate(std::size_t count) override
+  {
+    decltype(Indexes) indexes;
+
+    for (auto index : Indexes) {
+      indexes.push_back(this->NormalizeIndex(index, count));
+    }
+    this->Indexes = std::move(indexes);
+
+    return true;
+  }
+};
+class TransformSelectorFor : public TransformSelectorIndexes
+{
+public:
+  TransformSelectorFor(int start, int stop, int step)
+    : TransformSelectorIndexes("FOR")
+    , Start(start)
+    , Stop(stop)
+    , Step(step)
+  {
+  }
+
+  bool Validate(std::size_t count) override
+  {
+    this->Start = this->NormalizeIndex(this->Start, count);
+    this->Stop = this->NormalizeIndex(this->Stop, count);
+
+    // compute indexes
+    auto size = (this->Stop - this->Start + 1) / this->Step;
+    if ((this->Stop - this->Start + 1) % this->Step != 0) {
+      size += 1;
+    }
+
+    this->Indexes.resize(size);
+    auto start = this->Start, step = this->Step;
+    std::generate(this->Indexes.begin(), this->Indexes.end(),
+                  [&start, step]() -> int {
+                    auto r = start;
+                    start += step;
+                    return r;
+                  });
+
+    return true;
+  }
+
+private:
+  int Start, Stop, Step;
+};
+
+class TransformAction
+{
+public:
+  virtual ~TransformAction() {}
+
+  virtual std::string Transform(const std::string& input) = 0;
+};
+class TransformReplace : public TransformAction
+{
+public:
+  TransformReplace(const std::vector<std::string>& arguments,
+                   cmMakefile* makefile)
+    : ReplaceHelper(arguments[0], arguments[1], makefile)
+  {
+    makefile->ClearMatches();
+
+    if (!this->ReplaceHelper.IsRegularExpressionValid()) {
+      std::ostringstream error;
+      error
+        << "sub-command TRANSFORM, action REPLACE: Failed to compile regex \""
+        << arguments[0] << "\".";
+      throw transform_error(error.str());
+    }
+    if (!this->ReplaceHelper.IsReplaceExpressionValid()) {
+      std::ostringstream error;
+      error << "sub-command TRANSFORM, action REPLACE: "
+            << this->ReplaceHelper.GetError() << ".";
+      throw transform_error(error.str());
+    }
+  }
+
+  std::string Transform(const std::string& input) override
+  {
+    // Scan through the input for all matches.
+    std::string output;
+
+    if (!this->ReplaceHelper.Replace(input, output)) {
+      std::ostringstream error;
+      error << "sub-command TRANSFORM, action REPLACE: "
+            << this->ReplaceHelper.GetError() << ".";
+      throw transform_error(error.str());
+    }
+
+    return output;
+  }
+
+private:
+  cmStringReplaceHelper ReplaceHelper;
+};
+}
+
+bool cmListCommand::HandleTransformCommand(
+  std::vector<std::string> const& args)
+{
+  if (args.size() < 3) {
+    this->SetError(
+      "sub-command TRANSFORM requires an action to be specified.");
+    return false;
+  }
+
+  // Structure collecting all elements of the command
+  struct Command
+  {
+    Command(const std::string& listName)
+      : ListName(listName)
+      , OutputName(listName)
+    {
+    }
+
+    std::string Name;
+    std::string ListName;
+    std::vector<std::string> Arguments;
+    std::unique_ptr<TransformAction> Action;
+    std::unique_ptr<TransformSelector> Selector;
+    std::string OutputName;
+  } command(args[1]);
+
+  // Descriptor of action
+  // Arity: number of arguments required for the action
+  // Transform: lambda function implementing the action
+  struct ActionDescriptor
+  {
+    ActionDescriptor(const std::string& name)
+      : Name(name)
+    {
+    }
+    ActionDescriptor(const std::string& name, int arity,
+                     const transform_type& transform)
+      : Name(name)
+      , Arity(arity)
+      , Transform(transform)
+    {
+    }
+
+    operator const std::string&() const { return Name; }
+
+    std::string Name;
+    int Arity = 0;
+    transform_type Transform;
+  };
+
+  // Build a set of supported actions.
+  std::set<ActionDescriptor,
+           std::function<bool(const std::string&, const std::string&)>>
+  descriptors(
+    [](const std::string& x, const std::string& y) { return x < y; });
+  descriptors = { { "APPEND", 1,
+                    [&command](const std::string& s) -> std::string {
+                      if (command.Selector->InSelection(s)) {
+                        return s + command.Arguments[0];
+                      }
+
+                      return s;
+                    } },
+                  { "PREPEND", 1,
+                    [&command](const std::string& s) -> std::string {
+                      if (command.Selector->InSelection(s)) {
+                        return command.Arguments[0] + s;
+                      }
+
+                      return s;
+                    } },
+                  { "TOUPPER", 0,
+                    [&command](const std::string& s) -> std::string {
+                      if (command.Selector->InSelection(s)) {
+                        return cmSystemTools::UpperCase(s);
+                      }
+
+                      return s;
+                    } },
+                  { "TOLOWER", 0,
+                    [&command](const std::string& s) -> std::string {
+                      if (command.Selector->InSelection(s)) {
+                        return cmSystemTools::LowerCase(s);
+                      }
+
+                      return s;
+                    } },
+                  { "STRIP", 0,
+                    [&command](const std::string& s) -> std::string {
+                      if (command.Selector->InSelection(s)) {
+                        return cmSystemTools::TrimWhitespace(s);
+                      }
+
+                      return s;
+                    } },
+                  { "GENEX_STRIP", 0,
+                    [&command](const std::string& s) -> std::string {
+                      if (command.Selector->InSelection(s)) {
+                        return cmGeneratorExpression::Preprocess(
+                          s,
+                          cmGeneratorExpression::StripAllGeneratorExpressions);
+                      }
+
+                      return s;
+                    } },
+                  { "REPLACE", 2,
+                    [&command](const std::string& s) -> std::string {
+                      if (command.Selector->InSelection(s)) {
+                        return command.Action->Transform(s);
+                      }
+
+                      return s;
+                    } } };
+
+  using size_type = std::vector<std::string>::size_type;
+  size_type index = 2;
+
+  // Parse all possible function parameters
+  auto descriptor = descriptors.find(args[index]);
+
+  if (descriptor == descriptors.end()) {
+    std::ostringstream error;
+    error << " sub-command TRANSFORM, " << args[index] << " invalid action.";
+    this->SetError(error.str());
+    return false;
+  }
+
+  // Action arguments
+  index += 1;
+  if (args.size() < index + descriptor->Arity) {
+    std::ostringstream error;
+    error << "sub-command TRANSFORM, action " << descriptor->Name
+          << " expects " << descriptor->Arity << " argument(s).";
+    this->SetError(error.str());
+    return false;
+  }
+
+  command.Name = descriptor->Name;
+  index += descriptor->Arity;
+  if (descriptor->Arity > 0) {
+    command.Arguments =
+      std::vector<std::string>(args.begin() + 3, args.begin() + index);
+  }
+
+  if (command.Name == "REPLACE") {
+    try {
+      command.Action =
+        cm::make_unique<TransformReplace>(command.Arguments, this->Makefile);
+    } catch (const transform_error& e) {
+      this->SetError(e.what());
+      return false;
+    }
+  }
+
+  const std::string REGEX{ "REGEX" }, AT{ "AT" }, FOR{ "FOR" },
+    OUTPUT_VARIABLE{ "OUTPUT_VARIABLE" };
+
+  // handle optional arguments
+  while (args.size() > index) {
+    if ((args[index] == REGEX || args[index] == AT || args[index] == FOR) &&
+        command.Selector) {
+      std::ostringstream error;
+      error << "sub-command TRANSFORM, selector already specified ("
+            << command.Selector->Tag << ").";
+      this->SetError(error.str());
+      return false;
+    }
+
+    // REGEX selector
+    if (args[index] == REGEX) {
+      if (args.size() == ++index) {
+        this->SetError("sub-command TRANSFORM, selector REGEX expects "
+                       "'regular expression' argument.");
+        return false;
+      }
+
+      command.Selector = cm::make_unique<TransformSelectorRegex>(args[index]);
+      if (!command.Selector->Validate()) {
+        std::ostringstream error;
+        error << "sub-command TRANSFORM, selector REGEX failed to compile "
+                 "regex \"";
+        error << args[index] << "\".";
+        this->SetError(error.str());
+        return false;
+      }
+
+      index += 1;
+      continue;
+    }
+
+    // AT selector
+    if (args[index] == AT) {
+      // get all specified indexes
+      std::vector<int> indexes;
+      while (args.size() > ++index) {
+        std::size_t pos;
+        int value;
+
+        try {
+          value = std::stoi(args[index], &pos);
+          if (pos != args[index].length()) {
+            // this is not a number, stop processing
+            break;
+          }
+          indexes.push_back(value);
+        } catch (const std::invalid_argument&) {
+          // this is not a number, stop processing
+          break;
+        }
+      }
+
+      if (indexes.empty()) {
+        this->SetError(
+          "sub-command TRANSFORM, selector AT expects at least one "
+          "numeric value.");
+        return false;
+      }
+
+      command.Selector =
+        cm::make_unique<TransformSelectorAt>(std::move(indexes));
+
+      continue;
+    }
+
+    // FOR selector
+    if (args[index] == FOR) {
+      if (args.size() <= ++index + 1) {
+        this->SetError("sub-command TRANSFORM, selector FOR expects, at least,"
+                       " two arguments.");
+        return false;
+      }
+
+      int start = 0, stop = 0, step = 1;
+      bool valid = true;
+      try {
+        std::size_t pos;
+
+        start = std::stoi(args[index], &pos);
+        if (pos != args[index].length()) {
+          // this is not a number
+          valid = false;
+        } else {
+          stop = std::stoi(args[++index], &pos);
+          if (pos != args[index].length()) {
+            // this is not a number
+            valid = false;
+          }
+        }
+      } catch (const std::invalid_argument&) {
+        // this is not numbers
+        valid = false;
+      }
+      if (!valid) {
+        this->SetError("sub-command TRANSFORM, selector FOR expects, "
+                       "at least, two numeric values.");
+        return false;
+      }
+      // try to read a third numeric value for step
+      if (args.size() > ++index) {
+        try {
+          std::size_t pos;
+
+          step = std::stoi(args[index], &pos);
+          if (pos != args[index].length()) {
+            // this is not a number
+            step = 1;
+          } else {
+            index += 1;
+          }
+        } catch (const std::invalid_argument&) {
+          // this is not number, ignore exception
+        }
+      }
+
+      if (step < 0) {
+        this->SetError("sub-command TRANSFORM, selector FOR expects "
+                       "non negative numeric value for <step>.");
+      }
+
+      command.Selector =
+        cm::make_unique<TransformSelectorFor>(start, stop, step);
+
+      continue;
+    }
+
+    // output variable
+    if (args[index] == OUTPUT_VARIABLE) {
+      if (args.size() == ++index) {
+        this->SetError("sub-command TRANSFORM, OUTPUT_VARIABLE "
+                       "expects variable name argument.");
+        return false;
+      }
+
+      command.OutputName = args[index++];
+      continue;
+    }
+
+    std::ostringstream error;
+    error << "sub-command TRANSFORM, '"
+          << cmJoin(cmMakeRange(args).advance(index), " ")
+          << "': unexpected argument(s).";
+    this->SetError(error.str());
+    return false;
+  }
+
+  // expand the list variable
+  std::vector<std::string> varArgsExpanded;
+  if (!this->GetList(varArgsExpanded, command.ListName)) {
+    this->Makefile->AddDefinition(command.OutputName, "");
+    return true;
+  }
+
+  if (!command.Selector) {
+    // no selector specified, apply transformation to all elements
+    command.Selector = cm::make_unique<TransformNoSelector>();
+  }
+
+  try {
+    command.Selector->Transform(varArgsExpanded, descriptor->Transform);
+  } catch (const transform_error& e) {
+    this->SetError(e.what());
+    return false;
+  }
+
+  this->Makefile->AddDefinition(command.OutputName,
+                                cmJoin(varArgsExpanded, ";").c_str());
+
+  return true;
+}
+
 bool cmListCommand::HandleSortCommand(std::vector<std::string> const& args)
 {
   assert(args.size() >= 2);
diff --git a/Source/cmListCommand.h b/Source/cmListCommand.h
index d69d8f9..76a9856 100644
--- a/Source/cmListCommand.h
+++ b/Source/cmListCommand.h
@@ -41,6 +41,7 @@
   bool HandleRemoveAtCommand(std::vector<std::string> const& args);
   bool HandleRemoveItemCommand(std::vector<std::string> const& args);
   bool HandleRemoveDuplicatesCommand(std::vector<std::string> const& args);
+  bool HandleTransformCommand(std::vector<std::string> const& args);
   bool HandleSortCommand(std::vector<std::string> const& args);
   bool HandleSublistCommand(std::vector<std::string> const& args);
   bool HandleReverseCommand(std::vector<std::string> const& args);
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index acb5921..fcdcdc5 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -1364,7 +1364,18 @@
       for (size_t ci = 0; ci < configs.size(); ++ci) {
         acs.Configs.push_back(ci);
       }
-      sources.Sources.emplace_back(std::move(acs));
+      bool haveCMakeLists = false;
+      for (cmGeneratorTarget::AllConfigSource& si : sources.Sources) {
+        if (si.Source == sf) {
+          haveCMakeLists = true;
+          // Replace the explicit source reference with our generated one.
+          si = acs;
+          break;
+        }
+      }
+      if (!haveCMakeLists) {
+        sources.Sources.emplace_back(std::move(acs));
+      }
     }
   }
 
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index 9631912..dabec47 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -13,6 +13,7 @@
 #include "cmCryptoHash.h"
 #include "cmGeneratorExpression.h"
 #include "cmMakefile.h"
+#include "cmStringReplaceHelper.h"
 #include "cmSystemTools.h"
 #include "cmTimestamp.h"
 #include "cmUuid.h"
@@ -344,46 +345,17 @@
   std::string const& regex = args[2];
   std::string const& replace = args[3];
   std::string const& outvar = args[4];
+  cmStringReplaceHelper replaceHelper(regex, replace, this->Makefile);
 
-  // Pull apart the replace expression to find the escaped [0-9] values.
-  std::vector<RegexReplacement> replacement;
-  std::string::size_type l = 0;
-  while (l < replace.length()) {
-    std::string::size_type r = replace.find('\\', l);
-    if (r == std::string::npos) {
-      r = replace.length();
-      replacement.push_back(replace.substr(l, r - l));
-    } else {
-      if (r - l > 0) {
-        replacement.push_back(replace.substr(l, r - l));
-      }
-      if (r == (replace.length() - 1)) {
-        this->SetError("sub-command REGEX, mode REPLACE: "
-                       "replace-expression ends in a backslash.");
-        return false;
-      }
-      if ((replace[r + 1] >= '0') && (replace[r + 1] <= '9')) {
-        replacement.push_back(replace[r + 1] - '0');
-      } else if (replace[r + 1] == 'n') {
-        replacement.push_back("\n");
-      } else if (replace[r + 1] == '\\') {
-        replacement.push_back("\\");
-      } else {
-        std::string e = "sub-command REGEX, mode REPLACE: Unknown escape \"";
-        e += replace.substr(r, 2);
-        e += "\" in replace-expression.";
-        this->SetError(e);
-        return false;
-      }
-      r += 2;
-    }
-    l = r;
+  if (!replaceHelper.IsReplaceExpressionValid()) {
+    this->SetError("sub-command REGEX, mode REPLACE: " +
+                   replaceHelper.GetError() + ".");
+    return false;
   }
 
   this->Makefile->ClearMatches();
-  // Compile the regular expression.
-  cmsys::RegularExpression re;
-  if (!re.compile(regex.c_str())) {
+
+  if (!replaceHelper.IsRegularExpressionValid()) {
     std::string e =
       "sub-command REGEX, mode REPLACE failed to compile regex \"" + regex +
       "\".";
@@ -392,60 +364,16 @@
   }
 
   // Concatenate all the last arguments together.
-  std::string input = cmJoin(cmMakeRange(args).advance(5), std::string());
-
-  // Scan through the input for all matches.
+  const std::string input =
+    cmJoin(cmMakeRange(args).advance(5), std::string());
   std::string output;
-  std::string::size_type base = 0;
-  while (re.find(input.c_str() + base)) {
-    this->Makefile->ClearMatches();
-    this->Makefile->StoreMatches(re);
-    std::string::size_type l2 = re.start();
-    std::string::size_type r = re.end();
 
-    // Concatenate the part of the input that was not matched.
-    output += input.substr(base, l2);
-
-    // Make sure the match had some text.
-    if (r - l2 == 0) {
-      std::string e = "sub-command REGEX, mode REPLACE regex \"" + regex +
-        "\" matched an empty string.";
-      this->SetError(e);
-      return false;
-    }
-
-    // Concatenate the replacement for the match.
-    for (RegexReplacement const& i : replacement) {
-      if (i.number < 0) {
-        // This is just a plain-text part of the replacement.
-        output += i.value;
-      } else {
-        // Replace with part of the match.
-        int n = i.number;
-        std::string::size_type start = re.start(n);
-        std::string::size_type end = re.end(n);
-        std::string::size_type len = input.length() - base;
-        if ((start != std::string::npos) && (end != std::string::npos) &&
-            (start <= len) && (end <= len)) {
-          output += input.substr(base + start, end - start);
-        } else {
-          std::string e =
-            "sub-command REGEX, mode REPLACE: replace expression \"" +
-            replace + "\" contains an out-of-range escape for regex \"" +
-            regex + "\".";
-          this->SetError(e);
-          return false;
-        }
-      }
-    }
-
-    // Move past the match.
-    base += r;
+  if (!replaceHelper.Replace(input, output)) {
+    this->SetError("sub-command REGEX, mode REPLACE: " +
+                   replaceHelper.GetError() + ".");
+    return false;
   }
 
-  // Concatenate the text after the last match.
-  output += input.substr(base, input.length() - base);
-
   // Store the output in the provided variable.
   this->Makefile->AddDefinition(outvar, output.c_str());
   return true;
diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h
index 569ed83..cbff73e 100644
--- a/Source/cmStringCommand.h
+++ b/Source/cmStringCommand.h
@@ -60,29 +60,6 @@
 
   bool joinImpl(std::vector<std::string> const& args, std::string const& glue,
                 size_t varIdx);
-
-  class RegexReplacement
-  {
-  public:
-    RegexReplacement(const char* s)
-      : number(-1)
-      , value(s)
-    {
-    }
-    RegexReplacement(const std::string& s)
-      : number(-1)
-      , value(s)
-    {
-    }
-    RegexReplacement(int n)
-      : number(n)
-      , value()
-    {
-    }
-    RegexReplacement() {}
-    int number;
-    std::string value;
-  };
 };
 
 #endif
diff --git a/Source/cmStringReplaceHelper.cxx b/Source/cmStringReplaceHelper.cxx
new file mode 100644
index 0000000..69b7ced
--- /dev/null
+++ b/Source/cmStringReplaceHelper.cxx
@@ -0,0 +1,117 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+
+#include "cmStringReplaceHelper.h"
+
+#include "cmMakefile.h"
+#include <sstream>
+
+cmStringReplaceHelper::cmStringReplaceHelper(const std::string& regex,
+                                             const std::string& replace_expr,
+                                             cmMakefile* makefile)
+  : RegExString(regex)
+  , RegularExpression(regex)
+  , ReplaceExpression(replace_expr)
+  , Makefile(makefile)
+{
+  this->ParseReplaceExpression();
+}
+
+bool cmStringReplaceHelper::Replace(const std::string& input,
+                                    std::string& output)
+{
+  output.clear();
+
+  // Scan through the input for all matches.
+  std::string::size_type base = 0;
+  while (this->RegularExpression.find(input.c_str() + base)) {
+    if (this->Makefile != nullptr) {
+      this->Makefile->ClearMatches();
+      this->Makefile->StoreMatches(this->RegularExpression);
+    }
+    auto l2 = this->RegularExpression.start();
+    auto r = this->RegularExpression.end();
+
+    // Concatenate the part of the input that was not matched.
+    output += input.substr(base, l2);
+
+    // Make sure the match had some text.
+    if (r - l2 == 0) {
+      std::ostringstream error;
+      error << "regex \"" << this->RegExString << "\" matched an empty string";
+      this->ErrorString = error.str();
+      return false;
+    }
+
+    // Concatenate the replacement for the match.
+    for (const auto& replacement : this->Replacements) {
+      if (replacement.Number < 0) {
+        // This is just a plain-text part of the replacement.
+        output += replacement.Value;
+      } else {
+        // Replace with part of the match.
+        auto n = replacement.Number;
+        auto start = this->RegularExpression.start(n);
+        auto end = this->RegularExpression.end(n);
+        auto len = input.length() - base;
+        if ((start != std::string::npos) && (end != std::string::npos) &&
+            (start <= len) && (end <= len)) {
+          output += input.substr(base + start, end - start);
+        } else {
+          std::ostringstream error;
+          error << "replace expression \"" << this->ReplaceExpression
+                << "\" contains an out-of-range escape for regex \""
+                << this->RegExString << "\"";
+          this->ErrorString = error.str();
+          return false;
+        }
+      }
+    }
+
+    // Move past the match.
+    base += r;
+  }
+
+  // Concatenate the text after the last match.
+  output += input.substr(base, input.length() - base);
+
+  return true;
+}
+
+void cmStringReplaceHelper::ParseReplaceExpression()
+{
+  std::string::size_type l = 0;
+  while (l < this->ReplaceExpression.length()) {
+    auto r = this->ReplaceExpression.find('\\', l);
+    if (r == std::string::npos) {
+      r = this->ReplaceExpression.length();
+      this->Replacements.push_back(this->ReplaceExpression.substr(l, r - l));
+    } else {
+      if (r - l > 0) {
+        this->Replacements.push_back(this->ReplaceExpression.substr(l, r - l));
+      }
+      if (r == (this->ReplaceExpression.length() - 1)) {
+        this->ValidReplaceExpression = false;
+        this->ErrorString = "replace-expression ends in a backslash";
+        return;
+      }
+      if ((this->ReplaceExpression[r + 1] >= '0') &&
+          (this->ReplaceExpression[r + 1] <= '9')) {
+        this->Replacements.push_back(this->ReplaceExpression[r + 1] - '0');
+      } else if (this->ReplaceExpression[r + 1] == 'n') {
+        this->Replacements.push_back("\n");
+      } else if (this->ReplaceExpression[r + 1] == '\\') {
+        this->Replacements.push_back("\\");
+      } else {
+        this->ValidReplaceExpression = false;
+        std::ostringstream error;
+        error << "Unknown escape \"" << this->ReplaceExpression.substr(r, 2)
+              << "\" in replace-expression";
+        this->ErrorString = error.str();
+        return;
+      }
+      r += 2;
+    }
+    l = r;
+  }
+}
diff --git a/Source/cmStringReplaceHelper.h b/Source/cmStringReplaceHelper.h
new file mode 100644
index 0000000..938325a
--- /dev/null
+++ b/Source/cmStringReplaceHelper.h
@@ -0,0 +1,69 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmStringReplaceHelper_h
+#define cmStringReplaceHelper_h
+
+#include "cmsys/RegularExpression.hxx"
+
+#include <string>
+#include <vector>
+
+class cmMakefile;
+
+class cmStringReplaceHelper
+{
+public:
+  cmStringReplaceHelper(const std::string& regex,
+                        const std::string& replace_expr,
+                        cmMakefile* makefile = nullptr);
+
+  bool IsRegularExpressionValid() const
+  {
+    return this->RegularExpression.is_valid();
+  }
+  bool IsReplaceExpressionValid() const
+  {
+    return this->ValidReplaceExpression;
+  }
+
+  bool Replace(const std::string& input, std::string& output);
+
+  const std::string& GetError() { return this->ErrorString; }
+
+private:
+  class RegexReplacement
+  {
+  public:
+    RegexReplacement(const char* s)
+      : Number(-1)
+      , Value(s)
+    {
+    }
+    RegexReplacement(const std::string& s)
+      : Number(-1)
+      , Value(s)
+    {
+    }
+    RegexReplacement(int n)
+      : Number(n)
+      , Value()
+    {
+    }
+    RegexReplacement() {}
+
+    int Number;
+    std::string Value;
+  };
+
+  void ParseReplaceExpression();
+
+  std::string ErrorString;
+  std::string RegExString;
+  cmsys::RegularExpression RegularExpression;
+  bool ValidReplaceExpression = true;
+  std::string ReplaceExpression;
+  std::vector<RegexReplacement> Replacements;
+  cmMakefile* Makefile = nullptr;
+};
+
+#endif
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 13af167..19cb50b 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -1894,7 +1894,14 @@
   std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
     this->GeneratorTarget->GetAllConfigSources();
 
+  cmSourceFile const* srcCMakeLists =
+    this->LocalGenerator->CreateVCProjBuildRule();
+
   for (cmGeneratorTarget::AllConfigSource const& si : sources) {
+    if (si.Source == srcCMakeLists) {
+      // Skip explicit reference to CMakeLists.txt source.
+      continue;
+    }
     const char* tool = nullptr;
     switch (si.Kind) {
       case cmGeneratorTarget::SourceKindAppManifest:
@@ -2690,6 +2697,20 @@
     cudaOptions.AppendFlagString("AdditionalOptions", "-x cu");
   }
 
+  // Specify the compiler program database file if configured.
+  std::string pdb = this->GeneratorTarget->GetCompilePDBPath(configName);
+  if (!pdb.empty()) {
+    // CUDA does not have a field for this and does not honor the
+    // ProgramDataBaseFileName field in ClCompile.  Work around this
+    // limitation by creating the directory and passing the flag ourselves.
+    std::string const pdbDir = cmSystemTools::GetFilenamePath(pdb);
+    cmSystemTools::MakeDirectory(pdbDir);
+    pdb = this->ConvertPath(pdb, true);
+    ConvertToWindowsSlash(pdb);
+    std::string const clFd = "-Xcompiler=\"-Fd\\\"" + pdb + "\\\"\"";
+    cudaOptions.AppendFlagString("AdditionalOptions", clFd);
+  }
+
   // CUDA automatically passes the proper '--machine' flag to nvcc
   // for the current architecture, but does not reflect this default
   // in the user-visible IDE settings.  Set it explicitly.
@@ -3646,10 +3667,8 @@
                     "{" + this->GlobalGenerator->GetGUID(name) + "}", 3);
     this->WriteElem("Name", name, 3);
     this->WriteDotNetReferenceCustomTags(name);
-    if (csproj == this->ProjectType) {
-      if (!this->GlobalGenerator->TargetCanBeReferenced(dt)) {
-        this->WriteElem("ReferenceOutputAssembly", "false", 3);
-      }
+    if (!this->GlobalGenerator->TargetCanBeReferenced(dt)) {
+      this->WriteElem("ReferenceOutputAssembly", "false", 3);
     }
     this->WriteString("</ProjectReference>\n", 2);
   }
diff --git a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in
index 65487bb..9157c76 100644
--- a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in
+++ b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in
@@ -349,6 +349,12 @@
 set(aix_xlf90_64_dirs "/usr/lpp/xlf/lib")
 list(APPEND platforms aix_xlf90_64)
 
+# g++ dummy.c -v
+set(aix_g++_text " /prefix/libexec/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/collect2 -bpT:0x10000000 -bpD:0x20000000 -btextro /lib/crt0.o /prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/crtcxa.o /prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/crtdbase.o -L/prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0 -L/prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/../../.. /tmp//ccKROJ1f.o -lstdc++ -lm -lgcc_s /prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/libgcc.a -lc -lgcc_s /prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/libgcc.a")
+set(aix_g++_libs "stdc++;m;gcc_s;/prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/libgcc.a;c;gcc_s;/prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/libgcc.a")
+set(aix_g++_dirs "/prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0;/prefix/lib")
+list(APPEND platforms aix_g++)
+
 #-----------------------------------------------------------------------------
 # HP
 
diff --git a/Tests/CudaOnly/CMakeLists.txt b/Tests/CudaOnly/CMakeLists.txt
index 565baca..59f3e84 100644
--- a/Tests/CudaOnly/CMakeLists.txt
+++ b/Tests/CudaOnly/CMakeLists.txt
@@ -6,3 +6,7 @@
 ADD_TEST_MACRO(CudaOnly.ResolveDeviceSymbols CudaOnlyResolveDeviceSymbols)
 ADD_TEST_MACRO(CudaOnly.SeparateCompilation CudaOnlySeparateCompilation)
 ADD_TEST_MACRO(CudaOnly.WithDefs CudaOnlyWithDefs)
+
+if(MSVC)
+  ADD_TEST_MACRO(CudaOnly.PDB CudaOnlyPDB)
+endif()
diff --git a/Tests/CudaOnly/PDB/CMakeLists.txt b/Tests/CudaOnly/PDB/CMakeLists.txt
new file mode 100644
index 0000000..34e1e5c
--- /dev/null
+++ b/Tests/CudaOnly/PDB/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 3.11)
+project (CudaOnlyPDB CUDA)
+
+add_executable(CudaOnlyPDB main.cu)
+set_target_properties(CudaOnlyPDB PROPERTIES
+  PDB_NAME LinkPDBName
+  PDB_OUTPUT_DIRECTORY LinkPDBDir
+  COMPILE_PDB_NAME CompPDBName
+  COMPILE_PDB_OUTPUT_DIRECTORY CompPDBDir
+  )
+
+set(pdbs
+  ${CMAKE_CURRENT_BINARY_DIR}/CompPDBDir/${CMAKE_CFG_INTDIR}/CompPDBName.pdb
+  ${CMAKE_CURRENT_BINARY_DIR}/LinkPDBDir/${CMAKE_CFG_INTDIR}/LinkPDBName.pdb
+  )
+add_custom_command(TARGET CudaOnlyPDB POST_BUILD
+  COMMAND ${CMAKE_COMMAND} -Dconfig=$<CONFIG> "-Dpdbs=${pdbs}"
+                           -P ${CMAKE_CURRENT_SOURCE_DIR}/check_pdbs.cmake
+  )
diff --git a/Tests/CudaOnly/PDB/check_pdbs.cmake b/Tests/CudaOnly/PDB/check_pdbs.cmake
new file mode 100644
index 0000000..5e01ca7
--- /dev/null
+++ b/Tests/CudaOnly/PDB/check_pdbs.cmake
@@ -0,0 +1,10 @@
+if(NOT "${config}" MATCHES "[Dd][Ee][Bb]")
+  return()
+endif()
+foreach(pdb ${pdbs})
+  if(EXISTS "${pdb}")
+    message(STATUS "PDB Exists: ${pdb}")
+  else()
+    message(SEND_ERROR "PDB MISSING:\n ${pdb}")
+  endif()
+endforeach()
diff --git a/Tests/CudaOnly/PDB/main.cu b/Tests/CudaOnly/PDB/main.cu
new file mode 100644
index 0000000..f8b643a
--- /dev/null
+++ b/Tests/CudaOnly/PDB/main.cu
@@ -0,0 +1,4 @@
+int main()
+{
+  return 0;
+}
diff --git a/Tests/Module/ExternalData/Data5/CMakeLists.txt b/Tests/Module/ExternalData/Data5/CMakeLists.txt
index 13c7fab..ea67f05 100644
--- a/Tests/Module/ExternalData/Data5/CMakeLists.txt
+++ b/Tests/Module/ExternalData/Data5/CMakeLists.txt
@@ -2,21 +2,21 @@
 ExternalData_Add_Test(Data5.A
   NAME Data5Check.A
   COMMAND ${CMAKE_COMMAND}
-    -D Data5=DATA{../Data.dat}
+    -D Data5=DATA{Data5.dat}
     -P ${CMAKE_CURRENT_SOURCE_DIR}/Data5Check.cmake
   )
 ExternalData_Add_Target(Data5.A)
 ExternalData_Add_Test(Data5.B
   NAME Data5Check.B
   COMMAND ${CMAKE_COMMAND}
-    -D Data5=DATA{../Data.dat}
+    -D Data5=DATA{Data5.dat}
     -P ${CMAKE_CURRENT_SOURCE_DIR}/Data5Check.cmake
   )
 ExternalData_Add_Target(Data5.B)
 ExternalData_Add_Test(Data5.C
   NAME Data5Check.C
   COMMAND ${CMAKE_COMMAND}
-    -D Data5=DATA{../Data.dat}
+    -D Data5=DATA{Data5.dat}
     -P ${CMAKE_CURRENT_SOURCE_DIR}/Data5Check.cmake
   )
 ExternalData_Add_Target(Data5.C)
diff --git a/Tests/Module/ExternalData/Data5/Data5.dat.md5 b/Tests/Module/ExternalData/Data5/Data5.dat.md5
new file mode 100644
index 0000000..70e39bd
--- /dev/null
+++ b/Tests/Module/ExternalData/Data5/Data5.dat.md5
@@ -0,0 +1 @@
+8c018830e3efa5caf3c7415028335a57
diff --git a/Tests/RunCMake/Android/RunCMakeTest.cmake b/Tests/RunCMake/Android/RunCMakeTest.cmake
index 86a9896..2027c4f 100644
--- a/Tests/RunCMake/Android/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Android/RunCMakeTest.cmake
@@ -88,12 +88,14 @@
     -DCMAKE_ANDROID_ARM_MODE=0
     )
   run_cmake(ndk-badarm)
-  set(RunCMake_TEST_OPTIONS
-    -DCMAKE_SYSTEM_NAME=Android
-    -DCMAKE_ANDROID_NDK=${ndk}
-    -DCMAKE_ANDROID_ARM_NEON=0
-    )
-  run_cmake(ndk-badneon)
+  if("armeabi" IN_LIST _abis_)
+    set(RunCMake_TEST_OPTIONS
+      -DCMAKE_SYSTEM_NAME=Android
+      -DCMAKE_ANDROID_NDK=${ndk}
+      -DCMAKE_ANDROID_ARM_NEON=0
+      )
+    run_cmake(ndk-badneon)
+  endif()
   set(RunCMake_TEST_OPTIONS
     -DCMAKE_SYSTEM_NAME=Android
     -DCMAKE_ANDROID_NDK=${ndk}
diff --git a/Tests/RunCMake/Android/ndk-badvernum-stderr.txt b/Tests/RunCMake/Android/ndk-badvernum-stderr.txt
index 25bbaf9..adacaf1 100644
--- a/Tests/RunCMake/Android/ndk-badvernum-stderr.txt
+++ b/Tests/RunCMake/Android/ndk-badvernum-stderr.txt
@@ -1,5 +1,5 @@
 ^CMake Error at .*/Modules/Platform/Android/Determine-Compiler-NDK.cmake:[0-9]+ \(message\):
-  Android: No toolchain for ABI 'armeabi' found in the NDK:
+  Android: No toolchain for ABI 'armeabi(-v7a)?' found in the NDK:
 
     .*
 
diff --git a/Tests/RunCMake/VS10Project/ExplicitCMakeLists-check.cmake b/Tests/RunCMake/VS10Project/ExplicitCMakeLists-check.cmake
new file mode 100644
index 0000000..b671e35
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/ExplicitCMakeLists-check.cmake
@@ -0,0 +1,25 @@
+set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.vcxproj")
+if(NOT EXISTS "${vcProjectFile}")
+  set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.")
+  return()
+endif()
+
+set(foundCMakeLists 0)
+file(STRINGS "${vcProjectFile}" lines)
+foreach(line IN LISTS lines)
+  if(line MATCHES "<([A-Za-z0-9_]+) +Include=.*CMakeLists.txt")
+    set(rule "${CMAKE_MATCH_1}")
+    if(NOT rule STREQUAL "CustomBuild")
+      set(RunCMake_TEST_FAILED "CMakeLists.txt referenced as ${rule} instead of CustomBuild")
+      return()
+    endif()
+    if(foundCMakeLists)
+      set(RunCMake_TEST_FAILED "CMakeLists.txt referenced multiple times")
+      return()
+    endif()
+    set(foundCMakeLists 1)
+  endif()
+endforeach()
+if(NOT foundCMakeLists)
+  set(RunCMake_TEST_FAILED "CMakeLists.txt not referenced")
+endif()
diff --git a/Tests/RunCMake/VS10Project/ExplicitCMakeLists.cmake b/Tests/RunCMake/VS10Project/ExplicitCMakeLists.cmake
new file mode 100644
index 0000000..c9e4456
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/ExplicitCMakeLists.cmake
@@ -0,0 +1,3 @@
+set(CMAKE_CONFIGURATION_TYPES Debug)
+enable_language(CXX)
+add_executable(foo foo.cpp ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt)
diff --git a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
index afe9d6d..e42e662 100644
--- a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
+++ b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
@@ -1,4 +1,7 @@
 include(RunCMake)
+
+run_cmake(ExplicitCMakeLists)
+
 run_cmake(VsConfigurationType)
 run_cmake(VsTargetsFileReferences)
 run_cmake(VsCustomProps)
diff --git a/Tests/RunCMake/XcodeProject/ExplicitCMakeLists-check.cmake b/Tests/RunCMake/XcodeProject/ExplicitCMakeLists-check.cmake
new file mode 100644
index 0000000..3073e0b
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/ExplicitCMakeLists-check.cmake
@@ -0,0 +1,20 @@
+set(xcProjectFile "${RunCMake_TEST_BINARY_DIR}/ExplicitCMakeLists.xcodeproj/project.pbxproj")
+if(NOT EXISTS "${xcProjectFile}")
+  set(RunCMake_TEST_FAILED "Project file ${xcProjectFile} does not exist.")
+  return()
+endif()
+
+set(foundCMakeLists 0)
+file(STRINGS "${xcProjectFile}" lines)
+foreach(line IN LISTS lines)
+  if(line MATCHES "PBXBuildFile.*fileRef.*CMakeLists.txt")
+    if(foundCMakeLists)
+      set(RunCMake_TEST_FAILED "CMakeLists.txt referenced multiple times")
+      return()
+    endif()
+    set(foundCMakeLists 1)
+  endif()
+endforeach()
+if(NOT foundCMakeLists)
+  set(RunCMake_TEST_FAILED "CMakeLists.txt not referenced")
+endif()
diff --git a/Tests/RunCMake/XcodeProject/ExplicitCMakeLists.cmake b/Tests/RunCMake/XcodeProject/ExplicitCMakeLists.cmake
new file mode 100644
index 0000000..678b0ea
--- /dev/null
+++ b/Tests/RunCMake/XcodeProject/ExplicitCMakeLists.cmake
@@ -0,0 +1,2 @@
+enable_language(CXX)
+add_executable(foo foo.cpp ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt)
diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake
index 5eff6b9..1150666 100644
--- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake
+++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake
@@ -4,6 +4,8 @@
   set(IOS_DEPLOYMENT_TARGET "-DCMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET=10")
 endif()
 
+run_cmake(ExplicitCMakeLists)
+
 run_cmake(XcodeFileType)
 run_cmake(XcodeAttributeLocation)
 run_cmake(XcodeAttributeGenex)
diff --git a/Tests/RunCMake/list/RunCMakeTest.cmake b/Tests/RunCMake/list/RunCMakeTest.cmake
index 3913783..bdc23a4 100644
--- a/Tests/RunCMake/list/RunCMakeTest.cmake
+++ b/Tests/RunCMake/list/RunCMakeTest.cmake
@@ -43,3 +43,44 @@
 run_cmake(SUBLIST-NoVariable)
 run_cmake(SUBLIST-InvalidLength)
 run_cmake(SUBLIST)
+
+run_cmake(TRANSFORM-NoAction)
+run_cmake(TRANSFORM-InvalidAction)
+# 'action' oriented tests
+run_cmake(TRANSFORM-TOUPPER-TooManyArguments)
+run_cmake(TRANSFORM-TOLOWER-TooManyArguments)
+run_cmake(TRANSFORM-STRIP-TooManyArguments)
+run_cmake(TRANSFORM-GENEX_STRIP-TooManyArguments)
+run_cmake(TRANSFORM-APPEND-NoArguments)
+run_cmake(TRANSFORM-APPEND-TooManyArguments)
+run_cmake(TRANSFORM-PREPEND-NoArguments)
+run_cmake(TRANSFORM-PREPEND-TooManyArguments)
+run_cmake(TRANSFORM-REPLACE-NoArguments)
+run_cmake(TRANSFORM-REPLACE-NoEnoughArguments)
+run_cmake(TRANSFORM-REPLACE-TooManyArguments)
+run_cmake(TRANSFORM-REPLACE-InvalidRegex)
+run_cmake(TRANSFORM-REPLACE-InvalidReplace1)
+run_cmake(TRANSFORM-REPLACE-InvalidReplace2)
+# 'selector' oriented tests
+run_cmake(TRANSFORM-Selector-REGEX-NoArguments)
+run_cmake(TRANSFORM-Selector-REGEX-TooManyArguments)
+run_cmake(TRANSFORM-Selector-REGEX-InvalidRegex)
+run_cmake(TRANSFORM-Selector-AT-NoArguments)
+run_cmake(TRANSFORM-Selector-AT-BadArgument)
+run_cmake(TRANSFORM-Selector-AT-InvalidIndex)
+run_cmake(TRANSFORM-Selector-FOR-NoArguments)
+run_cmake(TRANSFORM-Selector-FOR-NoEnoughArguments)
+run_cmake(TRANSFORM-Selector-FOR-TooManyArguments)
+run_cmake(TRANSFORM-Selector-FOR-BadArgument)
+run_cmake(TRANSFORM-Selector-FOR-InvalidIndex)
+# 'output' oriented tests
+run_cmake(TRANSFORM-Output-OUTPUT_VARIABLE-NoArguments)
+run_cmake(TRANSFORM-Output-OUTPUT_VARIABLE-TooManyArguments)
+# Successful tests
+run_cmake(TRANSFORM-TOUPPER)
+run_cmake(TRANSFORM-TOLOWER)
+run_cmake(TRANSFORM-STRIP)
+run_cmake(TRANSFORM-GENEX_STRIP)
+run_cmake(TRANSFORM-APPEND)
+run_cmake(TRANSFORM-PREPEND)
+run_cmake(TRANSFORM-REPLACE)
diff --git a/Tests/RunCMake/list/TRANSFORM-APPEND-NoArguments-result.txt b/Tests/RunCMake/list/TRANSFORM-APPEND-NoArguments-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-APPEND-NoArguments-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-APPEND-NoArguments-stderr.txt b/Tests/RunCMake/list/TRANSFORM-APPEND-NoArguments-stderr.txt
new file mode 100644
index 0000000..028f8d5
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-APPEND-NoArguments-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-APPEND-NoArguments.cmake:2 \(list\):
+  list sub-command TRANSFORM, action APPEND expects 1 argument\(s\).
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-APPEND-NoArguments.cmake b/Tests/RunCMake/list/TRANSFORM-APPEND-NoArguments.cmake
new file mode 100644
index 0000000..f161187
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-APPEND-NoArguments.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist APPEND)
diff --git a/Tests/RunCMake/list/TRANSFORM-APPEND-TooManyArguments-result.txt b/Tests/RunCMake/list/TRANSFORM-APPEND-TooManyArguments-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-APPEND-TooManyArguments-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-APPEND-TooManyArguments-stderr.txt b/Tests/RunCMake/list/TRANSFORM-APPEND-TooManyArguments-stderr.txt
new file mode 100644
index 0000000..aeb646d
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-APPEND-TooManyArguments-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-APPEND-TooManyArguments.cmake:2 \(list\):
+  list sub-command TRANSFORM, 'one_too_many': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-APPEND-TooManyArguments.cmake b/Tests/RunCMake/list/TRANSFORM-APPEND-TooManyArguments.cmake
new file mode 100644
index 0000000..8430a4c
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-APPEND-TooManyArguments.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist APPEND delta one_too_many)
diff --git a/Tests/RunCMake/list/TRANSFORM-APPEND.cmake b/Tests/RunCMake/list/TRANSFORM-APPEND.cmake
new file mode 100644
index 0000000..9639088
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-APPEND.cmake
@@ -0,0 +1,48 @@
+set(mylist alpha bravo charlie delta)
+
+list(TRANSFORM mylist APPEND "_A" OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha_A;bravo_A;charlie_A;delta_A")
+  message (FATAL_ERROR "TRANSFORM(APPEND) is \"${output}\", expected is \"alpha_A;bravo_A;charlie_A;delta_A\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist APPEND "_A" AT 1 3 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo_A;charlie;delta_A")
+  message (FATAL_ERROR "TRANSFORM(APPEND) is \"${output}\", expected is \"alpha;bravo_A;charlie;delta_A\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist APPEND "_A" AT 1 -2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo_A;charlie_A;delta")
+  message (FATAL_ERROR "TRANSFORM(APPEND) is \"${output}\", expected is \"alpha;bravo_A;charlie_A;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist APPEND "_A" FOR 1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo_A;charlie_A;delta")
+  message (FATAL_ERROR "TRANSFORM(APPEND) is \"${output}\", expected is \"alpha;bravo_A;charlie_A;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist APPEND "_A" FOR 1 -1 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo_A;charlie_A;delta_A")
+  message (FATAL_ERROR "TRANSFORM(APPEND) is \"${output}\", expected is \"alpha;bravo_A;charlie_A;delta_A\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist APPEND "_A" FOR 0 -1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha_A;bravo;charlie_A;delta")
+  message (FATAL_ERROR "TRANSFORM(APPEND) is \"${output}\", expected is \"alpha_A;bravo;charlie_A;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist APPEND "_A" REGEX "(r|t)a" OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo_A;charlie;delta_A")
+  message (FATAL_ERROR "TRANSFORM(APPEND) is \"${output}\", expected is \"alpha;bravo_A;charlie;delta_A\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist APPEND "_A" REGEX "(r|t)a")
+if (NOT mylist STREQUAL "alpha;bravo_A;charlie;delta_A")
+  message (FATAL_ERROR "TRANSFORM(APPEND) is \"${mylist}\", expected is \"alpha;bravo_A;charlie;delta_A\"")
+endif()
diff --git a/Tests/RunCMake/list/TRANSFORM-GENEX_STRIP-TooManyArguments-result.txt b/Tests/RunCMake/list/TRANSFORM-GENEX_STRIP-TooManyArguments-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-GENEX_STRIP-TooManyArguments-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-GENEX_STRIP-TooManyArguments-stderr.txt b/Tests/RunCMake/list/TRANSFORM-GENEX_STRIP-TooManyArguments-stderr.txt
new file mode 100644
index 0000000..6071a00
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-GENEX_STRIP-TooManyArguments-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-GENEX_STRIP-TooManyArguments.cmake:2 \(list\):
+  list sub-command TRANSFORM, 'one_too_many': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-GENEX_STRIP-TooManyArguments.cmake b/Tests/RunCMake/list/TRANSFORM-GENEX_STRIP-TooManyArguments.cmake
new file mode 100644
index 0000000..257d7fe
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-GENEX_STRIP-TooManyArguments.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist GENEX_STRIP one_too_many)
diff --git a/Tests/RunCMake/list/TRANSFORM-GENEX_STRIP.cmake b/Tests/RunCMake/list/TRANSFORM-GENEX_STRIP.cmake
new file mode 100644
index 0000000..8045eef
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-GENEX_STRIP.cmake
@@ -0,0 +1,49 @@
+set(mylist one "$<1:two\;three>" four "$<TARGET_OBJECTS:some_target>")
+
+list(TRANSFORM mylist GENEX_STRIP OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "one;;four;")
+  message (FATAL_ERROR "TRANSFORM(GENEX_STRIP) is \"${output}\", expected is \"one;;four;\"")
+endif()
+
+set(mylist "one $<CONFIG>" "$<1:two\;three>-$<PLATFORM_ID>" "$<ANGLE-R>four" "$<TARGET_OBJECTS:some_target>")
+unset(output)
+list(TRANSFORM mylist GENEX_STRIP AT 1 3 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "one $<CONFIG>;-;$<ANGLE-R>four;")
+  message (FATAL_ERROR "TRANSFORM(GENEX_STRIP) is \"${output}\", expected is \"one $<CONFIG>;-;$<ANGLE-R>four;\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist GENEX_STRIP AT 1 -2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "one $<CONFIG>;-;four;$<TARGET_OBJECTS:some_target>")
+  message (FATAL_ERROR "TRANSFORM(GENEX_STRIP) is \"${output}\", expected is \"one $<CONFIG>;-;four;$<TARGET_OBJECTS:some_target>\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist GENEX_STRIP FOR 1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "one $<CONFIG>;-;four;$<TARGET_OBJECTS:some_target>")
+  message (FATAL_ERROR "TRANSFORM(GENEX_STRIP) is \"${output}\", expected is \"one $<CONFIG>;-;four;$<TARGET_OBJECTS:some_target>\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist GENEX_STRIP FOR 1 -1 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "one $<CONFIG>;-;four;")
+  message (FATAL_ERROR "TRANSFORM(GENEX_STRIP) is \"${output}\", expected is \"one $<CONFIG>;-;four;\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist GENEX_STRIP FOR 0 -1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "one ;$<1:two;three>-$<PLATFORM_ID>;four;$<TARGET_OBJECTS:some_target>")
+  message (FATAL_ERROR "TRANSFORM(GENEX_STRIP) is \"${output}\", expected is \"one ;$<1:two;three>-$<PLATFORM_ID>;four;$<TARGET_OBJECTS:some_target>\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist GENEX_STRIP REGEX "(D|G)>" OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "one ;-;$<ANGLE-R>four;$<TARGET_OBJECTS:some_target>")
+  message (FATAL_ERROR "TRANSFORM(GENEX_STRIP) is \"${output}\", expected is \"one ;-;$<ANGLE-R>four;$<TARGET_OBJECTS:some_target>\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist GENEX_STRIP REGEX "(D|G)>")
+if (NOT mylist STREQUAL "one ;-;$<ANGLE-R>four;$<TARGET_OBJECTS:some_target>")
+  message (FATAL_ERROR "TRANSFORM(GENEX_STRIP) is \"${mylist}\", expected is \"one ;-;$<ANGLE-R>four;$<TARGET_OBJECTS:some_target>\"")
+endif()
diff --git a/Tests/RunCMake/list/TRANSFORM-InvalidAction-result.txt b/Tests/RunCMake/list/TRANSFORM-InvalidAction-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-InvalidAction-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-InvalidAction-stderr.txt b/Tests/RunCMake/list/TRANSFORM-InvalidAction-stderr.txt
new file mode 100644
index 0000000..0fa45c9
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-InvalidAction-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-InvalidAction.cmake:2 \(list\):
+  list sub-command TRANSFORM, BAD_ACTION invalid action.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-InvalidAction.cmake b/Tests/RunCMake/list/TRANSFORM-InvalidAction.cmake
new file mode 100644
index 0000000..fb2cc30
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-InvalidAction.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist BAD_ACTION)
diff --git a/Tests/RunCMake/list/TRANSFORM-NoAction-result.txt b/Tests/RunCMake/list/TRANSFORM-NoAction-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-NoAction-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-NoAction-stderr.txt b/Tests/RunCMake/list/TRANSFORM-NoAction-stderr.txt
new file mode 100644
index 0000000..68e9e9d
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-NoAction-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-NoAction.cmake:2 \(list\):
+  list sub-command TRANSFORM requires an action to be specified.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-NoAction.cmake b/Tests/RunCMake/list/TRANSFORM-NoAction.cmake
new file mode 100644
index 0000000..3690f14
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-NoAction.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist)
diff --git a/Tests/RunCMake/list/TRANSFORM-Output-OUTPUT_VARIABLE-NoArguments-result.txt b/Tests/RunCMake/list/TRANSFORM-Output-OUTPUT_VARIABLE-NoArguments-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Output-OUTPUT_VARIABLE-NoArguments-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-Output-OUTPUT_VARIABLE-NoArguments-stderr.txt b/Tests/RunCMake/list/TRANSFORM-Output-OUTPUT_VARIABLE-NoArguments-stderr.txt
new file mode 100644
index 0000000..b4f4e06
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Output-OUTPUT_VARIABLE-NoArguments-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-Output-OUTPUT_VARIABLE-NoArguments.cmake:2 \(list\):
+  list sub-command TRANSFORM, OUTPUT_VARIABLE expects variable name argument.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-Output-OUTPUT_VARIABLE-NoArguments.cmake b/Tests/RunCMake/list/TRANSFORM-Output-OUTPUT_VARIABLE-NoArguments.cmake
new file mode 100644
index 0000000..acc4094
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Output-OUTPUT_VARIABLE-NoArguments.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER OUTPUT_VARIABLE)
diff --git a/Tests/RunCMake/list/TRANSFORM-Output-OUTPUT_VARIABLE-TooManyArguments-result.txt b/Tests/RunCMake/list/TRANSFORM-Output-OUTPUT_VARIABLE-TooManyArguments-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Output-OUTPUT_VARIABLE-TooManyArguments-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-Output-OUTPUT_VARIABLE-TooManyArguments-stderr.txt b/Tests/RunCMake/list/TRANSFORM-Output-OUTPUT_VARIABLE-TooManyArguments-stderr.txt
new file mode 100644
index 0000000..9a58346
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Output-OUTPUT_VARIABLE-TooManyArguments-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-Output-OUTPUT_VARIABLE-TooManyArguments.cmake:2 \(list\):
+  list sub-command TRANSFORM, 'one_too_many': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-Output-OUTPUT_VARIABLE-TooManyArguments.cmake b/Tests/RunCMake/list/TRANSFORM-Output-OUTPUT_VARIABLE-TooManyArguments.cmake
new file mode 100644
index 0000000..c4da864
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Output-OUTPUT_VARIABLE-TooManyArguments.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER OUTPUT_VARIABLE output one_too_many)
diff --git a/Tests/RunCMake/list/TRANSFORM-PREPEND-NoArguments-result.txt b/Tests/RunCMake/list/TRANSFORM-PREPEND-NoArguments-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-PREPEND-NoArguments-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-PREPEND-NoArguments-stderr.txt b/Tests/RunCMake/list/TRANSFORM-PREPEND-NoArguments-stderr.txt
new file mode 100644
index 0000000..413ce30
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-PREPEND-NoArguments-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-PREPEND-NoArguments.cmake:2 \(list\):
+  list sub-command TRANSFORM, action PREPEND expects 1 argument\(s\).
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-PREPEND-NoArguments.cmake b/Tests/RunCMake/list/TRANSFORM-PREPEND-NoArguments.cmake
new file mode 100644
index 0000000..a8e4530
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-PREPEND-NoArguments.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist PREPEND)
diff --git a/Tests/RunCMake/list/TRANSFORM-PREPEND-TooManyArguments-result.txt b/Tests/RunCMake/list/TRANSFORM-PREPEND-TooManyArguments-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-PREPEND-TooManyArguments-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-PREPEND-TooManyArguments-stderr.txt b/Tests/RunCMake/list/TRANSFORM-PREPEND-TooManyArguments-stderr.txt
new file mode 100644
index 0000000..6ff1b89
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-PREPEND-TooManyArguments-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-PREPEND-TooManyArguments.cmake:2 \(list\):
+  list sub-command TRANSFORM, 'one_too_many': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-PREPEND-TooManyArguments.cmake b/Tests/RunCMake/list/TRANSFORM-PREPEND-TooManyArguments.cmake
new file mode 100644
index 0000000..1f904ad
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-PREPEND-TooManyArguments.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist PREPEND delta one_too_many)
diff --git a/Tests/RunCMake/list/TRANSFORM-PREPEND.cmake b/Tests/RunCMake/list/TRANSFORM-PREPEND.cmake
new file mode 100644
index 0000000..55b8867
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-PREPEND.cmake
@@ -0,0 +1,48 @@
+set(mylist alpha bravo charlie delta)
+
+list(TRANSFORM mylist PREPEND "P_" OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "P_alpha;P_bravo;P_charlie;P_delta")
+  message (FATAL_ERROR "TRANSFORM(PREPEND) is \"${output}\", expected is \"P_alpha;P_bravo;P_charlie;P_delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist PREPEND "P_" AT 1 3 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;P_bravo;charlie;P_delta")
+  message (FATAL_ERROR "TRANSFORM(PREPEND) is \"${output}\", expected is \"alpha;P_bravo;charlie;P_delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist PREPEND "P_" AT 1 -2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;P_bravo;P_charlie;delta")
+  message (FATAL_ERROR "TRANSFORM(PREPEND) is \"${output}\", expected is \"alpha;P_bravo;P_charlie;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist PREPEND "P_" FOR 1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;P_bravo;P_charlie;delta")
+  message (FATAL_ERROR "TRANSFORM(PREPEND) is \"${output}\", expected is \"alpha;P_bravo;P_charlie;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist PREPEND "P_" FOR 1 -1 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;P_bravo;P_charlie;P_delta")
+  message (FATAL_ERROR "TRANSFORM(PREPEND) is \"${output}\", expected is \"alpha;P_bravo;P_charlie;P_delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist PREPEND "P_" FOR 0 -1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "P_alpha;bravo;P_charlie;delta")
+  message (FATAL_ERROR "TRANSFORM(PREPEND) is \"${output}\", expected is \"P_alpha;bravo;P_charlie;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist PREPEND "P_" REGEX "(r|t)a" OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;P_bravo;charlie;P_delta")
+  message (FATAL_ERROR "TRANSFORM(PREPEND) is \"${output}\", expected is \"alpha;P_bravo;charlie;P_delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist PREPEND "P_" REGEX "(r|t)a")
+if (NOT mylist STREQUAL "alpha;P_bravo;charlie;P_delta")
+  message (FATAL_ERROR "TRANSFORM(PREPEND) is \"${mylist}\", expected is \"alpha;P_bravo;charlie;P_delta\"")
+endif()
diff --git a/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidRegex-result.txt b/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidRegex-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidRegex-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidRegex-stderr.txt b/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidRegex-stderr.txt
new file mode 100644
index 0000000..334c96e
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidRegex-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at TRANSFORM-REPLACE-InvalidRegex.cmake:2 \(list\):
+  list sub-command TRANSFORM, action REPLACE: Failed to compile regex
+  "\^\(alpha\$".
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidRegex.cmake b/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidRegex.cmake
new file mode 100644
index 0000000..f440c35
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidRegex.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist REPLACE "^(alpha$" "zulu")
diff --git a/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidReplace-result.txt b/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidReplace-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidReplace-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidReplace1-result.txt b/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidReplace1-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidReplace1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidReplace1-stderr.txt b/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidReplace1-stderr.txt
new file mode 100644
index 0000000..7671c83
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidReplace1-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at TRANSFORM-REPLACE-InvalidReplace1.cmake:2 \(list\):
+  list sub-command TRANSFORM, action REPLACE: replace-expression ends in a
+  backslash.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidReplace1.cmake b/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidReplace1.cmake
new file mode 100644
index 0000000..35387f0
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidReplace1.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist REPLACE "^alpha$" "zulu\\")
diff --git a/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidReplace2-result.txt b/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidReplace2-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidReplace2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidReplace2-stderr.txt b/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidReplace2-stderr.txt
new file mode 100644
index 0000000..e0aabd7
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidReplace2-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at TRANSFORM-REPLACE-InvalidReplace2.cmake:2 \(list\):
+  list sub-command TRANSFORM, action REPLACE: Unknown escape "\\z" in
+  replace-expression.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidReplace2.cmake b/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidReplace2.cmake
new file mode 100644
index 0000000..2f1f2c7
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-REPLACE-InvalidReplace2.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist REPLACE "^alpha$" "\\zulu")
diff --git a/Tests/RunCMake/list/TRANSFORM-REPLACE-NoArguments-result.txt b/Tests/RunCMake/list/TRANSFORM-REPLACE-NoArguments-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-REPLACE-NoArguments-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-REPLACE-NoArguments-stderr.txt b/Tests/RunCMake/list/TRANSFORM-REPLACE-NoArguments-stderr.txt
new file mode 100644
index 0000000..3d39e72
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-REPLACE-NoArguments-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-REPLACE-NoArguments.cmake:2 \(list\):
+  list sub-command TRANSFORM, action REPLACE expects 2 argument\(s\).
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-REPLACE-NoArguments.cmake b/Tests/RunCMake/list/TRANSFORM-REPLACE-NoArguments.cmake
new file mode 100644
index 0000000..b7b1e9d
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-REPLACE-NoArguments.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist REPLACE)
diff --git a/Tests/RunCMake/list/TRANSFORM-REPLACE-NoEnoughArguments-result.txt b/Tests/RunCMake/list/TRANSFORM-REPLACE-NoEnoughArguments-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-REPLACE-NoEnoughArguments-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-REPLACE-NoEnoughArguments-stderr.txt b/Tests/RunCMake/list/TRANSFORM-REPLACE-NoEnoughArguments-stderr.txt
new file mode 100644
index 0000000..dc80f33
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-REPLACE-NoEnoughArguments-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-REPLACE-NoEnoughArguments.cmake:2 \(list\):
+  list sub-command TRANSFORM, action REPLACE expects 2 argument\(s\).
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-REPLACE-NoEnoughArguments.cmake b/Tests/RunCMake/list/TRANSFORM-REPLACE-NoEnoughArguments.cmake
new file mode 100644
index 0000000..1d418c0
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-REPLACE-NoEnoughArguments.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist REPLACE "^alpha$")
diff --git a/Tests/RunCMake/list/TRANSFORM-REPLACE-TooManyArguments-result.txt b/Tests/RunCMake/list/TRANSFORM-REPLACE-TooManyArguments-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-REPLACE-TooManyArguments-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-REPLACE-TooManyArguments-stderr.txt b/Tests/RunCMake/list/TRANSFORM-REPLACE-TooManyArguments-stderr.txt
new file mode 100644
index 0000000..3d4e15a
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-REPLACE-TooManyArguments-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-REPLACE-TooManyArguments.cmake:2 \(list\):
+  list sub-command TRANSFORM, 'one_too_many': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-REPLACE-TooManyArguments.cmake b/Tests/RunCMake/list/TRANSFORM-REPLACE-TooManyArguments.cmake
new file mode 100644
index 0000000..baed0af
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-REPLACE-TooManyArguments.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist REPLACE "^alpha$" "zulu" "one_too_many")
diff --git a/Tests/RunCMake/list/TRANSFORM-REPLACE.cmake b/Tests/RunCMake/list/TRANSFORM-REPLACE.cmake
new file mode 100644
index 0000000..256b1b8
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-REPLACE.cmake
@@ -0,0 +1,48 @@
+set(mylist alpha bravo charlie delta)
+
+list(TRANSFORM mylist REPLACE "(.+a)$" "\\1_\\1" OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha_alpha;bravo;charlie;delta_delta")
+  message (FATAL_ERROR "TRANSFORM(REPLACE) is \"${output}\", expected is \"alpha_alpha;bravo;charlie;delta_delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist REPLACE "(.+a)$" "\\1_\\1" AT 1 3 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo;charlie;delta_delta")
+  message (FATAL_ERROR "TRANSFORM(REPLACE) is \"${output}\", expected is \"alpha;bravo;charlie;delta_delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist REPLACE "(.+e)$" "\\1_\\1" AT 1 -2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo;charlie_charlie;delta")
+  message (FATAL_ERROR "TRANSFORM(REPLACE) is \"${output}\", expected is \"alpha;bravo;charlie_charlie;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist REPLACE "(.+e)$" "\\1_\\1" FOR 1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo;charlie_charlie;delta")
+  message (FATAL_ERROR "TRANSFORM(REPLACE) is \"${output}\", expected is \"alpha;bravo;charlie_charlie;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist REPLACE "(.+a)$" "\\1_\\1" FOR 1 -1 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo;charlie;delta_delta")
+  message (FATAL_ERROR "TRANSFORM(REPLACE) is \"${output}\", expected is \"alpha;bravo;charlie_A;delta_delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist REPLACE "(.+a)$" "\\1_\\1" FOR 0 -1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha_alpha;bravo;charlie;delta")
+  message (FATAL_ERROR "TRANSFORM(REPLACE) is \"${output}\", expected is \"alpha_alpha;bravo;charlie;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist REPLACE "(.+a)$" "\\1_\\1" REGEX "(r|t)a" OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo;charlie;delta_delta")
+  message (FATAL_ERROR "TRANSFORM(REPLACE) is \"${output}\", expected is \"alpha;bravo;charlie;delta_delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist REPLACE "(.+a)$" "\\1_\\1" REGEX "(r|t)a")
+if (NOT mylist STREQUAL "alpha;bravo;charlie;delta_delta")
+  message (FATAL_ERROR "TRANSFORM(REPLACE) is \"${mylist}\", expected is \"alpha;bravo;charlie;delta_delta\"")
+endif()
diff --git a/Tests/RunCMake/list/TRANSFORM-STRIP-TooManyArguments-result.txt b/Tests/RunCMake/list/TRANSFORM-STRIP-TooManyArguments-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-STRIP-TooManyArguments-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-STRIP-TooManyArguments-stderr.txt b/Tests/RunCMake/list/TRANSFORM-STRIP-TooManyArguments-stderr.txt
new file mode 100644
index 0000000..534f940
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-STRIP-TooManyArguments-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-STRIP-TooManyArguments.cmake:2 \(list\):
+  list sub-command TRANSFORM, 'one_too_many': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-STRIP-TooManyArguments.cmake b/Tests/RunCMake/list/TRANSFORM-STRIP-TooManyArguments.cmake
new file mode 100644
index 0000000..c6a8213
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-STRIP-TooManyArguments.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist STRIP one_too_many)
diff --git a/Tests/RunCMake/list/TRANSFORM-STRIP.cmake b/Tests/RunCMake/list/TRANSFORM-STRIP.cmake
new file mode 100644
index 0000000..366c63a
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-STRIP.cmake
@@ -0,0 +1,49 @@
+set(mylist " alpha" "bravo " " charlie " delta)
+
+list(TRANSFORM mylist STRIP OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo;charlie;delta")
+  message (FATAL_ERROR "TRANSFORM(STRIP) is \"${output}\", expected is \"alpha;bravo;charlie;delta\"")
+endif()
+
+set(mylist " alpha" "bravo " " charlie " "delta ")
+unset(output)
+list(TRANSFORM mylist STRIP AT 1 3 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL " alpha;bravo; charlie ;delta")
+  message (FATAL_ERROR "TRANSFORM(STRIP) is \"${output}\", expected is \" alpha;bravo; charlie ;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist STRIP AT 1 -2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL " alpha;bravo;charlie;delta ")
+  message (FATAL_ERROR "TRANSFORM(STRIP) is \"${output}\", expected is \" alpha;bravo;charlie;delta \"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist STRIP FOR 1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL " alpha;bravo;charlie;delta ")
+  message (FATAL_ERROR "TRANSFORM(STRIP) is \"${output}\", expected is \" alpha;bravo;charlie;delta \"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist STRIP FOR 1 -1 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL " alpha;bravo;charlie;delta")
+  message (FATAL_ERROR "TRANSFORM(STRIP) is \"${output}\", expected is \" alpha;bravo;charlie;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist STRIP FOR 0 -1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo ;charlie;delta ")
+  message (FATAL_ERROR "TRANSFORM(STRIP) is \"${output}\", expected is \"alpha;bravo ;charlie;delta \"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist STRIP REGEX "(r|t)a" OUTPUT_VARIABLE output)
+if (NOT output STREQUAL " alpha;bravo; charlie ;delta")
+  message (FATAL_ERROR "TRANSFORM(STRIP) is \"${output}\", expected is \" alpha;bravo; charlie ;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist STRIP REGEX "(r|t)a")
+if (NOT mylist STREQUAL " alpha;bravo; charlie ;delta")
+  message (FATAL_ERROR "TRANSFORM(STRIP) is \"${mylist}\", expected is \" alpha;bravo; charlie ;delta\"")
+endif()
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-AT-BadArgument-result.txt b/Tests/RunCMake/list/TRANSFORM-Selector-AT-BadArgument-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-AT-BadArgument-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-AT-BadArgument-stderr.txt b/Tests/RunCMake/list/TRANSFORM-Selector-AT-BadArgument-stderr.txt
new file mode 100644
index 0000000..cec520f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-AT-BadArgument-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-Selector-AT-BadArgument.cmake:2 \(list\):
+  list sub-command TRANSFORM, '1x 2': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-AT-BadArgument.cmake b/Tests/RunCMake/list/TRANSFORM-Selector-AT-BadArgument.cmake
new file mode 100644
index 0000000..f61b86b
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-AT-BadArgument.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER AT 0 1x 2)
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-AT-InvalidIndex-result.txt b/Tests/RunCMake/list/TRANSFORM-Selector-AT-InvalidIndex-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-AT-InvalidIndex-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-AT-InvalidIndex-stderr.txt b/Tests/RunCMake/list/TRANSFORM-Selector-AT-InvalidIndex-stderr.txt
new file mode 100644
index 0000000..7e2898b
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-AT-InvalidIndex-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-Selector-AT-InvalidIndex.cmake:2 \(list\):
+  list sub-command TRANSFORM, selector AT, index: 3 out of range \(-3, 2\).
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-AT-InvalidIndex.cmake b/Tests/RunCMake/list/TRANSFORM-Selector-AT-InvalidIndex.cmake
new file mode 100644
index 0000000..d33586c
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-AT-InvalidIndex.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER AT 0 3 2)
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-AT-NoArguments-result.txt b/Tests/RunCMake/list/TRANSFORM-Selector-AT-NoArguments-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-AT-NoArguments-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-AT-NoArguments-stderr.txt b/Tests/RunCMake/list/TRANSFORM-Selector-AT-NoArguments-stderr.txt
new file mode 100644
index 0000000..eaf5281
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-AT-NoArguments-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-Selector-AT-NoArguments.cmake:2 \(list\):
+  list sub-command TRANSFORM, selector AT expects at least one numeric value.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-AT-NoArguments.cmake b/Tests/RunCMake/list/TRANSFORM-Selector-AT-NoArguments.cmake
new file mode 100644
index 0000000..052b79b
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-AT-NoArguments.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER AT)
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-FOR-BadArgument-result.txt b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-BadArgument-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-BadArgument-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-FOR-BadArgument-stderr.txt b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-BadArgument-stderr.txt
new file mode 100644
index 0000000..a0f701f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-BadArgument-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at TRANSFORM-Selector-FOR-BadArgument.cmake:2 \(list\):
+  list sub-command TRANSFORM, selector FOR expects, at least, two numeric
+  values.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-FOR-BadArgument.cmake b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-BadArgument.cmake
new file mode 100644
index 0000000..55527be
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-BadArgument.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER FOR 0 1x 2)
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-FOR-InvalidIndex-result.txt b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-InvalidIndex-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-InvalidIndex-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-FOR-InvalidIndex-stderr.txt b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-InvalidIndex-stderr.txt
new file mode 100644
index 0000000..c50cc0a
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-InvalidIndex-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-Selector-FOR-InvalidIndex.cmake:2 \(list\):
+  list sub-command TRANSFORM, selector FOR, index: 6 out of range \(-3, 2\).
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-FOR-InvalidIndex.cmake b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-InvalidIndex.cmake
new file mode 100644
index 0000000..6e2374e
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-InvalidIndex.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER FOR 0 6 2)
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-FOR-NoArguments-result.txt b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-NoArguments-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-NoArguments-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-FOR-NoArguments-stderr.txt b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-NoArguments-stderr.txt
new file mode 100644
index 0000000..5881b67
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-NoArguments-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-Selector-FOR-NoArguments.cmake:2 \(list\):
+  list sub-command TRANSFORM, selector FOR expects, at least, two arguments.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-FOR-NoArguments.cmake b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-NoArguments.cmake
new file mode 100644
index 0000000..4902cc9
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-NoArguments.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER FOR)
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-FOR-NoEnoughArguments-result.txt b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-NoEnoughArguments-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-NoEnoughArguments-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-FOR-NoEnoughArguments-stderr.txt b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-NoEnoughArguments-stderr.txt
new file mode 100644
index 0000000..b1081d9
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-NoEnoughArguments-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-Selector-FOR-NoEnoughArguments.cmake:2 \(list\):
+  list sub-command TRANSFORM, selector FOR expects, at least, two arguments.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-FOR-NoEnoughArguments.cmake b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-NoEnoughArguments.cmake
new file mode 100644
index 0000000..81417de
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-NoEnoughArguments.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER FOR 1)
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-FOR-TooManyArguments-result.txt b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-TooManyArguments-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-TooManyArguments-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-FOR-TooManyArguments-stderr.txt b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-TooManyArguments-stderr.txt
new file mode 100644
index 0000000..2221cb3
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-TooManyArguments-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-Selector-FOR-TooManyArguments.cmake:2 \(list\):
+  list sub-command TRANSFORM, '3': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-FOR-TooManyArguments.cmake b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-TooManyArguments.cmake
new file mode 100644
index 0000000..80917d6
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-FOR-TooManyArguments.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER FOR 0 1 2 3)
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-InvalidRegex-result.txt b/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-InvalidRegex-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-InvalidRegex-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-InvalidRegex-stderr.txt b/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-InvalidRegex-stderr.txt
new file mode 100644
index 0000000..31ba939
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-InvalidRegex-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at TRANSFORM-Selector-REGEX-InvalidRegex.cmake:2 \(list\):
+  list sub-command TRANSFORM, selector REGEX failed to compile regex
+  "\^\(alpha\$".
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-InvalidRegex.cmake b/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-InvalidRegex.cmake
new file mode 100644
index 0000000..56e202b
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-InvalidRegex.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER REGEX "^(alpha$")
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-NoArguments-result.txt b/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-NoArguments-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-NoArguments-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-NoArguments-stderr.txt b/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-NoArguments-stderr.txt
new file mode 100644
index 0000000..2784785
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-NoArguments-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at TRANSFORM-Selector-REGEX-NoArguments.cmake:2 \(list\):
+  list sub-command TRANSFORM, selector REGEX expects 'regular expression'
+  argument.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-NoArguments.cmake b/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-NoArguments.cmake
new file mode 100644
index 0000000..f199d0e
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-NoArguments.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER REGEX)
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-TooManyArguments-result.txt b/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-TooManyArguments-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-TooManyArguments-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-TooManyArguments-stderr.txt b/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-TooManyArguments-stderr.txt
new file mode 100644
index 0000000..db5b1ff
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-TooManyArguments-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-Selector-REGEX-TooManyArguments.cmake:2 \(list\):
+  list sub-command TRANSFORM, 'one_too_many': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-TooManyArguments.cmake b/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-TooManyArguments.cmake
new file mode 100644
index 0000000..4aa1619
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-Selector-REGEX-TooManyArguments.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER REGEX "^alpha$" "one_too_many")
diff --git a/Tests/RunCMake/list/TRANSFORM-TOLOWER-TooManyArguments-result.txt b/Tests/RunCMake/list/TRANSFORM-TOLOWER-TooManyArguments-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-TOLOWER-TooManyArguments-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-TOLOWER-TooManyArguments-stderr.txt b/Tests/RunCMake/list/TRANSFORM-TOLOWER-TooManyArguments-stderr.txt
new file mode 100644
index 0000000..90248ae
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-TOLOWER-TooManyArguments-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-TOLOWER-TooManyArguments.cmake:2 \(list\):
+  list sub-command TRANSFORM, 'one_too_many': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-TOLOWER-TooManyArguments.cmake b/Tests/RunCMake/list/TRANSFORM-TOLOWER-TooManyArguments.cmake
new file mode 100644
index 0000000..1758e19
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-TOLOWER-TooManyArguments.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOLOWER one_too_many)
diff --git a/Tests/RunCMake/list/TRANSFORM-TOLOWER.cmake b/Tests/RunCMake/list/TRANSFORM-TOLOWER.cmake
new file mode 100644
index 0000000..a2d7348
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-TOLOWER.cmake
@@ -0,0 +1,48 @@
+set(mylist ALPHA BRAVO CHARLIE DELTA)
+
+list(TRANSFORM mylist TOLOWER OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;bravo;charlie;delta")
+  message (FATAL_ERROR "TRANSFORM(TOLOWER) is \"${output}\", expected is \"alpha;bravo;charlie;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOLOWER AT 1 3 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "ALPHA;bravo;CHARLIE;delta")
+  message (FATAL_ERROR "TRANSFORM(TOLOWER) is \"${output}\", expected is \"ALPHA;bravo;CHARLIE;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOLOWER AT 1 -2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "ALPHA;bravo;charlie;DELTA")
+  message (FATAL_ERROR "TRANSFORM(TOLOWER) is \"${output}\", expected is \"ALPHA;bravo;charlie;DELTA\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOLOWER FOR 1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "ALPHA;bravo;charlie;DELTA")
+  message (FATAL_ERROR "TRANSFORM(TOLOWER) is \"${output}\", expected is \"ALPHA;bravo;charlie;DELTA\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOLOWER FOR 1 -1 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "ALPHA;bravo;charlie;delta")
+  message (FATAL_ERROR "TRANSFORM(TOLOWER) is \"${output}\", expected is \"ALPHA;bravo;charlie;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOLOWER FOR 0 -1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;BRAVO;charlie;DELTA")
+  message (FATAL_ERROR "TRANSFORM(TOLOWER) is \"${output}\", expected is \"alpha;BRAVO;charlie;DELTA\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOLOWER REGEX "(R|T)A" OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "ALPHA;bravo;CHARLIE;delta")
+  message (FATAL_ERROR "TRANSFORM(TOLOWER) is \"${output}\", expected is \"ALPHA;bravo;CHARLIE;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOLOWER REGEX "(R|T)A")
+if (NOT mylist STREQUAL "ALPHA;bravo;CHARLIE;delta")
+  message (FATAL_ERROR "TRANSFORM(TOLOWER) is \"${mylist}\", expected is \"ALPHA;bravo;CHARLIE;delta\"")
+endif()
diff --git a/Tests/RunCMake/list/TRANSFORM-TOUPPER-TooManyArguments-result.txt b/Tests/RunCMake/list/TRANSFORM-TOUPPER-TooManyArguments-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-TOUPPER-TooManyArguments-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/list/TRANSFORM-TOUPPER-TooManyArguments-stderr.txt b/Tests/RunCMake/list/TRANSFORM-TOUPPER-TooManyArguments-stderr.txt
new file mode 100644
index 0000000..9da241b
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-TOUPPER-TooManyArguments-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TRANSFORM-TOUPPER-TooManyArguments.cmake:2 \(list\):
+  list sub-command TRANSFORM, 'one_too_many': unexpected argument\(s\).
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/list/TRANSFORM-TOUPPER-TooManyArguments.cmake b/Tests/RunCMake/list/TRANSFORM-TOUPPER-TooManyArguments.cmake
new file mode 100644
index 0000000..58d6a8c
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-TOUPPER-TooManyArguments.cmake
@@ -0,0 +1,2 @@
+set(mylist alpha bravo charlie)
+list(TRANSFORM mylist TOUPPER one_too_many)
diff --git a/Tests/RunCMake/list/TRANSFORM-TOUPPER.cmake b/Tests/RunCMake/list/TRANSFORM-TOUPPER.cmake
new file mode 100644
index 0000000..5b1fcb6
--- /dev/null
+++ b/Tests/RunCMake/list/TRANSFORM-TOUPPER.cmake
@@ -0,0 +1,48 @@
+set(mylist alpha bravo charlie delta)
+
+list(TRANSFORM mylist TOUPPER OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "ALPHA;BRAVO;CHARLIE;DELTA")
+  message (FATAL_ERROR "TRANSFORM(TOUPPER) is \"${output}\", expected is \"ALPHA;BRAVO;CHARLIE;DELTA\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOUPPER AT 1 3 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;BRAVO;charlie;DELTA")
+  message (FATAL_ERROR "TRANSFORM(TOUPPER) is \"${output}\", expected is \"alpha;BRAVO;charlie;DELTA\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOUPPER AT 1 -2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;BRAVO;CHARLIE;delta")
+  message (FATAL_ERROR "TRANSFORM(TOUPPER) is \"${output}\", expected is \"alpha;BRAVO;CHARLIE;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOUPPER FOR 1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;BRAVO;CHARLIE;delta")
+  message (FATAL_ERROR "TRANSFORM(TOUPPER) is \"${output}\", expected is \"alpha;BRAVO;CHARLIE;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOUPPER FOR 1 -1 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;BRAVO;CHARLIE;DELTA")
+  message (FATAL_ERROR "TRANSFORM(TOUPPER) is \"${output}\", expected is \"alpha;BRAVO;CHARLIE;DELTA\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOUPPER FOR 0 -1 2 OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "ALPHA;bravo;CHARLIE;delta")
+  message (FATAL_ERROR "TRANSFORM(TOUPPER) is \"${output}\", expected is \"ALPHA;bravo;CHARLIE;delta\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOUPPER REGEX "(r|t)a" OUTPUT_VARIABLE output)
+if (NOT output STREQUAL "alpha;BRAVO;charlie;DELTA")
+  message (FATAL_ERROR "TRANSFORM(TOUPPER) is \"${output}\", expected is \"alpha;BRAVO;charlie;DELTA\"")
+endif()
+
+unset(output)
+list(TRANSFORM mylist TOUPPER REGEX "(r|t)a")
+if (NOT mylist STREQUAL "alpha;BRAVO;charlie;DELTA")
+  message (FATAL_ERROR "TRANSFORM(TOUPPER) is \"${mylist}\", expected is \"alpha;BRAVO;charlie;DELTA\"")
+endif()
diff --git a/bootstrap b/bootstrap
index 3bcab60..6604f54 100755
--- a/bootstrap
+++ b/bootstrap
@@ -400,6 +400,7 @@
   cmState \
   cmStateDirectory \
   cmStateSnapshot \
+  cmStringReplaceHelper \
   cmStringCommand \
   cmSubdirCommand \
   cmSystemTools \
@@ -570,6 +571,8 @@
   --no-system-libarchive  use cmake-provided libarchive library (default)
   --system-librhash       use system-installed librhash library
   --no-system-librhash    use cmake-provided librhash library (default)
+  --system-libuv          use system-installed libuv library
+  --no-system-libuv       use cmake-provided libuv library (default)
 
   --qt-gui                build the Qt-based GUI (requires Qt >= 4.2)
   --no-qt-gui             do not build the Qt-based GUI (default)
@@ -804,10 +807,10 @@
   --init=*) cmake_init_file=`cmake_arg "$1"` ;;
   --system-libs) cmake_bootstrap_system_libs="${cmake_bootstrap_system_libs} -DCMAKE_USE_SYSTEM_LIBRARIES=1" ;;
   --no-system-libs) cmake_bootstrap_system_libs="${cmake_bootstrap_system_libs} -DCMAKE_USE_SYSTEM_LIBRARIES=0" ;;
-  --system-bzip2|--system-curl|--system-expat|--system-jsoncpp|--system-libarchive|--system-librhash|--system-zlib|--system-liblzma)
+  --system-bzip2|--system-curl|--system-expat|--system-jsoncpp|--system-libarchive|--system-librhash|--system-zlib|--system-liblzma|--system-libuv)
     lib=`cmake_arg "$1" "--system-"`
     cmake_bootstrap_system_libs="${cmake_bootstrap_system_libs} -DCMAKE_USE_SYSTEM_LIBRARY_`cmake_toupper $lib`=1" ;;
-  --no-system-bzip2|--no-system-curl|--no-system-expat|--no-system-jsoncpp|--no-system-libarchive|--no-system-librhash|--no-system-zlib|--no-system-liblzma)
+  --no-system-bzip2|--no-system-curl|--no-system-expat|--no-system-jsoncpp|--no-system-libarchive|--no-system-librhash|--no-system-zlib|--no-system-liblzma|--no-system-libuv)
     lib=`cmake_arg "$1" "--no-system-"`
     cmake_bootstrap_system_libs="${cmake_bootstrap_system_libs} -DCMAKE_USE_SYSTEM_LIBRARY_`cmake_toupper $lib`=0" ;;
   --qt-gui) cmake_bootstrap_qt_gui="1" ;;