Merge topic 'cmake-version'

fe2c558ba6 CMakeVersion: Preserve Git information during 'git archive'
0505a66cbf CMakeVersion: Add generic '-git' suffix when no git info is available
f7bf08754b CMakeVersion: Provide Git information in non-exact release versions
ac48259333 CMakeVersion: Re-order logic to obviate addition of each component
311f232f7a CMakeVersion: De-duplicate variable initialization
2f608566b4 CMakeVersion: Factor git execution into helper macro
74ff80323c CMakeVersion: Use FindGit module to find Git
e1e7986c00 CMakeVersion: Consider Git even with just a `.git` file
...

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !3622
diff --git a/Help/guide/tutorial/Complete/CMakeLists.txt b/Help/guide/tutorial/Complete/CMakeLists.txt
index bea611c..4541392 100644
--- a/Help/guide/tutorial/Complete/CMakeLists.txt
+++ b/Help/guide/tutorial/Complete/CMakeLists.txt
@@ -1,8 +1,17 @@
-cmake_minimum_required(VERSION 3.3)
+cmake_minimum_required(VERSION 3.15)
 project(Tutorial)
 
-set(CMAKE_CXX_STANDARD 11)
-set(CMAKE_CXX_STANDARD_REQUIRED True)
+add_library(tutorial_compiler_flags INTERFACE)
+target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
+
+# add compiler warning flags just when building this project via
+# the BUILD_INTERFACE genex
+set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU>")
+set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
+target_compile_options(tutorial_compiler_flags INTERFACE
+  "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>"
+  "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
+)
 
 # set the version number
 set(Tutorial_VERSION_MAJOR 1)
diff --git a/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt
index 63c0f5f..c12955d 100644
--- a/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt
@@ -21,6 +21,7 @@
 
   # first we add the executable that generates the table
   add_executable(MakeTable MakeTable.cxx)
+  target_link_libraries(MakeTable tutorial_compiler_flags)
 
   # add the command to generate the source code
   add_custom_command(
@@ -44,14 +45,18 @@
                         POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
                         )
 
-  target_compile_definitions(SqrtLibrary PRIVATE
-                             "$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>"
-                             "$<$<BOOL:${HAVE_EXP}>:HAVE_EXP>"
-                             )
+  target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags)
+
+
+  target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
+  if(HAVE_LOG AND HAVE_EXP)
+    target_compile_definitions(SqrtLibrary
+                               PRIVATE "HAVE_LOG" "HAVE_EXP")
+  endif()
   target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
 endif()
 
-target_compile_definitions(MathFunctions PRIVATE "$<$<BOOL:${USE_MYMATH}>:USE_MYMATH>")
+target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)
 
 # define the symbol stating we are using the declspec(dllexport) when
 # building on windows
@@ -62,7 +67,7 @@
 set_property(TARGET MathFunctions PROPERTY SOVERSION "1")
 
 # install rules
-install(TARGETS MathFunctions
+install(TARGETS MathFunctions tutorial_compiler_flags
         DESTINATION lib
         EXPORT MathFunctionsTargets)
 install(FILES MathFunctions.h DESTINATION include)
diff --git a/Help/guide/tutorial/Step11/CMakeLists.txt b/Help/guide/tutorial/Step11/CMakeLists.txt
index 8f29fe2..e54bdde 100644
--- a/Help/guide/tutorial/Step11/CMakeLists.txt
+++ b/Help/guide/tutorial/Step11/CMakeLists.txt
@@ -1,8 +1,17 @@
-cmake_minimum_required(VERSION 3.3)
+cmake_minimum_required(VERSION 3.15)
 project(Tutorial)
 
-set(CMAKE_CXX_STANDARD 11)
-set(CMAKE_CXX_STANDARD_REQUIRED True)
+add_library(tutorial_compiler_flags INTERFACE)
+target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
+
+# add compiler warning flags just when building this project via
+# the BUILD_INTERFACE genex
+set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU>")
+set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
+target_compile_options(tutorial_compiler_flags INTERFACE
+  "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>"
+  "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
+)
 
 # set the version number
 set(Tutorial_VERSION_MAJOR 1)
diff --git a/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt
index ea42770..daaaa55 100644
--- a/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt
@@ -19,6 +19,7 @@
 
   # first we add the executable that generates the table
   add_executable(MakeTable MakeTable.cxx)
+  target_link_libraries(MakeTable tutorial_compiler_flags)
 
   # add the command to generate the source code
   add_custom_command(
@@ -42,14 +43,17 @@
                         POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
                         )
 
-  target_compile_definitions(SqrtLibrary PRIVATE
-                             "$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>"
-                             "$<$<BOOL:${HAVE_EXP}>:HAVE_EXP>"
-                             )
+  target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags)
+
+  target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
+  if(HAVE_LOG AND HAVE_EXP)
+    target_compile_definitions(SqrtLibrary
+                               PRIVATE "HAVE_LOG" "HAVE_EXP")
+  endif()
   target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
 endif()
 
-target_compile_definitions(MathFunctions PRIVATE "$<$<BOOL:${USE_MYMATH}>:USE_MYMATH>")
+target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)
 
 # define the symbol stating we are using the declspec(dllexport) when
 #building on windows
diff --git a/Help/guide/tutorial/index.rst b/Help/guide/tutorial/index.rst
index 41ed0c4..068499e 100644
--- a/Help/guide/tutorial/index.rst
+++ b/Help/guide/tutorial/index.rst
@@ -598,27 +598,47 @@
 string, and ``<1:...>`` results in the content of "...".  They can also be
 nested.
 
-For example:
+A common usage of generator expressions is to conditionally add compiler
+flags, such as those as language levels or warnings. A nice pattern is
+to associate this information to an ``INTERFACE`` target allowing this
+information to propagate. Lets start by constructing an ``INTERFACE``
+target and specifying the required C++ standard level of ``11`` instead
+of using ``CMAKE_CXX_STANDARD``.
 
-.. code-block:: cmake
+So the following code:
 
-  if(HAVE_LOG AND HAVE_EXP)
-    target_compile_definitions(SqrtLibrary
-                               PRIVATE "HAVE_LOG" "HAVE_EXP")
-  endif()
+.. literalinclude:: Step10/CMakeLists.txt
+  :language: cmake
+  :start-after: project(Tutorial)
+  :end-before: # Set the version number
 
-Can be rewritten with generator expressions:
+Would be replaced with:
 
-.. code-block:: cmake
+.. literalinclude:: Step11/CMakeLists.txt
+  :language: cmake
+  :start-after: project(Tutorial)
+  :end-before: # add compiler warning flags just when building this project via
 
-  target_compile_definitions(SqrtLibrary PRIVATE
-                             "$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>"
-                             "$<$<BOOL:${HAVE_EXP}>:HAVE_EXP>"
-                            )
 
-Note that ``${HAVE_LOG}`` is evaluated at CMake configure time while
-``$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>`` is evaluated at build system generation
-time.
+Next we add the desired compiler warning flags that we want for our
+project. As warning flags vary based on the compiler we use
+the ``COMPILE_LANG_AND_ID`` generator expression to control which
+flags to apply given a language and a set of compiler ids as seen
+below:
+
+.. literalinclude:: Step11/CMakeLists.txt
+  :language: cmake
+  :start-after: # the BUILD_INTERFACE genex
+  :end-before: # set the version number
+
+Looking at this we see that the warning flags are encapsulated inside a
+``BUILD_INTERFACE`` condition. This is done so that consumers of our installed
+project will not inherit our warning flags.
+
+
+**Exercise**: Modify ``MathFunctions/CMakeLists.txt`` so that
+all targets have a ``target_link_libraries()`` call to ``tutorial_compiler_flags``.
+
 
 Adding Export Configuration (Step 11)
 =====================================
diff --git a/Help/manual/cmake-toolchains.7.rst b/Help/manual/cmake-toolchains.7.rst
index 7435d9a..f233d08 100644
--- a/Help/manual/cmake-toolchains.7.rst
+++ b/Help/manual/cmake-toolchains.7.rst
@@ -399,8 +399,10 @@
   be false unless using a NDK that does not provide unified headers.
 
 :variable:`CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION`
-  Set to the version of the NDK toolchain to be selected as the compiler.
-  If not specified, the default will be the latest available GCC toolchain.
+  On NDK r19 or above, this variable must be unset or set to ``clang``.
+  On NDK r18 or below, set this to the version of the NDK toolchain to
+  be selected as the compiler.  If not specified, the default will be
+  the latest available GCC toolchain.
 
 :variable:`CMAKE_ANDROID_STL_TYPE`
   Set to specify which C++ standard library to use.  If not specified,
diff --git a/Help/variable/CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION.rst b/Help/variable/CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION.rst
index 5ae55d1..22808e3 100644
--- a/Help/variable/CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION.rst
+++ b/Help/variable/CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION.rst
@@ -3,7 +3,11 @@
 
 When :ref:`Cross Compiling for Android with the NDK`, this variable
 may be set to specify the version of the toolchain to be used
-as the compiler.  The variable must be set to one of these forms:
+as the compiler.
+
+On NDK r19 or above, this variable must be unset or set to ``clang``.
+
+On NDK r18 or below, this variable must be set to one of these forms:
 
 * ``<major>.<minor>``: GCC of specified version
 * ``clang<major>.<minor>``: Clang of specified version
diff --git a/Modules/CheckCXXSymbolExists.cmake b/Modules/CheckCXXSymbolExists.cmake
index b112094..5c9079d 100644
--- a/Modules/CheckCXXSymbolExists.cmake
+++ b/Modules/CheckCXXSymbolExists.cmake
@@ -27,6 +27,17 @@
   not be recognized: consider using the :module:`CheckTypeSize`
   or :module:`CheckCXXSourceCompiles` module instead.
 
+.. note::
+
+  This command is unreliable when ``<symbol>`` is (potentially) an overloaded
+  function. Since there is no reliable way to predict whether a given function
+  in the system environment may be defined as an overloaded function or may be
+  an overloaded function on other systems or will become so in the future, it
+  is generally advised to use the :module:`CheckCXXSourceCompiles` module for
+  checking any function symbol (unless somehow you surely know the checked
+  function is not overloaded on other systems or will not be so in the
+  future).
+
 The following variables may be set before calling this macro to modify
 the way the check is run:
 
diff --git a/Modules/CheckSymbolExists.cmake b/Modules/CheckSymbolExists.cmake
index c2f488a..1053383 100644
--- a/Modules/CheckSymbolExists.cmake
+++ b/Modules/CheckSymbolExists.cmake
@@ -99,8 +99,28 @@
       string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT
         "#include <${FILE}>\n")
     endforeach()
-    string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT
-      "\nint main(int argc, char** argv)\n{\n  (void)argv;\n#ifndef ${SYMBOL}\n  return ((int*)(&${SYMBOL}))[argc];\n#else\n  (void)argc;\n  return 0;\n#endif\n}\n")
+    string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
+int main(int argc, char** argv)
+{
+  (void)argv;")
+    set(_CSE_CHECK_NON_MACRO "return ((int*)(&${SYMBOL}))[argc];")
+    if("${SYMBOL}" MATCHES "^[a-zA-Z_][a-zA-Z0-9_]*$")
+      # The SYMBOL has a legal macro name.  Test whether it exists as a macro.
+      string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
+#ifndef ${SYMBOL}
+  ${_CSE_CHECK_NON_MACRO}
+#else
+  (void)argc;
+  return 0;
+#endif")
+    else()
+      # The SYMBOL cannot be a macro (e.g., a template function).
+      string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
+  ${_CSE_CHECK_NON_MACRO}")
+    endif()
+    string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "
+}")
+    unset(_CSE_CHECK_NON_MACRO)
 
     configure_file("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in"
       "${SOURCEFILE}" @ONLY)
@@ -139,6 +159,7 @@
         "${OUTPUT}\nFile ${SOURCEFILE}:\n"
         "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n")
     endif()
+    unset(CMAKE_CONFIGURABLE_FILE_CONTENT)
   endif()
 endmacro()
 
diff --git a/Modules/Platform/Android-Clang.cmake b/Modules/Platform/Android-Clang.cmake
index 9ed1e01..847178f 100644
--- a/Modules/Platform/Android-Clang.cmake
+++ b/Modules/Platform/Android-Clang.cmake
@@ -40,6 +40,9 @@
   endif()
   if(NOT CMAKE_${lang}_COMPILER_TARGET)
     set(CMAKE_${lang}_COMPILER_TARGET "${_ANDROID_ABI_CLANG_TARGET}")
+    if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
+      string(APPEND CMAKE_${lang}_COMPILER_TARGET "${CMAKE_SYSTEM_VERSION}")
+    endif()
     list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "--target=${CMAKE_${lang}_COMPILER_TARGET}")
   endif()
 endmacro()
diff --git a/Modules/Platform/Android-Common.cmake b/Modules/Platform/Android-Common.cmake
index f8b9346..1affcd0 100644
--- a/Modules/Platform/Android-Common.cmake
+++ b/Modules/Platform/Android-Common.cmake
@@ -47,7 +47,41 @@
 endif()
 
 if(CMAKE_ANDROID_STL_TYPE)
-  if(CMAKE_ANDROID_NDK)
+  if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
+    if(CMAKE_ANDROID_STL_TYPE STREQUAL "system")
+      set(_ANDROID_STL_EXCEPTIONS 0)
+      set(_ANDROID_STL_RTTI 0)
+      macro(__android_stl lang)
+        string(APPEND CMAKE_${lang}_FLAGS_INIT " -stdlib=libstdc++")
+      endmacro()
+    elseif(CMAKE_ANDROID_STL_TYPE STREQUAL "c++_static")
+      set(_ANDROID_STL_EXCEPTIONS 1)
+      set(_ANDROID_STL_RTTI 1)
+      macro(__android_stl lang)
+        string(APPEND CMAKE_${lang}_FLAGS_INIT " -stdlib=libc++")
+        string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " -static-libstdc++")
+      endmacro()
+    elseif(CMAKE_ANDROID_STL_TYPE STREQUAL "c++_shared")
+      set(_ANDROID_STL_EXCEPTIONS 1)
+      set(_ANDROID_STL_RTTI 1)
+      macro(__android_stl lang)
+        string(APPEND CMAKE_${lang}_FLAGS_INIT " -stdlib=libc++")
+      endmacro()
+    elseif(CMAKE_ANDROID_STL_TYPE STREQUAL "none")
+      set(_ANDROID_STL_RTTI 0)
+      set(_ANDROID_STL_EXCEPTIONS 0)
+      macro(__android_stl lang)
+        # FIXME: Add a way to add project-wide language-specific compile-only flags.
+        set(CMAKE_CXX_COMPILE_OBJECT
+          "<CMAKE_CXX_COMPILER>  <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE> -nostdinc++")
+        string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " -nostdlib++")
+      endmacro()
+    else()
+      message(FATAL_ERROR
+        "Android: STL '${CMAKE_ANDROID_STL_TYPE}' not supported by this NDK."
+        )
+    endif()
+  elseif(CMAKE_ANDROID_NDK)
 
     macro(__android_stl_inc lang dir req)
       if(EXISTS "${dir}")
@@ -152,6 +186,10 @@
     __android_stl(CXX)
   endif()
 
+  if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
+    string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " -latomic -lm")
+  endif()
+
   # <ndk>/build/core/definitions.mk appends the sysroot's include directory
   # explicitly at the end of the command-line include path so that it
   # precedes the toolchain's builtin include directories.  This is
@@ -161,7 +199,7 @@
   #
   # Do not do this for a standalone toolchain because it is already
   # tied to a specific API version.
-  if(CMAKE_ANDROID_NDK)
+  if(CMAKE_ANDROID_NDK AND NOT CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
     if(CMAKE_SYSROOT_COMPILE)
       set(_cmake_sysroot_compile "${CMAKE_SYSROOT_COMPILE}")
     else()
@@ -170,7 +208,7 @@
     if(NOT CMAKE_ANDROID_NDK_DEPRECATED_HEADERS)
       list(APPEND CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES
         "${_cmake_sysroot_compile}/usr/include"
-        "${_cmake_sysroot_compile}/usr/include/${CMAKE_ANDROID_ARCH_HEADER_TRIPLE}"
+        "${_cmake_sysroot_compile}/usr/include/${CMAKE_ANDROID_ARCH_TRIPLE}"
         )
     else()
       list(APPEND CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES "${_cmake_sysroot_compile}/usr/include")
diff --git a/Modules/Platform/Android-Determine.cmake b/Modules/Platform/Android-Determine.cmake
index bb42eed..e7c1b48 100644
--- a/Modules/Platform/Android-Determine.cmake
+++ b/Modules/Platform/Android-Determine.cmake
@@ -198,32 +198,66 @@
   message(FATAL_ERROR "Android: The API specified by CMAKE_SYSTEM_VERSION='${CMAKE_SYSTEM_VERSION}' is not an integer.")
 endif()
 
+if(CMAKE_ANDROID_NDK)
+  # Identify the host platform.
+  if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
+    if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64")
+      set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "darwin-x86_64")
+    else()
+      set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "darwin-x86")
+    endif()
+  elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
+    if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64")
+      set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "linux-x86_64")
+    else()
+      set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "linux-x86")
+    endif()
+  elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
+    if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "AMD64")
+      set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "windows-x86_64")
+    else()
+      set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "windows")
+    endif()
+  else()
+    message(FATAL_ERROR "Android: Builds hosted on '${CMAKE_HOST_SYSTEM_NAME}' not supported.")
+  endif()
+
+  # Look for a unified toolchain/sysroot provided with the NDK.
+  set(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED "${CMAKE_ANDROID_NDK}/toolchains/llvm/prebuilt/${CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG}")
+  if(NOT IS_DIRECTORY "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/sysroot")
+    set(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED "")
+  endif()
+else()
+  set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "")
+  set(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED "")
+endif()
+
 # https://developer.android.com/ndk/guides/abis.html
 
 set(_ANDROID_ABI_arm64-v8a_PROC     "aarch64")
 set(_ANDROID_ABI_arm64-v8a_ARCH     "arm64")
-set(_ANDROID_ABI_arm64-v8a_HEADER   "aarch64-linux-android")
+set(_ANDROID_ABI_arm64-v8a_TRIPLE   "aarch64-linux-android")
 set(_ANDROID_ABI_armeabi-v7a_PROC   "armv7-a")
 set(_ANDROID_ABI_armeabi-v7a_ARCH   "arm")
-set(_ANDROID_ABI_armeabi-v7a_HEADER "arm-linux-androideabi")
+set(_ANDROID_ABI_armeabi-v7a_TRIPLE "arm-linux-androideabi")
 set(_ANDROID_ABI_armeabi-v6_PROC    "armv6")
 set(_ANDROID_ABI_armeabi-v6_ARCH    "arm")
-set(_ANDROID_ABI_armeabi-v6_HEADER  "arm-linux-androideabi")
+set(_ANDROID_ABI_armeabi-v6_TRIPLE  "arm-linux-androideabi")
 set(_ANDROID_ABI_armeabi_PROC       "armv5te")
 set(_ANDROID_ABI_armeabi_ARCH       "arm")
-set(_ANDROID_ABI_armeabi_HEADER     "arm-linux-androideabi")
+set(_ANDROID_ABI_armeabi_TRIPLE     "arm-linux-androideabi")
 set(_ANDROID_ABI_mips_PROC          "mips")
 set(_ANDROID_ABI_mips_ARCH          "mips")
-set(_ANDROID_ABI_mips_HEADER        "mipsel-linux-android")
+set(_ANDROID_ABI_mips_TRIPLE        "mipsel-linux-android")
 set(_ANDROID_ABI_mips64_PROC        "mips64")
 set(_ANDROID_ABI_mips64_ARCH        "mips64")
-set(_ANDROID_ABI_mips64_HEADER      "mips64el-linux-android")
+set(_ANDROID_ABI_mips64_TRIPLE      "mips64el-linux-android")
 set(_ANDROID_ABI_x86_PROC           "i686")
 set(_ANDROID_ABI_x86_ARCH           "x86")
-set(_ANDROID_ABI_x86_HEADER         "i686-linux-android")
+set(_ANDROID_ABI_x86_TRIPLE         "i686-linux-android")
 set(_ANDROID_ABI_x86_64_PROC        "x86_64")
 set(_ANDROID_ABI_x86_64_ARCH        "x86_64")
-set(_ANDROID_ABI_x86_64_HEADER      "x86_64-linux-android")
+set(_ANDROID_ABI_x86_64_TRIPLE      "x86_64-linux-android")
 
 set(_ANDROID_PROC_aarch64_ARCH_ABI "arm64-v8a")
 set(_ANDROID_PROC_armv7-a_ARCH_ABI "armeabi-v7a")
@@ -308,7 +342,7 @@
     "does not match architecture '${CMAKE_ANDROID_ARCH}' for the ABI '${CMAKE_ANDROID_ARCH_ABI}'."
     )
 endif()
-set(CMAKE_ANDROID_ARCH_HEADER_TRIPLE "${_ANDROID_ABI_${CMAKE_ANDROID_ARCH_ABI}_HEADER}")
+set(CMAKE_ANDROID_ARCH_TRIPLE "${_ANDROID_ABI_${CMAKE_ANDROID_ARCH_ABI}_TRIPLE}")
 
 # Select a processor.
 if(NOT CMAKE_SYSTEM_PROCESSOR)
@@ -321,7 +355,7 @@
 endif()
 
 if(CMAKE_ANDROID_NDK AND NOT DEFINED CMAKE_ANDROID_NDK_DEPRECATED_HEADERS)
-  if(IS_DIRECTORY "${CMAKE_ANDROID_NDK}/sysroot/usr/include/${CMAKE_ANDROID_ARCH_HEADER_TRIPLE}")
+  if(IS_DIRECTORY "${CMAKE_ANDROID_NDK}/sysroot/usr/include/${CMAKE_ANDROID_ARCH_TRIPLE}")
     # Unified headers exist so we use them by default.
     set(CMAKE_ANDROID_NDK_DEPRECATED_HEADERS 0)
   else()
@@ -340,8 +374,10 @@
 
 if(CMAKE_ANDROID_NDK)
   string(APPEND CMAKE_SYSTEM_CUSTOM_CODE
-    "set(CMAKE_ANDROID_ARCH_HEADER_TRIPLE \"${CMAKE_ANDROID_ARCH_HEADER_TRIPLE}\")\n"
+    "set(CMAKE_ANDROID_ARCH_TRIPLE \"${CMAKE_ANDROID_ARCH_TRIPLE}\")\n"
     "set(CMAKE_ANDROID_NDK_DEPRECATED_HEADERS \"${CMAKE_ANDROID_NDK_DEPRECATED_HEADERS}\")\n"
+    "set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG \"${CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG}\")\n"
+    "set(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED \"${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}\")\n"
     )
 endif()
 
diff --git a/Modules/Platform/Android-Initialize.cmake b/Modules/Platform/Android-Initialize.cmake
index a434f90..a5d2820 100644
--- a/Modules/Platform/Android-Initialize.cmake
+++ b/Modules/Platform/Android-Initialize.cmake
@@ -17,6 +17,13 @@
   return()
 endif()
 
+set(CMAKE_BUILD_TYPE_INIT Debug)
+
+# Skip sysroot selection if the NDK has a unified toolchain.
+if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
+  return()
+endif()
+
 if(NOT CMAKE_SYSROOT)
   if(CMAKE_ANDROID_NDK)
     set(CMAKE_SYSROOT "${CMAKE_ANDROID_NDK}/platforms/android-${CMAKE_SYSTEM_VERSION}/arch-${CMAKE_ANDROID_ARCH}")
@@ -40,5 +47,3 @@
     "Android: No CMAKE_SYSROOT was selected."
     )
 endif()
-
-set(CMAKE_BUILD_TYPE_INIT Debug)
diff --git a/Modules/Platform/Android/Determine-Compiler-NDK.cmake b/Modules/Platform/Android/Determine-Compiler-NDK.cmake
index 5f2cc52..e009c10 100644
--- a/Modules/Platform/Android/Determine-Compiler-NDK.cmake
+++ b/Modules/Platform/Android/Determine-Compiler-NDK.cmake
@@ -1,6 +1,31 @@
 # Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
 # file Copyright.txt or https://cmake.org/licensing for details.
 
+# In Android NDK r19 and above there is a single clang toolchain.
+if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
+  if(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION AND NOT CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION STREQUAL "clang")
+    message(FATAL_ERROR
+      "Android: The CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION value '${CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION}' "
+      "is not supported by this NDK.  It must be 'clang' or not set at all."
+      )
+  endif()
+  message(STATUS "Android: Selected unified Clang toolchain")
+  set(_ANDROID_TOOL_NDK_TOOLCHAIN_VERSION "clang")
+  set(_ANDROID_TOOL_C_COMPILER "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/bin/clang${_ANDROID_HOST_EXT}")
+  set(_ANDROID_TOOL_C_TOOLCHAIN_MACHINE "${CMAKE_ANDROID_ARCH_TRIPLE}")
+  set(_ANDROID_TOOL_C_TOOLCHAIN_VERSION "")
+  set(_ANDROID_TOOL_C_COMPILER_EXTERNAL_TOOLCHAIN "")
+  set(_ANDROID_TOOL_C_TOOLCHAIN_PREFIX "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/bin/${CMAKE_ANDROID_ARCH_TRIPLE}-")
+  set(_ANDROID_TOOL_C_TOOLCHAIN_SUFFIX "${_ANDROID_HOST_EXT}")
+  set(_ANDROID_TOOL_CXX_COMPILER "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/bin/clang++${_ANDROID_HOST_EXT}")
+  set(_ANDROID_TOOL_CXX_TOOLCHAIN_MACHINE "${CMAKE_ANDROID_ARCH_TRIPLE}")
+  set(_ANDROID_TOOL_CXX_TOOLCHAIN_VERSION "")
+  set(_ANDROID_TOOL_CXX_COMPILER_EXTERNAL_TOOLCHAIN "")
+  set(_ANDROID_TOOL_CXX_TOOLCHAIN_PREFIX "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/bin/${CMAKE_ANDROID_ARCH_TRIPLE}-")
+  set(_ANDROID_TOOL_CXX_TOOLCHAIN_SUFFIX "${_ANDROID_HOST_EXT}")
+  return()
+endif()
+
 # In Android NDK releases there is build system toolchain selection logic in
 # these files:
 #
@@ -195,40 +220,16 @@
   set(_ANDROID_TOOL_PREFIX "${CMAKE_MATCH_1}")
 endif()
 
-# Identify the host platform.
-if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
-  if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64")
-    set(_ANDROID_HOST_DIR "darwin-x86_64")
-  else()
-    set(_ANDROID_HOST_DIR "darwin-x86")
-  endif()
-elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
-  if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64")
-    set(_ANDROID_HOST_DIR "linux-x86_64")
-  else()
-    set(_ANDROID_HOST_DIR "linux-x86")
-  endif()
-elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
-  if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "AMD64")
-    set(_ANDROID_HOST_DIR "windows-x86_64")
-  else()
-    set(_ANDROID_HOST_DIR "windows")
-  endif()
-else()
-  message(FATAL_ERROR "Android: Builds hosted on '${CMAKE_HOST_SYSTEM_NAME}' not supported.")
-endif()
-
 # Help CMakeFindBinUtils locate things.
 set(_CMAKE_TOOLCHAIN_PREFIX "${_ANDROID_TOOL_PREFIX}")
 
-set(_ANDROID_TOOL_NDK_TOOLCHAIN_HOST_TAG "${_ANDROID_HOST_DIR}")
 set(_ANDROID_TOOL_NDK_TOOLCHAIN_VERSION "${_ANDROID_TOOL_VERS_NDK}")
 
 # _ANDROID_TOOL_PREFIX should now match `gcc -dumpmachine`.
 string(REGEX REPLACE "-$" "" _ANDROID_TOOL_C_TOOLCHAIN_MACHINE "${_ANDROID_TOOL_PREFIX}")
 
 set(_ANDROID_TOOL_C_TOOLCHAIN_VERSION "${_ANDROID_TOOL_VERS}")
-set(_ANDROID_TOOL_C_TOOLCHAIN_PREFIX "${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_NAME}/prebuilt/${_ANDROID_HOST_DIR}/bin/${_ANDROID_TOOL_PREFIX}")
+set(_ANDROID_TOOL_C_TOOLCHAIN_PREFIX "${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_NAME}/prebuilt/${CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG}/bin/${_ANDROID_TOOL_PREFIX}")
 set(_ANDROID_TOOL_C_TOOLCHAIN_SUFFIX "${_ANDROID_HOST_EXT}")
 
 set(_ANDROID_TOOL_CXX_TOOLCHAIN_MACHINE "${_ANDROID_TOOL_C_TOOLCHAIN_MACHINE}")
@@ -238,9 +239,9 @@
 
 if(_ANDROID_TOOL_CLANG_NAME)
   message(STATUS "Android: Selected Clang toolchain '${_ANDROID_TOOL_CLANG_NAME}' with GCC toolchain '${_ANDROID_TOOL_NAME}'")
-  set(_ANDROID_TOOL_C_COMPILER "${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_LLVM_NAME}/prebuilt/${_ANDROID_HOST_DIR}/bin/clang${_ANDROID_HOST_EXT}")
-  set(_ANDROID_TOOL_C_COMPILER_EXTERNAL_TOOLCHAIN ${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_NAME}/prebuilt/${_ANDROID_HOST_DIR})
-  set(_ANDROID_TOOL_CXX_COMPILER "${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_LLVM_NAME}/prebuilt/${_ANDROID_HOST_DIR}/bin/clang++${_ANDROID_HOST_EXT}")
+  set(_ANDROID_TOOL_C_COMPILER "${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_LLVM_NAME}/prebuilt/${CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG}/bin/clang${_ANDROID_HOST_EXT}")
+  set(_ANDROID_TOOL_C_COMPILER_EXTERNAL_TOOLCHAIN ${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_NAME}/prebuilt/${CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG})
+  set(_ANDROID_TOOL_CXX_COMPILER "${CMAKE_ANDROID_NDK}/toolchains/${_ANDROID_TOOL_LLVM_NAME}/prebuilt/${CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG}/bin/clang++${_ANDROID_HOST_EXT}")
   set(_ANDROID_TOOL_CXX_COMPILER_EXTERNAL_TOOLCHAIN "${_ANDROID_TOOL_C_COMPILER_EXTERNAL_TOOLCHAIN}")
 else()
   message(STATUS "Android: Selected GCC toolchain '${_ANDROID_TOOL_NAME}'")
@@ -267,4 +268,3 @@
 unset(_ANDROID_TOOL_CLANG_NAME)
 unset(_ANDROID_TOOL_CLANG_VERS)
 unset(_ANDROID_TOOL_LLVM_NAME)
-unset(_ANDROID_HOST_DIR)
diff --git a/Modules/Platform/Android/Determine-Compiler-Standalone.cmake b/Modules/Platform/Android/Determine-Compiler-Standalone.cmake
index 4c1ac1f..5095aff 100644
--- a/Modules/Platform/Android/Determine-Compiler-Standalone.cmake
+++ b/Modules/Platform/Android/Determine-Compiler-Standalone.cmake
@@ -62,5 +62,4 @@
   set(_ANDROID_TOOL_CXX_COMPILER_EXTERNAL_TOOLCHAIN "")
 endif()
 
-set(_ANDROID_TOOL_NDK_TOOLCHAIN_HOST_TAG "")
 set(_ANDROID_TOOL_NDK_TOOLCHAIN_VERSION "")
diff --git a/Modules/Platform/Android/Determine-Compiler.cmake b/Modules/Platform/Android/Determine-Compiler.cmake
index a03ebcc..5c6b97b 100644
--- a/Modules/Platform/Android/Determine-Compiler.cmake
+++ b/Modules/Platform/Android/Determine-Compiler.cmake
@@ -40,7 +40,6 @@
 elseif(CMAKE_ANDROID_STANDALONE_TOOLCHAIN)
   include(Platform/Android/Determine-Compiler-Standalone)
 else()
-  set(_ANDROID_TOOL_NDK_TOOLCHAIN_HOST_TAG "")
   set(_ANDROID_TOOL_NDK_TOOLCHAIN_VERSION "")
   set(_ANDROID_TOOL_C_COMPILER "")
   set(_ANDROID_TOOL_C_TOOLCHAIN_MACHINE "")
@@ -65,7 +64,6 @@
 
     # Save the Android-specific information in CMake${lang}Compiler.cmake.
     set(CMAKE_${lang}_COMPILER_CUSTOM_CODE "
-set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG \"${_ANDROID_TOOL_NDK_TOOLCHAIN_HOST_TAG}\")
 set(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION \"${_ANDROID_TOOL_NDK_TOOLCHAIN_VERSION}\")
 set(CMAKE_${lang}_ANDROID_TOOLCHAIN_MACHINE \"${_ANDROID_TOOL_${lang}_TOOLCHAIN_MACHINE}\")
 set(CMAKE_${lang}_ANDROID_TOOLCHAIN_VERSION \"${_ANDROID_TOOL_${lang}_TOOLCHAIN_VERSION}\")
diff --git a/Modules/Platform/Android/abi-common.cmake b/Modules/Platform/Android/abi-common.cmake
index 6bce3c7..b01ef61 100644
--- a/Modules/Platform/Android/abi-common.cmake
+++ b/Modules/Platform/Android/abi-common.cmake
@@ -3,7 +3,7 @@
   " -no-canonical-prefixes"
   )
 
-if(CMAKE_ANDROID_NDK AND NOT CMAKE_ANDROID_NDK_DEPRECATED_HEADERS)
+if(CMAKE_ANDROID_NDK AND NOT CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED AND NOT CMAKE_ANDROID_NDK_DEPRECATED_HEADERS)
   string(APPEND _ANDROID_ABI_INIT_CFLAGS " -D__ANDROID_API__=${CMAKE_SYSTEM_VERSION}")
 endif()
 
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 193c14f..63a4207 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
 # CMake version number components.
 set(CMake_VERSION_MAJOR 3)
 set(CMake_VERSION_MINOR 15)
-set(CMake_VERSION_PATCH 20190726)
+set(CMake_VERSION_PATCH 20190730)
 #set(CMake_VERSION_RC 0)
 set(CMake_VERSION_IS_DIRTY 0)
 
diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx
index d7bcf7e..da7f8bc 100644
--- a/Source/cmOutputConverter.cxx
+++ b/Source/cmOutputConverter.cxx
@@ -6,7 +6,6 @@
 #include <assert.h>
 #include <ctype.h>
 #include <set>
-#include <string.h>
 #include <vector>
 
 #include "cmState.h"
@@ -38,10 +37,10 @@
   return this->ConvertToOutputFormat(remote, format);
 }
 
-std::string cmOutputConverter::ConvertToOutputFormat(const std::string& source,
+std::string cmOutputConverter::ConvertToOutputFormat(cm::string_view source,
                                                      OutputFormat output) const
 {
-  std::string result = source;
+  std::string result(source);
   // Convert it to an output path.
   if (output == SHELL || output == WATCOMQUOTE) {
     result = this->ConvertDirectorySeparatorsForShell(source);
@@ -53,9 +52,9 @@
 }
 
 std::string cmOutputConverter::ConvertDirectorySeparatorsForShell(
-  const std::string& source) const
+  cm::string_view source) const
 {
-  std::string result = source;
+  std::string result(source);
   // For the MSYS shell convert drive letters to posix paths, so
   // that c:/some/path becomes /c/some/path.  This is needed to
   // avoid problems with the shell path translation.
@@ -71,21 +70,21 @@
   return result;
 }
 
-static bool cmOutputConverterIsShellOperator(const std::string& str)
+static bool cmOutputConverterIsShellOperator(cm::string_view str)
 {
-  static std::set<std::string> const shellOperators{
+  static std::set<cm::string_view> const shellOperators{
     "<", ">", "<<", ">>", "|", "||", "&&", "&>", "1>", "2>", "2>&1", "1>&2"
   };
   return (shellOperators.count(str) != 0);
 }
 
-std::string cmOutputConverter::EscapeForShell(const std::string& str,
+std::string cmOutputConverter::EscapeForShell(cm::string_view str,
                                               bool makeVars, bool forEcho,
                                               bool useWatcomQuote) const
 {
   // Do not escape shell operators.
   if (cmOutputConverterIsShellOperator(str)) {
-    return str;
+    return std::string(str);
   }
 
   // Compute the flags for the target shell environment.
@@ -117,46 +116,44 @@
     flags |= Shell_Flag_IsUnix;
   }
 
-  return Shell__GetArgument(str.c_str(), flags);
+  return Shell__GetArgument(str, flags);
 }
 
-std::string cmOutputConverter::EscapeForCMake(const std::string& str)
+std::string cmOutputConverter::EscapeForCMake(cm::string_view str)
 {
   // Always double-quote the argument to take care of most escapes.
   std::string result = "\"";
-  for (const char* c = str.c_str(); *c; ++c) {
-    if (*c == '"') {
+  for (const char c : str) {
+    if (c == '"') {
       // Escape the double quote to avoid ending the argument.
       result += "\\\"";
-    } else if (*c == '$') {
+    } else if (c == '$') {
       // Escape the dollar to avoid expanding variables.
       result += "\\$";
-    } else if (*c == '\\') {
+    } else if (c == '\\') {
       // Escape the backslash to avoid other escapes.
       result += "\\\\";
     } else {
       // Other characters will be parsed correctly.
-      result += *c;
+      result += c;
     }
   }
   result += "\"";
   return result;
 }
 
-std::string cmOutputConverter::EscapeWindowsShellArgument(const char* arg,
+std::string cmOutputConverter::EscapeWindowsShellArgument(cm::string_view arg,
                                                           int shell_flags)
 {
   return Shell__GetArgument(arg, shell_flags);
 }
 
 cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat(
-  const char* value)
+  cm::string_view value)
 {
   FortranFormat format = FortranFormatNone;
-  if (value && *value) {
-    std::vector<std::string> fmt;
-    cmSystemTools::ExpandListArgument(value, fmt);
-    for (std::string const& fi : fmt) {
+  if (!value.empty()) {
+    for (std::string const& fi : cmSystemTools::ExpandedListArgument(value)) {
       if (fi == "FIXED") {
         format = FortranFormatFixed;
       }
@@ -168,6 +165,15 @@
   return format;
 }
 
+cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat(
+  const char* value)
+{
+  if (!value) {
+    return FortranFormatNone;
+  }
+  return GetFortranFormat(cm::string_view(value));
+}
+
 void cmOutputConverter::SetLinkScriptShell(bool linkScriptShell)
 {
   this->LinkScriptShell = linkScriptShell;
@@ -213,12 +219,12 @@
 */
 
 /* Some helpers to identify character classes */
-static int Shell__CharIsWhitespace(char c)
+static bool Shell__CharIsWhitespace(char c)
 {
   return ((c == ' ') || (c == '\t'));
 }
 
-static int Shell__CharNeedsQuotesOnUnix(char c)
+static bool Shell__CharNeedsQuotesOnUnix(char c)
 {
   return ((c == '\'') || (c == '`') || (c == ';') || (c == '#') ||
           (c == '&') || (c == '$') || (c == '(') || (c == ')') || (c == '~') ||
@@ -226,51 +232,52 @@
           (c == '\\'));
 }
 
-static int Shell__CharNeedsQuotesOnWindows(char c)
+static bool Shell__CharNeedsQuotesOnWindows(char c)
 {
   return ((c == '\'') || (c == '#') || (c == '&') || (c == '<') ||
           (c == '>') || (c == '|') || (c == '^'));
 }
 
-static int Shell__CharIsMakeVariableName(char c)
+static bool Shell__CharIsMakeVariableName(char c)
 {
   return c && (c == '_' || isalpha((static_cast<int>(c))));
 }
 
-int cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags)
+bool cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags)
 {
   /* On Windows the built-in command shell echo never needs quotes.  */
   if (!(flags & Shell_Flag_IsUnix) && (flags & Shell_Flag_EchoWindows)) {
-    return 0;
+    return false;
   }
 
   /* On all platforms quotes are needed to preserve whitespace.  */
   if (Shell__CharIsWhitespace(c)) {
-    return 1;
+    return true;
   }
 
   if (flags & Shell_Flag_IsUnix) {
     /* On UNIX several special characters need quotes to preserve them.  */
     if (Shell__CharNeedsQuotesOnUnix(c)) {
-      return 1;
+      return true;
     }
   } else {
     /* On Windows several special characters need quotes to preserve them.  */
     if (Shell__CharNeedsQuotesOnWindows(c)) {
-      return 1;
+      return true;
     }
   }
-  return 0;
+  return false;
 }
 
-const char* cmOutputConverter::Shell__SkipMakeVariables(const char* c)
+cm::string_view::iterator cmOutputConverter::Shell__SkipMakeVariables(
+  cm::string_view::iterator c, cm::string_view::iterator end)
 {
-  while (*c == '$' && *(c + 1) == '(') {
-    const char* skip = c + 2;
-    while (Shell__CharIsMakeVariableName(*skip)) {
+  while ((c != end && (c + 1) != end) && (*c == '$' && *(c + 1) == '(')) {
+    cm::string_view::iterator skip = c + 2;
+    while ((skip != end) && Shell__CharIsMakeVariableName(*skip)) {
       ++skip;
     }
-    if (*skip == ')') {
+    if ((skip != end) && *skip == ')') {
       c = skip + 1;
     } else {
       break;
@@ -302,63 +309,60 @@
 */
 #define KWSYS_SYSTEM_SHELL_QUOTE_MAKE_VARIABLES 0
 
-int cmOutputConverter::Shell__ArgumentNeedsQuotes(const char* in, int flags)
+bool cmOutputConverter::Shell__ArgumentNeedsQuotes(cm::string_view in,
+                                                   int flags)
 {
   /* The empty string needs quotes.  */
-  if (!*in) {
-    return 1;
+  if (in.empty()) {
+    return true;
   }
 
   /* Scan the string for characters that require quoting.  */
-  {
-    const char* c;
-    for (c = in; *c; ++c) {
-      /* Look for $(MAKEVAR) syntax if requested.  */
-      if (flags & Shell_Flag_AllowMakeVariables) {
+  for (cm::string_view::iterator cit = in.begin(), cend = in.end();
+       cit != cend; ++cit) {
+    /* Look for $(MAKEVAR) syntax if requested.  */
+    if (flags & Shell_Flag_AllowMakeVariables) {
 #if KWSYS_SYSTEM_SHELL_QUOTE_MAKE_VARIABLES
-        const char* skip = Shell__SkipMakeVariables(c);
-        if (skip != c) {
-          /* We need to quote make variable references to preserve the
-             string with contents substituted in its place.  */
-          return 1;
-        }
+      cm::string_view::iterator skip = Shell__SkipMakeVariables(cit, cend);
+      if (skip != cit) {
+        /* We need to quote make variable references to preserve the
+           string with contents substituted in its place.  */
+        return true;
+      }
 #else
-        /* Skip over the make variable references if any are present.  */
-        c = Shell__SkipMakeVariables(c);
+      /* Skip over the make variable references if any are present.  */
+      cit = Shell__SkipMakeVariables(cit, cend);
 
-        /* Stop if we have reached the end of the string.  */
-        if (!*c) {
-          break;
-        }
+      /* Stop if we have reached the end of the string.  */
+      if (cit == cend) {
+        break;
+      }
 #endif
-      }
+    }
 
-      /* Check whether this character needs quotes.  */
-      if (Shell__CharNeedsQuotes(*c, flags)) {
-        return 1;
-      }
+    /* Check whether this character needs quotes.  */
+    if (Shell__CharNeedsQuotes(*cit, flags)) {
+      return true;
     }
   }
 
   /* On Windows some single character arguments need quotes.  */
-  if (flags & Shell_Flag_IsUnix && *in && !*(in + 1)) {
-    char c = *in;
+  if (flags & Shell_Flag_IsUnix && in.size() == 1) {
+    char c = in[0];
     if ((c == '?') || (c == '&') || (c == '^') || (c == '|') || (c == '#')) {
-      return 1;
+      return true;
     }
   }
 
-  return 0;
+  return false;
 }
 
-std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
+std::string cmOutputConverter::Shell__GetArgument(cm::string_view in,
+                                                  int flags)
 {
   /* Output will be at least as long as input string.  */
   std::string out;
-  out.reserve(strlen(in));
-
-  /* String iterator.  */
-  const char* c;
+  out.reserve(in.size());
 
   /* Keep track of how many backslashes have been encountered in a row.  */
   int windows_backslashes = 0;
@@ -378,14 +382,15 @@
   }
 
   /* Scan the string for characters that require escaping or quoting.  */
-  for (c = in; *c; ++c) {
+  for (cm::string_view::iterator cit = in.begin(), cend = in.end();
+       cit != cend; ++cit) {
     /* Look for $(MAKEVAR) syntax if requested.  */
     if (flags & Shell_Flag_AllowMakeVariables) {
-      const char* skip = Shell__SkipMakeVariables(c);
-      if (skip != c) {
+      cm::string_view::iterator skip = Shell__SkipMakeVariables(cit, cend);
+      if (skip != cit) {
         /* Copy to the end of the make variable references.  */
-        while (c != skip) {
-          out += *c++;
+        while (cit != skip) {
+          out += *cit++;
         }
 
         /* The make variable reference eliminates any escaping needed
@@ -393,7 +398,7 @@
         windows_backslashes = 0;
 
         /* Stop if we have reached the end of the string.  */
-        if (!*c) {
+        if (cit == cend) {
           break;
         }
       }
@@ -403,7 +408,7 @@
     if (flags & Shell_Flag_IsUnix) {
       /* On Unix a few special characters need escaping even inside a
          quoted argument.  */
-      if (*c == '\\' || *c == '"' || *c == '`' || *c == '$') {
+      if (*cit == '\\' || *cit == '"' || *cit == '`' || *cit == '$') {
         /* This character needs a backslash to escape it.  */
         out += '\\';
       }
@@ -411,10 +416,10 @@
       /* On Windows the built-in command shell echo never needs escaping.  */
     } else {
       /* On Windows only backslashes and double-quotes need escaping.  */
-      if (*c == '\\') {
+      if (*cit == '\\') {
         /* Found a backslash.  It may need to be escaped later.  */
         ++windows_backslashes;
-      } else if (*c == '"') {
+      } else if (*cit == '"') {
         /* Found a double-quote.  Escape all immediately preceding
            backslashes.  */
         while (windows_backslashes > 0) {
@@ -432,7 +437,7 @@
     }
 
     /* Check whether this character needs escaping for a make tool.  */
-    if (*c == '$') {
+    if (*cit == '$') {
       if (flags & Shell_Flag_Make) {
         /* In Makefiles a dollar is written $$.  The make tool will
            replace it with just $ before passing it to the shell.  */
@@ -449,7 +454,7 @@
         /* Otherwise a dollar is written just $. */
         out += '$';
       }
-    } else if (*c == '#') {
+    } else if (*cit == '#') {
       if ((flags & Shell_Flag_Make) && (flags & Shell_Flag_WatcomWMake)) {
         /* In Watcom WMake makefiles a pound is written $#.  The make
            tool will replace it with just # before passing it to the
@@ -459,7 +464,7 @@
         /* Otherwise a pound is written just #. */
         out += '#';
       }
-    } else if (*c == '%') {
+    } else if (*cit == '%') {
       if ((flags & Shell_Flag_VSIDE) ||
           ((flags & Shell_Flag_Make) &&
            ((flags & Shell_Flag_MinGWMake) || (flags & Shell_Flag_NMake)))) {
@@ -469,7 +474,7 @@
         /* Otherwise a percent is written just %. */
         out += '%';
       }
-    } else if (*c == ';') {
+    } else if (*cit == ';') {
       if (flags & Shell_Flag_VSIDE) {
         /* In a VS IDE a semicolon is written ";".  If this is written
            in an un-quoted argument it starts a quoted segment,
@@ -483,7 +488,7 @@
       }
     } else {
       /* Store this character.  */
-      out += *c;
+      out += *cit;
     }
   }
 
diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h
index deca767..671efe7 100644
--- a/Source/cmOutputConverter.h
+++ b/Source/cmOutputConverter.h
@@ -5,9 +5,10 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include <string>
-
 #include "cmStateSnapshot.h"
+#include "cm_string_view.hxx"
+
+#include <string>
 
 class cmState;
 
@@ -22,10 +23,9 @@
     WATCOMQUOTE,
     RESPONSE
   };
-  std::string ConvertToOutputFormat(const std::string& source,
+  std::string ConvertToOutputFormat(cm::string_view source,
                                     OutputFormat output) const;
-  std::string ConvertDirectorySeparatorsForShell(
-    const std::string& source) const;
+  std::string ConvertDirectorySeparatorsForShell(cm::string_view source) const;
 
   //! for existing files convert to output path and short path if spaces
   std::string ConvertToOutputForExisting(const std::string& remote,
@@ -72,15 +72,15 @@
     Shell_Flag_IsUnix = (1 << 8)
   };
 
-  std::string EscapeForShell(const std::string& str, bool makeVars = false,
+  std::string EscapeForShell(cm::string_view str, bool makeVars = false,
                              bool forEcho = false,
                              bool useWatcomQuote = false) const;
 
-  static std::string EscapeForCMake(const std::string& str);
+  static std::string EscapeForCMake(cm::string_view str);
 
   /** Compute an escaped version of the given argument for use in a
       windows shell.  */
-  static std::string EscapeWindowsShellArgument(const char* arg,
+  static std::string EscapeWindowsShellArgument(cm::string_view arg,
                                                 int shell_flags);
 
   enum FortranFormat
@@ -89,15 +89,17 @@
     FortranFormatFixed,
     FortranFormatFree
   };
+  static FortranFormat GetFortranFormat(cm::string_view value);
   static FortranFormat GetFortranFormat(const char* value);
 
 private:
   cmState* GetState() const;
 
-  static int Shell__CharNeedsQuotes(char c, int flags);
-  static const char* Shell__SkipMakeVariables(const char* c);
-  static int Shell__ArgumentNeedsQuotes(const char* in, int flags);
-  static std::string Shell__GetArgument(const char* in, int flags);
+  static bool Shell__CharNeedsQuotes(char c, int flags);
+  static cm::string_view::iterator Shell__SkipMakeVariables(
+    cm::string_view::iterator begin, cm::string_view::iterator end);
+  static bool Shell__ArgumentNeedsQuotes(cm::string_view in, int flags);
+  static std::string Shell__GetArgument(cm::string_view in, int flags);
 
 private:
   cmStateSnapshot StateSnapshot;
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 3ba3640..e0005a0 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -176,36 +176,37 @@
 }
 #endif
 
-std::string cmSystemTools::EscapeQuotes(const std::string& str)
+std::string cmSystemTools::EscapeQuotes(cm::string_view str)
 {
   std::string result;
   result.reserve(str.size());
-  for (const char* ch = str.c_str(); *ch != '\0'; ++ch) {
-    if (*ch == '"') {
+  for (const char ch : str) {
+    if (ch == '"') {
       result += '\\';
     }
-    result += *ch;
+    result += ch;
   }
   return result;
 }
 
-std::string cmSystemTools::HelpFileName(std::string name)
+std::string cmSystemTools::HelpFileName(cm::string_view str)
 {
+  std::string name(str);
   cmSystemTools::ReplaceString(name, "<", "");
   cmSystemTools::ReplaceString(name, ">", "");
   return name;
 }
 
-std::string cmSystemTools::TrimWhitespace(const std::string& s)
+std::string cmSystemTools::TrimWhitespace(cm::string_view str)
 {
-  std::string::const_iterator start = s.begin();
-  while (start != s.end() && cm_isspace(*start)) {
+  auto start = str.begin();
+  while (start != str.end() && cm_isspace(*start)) {
     ++start;
   }
-  if (start == s.end()) {
-    return "";
+  if (start == str.end()) {
+    return std::string();
   }
-  std::string::const_iterator stop = s.end() - 1;
+  auto stop = str.end() - 1;
   while (cm_isspace(*stop)) {
     --stop;
   }
@@ -1121,7 +1122,7 @@
   }
 }
 
-void cmSystemTools::ExpandListArgument(const std::string& arg,
+void cmSystemTools::ExpandListArgument(cm::string_view arg,
                                        std::vector<std::string>& argsOut,
                                        bool emptyArgs)
 {
@@ -1129,25 +1130,29 @@
   if (!emptyArgs && arg.empty()) {
     return;
   }
+
   // if there are no ; in the name then just copy the current string
-  if (arg.find(';') == std::string::npos) {
-    argsOut.push_back(arg);
+  if (arg.find(';') == cm::string_view::npos) {
+    argsOut.emplace_back(arg);
     return;
   }
+
   std::string newArg;
-  const char* last = arg.c_str();
   // Break the string at non-escaped semicolons not nested in [].
   int squareNesting = 0;
-  for (const char* c = last; *c; ++c) {
+  cm::string_view::iterator last = arg.begin();
+  cm::string_view::iterator const cend = arg.end();
+  for (cm::string_view::iterator c = last; c != cend; ++c) {
     switch (*c) {
       case '\\': {
         // We only want to allow escaping of semicolons.  Other
         // escapes should not be processed here.
-        const char* next = c + 1;
-        if (*next == ';') {
-          newArg.append(last, c - last);
+        cm::string_view::iterator cnext = c + 1;
+        if ((cnext != cend) && *cnext == ';') {
+          newArg.append(last, c);
           // Skip over the escape character
-          last = c = next;
+          last = cnext;
+          c = cnext;
         }
       } break;
       case '[': {
@@ -1160,7 +1165,7 @@
         // Break the string here if we are not nested inside square
         // brackets.
         if (squareNesting == 0) {
-          newArg.append(last, c - last);
+          newArg.append(last, c);
           // Skip over the semicolon
           last = c + 1;
           if (!newArg.empty() || emptyArgs) {
@@ -1175,15 +1180,15 @@
       } break;
     }
   }
-  newArg.append(last);
+  newArg.append(last, cend);
   if (!newArg.empty() || emptyArgs) {
     // Add the last argument if the string is not empty.
-    argsOut.push_back(newArg);
+    argsOut.push_back(std::move(newArg));
   }
 }
 
 std::vector<std::string> cmSystemTools::ExpandedListArgument(
-  const std::string& arg, bool emptyArgs)
+  cm::string_view arg, bool emptyArgs)
 {
   std::vector<std::string> argsOut;
   ExpandListArgument(arg, argsOut, emptyArgs);
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 1962389..ac1aa80 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -32,7 +32,7 @@
    * Expand the ; separated string @a arg into multiple arguments.
    * All found arguments are appended to @a argsOut.
    */
-  static void ExpandListArgument(const std::string& arg,
+  static void ExpandListArgument(cm::string_view arg,
                                  std::vector<std::string>& argsOut,
                                  bool emptyArgs = false);
 
@@ -54,7 +54,7 @@
    * Same as ExpandListArgument but a new vector is created containing
    * the expanded arguments from the string @a arg.
    */
-  static std::vector<std::string> ExpandedListArgument(const std::string& arg,
+  static std::vector<std::string> ExpandedListArgument(cm::string_view arg,
                                                        bool emptyArgs = false);
 
   /**
@@ -78,15 +78,15 @@
                                    KeyWOW64 view = KeyWOW64_Default);
 
   //! Escape quotes in a string.
-  static std::string EscapeQuotes(const std::string& str);
+  static std::string EscapeQuotes(cm::string_view str);
 
   /** Map help document name to file name.  */
-  static std::string HelpFileName(std::string);
+  static std::string HelpFileName(cm::string_view);
 
   /**
    * Returns a string that has whitespace removed from the start and the end.
    */
-  static std::string TrimWhitespace(const std::string& s);
+  static std::string TrimWhitespace(cm::string_view str);
 
   using MessageCallback = std::function<void(const std::string&, const char*)>;
   /**
diff --git a/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt b/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt
index f058c19..2028a13 100644
--- a/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt
+++ b/Tests/CMakeOnly/CheckCXXSymbolExists/CMakeLists.txt
@@ -49,6 +49,15 @@
   message(STATUS "errno found in <cerrno>")
 endif ()
 
+check_cxx_symbol_exists("std::fopen" "cstdio" CSE_RESULT_FOPEN)
+if (NOT CSE_RESULT_FOPEN)
+  if(NOT ("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.10))
+    message(SEND_ERROR "CheckCXXSymbolExists did not find std::fopen in <cstdio>")
+  endif()
+else()
+  message(STATUS "std::fopen found in <cstdio>")
+endif()
+
 if (CMAKE_COMPILER_IS_GNUCXX)
   string(APPEND CMAKE_CXX_FLAGS " -O3")
   unset(CSE_RESULT_O3 CACHE)
@@ -60,3 +69,8 @@
     message(SEND_ERROR "CheckCXXSymbolExists reported a nonexistent symbol as existing with optimization -O3")
   endif ()
 endif ()
+
+check_cxx_symbol_exists("std::non_existent_function_for_symbol_test<int*>" "algorithm" CSE_RESULT_NON_SYMBOL)
+if (CSE_RESULT_NON_SYMBOL)
+  message(SEND_ERROR "CheckCXXSymbolExists reported a nonexistent symbol.")
+endif()
diff --git a/Tests/RunCMake/Android/common.cmake b/Tests/RunCMake/Android/common.cmake
index aaa7c89..d96ab86 100644
--- a/Tests/RunCMake/Android/common.cmake
+++ b/Tests/RunCMake/Android/common.cmake
@@ -6,8 +6,6 @@
 endif()
 
 foreach(f
-    "${CMAKE_C_ANDROID_TOOLCHAIN_PREFIX}gcc${CMAKE_C_ANDROID_TOOLCHAIN_SUFFIX}"
-    "${CMAKE_CXX_ANDROID_TOOLCHAIN_PREFIX}g++${CMAKE_CXX_ANDROID_TOOLCHAIN_SUFFIX}"
     "${CMAKE_CXX_ANDROID_TOOLCHAIN_PREFIX}ar${CMAKE_CXX_ANDROID_TOOLCHAIN_SUFFIX}"
     "${CMAKE_CXX_ANDROID_TOOLCHAIN_PREFIX}ld${CMAKE_CXX_ANDROID_TOOLCHAIN_SUFFIX}"
     )
@@ -51,23 +49,26 @@
   endif()
 endif()
 
-execute_process(
-  COMMAND "${CMAKE_C_ANDROID_TOOLCHAIN_PREFIX}gcc${CMAKE_C_ANDROID_TOOLCHAIN_SUFFIX}" -dumpmachine
-  OUTPUT_VARIABLE _out OUTPUT_STRIP_TRAILING_WHITESPACE
-  ERROR_VARIABLE _err
-  RESULT_VARIABLE _res
-  )
-if(NOT _res EQUAL 0)
-  message(SEND_ERROR "Failed to run 'gcc -dumpmachine':\n ${_res}")
-endif()
-string(REPLACE "--" "-" _out_check "${_out}")
-if(NOT _out_check STREQUAL "${CMAKE_C_ANDROID_TOOLCHAIN_MACHINE}"
-    AND NOT (_out STREQUAL "arm--linux-android" AND CMAKE_C_ANDROID_TOOLCHAIN_MACHINE STREQUAL "arm-linux-androideabi"))
-  message(SEND_ERROR "'gcc -dumpmachine' produced:\n"
-    " ${_out}\n"
-    "which does not match CMAKE_C_ANDROID_TOOLCHAIN_MACHINE:\n"
-    " ${CMAKE_C_ANDROID_TOOLCHAIN_MACHINE}"
+set(gcc ${CMAKE_C_ANDROID_TOOLCHAIN_PREFIX}gcc${CMAKE_C_ANDROID_TOOLCHAIN_SUFFIX})
+if(EXISTS "${gcc}")
+  execute_process(
+    COMMAND "${CMAKE_C_ANDROID_TOOLCHAIN_PREFIX}gcc${CMAKE_C_ANDROID_TOOLCHAIN_SUFFIX}" -dumpmachine
+    OUTPUT_VARIABLE _out OUTPUT_STRIP_TRAILING_WHITESPACE
+    ERROR_VARIABLE _err
+    RESULT_VARIABLE _res
     )
+  if(NOT _res EQUAL 0)
+    message(SEND_ERROR "Failed to run 'gcc -dumpmachine':\n ${_res}")
+  endif()
+  string(REPLACE "--" "-" _out_check "${_out}")
+  if(NOT _out_check STREQUAL "${CMAKE_C_ANDROID_TOOLCHAIN_MACHINE}"
+      AND NOT (_out STREQUAL "arm--linux-android" AND CMAKE_C_ANDROID_TOOLCHAIN_MACHINE STREQUAL "arm-linux-androideabi"))
+    message(SEND_ERROR "'gcc -dumpmachine' produced:\n"
+      " ${_out}\n"
+      "which does not match CMAKE_C_ANDROID_TOOLCHAIN_MACHINE:\n"
+      " ${CMAKE_C_ANDROID_TOOLCHAIN_MACHINE}"
+      )
+  endif()
 endif()
 
 if(CMAKE_ANDROID_STL_TYPE STREQUAL "none")
diff --git a/Tests/RunCMake/Android/ndk-arm64-v8a-stdout.txt b/Tests/RunCMake/Android/ndk-arm64-v8a-stdout.txt
index 8d0bdc2..a228ccc 100644
--- a/Tests/RunCMake/Android/ndk-arm64-v8a-stdout.txt
+++ b/Tests/RunCMake/Android/ndk-arm64-v8a-stdout.txt
@@ -1,2 +1,2 @@
 -- Android: Targeting API '[0-9]+' with architecture 'arm64', ABI 'arm64-v8a', and processor 'aarch64'
--- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+'
+-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+')
diff --git a/Tests/RunCMake/Android/ndk-armeabi-arm-stdout.txt b/Tests/RunCMake/Android/ndk-armeabi-arm-stdout.txt
index 3741da3..72ec00e 100644
--- a/Tests/RunCMake/Android/ndk-armeabi-arm-stdout.txt
+++ b/Tests/RunCMake/Android/ndk-armeabi-arm-stdout.txt
@@ -1,3 +1,3 @@
 -- Android: Targeting API '[0-9]+' with architecture 'arm', ABI 'armeabi', and processor 'armv5te'
--- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+'
+-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+')
 .*-- CMAKE_ANDROID_ARM_MODE=1
diff --git a/Tests/RunCMake/Android/ndk-armeabi-v7a-neon-stdout.txt b/Tests/RunCMake/Android/ndk-armeabi-v7a-neon-stdout.txt
index ac2bfd5..8bd87fa 100644
--- a/Tests/RunCMake/Android/ndk-armeabi-v7a-neon-stdout.txt
+++ b/Tests/RunCMake/Android/ndk-armeabi-v7a-neon-stdout.txt
@@ -1,3 +1,3 @@
 -- Android: Targeting API '[0-9]+' with architecture 'arm', ABI 'armeabi-v7a', and processor 'armv7-a'
--- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+'
+-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+')
 .*-- CMAKE_ANDROID_ARM_NEON=1
diff --git a/Tests/RunCMake/Android/ndk-armeabi-v7a-stdout.txt b/Tests/RunCMake/Android/ndk-armeabi-v7a-stdout.txt
index 0edb4f7..554548e 100644
--- a/Tests/RunCMake/Android/ndk-armeabi-v7a-stdout.txt
+++ b/Tests/RunCMake/Android/ndk-armeabi-v7a-stdout.txt
@@ -1,3 +1,3 @@
 -- Android: Targeting API '[0-9]+' with architecture 'arm', ABI 'armeabi-v7a', and processor 'armv7-a'
--- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+'
+-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+')
 .*-- CMAKE_ANDROID_ARM_NEON=0
diff --git a/Tests/RunCMake/Android/ndk-badver-stderr.txt b/Tests/RunCMake/Android/ndk-badver-stderr.txt
index df2c5e6..ce6bc4e 100644
--- a/Tests/RunCMake/Android/ndk-badver-stderr.txt
+++ b/Tests/RunCMake/Android/ndk-badver-stderr.txt
@@ -1,11 +1,12 @@
 ^CMake Error at .*/Modules/Platform/Android/Determine-Compiler-NDK.cmake:[0-9]+ \(message\):
-  Android: The CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION value 'badver' is not one
+  Android: The CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION value 'badver' is not(
+  supported by this NDK.  It must be 'clang' or not set at all\.| one
   of the allowed forms:
 
     <major>.<minor>       = GCC of specified version
     clang<major>.<minor>  = Clang of specified version
     clang                 = Clang of most recent available version
-
+)
 Call Stack \(most recent call first\):
 .*
   ndk-badver.cmake:1 \(enable_language\)
diff --git a/Tests/RunCMake/Android/ndk-badvernum-stderr.txt b/Tests/RunCMake/Android/ndk-badvernum-stderr.txt
index adacaf1..aec91d9 100644
--- a/Tests/RunCMake/Android/ndk-badvernum-stderr.txt
+++ b/Tests/RunCMake/Android/ndk-badvernum-stderr.txt
@@ -1,4 +1,6 @@
-^CMake Error at .*/Modules/Platform/Android/Determine-Compiler-NDK.cmake:[0-9]+ \(message\):
+^CMake Error at .*/Modules/Platform/Android/Determine-Compiler-NDK.cmake:[0-9]+ \(message\):(
+  Android: The CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION value '1.0' is not
+  supported by this NDK.  It must be 'clang' or not set at all.|
   Android: No toolchain for ABI 'armeabi(-v7a)?' found in the NDK:
 
     .*
@@ -6,7 +8,7 @@
   of the version specified by CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION:
 
     1\.0
-
+)
 Call Stack \(most recent call first\):
 .*
   ndk-badvernum.cmake:1 \(enable_language\)
diff --git a/Tests/RunCMake/Android/ndk-mips-stdout.txt b/Tests/RunCMake/Android/ndk-mips-stdout.txt
index c744683..8ce544d 100644
--- a/Tests/RunCMake/Android/ndk-mips-stdout.txt
+++ b/Tests/RunCMake/Android/ndk-mips-stdout.txt
@@ -1,2 +1,2 @@
 -- Android: Targeting API '[0-9]+' with architecture 'mips', ABI 'mips', and processor 'mips'
--- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+'
+-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+')
diff --git a/Tests/RunCMake/Android/ndk-mips64-stdout.txt b/Tests/RunCMake/Android/ndk-mips64-stdout.txt
index 839ddfd..1d7edea 100644
--- a/Tests/RunCMake/Android/ndk-mips64-stdout.txt
+++ b/Tests/RunCMake/Android/ndk-mips64-stdout.txt
@@ -1,2 +1,2 @@
 -- Android: Targeting API '[0-9]+' with architecture 'mips64', ABI 'mips64', and processor 'mips64'
--- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+'
+-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+')
diff --git a/Tests/RunCMake/Android/ndk-x86-stdout.txt b/Tests/RunCMake/Android/ndk-x86-stdout.txt
index 2dbb2f0..8d710fe 100644
--- a/Tests/RunCMake/Android/ndk-x86-stdout.txt
+++ b/Tests/RunCMake/Android/ndk-x86-stdout.txt
@@ -1,2 +1,2 @@
 -- Android: Targeting API '[0-9]+' with architecture 'x86', ABI 'x86', and processor 'i686'
--- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+'
+-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+')
diff --git a/Tests/RunCMake/Android/ndk-x86_64-stdout.txt b/Tests/RunCMake/Android/ndk-x86_64-stdout.txt
index a7ae91d..695a088 100644
--- a/Tests/RunCMake/Android/ndk-x86_64-stdout.txt
+++ b/Tests/RunCMake/Android/ndk-x86_64-stdout.txt
@@ -1,2 +1,2 @@
 -- Android: Targeting API '[0-9]+' with architecture 'x86_64', ABI 'x86_64', and processor 'x86_64'
--- Android: Selected (Clang toolchain '[^']+' with )?GCC toolchain '[^']+'
+-- Android: Selected (unified Clang toolchain|(Clang toolchain '[^']+' with )?GCC toolchain '[^']+')
diff --git a/Tests/RunCMake/find_program/RelAndAbsPath.cmake b/Tests/RunCMake/find_program/RelAndAbsPath.cmake
index 3c60a20..6b61980 100644
--- a/Tests/RunCMake/find_program/RelAndAbsPath.cmake
+++ b/Tests/RunCMake/find_program/RelAndAbsPath.cmake
@@ -10,7 +10,6 @@
 
 strip_windows_path_prefix("${CMAKE_CURRENT_SOURCE_DIR}" srcdir)
 
-file(MAKE_DIRECTORY "tmp${srcdir}")
 configure_file(testCWD "tmp${srcdir}/testNoSuchFile" COPYONLY)
 
 find_program(PROG_ABS