Merge topic 'CMAKE_FIND_USE_INSTALL_PREFIX-support-staging-prefix' into release-3.24

0fc10bb19b CMAKE_FIND_USE_INSTALL_PREFIX considers CMAKE_STAGING_PREFIX
43d31c5198 cmFindBase: Refactor CMAKE_FIND_USE_INSTALL_PREFIX handling

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: buildbot <buildbot@kitware.com>
Merge-request: !7623
diff --git a/Help/command/FIND_XXX.txt b/Help/command/FIND_XXX.txt
index 83860b7..cd3c78b 100644
--- a/Help/command/FIND_XXX.txt
+++ b/Help/command/FIND_XXX.txt
@@ -166,7 +166,8 @@
    * |SYSTEM_ENVIRONMENT_PATH_WINDOWS_XXX|
 
 6. Search cmake variables defined in the Platform files
-   for the current system.  The searching of ``CMAKE_INSTALL_PREFIX`` can be
+   for the current system.  The searching of ``CMAKE_INSTALL_PREFIX`` and
+   ``CMAKE_STAGING_PREFIX`` can be
    skipped if ``NO_CMAKE_INSTALL_PREFIX`` is passed or by setting the
    :variable:`CMAKE_FIND_USE_INSTALL_PREFIX` to ``FALSE``. All these locations
    can be skipped if ``NO_CMAKE_SYSTEM_PATH`` is passed or by setting the
diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst
index 2f3c2cb..c96d84e 100644
--- a/Help/command/find_package.rst
+++ b/Help/command/find_package.rst
@@ -412,7 +412,8 @@
    package registry.
 
 7. Search cmake variables defined in the Platform files for the
-   current system. The searching of :variable:`CMAKE_INSTALL_PREFIX` can be
+   current system. The searching of :variable:`CMAKE_INSTALL_PREFIX` and
+   :variable:`CMAKE_STAGING_PREFIX` can be
    skipped if ``NO_CMAKE_INSTALL_PREFIX`` is passed or by setting the
    :variable:`CMAKE_FIND_USE_INSTALL_PREFIX` to ``FALSE``. All these locations
    can be skipped if ``NO_CMAKE_SYSTEM_PATH`` is passed or by setting the
diff --git a/Help/variable/CMAKE_FIND_USE_INSTALL_PREFIX.rst b/Help/variable/CMAKE_FIND_USE_INSTALL_PREFIX.rst
index 8494e95..d577a8a 100644
--- a/Help/variable/CMAKE_FIND_USE_INSTALL_PREFIX.rst
+++ b/Help/variable/CMAKE_FIND_USE_INSTALL_PREFIX.rst
@@ -4,7 +4,8 @@
 .. versionadded:: 3.24
 
 Controls the default behavior of the following commands for whether or not to
-search the install location:
+search the locations in the :variable:`CMAKE_INSTALL_PREFIX` and
+:variable:`CMAKE_STAGING_PREFIX` variables.
 
 * :command:`find_program`
 * :command:`find_library`
diff --git a/Modules/CMakeSystemSpecificInformation.cmake b/Modules/CMakeSystemSpecificInformation.cmake
index 59f552a..e045932 100644
--- a/Modules/CMakeSystemSpecificInformation.cmake
+++ b/Modules/CMakeSystemSpecificInformation.cmake
@@ -19,13 +19,19 @@
 
 function(_cmake_record_install_prefix )
   set(_CMAKE_SYSTEM_PREFIX_PATH_INSTALL_PREFIX_VALUE "${CMAKE_INSTALL_PREFIX}" PARENT_SCOPE)
-  set(count 0)
+  set(_CMAKE_SYSTEM_PREFIX_PATH_STAGING_PREFIX_VALUE "${CMAKE_STAGING_PREFIX}" PARENT_SCOPE)
+  set(icount 0)
+  set(scount 0)
   foreach(value IN LISTS CMAKE_SYSTEM_PREFIX_PATH)
     if(value STREQUAL CMAKE_INSTALL_PREFIX)
-      math(EXPR count "${count}+1")
+      math(EXPR icount "${icount}+1")
+    endif()
+    if(value STREQUAL CMAKE_STAGING_PREFIX)
+      math(EXPR scount "${scount}+1")
     endif()
   endforeach()
-  set(_CMAKE_SYSTEM_PREFIX_PATH_INSTALL_PREFIX_COUNT "${count}" PARENT_SCOPE)
+  set(_CMAKE_SYSTEM_PREFIX_PATH_INSTALL_PREFIX_COUNT "${icount}" PARENT_SCOPE)
+  set(_CMAKE_SYSTEM_PREFIX_PATH_STAGING_PREFIX_COUNT "${scount}" PARENT_SCOPE)
 endfunction()
 
 # include Generic system information
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx
index 4dfbef9..1da995a 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -278,6 +278,43 @@
   paths.AddSuffixes(this->SearchPathSuffixes);
 }
 
+namespace {
+struct entry_to_remove
+{
+  entry_to_remove(std::string const& name, cmMakefile* makefile)
+    : value()
+  {
+    if (cmValue to_skip = makefile->GetDefinition(
+          cmStrCat("_CMAKE_SYSTEM_PREFIX_PATH_", name, "_PREFIX_COUNT"))) {
+      cmStrToLong(to_skip, &count);
+    }
+    if (cmValue prefix_value = makefile->GetDefinition(
+          cmStrCat("_CMAKE_SYSTEM_PREFIX_PATH_", name, "_PREFIX_VALUE"))) {
+      value = *prefix_value;
+    }
+  }
+  bool valid() const { return count > 0 && !value.empty(); }
+
+  void remove_self(std::vector<std::string>& entries) const
+  {
+    if (this->valid()) {
+      long to_skip = this->count;
+      long index_to_remove = 0;
+      for (const auto& path : entries) {
+        if (path == this->value && --to_skip == 0) {
+          break;
+        }
+        ++index_to_remove;
+      }
+      entries.erase(entries.begin() + index_to_remove);
+    }
+  }
+
+  long count = -1;
+  std::string value;
+};
+}
+
 void cmFindBase::FillCMakeSystemVariablePath()
 {
   cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeSystem];
@@ -298,38 +335,25 @@
   // computed by `CMakeSystemSpecificInformation.cmake` while constructing
   // `CMAKE_SYSTEM_PREFIX_PATH`. This ensures that if projects / toolchains
   // have removed `CMAKE_INSTALL_PREFIX` from the list, we don't remove
-  // some other entry by mistake
-  long install_prefix_count = -1;
-  std::string install_path_to_remove;
-  if (cmValue to_skip = this->Makefile->GetDefinition(
-        "_CMAKE_SYSTEM_PREFIX_PATH_INSTALL_PREFIX_COUNT")) {
-    cmStrToLong(to_skip, &install_prefix_count);
-  }
-  if (cmValue install_value = this->Makefile->GetDefinition(
-        "_CMAKE_SYSTEM_PREFIX_PATH_INSTALL_PREFIX_VALUE")) {
-    install_path_to_remove = *install_value;
-  }
+  // some other entry by mistake ( likewise for `CMAKE_STAGING_PREFIX` )
+  entry_to_remove install_entry("INSTALL", this->Makefile);
+  entry_to_remove staging_entry("STAGING", this->Makefile);
 
   if (remove_install_prefix && install_prefix_in_list &&
-      install_prefix_count > 0 && !install_path_to_remove.empty()) {
+      (install_entry.valid() || staging_entry.valid())) {
     cmValue prefix_paths =
       this->Makefile->GetDefinition("CMAKE_SYSTEM_PREFIX_PATH");
 
-    // remove entry from CMAKE_SYSTEM_PREFIX_PATH
+    // remove entries from CMAKE_SYSTEM_PREFIX_PATH
     std::vector<std::string> expanded = cmExpandedList(*prefix_paths);
-    long index_to_remove = 0;
-    for (const auto& path : expanded) {
-      if (path == install_path_to_remove && --install_prefix_count == 0) {
-        break;
-      }
-      ++index_to_remove;
-    }
-    expanded.erase(expanded.begin() + index_to_remove);
+    install_entry.remove_self(expanded);
+    staging_entry.remove_self(expanded);
+
     paths.AddPrefixPaths(expanded,
                          this->Makefile->GetCurrentSourceDirectory().c_str());
   } else if (add_install_prefix && !install_prefix_in_list) {
-
     paths.AddCMakePrefixPath("CMAKE_INSTALL_PREFIX");
+    paths.AddCMakePrefixPath("CMAKE_STAGING_PREFIX");
     paths.AddCMakePrefixPath("CMAKE_SYSTEM_PREFIX_PATH");
   } else {
     // Otherwise the current setup of `CMAKE_SYSTEM_PREFIX_PATH` is correct
diff --git a/Tests/RunCMake/find_library/IgnoreStagingAndInstallPrefix-stderr.txt b/Tests/RunCMake/find_library/IgnoreStagingAndInstallPrefix-stderr.txt
new file mode 100644
index 0000000..48d2fad
--- /dev/null
+++ b/Tests/RunCMake/find_library/IgnoreStagingAndInstallPrefix-stderr.txt
@@ -0,0 +1,43 @@
+  find_library called with the following settings:.*
+    VAR: CREATED_LIBRARY
+    NAMES: \"created\"
+    Documentation.*
+    Framework.*
+    AppBundle.*
+    CMAKE_FIND_USE_CMAKE_PATH: 1
+    CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH: 1
+    CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH: 1
+    CMAKE_FIND_USE_CMAKE_SYSTEM_PATH: 1
+    CMAKE_FIND_USE_INSTALL_PREFIX: 0
+
+  find_library considered the following locations:.*
+  The item was not found.*
+  find_library called with the following settings:.*
+    VAR: CREATED_LIBRARY
+    NAMES: \"created\"
+    Documentation.*
+    Framework.*
+    AppBundle.*
+    CMAKE_FIND_USE_CMAKE_PATH: 1
+    CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH: 1
+    CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH: 1
+    CMAKE_FIND_USE_CMAKE_SYSTEM_PATH: 1
+    CMAKE_FIND_USE_INSTALL_PREFIX: 1
+
+  find_library considered the following locations:.*
+  The item was found at.*
+  .*IgnoreStagingAndInstallPrefix-build/lib.*
+  find_library called with the following settings:.*
+    VAR: CREATED_LIBRARY
+    NAMES: \"created\"
+    Documentation.*
+    Framework.*
+    AppBundle.*
+    CMAKE_FIND_USE_CMAKE_PATH: 1
+    CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH: 1
+    CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH: 1
+    CMAKE_FIND_USE_CMAKE_SYSTEM_PATH: 1
+    CMAKE_FIND_USE_INSTALL_PREFIX: 0
+
+  find_library considered the following locations:.*
+  The item was not found.*
diff --git a/Tests/RunCMake/find_library/IgnoreStagingAndInstallPrefix-stdout.txt b/Tests/RunCMake/find_library/IgnoreStagingAndInstallPrefix-stdout.txt
new file mode 100644
index 0000000..ea6614e
--- /dev/null
+++ b/Tests/RunCMake/find_library/IgnoreStagingAndInstallPrefix-stdout.txt
@@ -0,0 +1,3 @@
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
+-- CREATED_LIBRARY='[^']*/Tests/RunCMake/find_library/IgnoreStagingAndInstallPrefix-build/lib/libcreated.a'
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
diff --git a/Tests/RunCMake/find_library/IgnoreStagingAndInstallPrefix.cmake b/Tests/RunCMake/find_library/IgnoreStagingAndInstallPrefix.cmake
new file mode 100644
index 0000000..9b5700a
--- /dev/null
+++ b/Tests/RunCMake/find_library/IgnoreStagingAndInstallPrefix.cmake
@@ -0,0 +1 @@
+include(IgnoreInstallPrefix.cmake)
diff --git a/Tests/RunCMake/find_library/IgnoreStagingPrefix-stderr.txt b/Tests/RunCMake/find_library/IgnoreStagingPrefix-stderr.txt
new file mode 100644
index 0000000..784c5fd
--- /dev/null
+++ b/Tests/RunCMake/find_library/IgnoreStagingPrefix-stderr.txt
@@ -0,0 +1,43 @@
+  find_library called with the following settings:.*
+    VAR: CREATED_LIBRARY
+    NAMES: \"created\"
+    Documentation.*
+    Framework.*
+    AppBundle.*
+    CMAKE_FIND_USE_CMAKE_PATH: 1
+    CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH: 1
+    CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH: 1
+    CMAKE_FIND_USE_CMAKE_SYSTEM_PATH: 1
+    CMAKE_FIND_USE_INSTALL_PREFIX: 0
+
+  find_library considered the following locations:.*
+  The item was not found.*
+  find_library called with the following settings:.*
+    VAR: CREATED_LIBRARY
+    NAMES: \"created\"
+    Documentation.*
+    Framework.*
+    AppBundle.*
+    CMAKE_FIND_USE_CMAKE_PATH: 1
+    CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH: 1
+    CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH: 1
+    CMAKE_FIND_USE_CMAKE_SYSTEM_PATH: 1
+    CMAKE_FIND_USE_INSTALL_PREFIX: 1
+
+  find_library considered the following locations:.*
+  The item was found at.*
+  .*IgnoreStagingPrefix-build/lib.*
+  find_library called with the following settings:.*
+    VAR: CREATED_LIBRARY
+    NAMES: \"created\"
+    Documentation.*
+    Framework.*
+    AppBundle.*
+    CMAKE_FIND_USE_CMAKE_PATH: 1
+    CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH: 1
+    CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH: 1
+    CMAKE_FIND_USE_CMAKE_SYSTEM_PATH: 1
+    CMAKE_FIND_USE_INSTALL_PREFIX: 0
+
+  find_library considered the following locations:.*
+  The item was not found.*
diff --git a/Tests/RunCMake/find_library/IgnoreStagingPrefix-stdout.txt b/Tests/RunCMake/find_library/IgnoreStagingPrefix-stdout.txt
new file mode 100644
index 0000000..fd414fb
--- /dev/null
+++ b/Tests/RunCMake/find_library/IgnoreStagingPrefix-stdout.txt
@@ -0,0 +1,3 @@
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
+-- CREATED_LIBRARY='[^']*/Tests/RunCMake/find_library/IgnoreStagingPrefix-build/lib/libcreated.a'
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
diff --git a/Tests/RunCMake/find_library/IgnoreStagingPrefix.cmake b/Tests/RunCMake/find_library/IgnoreStagingPrefix.cmake
new file mode 100644
index 0000000..9b5700a
--- /dev/null
+++ b/Tests/RunCMake/find_library/IgnoreStagingPrefix.cmake
@@ -0,0 +1 @@
+include(IgnoreInstallPrefix.cmake)
diff --git a/Tests/RunCMake/find_library/RunCMakeTest.cmake b/Tests/RunCMake/find_library/RunCMakeTest.cmake
index de0ee14..a912077 100644
--- a/Tests/RunCMake/find_library/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_library/RunCMakeTest.cmake
@@ -4,6 +4,8 @@
 run_cmake(FromPrefixPath)
 run_cmake(FromPATHEnv)
 run_cmake_with_options(IgnoreInstallPrefix "-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/IgnoreInstallPrefix-build/")
+run_cmake_with_options(IgnoreStagingPrefix "-DCMAKE_STAGING_PREFIX=${RunCMake_BINARY_DIR}/IgnoreStagingPrefix-build/")
+run_cmake_with_options(IgnoreStagingAndInstallPrefix "-DCMAKE_STAGING_PREFIX=${RunCMake_BINARY_DIR}/IgnoreStagingAndInstallPrefix-build/" "-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/IgnoreStagingAndInstallPrefix-build/")
 if(UNIX AND NOT CYGWIN)
   run_cmake(LibArchLink)
   run_cmake(LibSymLink)