Merge topic 'cmake-P-path-args' into release-3.24

febe3190f0 Merge branch 'backport-3.23-cmake-P-path-args'
846a650ff7 cmake: In -P mode ignore extra paths on the command line
c362cba566 cmake: simplify to a single source of truth of working mode
261fa5db39 cmake: In -P mode ignore extra paths on the command line
314135cdf1 cmake: simplify to a single source of truth of working mode

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: buildbot <buildbot@kitware.com>
Merge-request: !7494
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index e6fa219..1c1cab3 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -405,9 +405,6 @@
 // Parse the args
 bool cmake::SetCacheArgs(const std::vector<std::string>& args)
 {
-  auto findPackageMode = false;
-  auto seenScriptOption = false;
-
   auto DefineLambda = [](std::string const& entry, cmake* state) -> bool {
     std::string var;
     std::string value;
@@ -498,10 +495,10 @@
     GetProjectCommandsInScriptMode(state->GetState());
     // Documented behavior of CMAKE{,_CURRENT}_{SOURCE,BINARY}_DIR is to be
     // set to $PWD for -P mode.
+    state->SetWorkingMode(SCRIPT_MODE);
     state->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory());
     state->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory());
     state->ReadListFile(args, path);
-    seenScriptOption = true;
     return true;
   };
 
@@ -565,12 +562,12 @@
                      "No install directory specified for --install-prefix",
                      CommandArgument::Values::One, PrefixLambda },
     CommandArgument{ "--find-package", CommandArgument::Values::Zero,
-                     CommandArgument::setToTrue(findPackageMode) },
+                     IgnoreAndTrueLambda },
   };
   for (decltype(args.size()) i = 1; i < args.size(); ++i) {
     std::string const& arg = args[i];
 
-    if (arg == "--" && seenScriptOption) {
+    if (arg == "--" && this->GetWorkingMode() == SCRIPT_MODE) {
       // Stop processing CMake args and avoid possible errors
       // when arbitrary args are given to CMake script.
       break;
@@ -585,7 +582,7 @@
     }
   }
 
-  if (findPackageMode) {
+  if (this->GetWorkingMode() == FIND_PACKAGE_MODE) {
     return this->FindPackage(args);
   }
 
@@ -790,7 +787,6 @@
   bool haveToolset = false;
   bool havePlatform = false;
   bool haveBArg = false;
-  bool scriptMode = false;
   std::string possibleUnknownArg;
   std::string extraProvidedPath;
 #if !defined(CMAKE_BOOTSTRAP)
@@ -873,7 +869,7 @@
     CommandArgument{ "-P", "-P must be followed by a file name.",
                      CommandArgument::Values::One,
                      CommandArgument::RequiresSeparator::No,
-                     CommandArgument::setToTrue(scriptMode) },
+                     IgnoreAndTrueLambda },
     CommandArgument{ "-D", "-D must be followed with VAR=VALUE.",
                      CommandArgument::Values::One,
                      CommandArgument::RequiresSeparator::No,
@@ -1165,7 +1161,7 @@
     // iterate each argument
     std::string const& arg = args[i];
 
-    if (scriptMode && arg == "--") {
+    if (this->GetWorkingMode() == SCRIPT_MODE && arg == "--") {
       // Stop processing CMake args and avoid possible errors
       // when arbitrary args are given to CMake script.
       break;
@@ -1211,12 +1207,12 @@
     }
   }
 
-  if (!extraProvidedPath.empty() && !scriptMode) {
+  if (!extraProvidedPath.empty() && this->GetWorkingMode() == NORMAL_MODE) {
     this->IssueMessage(MessageType::WARNING,
                        cmStrCat("Ignoring extra path from command line:\n \"",
                                 extraProvidedPath, "\""));
   }
-  if (!possibleUnknownArg.empty() && !scriptMode) {
+  if (!possibleUnknownArg.empty() && this->GetWorkingMode() != SCRIPT_MODE) {
     cmSystemTools::Error(cmStrCat("Unknown argument ", possibleUnknownArg));
     cmSystemTools::Error("Run 'cmake --help' for all supported options.");
     exit(1);
@@ -1800,7 +1796,8 @@
   }
 
   auto prev_path = this->GetHomeDirectory();
-  if (prev_path != path && !prev_path.empty()) {
+  if (prev_path != path && !prev_path.empty() &&
+      this->GetWorkingMode() == NORMAL_MODE) {
     this->IssueMessage(MessageType::WARNING,
                        cmStrCat("Ignoring extra path from command line:\n \"",
                                 prev_path, "\""));
diff --git a/Tests/RunCMake/CommandLine/P_args-stdout.txt b/Tests/RunCMake/CommandLine/P_args-stdout.txt
new file mode 100644
index 0000000..f9d039f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/P_args-stdout.txt
@@ -0,0 +1,6 @@
+^-- CMAKE_ARGC='5'
+-- CMAKE_ARGV1='-P'
+-- CMAKE_ARGV2='[^']*/Tests/RunCMake/CommandLine/P_args.cmake'
+-- CMAKE_ARGV3='relative/path'
+-- CMAKE_ARGV4='[^']*/Tests/RunCMake/CommandLine'
+-- CMAKE_ARGV5=''$
diff --git a/Tests/RunCMake/CommandLine/P_args.cmake b/Tests/RunCMake/CommandLine/P_args.cmake
new file mode 100644
index 0000000..6c4fa4c
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/P_args.cmake
@@ -0,0 +1,6 @@
+message(STATUS "CMAKE_ARGC='${CMAKE_ARGC}'")
+message(STATUS "CMAKE_ARGV1='${CMAKE_ARGV1}'")
+message(STATUS "CMAKE_ARGV2='${CMAKE_ARGV2}'")
+message(STATUS "CMAKE_ARGV3='${CMAKE_ARGV3}'")
+message(STATUS "CMAKE_ARGV4='${CMAKE_ARGV4}'")
+message(STATUS "CMAKE_ARGV5='${CMAKE_ARGV5}'")
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index c8234ec..1663fa8 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -52,6 +52,7 @@
 run_cmake_command(G_bad-arg ${CMAKE_COMMAND} -B DummyBuildDir -G NoSuchGenerator)
 run_cmake_command(P_no-arg ${CMAKE_COMMAND} -P)
 run_cmake_command(P_no-file ${CMAKE_COMMAND} -P nosuchscriptfile.cmake)
+run_cmake_command(P_args ${CMAKE_COMMAND} -P "${RunCMake_SOURCE_DIR}/P_args.cmake" relative/path "${RunCMake_SOURCE_DIR}")
 run_cmake_command(P_arbitrary_args ${CMAKE_COMMAND} -P "${RunCMake_SOURCE_DIR}/P_arbitrary_args.cmake" -- -DFOO -S -B --fresh)
 run_cmake_command(P_fresh ${CMAKE_COMMAND} -P "${RunCMake_SOURCE_DIR}/P_fresh.cmake" --fresh)