Merge topic 'implicit_lapack_library'

68dcbeee01 FindLAPACK: Test for implicitly linked LAPACK libraries

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !3451
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index 1d023cb..bac1c6c 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -57,6 +57,7 @@
 .. toctree::
    :maxdepth: 1
 
+   CMP0095: RPATH entries are properly escaped in the intermediary CMake install script. </policy/CMP0095>
    CMP0094: FindPython3, FindPython2 and FindPython use LOCATION for lookup strategy. </policy/CMP0094>
    CMP0093: FindBoost reports Boost_VERSION in x.y.z format. </policy/CMP0093>
    CMP0092: MSVC warning flags are not in CMAKE_{C,CXX}_FLAGS by default. </policy/CMP0092>
diff --git a/Help/policy/CMP0095.rst b/Help/policy/CMP0095.rst
new file mode 100644
index 0000000..4c56a05
--- /dev/null
+++ b/Help/policy/CMP0095.rst
@@ -0,0 +1,30 @@
+CMP0095
+-------
+
+``RPATH`` entries are properly escaped in the intermediary CMake install script.
+
+In CMake 3.15 and earlier, ``RPATH`` entries set via
+:variable:`CMAKE_INSTALL_RPATH` or via :prop_tgt:`INSTALL_RPATH` have not been
+escaped before being inserted into the ``cmake_install.cmake`` script. Dynamic
+linkers on ELF-based systems (e.g. Linux and FreeBSD) allow certain keywords in
+``RPATH`` entries, such as ``${ORIGIN}`` (More details are available in the
+``ld.so`` man pages on those systems). The syntax of these keywords can match
+CMake's variable syntax. In order to not be substituted (usually to an empty
+string) already by the intermediary ``cmake_install.cmake`` script, the user had
+to double-escape such ``RPATH`` keywords, e.g.
+``set(CMAKE_INSTALL_RPATH "\\\${ORIGIN}/../lib")``. Since the intermediary
+``cmake_install.cmake`` script is an implementation detail of CMake, CMake 3.16
+and later will make sure ``RPATH`` entries are inserted literally by escaping
+any coincidental CMake syntax.
+
+The ``OLD`` behavior of this policy is to not escape ``RPATH`` entries in the
+intermediary ``cmake_install.cmake`` script. The ``NEW`` behavior is to properly
+escape coincidental CMake syntax in ``RPATH`` entries when generating the
+intermediary ``cmake_install.cmake`` script.
+
+This policy was introduced in CMake version 3.16. CMake version |release| warns
+when the policy is not set and detected usage of CMake-like syntax and uses
+``OLD`` behavior. Use the :command:`cmake_policy` command to set it to ``OLD``
+or ``NEW`` explicitly.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/release/dev/CMP0095.rst b/Help/release/dev/CMP0095.rst
new file mode 100644
index 0000000..21d0550
--- /dev/null
+++ b/Help/release/dev/CMP0095.rst
@@ -0,0 +1,5 @@
+CMP0095
+-------
+
+* ``RPATH`` entries are properly escaped in the intermediary CMake install script.
+  See policy :policy:`CMP0095`.
diff --git a/Help/variable/CMAKE_PROJECT_INCLUDE.rst b/Help/variable/CMAKE_PROJECT_INCLUDE.rst
index 7de767a..965c94e 100644
--- a/Help/variable/CMAKE_PROJECT_INCLUDE.rst
+++ b/Help/variable/CMAKE_PROJECT_INCLUDE.rst
@@ -1,6 +1,9 @@
 CMAKE_PROJECT_INCLUDE
 ---------------------
 
-A CMake language file or module to be included by the :command:`project`
-command.  This is intended for injecting custom code into project
-builds without modifying their source.
+A CMake language file or module to be included as the last step of all
+:command:`project` command calls.  This is intended for injecting custom code
+into project builds without modifying their source.
+
+See also the :variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE` and
+:variable:`CMAKE_PROJECT_INCLUDE_BEFORE` variables.
diff --git a/Help/variable/CMAKE_PROJECT_INCLUDE_BEFORE.rst b/Help/variable/CMAKE_PROJECT_INCLUDE_BEFORE.rst
index 12a5263..70b15e6 100644
--- a/Help/variable/CMAKE_PROJECT_INCLUDE_BEFORE.rst
+++ b/Help/variable/CMAKE_PROJECT_INCLUDE_BEFORE.rst
@@ -1,6 +1,9 @@
 CMAKE_PROJECT_INCLUDE_BEFORE
 ----------------------------
 
-A CMake language file or module to be included before processing the
-:command:`project` command. This is intended for injecting custom code into
-project builds without modifying their source.
+A CMake language file or module to be included as the first step of all
+:command:`project` command calls.  This is intended for injecting custom code
+into project builds without modifying their source.
+
+See also the :variable:`CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE` and
+:variable:`CMAKE_PROJECT_INCLUDE` variables.
diff --git a/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE.rst b/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE.rst
index 5ca40a3..3485c38 100644
--- a/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE.rst
+++ b/Help/variable/CMAKE_PROJECT_PROJECT-NAME_INCLUDE.rst
@@ -1,6 +1,10 @@
 CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE
 ------------------------------------
 
-A CMake language file or module to be included by the :command:`project`
-command.  This is intended for injecting custom code into project
-builds without modifying their source.
+A CMake language file or module to be included as the last step of any
+:command:`project` command calls that specify ``<PROJECT-NAME>`` as the project
+name.  This is intended for injecting custom code into project builds without
+modifying their source.
+
+See also the :variable:`CMAKE_PROJECT_INCLUDE` and
+:variable:`CMAKE_PROJECT_INCLUDE_BEFORE` variables.
diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake
index 65e5d1c..77f9d0e 100644
--- a/Modules/FindBLAS.cmake
+++ b/Modules/FindBLAS.cmake
@@ -152,7 +152,9 @@
 
   foreach(_library ${_list})
     set(_combined_name ${_combined_name}_${_library})
-
+    if(NOT "${_thread}" STREQUAL "")
+      set(_combined_name ${_combined_name}_thread)
+    endif()
     if(_libraries_work)
       if (BLA_STATIC)
         if (WIN32)
@@ -479,6 +481,18 @@
       ""
       )
   endif()
+  if(NOT BLAS_LIBRARIES)
+    find_package(Threads)
+    # OpenBLAS (http://www.openblas.net)
+    check_fortran_libraries(
+      BLAS_LIBRARIES
+      BLAS
+      sgemm
+      ""
+      "openblas"
+      "${CMAKE_THREAD_LIBS_INIT}"
+      )
+  endif()
 endif ()
 
 if (BLA_VENDOR STREQUAL "FLAME" OR BLA_VENDOR STREQUAL "All")
diff --git a/Modules/Internal/CPack/CPackDeb.cmake b/Modules/Internal/CPack/CPackDeb.cmake
index 89dc6f0..7791822 100644
--- a/Modules/Internal/CPack/CPackDeb.cmake
+++ b/Modules/Internal/CPack/CPackDeb.cmake
@@ -45,7 +45,7 @@
       ERROR_QUIET
       OUTPUT_STRIP_TRAILING_WHITESPACE)
     if(result EQUAL 0)
-      string(REGEX MATCH "\\(SONAME\\)[^\n]*\\[([^\n]+)\\.so\\.([^\n]*)\\]" soname "${output}")
+      string(REGEX MATCH "\\(?SONAME\\)?[^\n]*\\[([^\n]+)\\.so\\.([^\n]*)\\]" soname "${output}")
       set(${libname} "${CMAKE_MATCH_1}" PARENT_SCOPE)
       set(${version} "${CMAKE_MATCH_2}" PARENT_SCOPE)
     else()
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 6f6bafb..9bef298 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 15)
-set(CMake_VERSION_PATCH 20190615)
+set(CMake_VERSION_PATCH 20190618)
 #set(CMake_VERSION_RC 1)
diff --git a/Source/cmDefinitions.cxx b/Source/cmDefinitions.cxx
index 5fafaf9..894447c 100644
--- a/Source/cmDefinitions.cxx
+++ b/Source/cmDefinitions.cxx
@@ -57,8 +57,7 @@
 
 void cmDefinitions::Set(const std::string& key, const char* value)
 {
-  Def def(value);
-  this->Map[key] = def;
+  this->Map[key] = Def(value);
 }
 
 std::vector<std::string> cmDefinitions::UnusedKeys() const
diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx
index ed45398..ba42669 100644
--- a/Source/cmFileAPI.cxx
+++ b/Source/cmFileAPI.cxx
@@ -812,7 +812,7 @@
     request["kind"] = ObjectKindName(ObjectKind::CodeModel);
     Json::Value& versions = request["version"] = Json::arrayValue;
     versions.append(BuildVersion(2, CodeModelV2Minor));
-    requests.append(std::move(request));
+    requests.append(std::move(request)); // NOLINT(*)
   }
 
   {
@@ -820,7 +820,7 @@
     request["kind"] = ObjectKindName(ObjectKind::Cache);
     Json::Value& versions = request["version"] = Json::arrayValue;
     versions.append(BuildVersion(2, CacheV2Minor));
-    requests.append(std::move(request));
+    requests.append(std::move(request)); // NOLINT(*)
   }
 
   {
@@ -828,7 +828,7 @@
     request["kind"] = ObjectKindName(ObjectKind::CMakeFiles);
     Json::Value& versions = request["version"] = Json::arrayValue;
     versions.append(BuildVersion(1, CMakeFilesV1Minor));
-    requests.append(std::move(request));
+    requests.append(std::move(request)); // NOLINT(*)
   }
 
   return capabilities;
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 8eefaa7..828488f 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -502,8 +502,13 @@
   if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_PREFER_CONFIG")) {
     if (this->UseConfigFiles && this->FindPackageUsingConfigMode()) {
       loadedPackage = true;
-    } else if (this->FindPackageUsingModuleMode()) {
-      loadedPackage = true;
+    } else {
+      if (this->FindPackageUsingModuleMode()) {
+        loadedPackage = true;
+      } else {
+        // The package was not loaded. Report errors.
+        HandlePackageMode(HandlePackageModeType::Module);
+      }
     }
   } else {
     if (this->UseFindModules && this->FindPackageUsingModuleMode()) {
@@ -603,7 +608,7 @@
   this->IgnoredPaths.insert(ignored.begin(), ignored.end());
 
   // Find and load the package.
-  return this->HandlePackageMode();
+  return this->HandlePackageMode(HandlePackageModeType::Config);
 }
 
 void cmFindPackageCommand::SetModuleVariables(const std::string& components)
@@ -722,7 +727,8 @@
   return true;
 }
 
-bool cmFindPackageCommand::HandlePackageMode()
+bool cmFindPackageCommand::HandlePackageMode(
+  HandlePackageModeType handlePackageModeType)
 {
   this->ConsideredConfigs.clear();
 
@@ -817,6 +823,12 @@
     }
   }
 
+  if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_PREFER_CONFIG") && !found &&
+      handlePackageModeType == HandlePackageModeType::Config) {
+    // Config mode failed. Allow Module case.
+    result = false;
+  }
+
   // package not found
   if (result && !found) {
     // warn if package required or neither quiet nor in config mode
diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h
index 4f6d97c..316ca0f 100644
--- a/Source/cmFindPackageCommand.h
+++ b/Source/cmFindPackageCommand.h
@@ -103,7 +103,14 @@
   bool FindModule(bool& found);
   void AddFindDefinition(const std::string& var, const char* val);
   void RestoreFindDefinitions();
-  bool HandlePackageMode();
+
+  enum /*class*/ HandlePackageModeType
+  {
+    Module,
+    Config
+  };
+  bool HandlePackageMode(HandlePackageModeType type);
+
   bool FindConfig();
   bool FindPrefixedConfig();
   bool FindFrameworkConfig();
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index 7c5a55b..0774436 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -16,6 +16,8 @@
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
+#include "cmOutputConverter.h"
+#include "cmPolicies.h"
 #include "cmStateTypes.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
@@ -632,17 +634,34 @@
     return;
   }
 
-  // Get the install RPATH from the link information.
-  std::string newRpath = cli->GetChrpathString();
-
   // Write a rule to remove the installed file if its rpath is not the
   // new rpath.  This is needed for existing build/install trees when
   // the installed rpath changes but the file is not rebuilt.
-  /* clang-format off */
   os << indent << "file(RPATH_CHECK\n"
-     << indent << "     FILE \"" << toDestDirPath << "\"\n"
-     << indent << "     RPATH \"" << newRpath << "\")\n";
-  /* clang-format on */
+     << indent << "     FILE \"" << toDestDirPath << "\"\n";
+
+  // CMP0095: ``RPATH`` entries are properly escaped in the intermediary
+  // CMake install script.
+  switch (this->Target->GetPolicyStatusCMP0095()) {
+    case cmPolicies::WARN:
+      // No author warning needed here, we warn later in
+      // cmInstallTargetGenerator::AddChrpathPatchRule().
+      CM_FALLTHROUGH;
+    case cmPolicies::OLD: {
+      // Get the install RPATH from the link information.
+      std::string newRpath = cli->GetChrpathString();
+      os << indent << "     RPATH \"" << newRpath << "\")\n";
+      break;
+    }
+    default: {
+      // Get the install RPATH from the link information and
+      // escape any CMake syntax in the install RPATH.
+      std::string escapedNewRpath =
+        cmOutputConverter::EscapeForCMake(cli->GetChrpathString());
+      os << indent << "     RPATH " << escapedNewRpath << ")\n";
+      break;
+    }
+  }
 }
 
 void cmInstallTargetGenerator::AddChrpathPatchRule(
@@ -731,11 +750,28 @@
       return;
     }
 
+    // Escape any CMake syntax in the RPATHs.
+    std::string escapedOldRpath = cmOutputConverter::EscapeForCMake(oldRpath);
+    std::string escapedNewRpath = cmOutputConverter::EscapeForCMake(newRpath);
+
     // Write a rule to run chrpath to set the install-tree RPATH
     os << indent << "file(RPATH_CHANGE\n"
        << indent << "     FILE \"" << toDestDirPath << "\"\n"
-       << indent << "     OLD_RPATH \"" << oldRpath << "\"\n"
-       << indent << "     NEW_RPATH \"" << newRpath << "\")\n";
+       << indent << "     OLD_RPATH " << escapedOldRpath << "\n";
+
+    // CMP0095: ``RPATH`` entries are properly escaped in the intermediary
+    // CMake install script.
+    switch (this->Target->GetPolicyStatusCMP0095()) {
+      case cmPolicies::WARN:
+        this->IssueCMP0095Warning(newRpath);
+        CM_FALLTHROUGH;
+      case cmPolicies::OLD:
+        os << indent << "     NEW_RPATH \"" << newRpath << "\")\n";
+        break;
+      default:
+        os << indent << "     NEW_RPATH " << escapedNewRpath << ")\n";
+        break;
+    }
   }
 }
 
@@ -838,3 +874,26 @@
      << "\"" << this->Target->Target->GetName() << "\" "
      << "\"" << toDestDirPath << "\")\n";
 }
+
+void cmInstallTargetGenerator::IssueCMP0095Warning(
+  const std::string& unescapedRpath)
+{
+  // Reduce warning noise to cases where used RPATHs may actually be affected
+  // by CMP0095. This filter is meant to skip warnings in cases when
+  // non-curly-braces syntax (e.g. $ORIGIN) or no keyword is used which has
+  // worked already before CMP0095. We intend to issue a warning in all cases
+  // with curly-braces syntax, even if the workaround of double-escaping is in
+  // place, since we deprecate the need for it with CMP0095.
+  const bool potentially_affected(unescapedRpath.find("${") !=
+                                  std::string::npos);
+
+  if (potentially_affected) {
+    std::ostringstream w;
+    w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0095) << "\n";
+    w << "RPATH entries for target '" << this->Target->GetName() << "' "
+      << "will not be escaped in the intermediary "
+      << "cmake_install.cmake script.";
+    this->Target->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
+      MessageType::AUTHOR_WARNING, w.str(), this->GetBacktrace());
+  }
+}
diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h
index ed3ab52..9ccad63 100644
--- a/Source/cmInstallTargetGenerator.h
+++ b/Source/cmInstallTargetGenerator.h
@@ -104,6 +104,7 @@
                      const std::string& toDestDirPath);
   void AddUniversalInstallRule(std::ostream& os, Indent indent,
                                const std::string& toDestDirPath);
+  void IssueCMP0095Warning(const std::string& unescapedRpath);
 
   std::string TargetName;
   cmGeneratorTarget* Target;
diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx
index 2a8bee6..469faca 100644
--- a/Source/cmLinkLineComputer.cxx
+++ b/Source/cmLinkLineComputer.cxx
@@ -99,14 +99,34 @@
   std::string const& libPathTerminator)
 {
   std::string linkPath;
-  std::vector<std::string> const& libDirs = cli.GetDirectories();
-  for (std::string const& libDir : libDirs) {
-    std::string libpath = this->ConvertToOutputForExisting(libDir);
-    linkPath += " " + libPathFlag;
-    linkPath += libpath;
-    linkPath += libPathTerminator;
-    linkPath += " ";
+
+  if (cli.GetLinkLanguage() == "Swift") {
+    for (const cmComputeLinkInformation::Item& item : cli.GetItems()) {
+      const cmGeneratorTarget* target = item.Target;
+      if (!target) {
+        continue;
+      }
+
+      if (target->GetType() == cmStateEnums::STATIC_LIBRARY ||
+          target->GetType() == cmStateEnums::SHARED_LIBRARY) {
+        cmStateEnums::ArtifactType type = cmStateEnums::RuntimeBinaryArtifact;
+        if (target->GetType() == cmStateEnums::SHARED_LIBRARY &&
+            target->IsDLLPlatform()) {
+          type = cmStateEnums::ImportLibraryArtifact;
+        }
+
+        linkPath += " " + libPathFlag +
+          item.Target->GetDirectory(cli.GetConfig(), type) +
+          libPathTerminator + " ";
+      }
+    }
   }
+
+  for (std::string const& libDir : cli.GetDirectories()) {
+    linkPath += " " + libPathFlag + this->ConvertToOutputForExisting(libDir) +
+      libPathTerminator + " ";
+  }
+
   return linkPath;
 }
 
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index b705119..c16a46f 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -279,7 +279,11 @@
   SELECT(POLICY, CMP0094,                                                     \
          "FindPython3,  FindPython2 and FindPyton use "                       \
          "LOCATION for lookup strategy.",                                     \
-         3, 15, 0, cmPolicies::WARN)
+         3, 15, 0, cmPolicies::WARN)                                          \
+  SELECT(POLICY, CMP0095,                                                     \
+         "RPATH entries are properly escaped in the intermediary CMake "      \
+         "install script.",                                                   \
+         3, 16, 0, cmPolicies::WARN)
 
 #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
 #define CM_FOR_EACH_POLICY_ID(POLICY)                                         \
@@ -307,7 +311,8 @@
   F(CMP0073)                                                                  \
   F(CMP0076)                                                                  \
   F(CMP0081)                                                                  \
-  F(CMP0083)
+  F(CMP0083)                                                                  \
+  F(CMP0095)
 
 /** \class cmPolicies
  * \brief Handles changes in CMake behavior and policies
diff --git a/Tests/FindPackageTest/CMakeLists.txt b/Tests/FindPackageTest/CMakeLists.txt
index 8802b73..affe5d5 100644
--- a/Tests/FindPackageTest/CMakeLists.txt
+++ b/Tests/FindPackageTest/CMakeLists.txt
@@ -579,3 +579,16 @@
 
 set(CMAKE_FIND_PACKAGE_PREFER_CONFIG OFF)
 set(CMAKE_PREFIX_PATH)
+
+############################################################################
+##Test find_package CMAKE_FIND_PACKAGE_PREFER_CONFIG with module fallback
+
+set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/PreferConfigOnlyModule)
+
+set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
+
+find_package(ACME REQUIRED)
+
+if(NOT ACME_FOUND)
+    message(SEND_ERROR "Did not find ACME package")
+endif()
diff --git a/Tests/FindPackageTest/PreferConfigOnlyModule/FindACME.cmake b/Tests/FindPackageTest/PreferConfigOnlyModule/FindACME.cmake
new file mode 100644
index 0000000..7a4e1b3
--- /dev/null
+++ b/Tests/FindPackageTest/PreferConfigOnlyModule/FindACME.cmake
@@ -0,0 +1 @@
+set(ACME_FOUND TRUE)
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 788d947..735ad5f 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -408,7 +408,12 @@
   set(NO_NAMELINK 0)
 endif()
 
-add_RunCMake_test(install -DNO_NAMELINK=${NO_NAMELINK} -DCYGWIN=${CYGWIN} -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID})
+add_RunCMake_test(install -DNO_NAMELINK=${NO_NAMELINK} -DCYGWIN=${CYGWIN} -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
+  -DCMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN=${CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN}
+  -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}
+  -DCMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG=${CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG}
+  -DCMAKE_EXECUTABLE_FORMAT=${CMAKE_EXECUTABLE_FORMAT})
+
 add_RunCMake_test(CPackCommandLine)
 add_RunCMake_test(CPackConfig)
 add_RunCMake_test(CPackInstallProperties)
diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
index 0bcf886..6d72fac 100644
--- a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
+++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
@@ -27,6 +27,7 @@
    \* CMP0076
    \* CMP0081
    \* CMP0083
+   \* CMP0095
 
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake
index 026148e..21c320b 100644
--- a/Tests/RunCMake/install/RunCMakeTest.cmake
+++ b/Tests/RunCMake/install/RunCMakeTest.cmake
@@ -48,6 +48,22 @@
   endif()
 endfunction()
 
+# Wrapper for run_cmake() that skips platforms that are non-ELF or have no RPATH support
+function(run_cmake_ELFRPATH_only case)
+  if(UNIX AND CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG AND CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF")
+    run_cmake(${case})
+  else()
+    # Sanity check against a platform known to be ELF-based
+    if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+      message(FATAL_ERROR "Expected platform Linux to advertize itself as ELF-based, but it did not.")
+    else()
+      message(STATUS "${case} - SKIPPED (No ELF-based platform found)")
+    endif()
+  endif()
+endfunction()
+
+run_cmake(TARGETS-FILE_RPATH_CHANGE-old_rpath)
+run_cmake_ELFRPATH_only(TARGETS-FILE_RPATH_CHANGE-new_rpath)
 run_cmake(DIRECTORY-MESSAGE_NEVER)
 run_cmake(DIRECTORY-PATTERN-MESSAGE_NEVER)
 run_cmake(DIRECTORY-message)
diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-check-common.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-check-common.cmake
new file mode 100644
index 0000000..673fdde
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-check-common.cmake
@@ -0,0 +1,30 @@
+file(READ ${RunCMake_TEST_BINARY_DIR}/cmake_install.cmake install_script)
+#message(STATUS ${install_script})
+
+set(wsnl " *[\n\r]+ *") # whitespace + single newline + whitespace
+set(wssl " *[\n\r]+[^\n\r]*[\n\r]+ *") # ws nl skipline nl ws
+string(CONCAT prefix [[file\(RPATH_CHANGE]])
+set(_msg "cmake_install.cmake does not match ")
+
+macro(check)
+  if(NOT install_script MATCHES "${regex}")
+    message(STATUS "${test} - check \"${target}\" - FAILED:")
+    string(CONCAT RunCMake_TEST_FAILED "${_msg}" ">>>${regex}<<<")
+    return()
+  else()
+    message(STATUS "${test} - check \"${target}\" - PASSED")
+  endif()
+endmacro()
+
+macro(skip_without_rpath_change_rule)
+# Not all platforms generate a file(RPATH_CHANGE) rule
+  if(NOT install_script MATCHES [[file\(RPATH_CHANGE]])
+    # Sanity check against a platform known to generate a file(RPATH_CHANGE) rule
+    if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+      message(FATAL_ERROR "Expected generated file(RPATH_CHANGE) rule on platform Linux.")
+    else()
+      message(STATUS "${test} - All checks skipped. No file(RPATH_CHANGE) rule found on this platform.")
+      return()
+    endif()
+  endif()
+endmacro()
diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-check.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-check.cmake
new file mode 100644
index 0000000..930ef70
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-check.cmake
@@ -0,0 +1,63 @@
+include(${RunCMake_SOURCE_DIR}/TARGETS-FILE_RPATH_CHANGE-check-common.cmake)
+skip_without_rpath_change_rule()
+string(APPEND prefix "${wsnl}" [[FILE "[^"]*/]])
+
+set(target "exe1_cmp0095_old")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "/foo/bar]])
+check()
+
+set(target "exe1_cmp0095_warn")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "/foo/bar]])
+check()
+
+set(target "exe1_cmp0095_new")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "/foo/bar]])
+check()
+
+set(target "exe2_cmp0095_old")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "\$ORIGIN/../lib]])
+check()
+
+set(target "exe2_cmp0095_warn")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "\$ORIGIN/../lib]])
+check()
+
+set(target "exe2_cmp0095_new")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "\\\$ORIGIN/../lib]])
+check()
+
+set(target "exe3_cmp0095_old")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "\${ORIGIN}/../lib]])
+check()
+
+set(target "exe3_cmp0095_warn")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "\${ORIGIN}/../lib]])
+check()
+
+set(target "exe3_cmp0095_new")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "\\\${ORIGIN}/../lib]])
+check()
+
+set(target "exe4_cmp0095_old")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "/foo/bar/\${PLATFORM}]])
+check()
+
+set(target "exe4_cmp0095_warn")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "/foo/bar/\${PLATFORM}]])
+check()
+
+set(target "exe4_cmp0095_new")
+string(CONCAT regex "${prefix}${target}\"${wssl}"
+              [[NEW_RPATH "/foo/bar/\\\${PLATFORM}]])
+check()
diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt
new file mode 100644
index 0000000..1e123f6
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath-stderr.txt
@@ -0,0 +1,23 @@
+^CMake Warning \(dev\) at TARGETS-FILE_RPATH_CHANGE-new_rpath\.cmake:[0-9]+ \(install\):
+  Policy CMP0095 is not set: RPATH entries are properly escaped in the
+  intermediary CMake install script\.  Run "cmake --help-policy CMP0095" for
+  policy details\.  Use the cmake_policy command to set the policy and
+  suppress this warning\.
+
+  RPATH entries for target 'exe3_cmp0095_warn' will not be escaped in the
+  intermediary cmake_install\.cmake script\.
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\.  Use -Wno-dev to suppress it\.
+
+CMake Warning \(dev\) at TARGETS-FILE_RPATH_CHANGE-new_rpath\.cmake:[0-9]+ \(install\):
+  Policy CMP0095 is not set: RPATH entries are properly escaped in the
+  intermediary CMake install script\.  Run "cmake --help-policy CMP0095" for
+  policy details\.  Use the cmake_policy command to set the policy and
+  suppress this warning\.
+
+  RPATH entries for target 'exe4_cmp0095_warn' will not be escaped in the
+  intermediary cmake_install\.cmake script\.
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\.  Use -Wno-dev to suppress it\.$
diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath.cmake
new file mode 100644
index 0000000..cba04b2
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-new_rpath.cmake
@@ -0,0 +1,72 @@
+cmake_minimum_required(VERSION 3.14)
+enable_language(C)
+
+# test matrix
+#
+# A :=
+#                        | no cmake syntax | cmake syntax |
+# -----------------------+-----------------+--------------+
+# absolute install RPATH |       exe1      |     exe4     |
+# relative install RPATH |       exe2      |     exe3     |
+#
+# all := A * CMP005_OLD + A * CMP0095_WARN + A * CMP0095_NEW
+
+add_library(utils SHARED obj1.c)
+set(targets utils)
+
+set(exe1_install_rpath "/foo/bar")
+set(exe2_install_rpath "\$ORIGIN/../lib")
+set(exe3_install_rpath "\${ORIGIN}/../lib")
+set(exe4_install_rpath "/foo/bar/\${PLATFORM}")
+
+macro(A_CMP0095 policy_value)
+  cmake_policy(PUSH)
+  if(NOT "x${policy_value}x" STREQUAL "xWARNx")
+    cmake_policy(SET CMP0095 ${policy_value})
+  endif()
+  string(TOLOWER "${policy_value}" p)
+
+  # exe1: absolute install RPATH, no cmake syntax
+  set(case "exe1")
+  set(target "${case}_cmp0095_${p}")
+  list(APPEND targets ${target})
+  add_executable(${target} main.c)
+  target_link_libraries(${target} PRIVATE utils)
+  set_target_properties(${target} PROPERTIES
+    INSTALL_RPATH "${${case}_install_rpath}")
+
+  # exe2: relative install RPATH, no cmake syntax
+  set(case "exe2")
+  set(target "${case}_cmp0095_${p}")
+  list(APPEND targets ${target})
+  add_executable(${target} main.c)
+  target_link_libraries(${target} PRIVATE utils)
+  set_target_properties(${target} PROPERTIES
+    INSTALL_RPATH "${${case}_install_rpath}")
+
+  # exe3: relative install RPATH, cmake syntax
+  set(case "exe3")
+  set(target "${case}_cmp0095_${p}")
+  list(APPEND targets ${target})
+  add_executable(${target} main.c)
+  target_link_libraries(${target} PRIVATE utils)
+  set_target_properties(${target} PROPERTIES
+    INSTALL_RPATH "${${case}_install_rpath}")
+
+  # exe4: absolute install RPATH, cmake syntax
+  set(case "exe4")
+  set(target "${case}_cmp0095_${p}")
+  list(APPEND targets ${target})
+  add_executable(${target} main.c)
+  target_link_libraries(${target} PRIVATE utils)
+  set_target_properties(${target} PROPERTIES
+    INSTALL_RPATH "${${case}_install_rpath}")
+
+  cmake_policy(POP)
+endmacro()
+
+A_CMP0095("OLD")
+A_CMP0095("WARN") # exe3 and exe4 are expected to issue an author warning
+A_CMP0095("NEW")
+
+install(TARGETS ${targets})
diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath-check.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath-check.cmake
new file mode 100644
index 0000000..814f405
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath-check.cmake
@@ -0,0 +1,15 @@
+include(${RunCMake_SOURCE_DIR}/TARGETS-FILE_RPATH_CHANGE-check-common.cmake)
+skip_without_rpath_change_rule()
+string(APPEND prefix "${wsnl}" [[FILE "[^"]*/]])
+
+set(target "exe1")
+string(CONCAT regex "${prefix}${target}\"${wsnl}"
+              [[OLD_RPATH "]] "${RunCMake_BINARY_DIR}")
+check()
+
+if("x${CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN}" STREQUAL "x\$ORIGIN")
+  set(target "exe2")
+  string(CONCAT regex "${prefix}${target}\"${wsnl}"
+                [[OLD_RPATH "\\\$ORIGIN]])
+  check()
+endif()
diff --git a/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath.cmake b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath.cmake
new file mode 100644
index 0000000..43ae787
--- /dev/null
+++ b/Tests/RunCMake/install/TARGETS-FILE_RPATH_CHANGE-old_rpath.cmake
@@ -0,0 +1,18 @@
+cmake_minimum_required(VERSION 3.14)
+enable_language(C)
+
+add_library(utils SHARED obj1.c)
+
+# exe1: absolute build RPATH, no cmake syntax
+set(CMAKE_BUILD_RPATH_USE_ORIGIN OFF)
+set(CMAKE_INSTALL_RPATH "/foo/bar")
+add_executable(exe1 main.c)
+target_link_libraries(exe1 PRIVATE utils)
+
+# exe2: relative build RPATH, no cmake syntax
+set(CMAKE_BUILD_RPATH_USE_ORIGIN ON)
+set(CMAKE_INSTALL_RPATH "/foo/bar")
+add_executable(exe2 main.c)
+target_link_libraries(exe2 PRIVATE utils)
+
+install(TARGETS utils exe1 exe2)
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile.cmake
index 6e718f8..6567438 100644
--- a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile.cmake
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux-notfile.cmake
@@ -1,4 +1,5 @@
 enable_language(C)
+cmake_policy(SET CMP0095 NEW)
 
 file(WRITE "${CMAKE_BINARY_DIR}/test.c" "void test(void) {}\n")
 file(WRITE "${CMAKE_BINARY_DIR}/main.c" [[extern void test(void);
@@ -13,7 +14,7 @@
 add_library(test SHARED "${CMAKE_BINARY_DIR}/test.c")
 add_executable(exe "${CMAKE_BINARY_DIR}/main.c")
 target_link_libraries(exe PRIVATE test)
-set_property(TARGET exe PROPERTY INSTALL_RPATH "\\\${ORIGIN}/../lib")
+set_property(TARGET exe PROPERTY INSTALL_RPATH "\${ORIGIN}/../lib")
 
 install(TARGETS exe DESTINATION bin)
 
diff --git a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux.cmake b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux.cmake
index 433dd3b..bd0f9f1 100644
--- a/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux.cmake
+++ b/Tests/RunCMake/install/file-GET_RUNTIME_DEPENDENCIES-linux.cmake
@@ -1,4 +1,5 @@
 enable_language(C)
+cmake_policy(SET CMP0095 NEW)
 
 set(test_rpath_names
   preexcluded
@@ -52,8 +53,8 @@
 set_property(TARGET test_rpath PROPERTY INSTALL_RPATH
   "${CMAKE_BINARY_DIR}/root-all/lib/rpath_postexcluded"
   "${CMAKE_BINARY_DIR}/root-all/lib/rpath"
-  "\\\$ORIGIN/rpath_origin_postexcluded"
-  "\\\${ORIGIN}/rpath_origin" # This must be double-escaped because of issue #19225.
+  "\$ORIGIN/rpath_origin_postexcluded"
+  "\${ORIGIN}/rpath_origin"
   "${CMAKE_BINARY_DIR}/root-all/lib/conflict"
   )
 target_link_options(test_rpath PRIVATE -Wl,--disable-new-dtags)
@@ -88,8 +89,8 @@
   "${CMAKE_BINARY_DIR}/root-all/lib/runpath/../rpath" # Ensure that files that don't conflict are treated correctly
   "${CMAKE_BINARY_DIR}/root-all/lib/runpath_postexcluded"
   "${CMAKE_BINARY_DIR}/root-all/lib/runpath"
-  "\\\${ORIGIN}/runpath_origin_postexcluded" # This must be double-escaped because of issue #19225.
-  "\\\$ORIGIN/runpath_origin"
+  "\${ORIGIN}/runpath_origin_postexcluded"
+  "\$ORIGIN/runpath_origin"
   "${CMAKE_BINARY_DIR}/root-all/lib/conflict2"
   )
 target_link_options(test_runpath PRIVATE -Wl,--enable-new-dtags)
diff --git a/Tests/Tutorial/Complete/tutorial.cxx b/Tests/Tutorial/Complete/tutorial.cxx
index 443d195..4451cbd 100644
--- a/Tests/Tutorial/Complete/tutorial.cxx
+++ b/Tests/Tutorial/Complete/tutorial.cxx
@@ -10,7 +10,7 @@
 {
   if (argc < 2) {
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
diff --git a/Tests/Tutorial/MultiPackage/tutorial.cxx b/Tests/Tutorial/MultiPackage/tutorial.cxx
index 443d195..4451cbd 100644
--- a/Tests/Tutorial/MultiPackage/tutorial.cxx
+++ b/Tests/Tutorial/MultiPackage/tutorial.cxx
@@ -10,7 +10,7 @@
 {
   if (argc < 2) {
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
diff --git a/Tests/Tutorial/Step10/tutorial.cxx b/Tests/Tutorial/Step10/tutorial.cxx
index 443d195..4451cbd 100644
--- a/Tests/Tutorial/Step10/tutorial.cxx
+++ b/Tests/Tutorial/Step10/tutorial.cxx
@@ -10,7 +10,7 @@
 {
   if (argc < 2) {
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
diff --git a/Tests/Tutorial/Step11/tutorial.cxx b/Tests/Tutorial/Step11/tutorial.cxx
index 3768855..38d4a79 100644
--- a/Tests/Tutorial/Step11/tutorial.cxx
+++ b/Tests/Tutorial/Step11/tutorial.cxx
@@ -10,7 +10,7 @@
 {
   if (argc < 2) {
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
diff --git a/Tests/Tutorial/Step2/tutorial.cxx b/Tests/Tutorial/Step2/tutorial.cxx
index 75b7d67..5ba34e8 100644
--- a/Tests/Tutorial/Step2/tutorial.cxx
+++ b/Tests/Tutorial/Step2/tutorial.cxx
@@ -9,7 +9,7 @@
 {
   if (argc < 2) {
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
diff --git a/Tests/Tutorial/Step3/tutorial.cxx b/Tests/Tutorial/Step3/tutorial.cxx
index 1d5742d..c2b89df 100644
--- a/Tests/Tutorial/Step3/tutorial.cxx
+++ b/Tests/Tutorial/Step3/tutorial.cxx
@@ -13,7 +13,7 @@
 {
   if (argc < 2) {
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
diff --git a/Tests/Tutorial/Step4/tutorial.cxx b/Tests/Tutorial/Step4/tutorial.cxx
index 1d5742d..c2b89df 100644
--- a/Tests/Tutorial/Step4/tutorial.cxx
+++ b/Tests/Tutorial/Step4/tutorial.cxx
@@ -13,7 +13,7 @@
 {
   if (argc < 2) {
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
diff --git a/Tests/Tutorial/Step5/tutorial.cxx b/Tests/Tutorial/Step5/tutorial.cxx
index 1d5742d..c2b89df 100644
--- a/Tests/Tutorial/Step5/tutorial.cxx
+++ b/Tests/Tutorial/Step5/tutorial.cxx
@@ -13,7 +13,7 @@
 {
   if (argc < 2) {
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
diff --git a/Tests/Tutorial/Step6/tutorial.cxx b/Tests/Tutorial/Step6/tutorial.cxx
index 1d5742d..c2b89df 100644
--- a/Tests/Tutorial/Step6/tutorial.cxx
+++ b/Tests/Tutorial/Step6/tutorial.cxx
@@ -13,7 +13,7 @@
 {
   if (argc < 2) {
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
diff --git a/Tests/Tutorial/Step7/tutorial.cxx b/Tests/Tutorial/Step7/tutorial.cxx
index 1d5742d..c2b89df 100644
--- a/Tests/Tutorial/Step7/tutorial.cxx
+++ b/Tests/Tutorial/Step7/tutorial.cxx
@@ -13,7 +13,7 @@
 {
   if (argc < 2) {
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
diff --git a/Tests/Tutorial/Step8/tutorial.cxx b/Tests/Tutorial/Step8/tutorial.cxx
index 1d5742d..c2b89df 100644
--- a/Tests/Tutorial/Step8/tutorial.cxx
+++ b/Tests/Tutorial/Step8/tutorial.cxx
@@ -13,7 +13,7 @@
 {
   if (argc < 2) {
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
diff --git a/Tests/Tutorial/Step9/tutorial.cxx b/Tests/Tutorial/Step9/tutorial.cxx
index 73e67a9..6c41859 100644
--- a/Tests/Tutorial/Step9/tutorial.cxx
+++ b/Tests/Tutorial/Step9/tutorial.cxx
@@ -14,7 +14,7 @@
 {
   if (argc < 2) {
     std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
-              << Tutorial_VERSION_MAJOR << std::endl;
+              << Tutorial_VERSION_MINOR << std::endl;
     std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }