From 38140713ad24576f1c4e6253a1de91ff217dd475 Mon Sep 17 00:00:00 2001
From: Robert Maynard <rmaynard@nvidia.com>
Date: Mon, 22 Feb 2021 11:52:14 -0500
Subject: cmake: add support for --install-prefix command argument

Fixes: #21781
---
 Help/manual/OPTIONS_BUILD.txt                     |  3 +++
 Help/release/dev/cmake-install-prefix-command.rst |  5 +++++
 Source/cmake.cxx                                  | 17 +++++++++++++++++
 Source/cmake.h                                    |  2 ++
 Tests/ExternalProjectLocal/CMakeLists.txt         |  6 +++---
 Tests/RunCMake/CMP0041/RunCMakeTest.cmake         |  4 ++++
 Tests/RunCMake/CommandLine/RunCMakeTest.cmake     |  3 +++
 Tests/RunCMake/IfacePaths/RunCMakeTest.cmake      |  8 +++++---
 8 files changed, 42 insertions(+), 6 deletions(-)
 create mode 100644 Help/release/dev/cmake-install-prefix-command.rst

diff --git a/Help/manual/OPTIONS_BUILD.txt b/Help/manual/OPTIONS_BUILD.txt
index 0947e41..251672e 100644
--- a/Help/manual/OPTIONS_BUILD.txt
+++ b/Help/manual/OPTIONS_BUILD.txt
@@ -76,6 +76,9 @@
  native build system to choose a compiler or SDK.  See the
  :variable:`CMAKE_GENERATOR_PLATFORM` variable for details.
 
+``--install-prefix <directory>``
+ Specify the installation prefix, :variable:`CMAKE_INSTALL_PREFIX`.
+
 ``-Wno-dev``
  Suppress developer warnings.
 
diff --git a/Help/release/dev/cmake-install-prefix-command.rst b/Help/release/dev/cmake-install-prefix-command.rst
new file mode 100644
index 0000000..a5b140a
--- /dev/null
+++ b/Help/release/dev/cmake-install-prefix-command.rst
@@ -0,0 +1,5 @@
+cmake-install-prefix-command
+----------------------------
+
+* The :manual:`cmake(1)` command gained the ``--install-prefix <dir>``
+  command line option to specify the location of the install prefix.
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 7e6d5c3..f96badd 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -493,6 +493,16 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
     return true;
   };
 
+  auto PrefixLambda = [&](std::string const& path, cmake* state) -> bool {
+    const std::string var = "CMAKE_INSTALL_PREFIX";
+    cmStateEnums::CacheEntryType type = cmStateEnums::PATH;
+#ifndef CMAKE_BOOTSTRAP
+    state->UnprocessedPresetVariables.erase(var);
+#endif
+    state->ProcessCacheArg(var, path, type);
+    return true;
+  };
+
   std::vector<CommandArgument> arguments = {
     CommandArgument{ "-D", "-D must be followed with VAR=VALUE.",
                      CommandArgument::Values::One, DefineLambda },
@@ -511,8 +521,12 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
                        state->ReadListFile(args, path);
                        return true;
                      } },
+
     CommandArgument{ "-P", "-P must be followed by a file name.",
                      CommandArgument::Values::One, ScriptLambda },
+    CommandArgument{ "--install-prefix",
+                     "No install directory specified for --install-prefix",
+                     CommandArgument::Values::One, PrefixLambda },
     CommandArgument{ "--find-package", CommandArgument::Values::Zero,
                      [&](std::string const&, cmake*) -> bool {
                        findPackageMode = true;
@@ -815,6 +829,9 @@ void cmake::SetArgs(const std::vector<std::string>& args)
                      CommandArgument::Values::One, PlatformLambda },
     CommandArgument{ "-T", "No toolset specified for -T",
                      CommandArgument::Values::One, ToolsetLamda },
+    CommandArgument{ "--install-prefix",
+                     "No install directory specified for --install-prefix",
+                     CommandArgument::Values::One, IgnoreAndTrueLambda },
 
     CommandArgument{ "--check-build-system", CommandArgument::Values::Two,
                      [](std::string const& value, cmake* state) -> bool {
diff --git a/Source/cmake.h b/Source/cmake.h
index d6d129f..ab2ed21 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -712,6 +712,8 @@ private:
       "Specify toolset name if supported by generator." },                    \
     { "-A <platform-name>",                                                   \
       "Specify platform name if supported by generator." },                   \
+    { "--install-prefix <directory>",                                         \
+      "Specify install directory [CMAKE_INSTALL_PREFIX]." },                  \
     { "-Wdev", "Enable developer warnings." },                                \
     { "-Wno-dev", "Suppress developer warnings." },                           \
     { "-Werror=dev", "Make developer warnings errors." },                     \
diff --git a/Tests/ExternalProjectLocal/CMakeLists.txt b/Tests/ExternalProjectLocal/CMakeLists.txt
index 9a0241c..57e8105 100644
--- a/Tests/ExternalProjectLocal/CMakeLists.txt
+++ b/Tests/ExternalProjectLocal/CMakeLists.txt
@@ -41,7 +41,7 @@ set(TutorialStep5_install_dir ${install_dir})
 set(proj TutorialStep5-Local-TestAfterInstall)
 ExternalProject_Add(${proj}
 URL "${CMAKE_CURRENT_SOURCE_DIR}/Step5"
-CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -G ${CMAKE_GENERATOR} <SOURCE_DIR>
+CMAKE_ARGS --install-prefix=<INSTALL_DIR> -G ${CMAKE_GENERATOR} <SOURCE_DIR>
 CMAKE_CACHE_DEFAULT_ARGS -DUSE_MYMATH:BOOL=OFF
 TEST_AFTER_INSTALL 1
 LOG_TEST 1
@@ -51,7 +51,7 @@ set_property(TARGET ${proj} PROPERTY FOLDER "Local")
 set(proj TutorialStep5-Local-TestExcludeFromMainBefore)
 ExternalProject_Add(${proj}
 URL "${CMAKE_CURRENT_SOURCE_DIR}/Step5"
-CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>  -G ${CMAKE_GENERATOR} <SOURCE_DIR>
+CMAKE_ARGS --install-prefix=<INSTALL_DIR>  -G ${CMAKE_GENERATOR} <SOURCE_DIR>
 CMAKE_CACHE_DEFAULT_ARGS -DUSE_MYMATH:BOOL=OFF
 TEST_BEFORE_INSTALL 1
 TEST_EXCLUDE_FROM_MAIN 1
@@ -63,7 +63,7 @@ set_property(TARGET ${proj} PROPERTY FOLDER "Local")
 set(proj TutorialStep5-Local-TestExcludeFromMainAfter)
 ExternalProject_Add(${proj}
 URL "${CMAKE_CURRENT_SOURCE_DIR}/Step5"
-CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>  -G ${CMAKE_GENERATOR} <SOURCE_DIR>
+CMAKE_ARGS --install-prefix=<INSTALL_DIR>  -G ${CMAKE_GENERATOR} <SOURCE_DIR>
 CMAKE_CACHE_DEFAULT_ARGS -DUSE_MYMATH:BOOL=OFF
 TEST_AFTER_INSTALL 1
 TEST_EXCLUDE_FROM_MAIN 1
diff --git a/Tests/RunCMake/CMP0041/RunCMakeTest.cmake b/Tests/RunCMake/CMP0041/RunCMakeTest.cmake
index e7f27a1..f47bb2e 100644
--- a/Tests/RunCMake/CMP0041/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMP0041/RunCMakeTest.cmake
@@ -6,6 +6,10 @@ set(RunCMake_TEST_OPTIONS "-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/NotDefa
 run_cmake(CMP0041-OLD)
 run_cmake(CMP0041-NEW)
 run_cmake(CMP0041-WARN)
+
+# Protect tests from running inside the default install prefix.
+set(RunCMake_TEST_OPTIONS "--install-prefix ${RunCMake_BINARY_DIR}/NotDefaultPrefix")
+
 run_cmake(CMP0041-tid-OLD)
 run_cmake(CMP0041-tid-NEW)
 run_cmake(CMP0041-tid-WARN)
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index 51754fc..a2b2044 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -61,6 +61,9 @@ run_cmake_command(build-bad-dir
 run_cmake_command(build-bad-generator
   ${CMAKE_COMMAND} --build ${RunCMake_SOURCE_DIR}/cache-bad-generator)
 
+
+run_cmake_command(install-prefix-no-arg ${CMAKE_COMMAND} -B DummyBuildDir --install-prefix)
+
 run_cmake_command(install-no-dir
   ${CMAKE_COMMAND} --install)
 run_cmake_command(install-bad-dir
diff --git a/Tests/RunCMake/IfacePaths/RunCMakeTest.cmake b/Tests/RunCMake/IfacePaths/RunCMakeTest.cmake
index 066c83e..6530aee 100644
--- a/Tests/RunCMake/IfacePaths/RunCMakeTest.cmake
+++ b/Tests/RunCMake/IfacePaths/RunCMakeTest.cmake
@@ -18,6 +18,9 @@ run_cmake(BinaryDirectoryInInterface)
 set(RunCMake_TEST_OPTIONS "-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/DirInInstallPrefix/prefix")
 run_cmake(DirInInstallPrefix)
 
+set(RunCMake_TEST_OPTIONS "--install-prefix=${RunCMake_BINARY_DIR}/DirInInstallPrefix/prefix")
+run_cmake(DirInInstallPrefix)
+
 configure_file(
   "${RunCMake_SOURCE_DIR}/CMakeLists.txt"
   "${RunCMake_BINARY_DIR}/copy/CMakeLists.txt"
@@ -34,14 +37,13 @@ configure_file(
   COPYONLY
 )
 set(RunCMake_TEST_OPTIONS
-  "-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/copy/SourceDirectoryInInterface/prefix"
+  "--install-prefix=${RunCMake_BINARY_DIR}/copy/SourceDirectoryInInterface/prefix"
   "-DTEST_FILE=${RunCMake_BINARY_DIR}/copy/SourceDirectoryInInterface.cmake"
   )
 set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/copy")
 run_cmake(InstallInSrcDir)
 unset(RunCMake_TEST_SOURCE_DIR)
 
-set(RunCMake_TEST_OPTIONS "-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/InstallInBinDir-build/prefix")
 set(RunCMake_TEST_OPTIONS
   "-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/InstallInBinDir-build/prefix"
   "-DTEST_FILE=${RunCMake_SOURCE_DIR}/BinaryDirectoryInInterface.cmake"
@@ -77,7 +79,7 @@ foreach(policyStatus NEW OLD "")
     set(policySuffix -CMP0052-${policyStatus})
   endif()
   set(RunCMake_TEST_OPTIONS
-    "-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/prefix" ${policyOption}
+    "--install-prefix=${RunCMake_BINARY_DIR}/prefix" ${policyOption}
     "-DTEST_FILE=${RunCMake_SOURCE_DIR}/BinaryDirectoryInInterface.cmake"
     )
   # Set the RunCMake_TEST_SOURCE_DIR here to the copy too. This is needed to run
-- 
cgit v0.12