Selaa lähdekoodia

Find: Support per call disabling of CMAKE_INSTALL_PREFIX

Fixes #23359
Robert Maynard 3 vuotta sitten
vanhempi
sitoutus
42f7e39789
38 muutettua tiedostoa jossa 328 lisäystä ja 13 poistoa
  1. 1 0
      Auxiliary/vim/syntax/cmake.vim
  2. 6 3
      Help/command/FIND_XXX.txt
  3. 6 3
      Help/command/find_package.rst
  4. 1 0
      Help/manual/cmake-variables.7.rst
  5. 12 0
      Help/release/dev/find-calls-search-install-prefix.rst
  6. 1 0
      Help/variable/CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH.rst
  7. 1 0
      Help/variable/CMAKE_FIND_USE_CMAKE_SYSTEM_PATH.rst
  8. 39 0
      Help/variable/CMAKE_FIND_USE_INSTALL_PREFIX.rst
  9. 1 0
      Help/variable/CMAKE_FIND_USE_PACKAGE_REGISTRY.rst
  10. 1 0
      Help/variable/CMAKE_FIND_USE_PACKAGE_ROOT_PATH.rst
  11. 1 0
      Help/variable/CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH.rst
  12. 1 0
      Help/variable/CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY.rst
  13. 10 0
      Modules/CMakeSystemSpecificInformation.cmake
  14. 1 0
      Modules/Platform/CrayLinuxEnvironment.cmake
  15. 1 0
      Modules/Platform/UnixPaths.cmake
  16. 1 0
      Modules/Platform/WindowsPaths.cmake
  17. 57 2
      Source/cmFindBase.cxx
  18. 6 2
      Source/cmFindCommon.cxx
  19. 1 0
      Source/cmFindCommon.h
  20. 51 1
      Source/cmFindPackageCommand.cxx
  21. 2 0
      Tests/RunCMake/find_file/FromPATHEnvDebugVar-stderr.txt
  22. 1 0
      Tests/RunCMake/find_file/PrefixInPATH-stderr.txt
  23. 2 0
      Tests/RunCMake/find_library/FromPATHEnv-stderr.txt
  24. 2 0
      Tests/RunCMake/find_library/FromPATHEnvDebugVar-stderr.txt
  25. 43 0
      Tests/RunCMake/find_library/IgnoreInstallPrefix-stderr.txt
  26. 3 0
      Tests/RunCMake/find_library/IgnoreInstallPrefix-stdout.txt
  27. 32 0
      Tests/RunCMake/find_library/IgnoreInstallPrefix.cmake
  28. 1 0
      Tests/RunCMake/find_library/PrefixInPATH-stderr.txt
  29. 1 0
      Tests/RunCMake/find_library/RunCMakeTest.cmake
  30. 17 0
      Tests/RunCMake/find_package/IgnoreInstallPrefix.cmake
  31. 1 0
      Tests/RunCMake/find_package/RunCMakeTest.cmake
  32. 2 0
      Tests/RunCMake/find_path/FromPATHEnv-stderr.txt
  33. 2 0
      Tests/RunCMake/find_path/FromPATHEnvDebugVar-stderr.txt
  34. 2 0
      Tests/RunCMake/find_program/EnvAndHints-stderr.txt
  35. 2 0
      Tests/RunCMake/find_program/EnvAndHintsDebugVar-stderr.txt
  36. 1 1
      Tests/RunCMake/no_install_prefix/RunCMakeTest.cmake
  37. 14 0
      Tests/RunCMake/no_install_prefix/do_test.cmake
  38. 1 1
      Tests/RunCMake/no_install_prefix/no_install_prefix-stderr.txt

+ 1 - 0
Auxiliary/vim/syntax/cmake.vim

@@ -1046,6 +1046,7 @@ syn keyword cmakeVariable contained
             \ CMAKE_FIND_ROOT_PATH_MODE_PACKAGE
             \ CMAKE_FIND_ROOT_PATH_MODE_PROGRAM
             \ CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH
+            \ CMAKE_FIND_USE_INSTALL_PREFIX
             \ CMAKE_FIND_USE_CMAKE_PATH
             \ CMAKE_FIND_USE_CMAKE_SYSTEM_PATH
             \ CMAKE_FIND_USE_PACKAGE_REGISTRY

+ 6 - 3
Help/command/FIND_XXX.txt

@@ -23,6 +23,7 @@ The general signature is:
              [NO_CMAKE_ENVIRONMENT_PATH]
              [NO_SYSTEM_ENVIRONMENT_PATH]
              [NO_CMAKE_SYSTEM_PATH]
+             [NO_CMAKE_INSTALL_PREFIX]
              [CMAKE_FIND_ROOT_PATH_BOTH |
               ONLY_CMAKE_FIND_ROOT_PATH |
               NO_CMAKE_FIND_ROOT_PATH]
@@ -154,9 +155,11 @@ If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows:
    * |SYSTEM_ENVIRONMENT_PATH_WINDOWS_XXX|
 
 6. Search cmake variables defined in the Platform files
-   for the current system.  This can be skipped if ``NO_CMAKE_SYSTEM_PATH``
-   is passed or by setting the :variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH`
-   to ``FALSE``.
+   for the current system.  The searching of ``CMAKE_INSTALL_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
+   :variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH` to ``FALSE``.
 
    * |CMAKE_SYSTEM_PREFIX_PATH_XXX|
    * |CMAKE_SYSTEM_XXX_PATH|

+ 6 - 3
Help/command/find_package.rst

@@ -175,6 +175,7 @@ Full Signature
                [NO_CMAKE_PACKAGE_REGISTRY]
                [NO_CMAKE_BUILDS_PATH] # Deprecated; does nothing.
                [NO_CMAKE_SYSTEM_PATH]
+               [NO_CMAKE_INSTALL_PREFIX]
                [NO_CMAKE_SYSTEM_PACKAGE_REGISTRY]
                [CMAKE_FIND_ROOT_PATH_BOTH |
                 ONLY_CMAKE_FIND_ROOT_PATH |
@@ -345,9 +346,11 @@ enabled.
    package registry.
 
 7. Search cmake variables defined in the Platform files for the
-   current system.  This can be skipped if ``NO_CMAKE_SYSTEM_PATH`` is
-   passed or by setting the :variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH`
-   to ``FALSE``:
+   current system. The searching of ``CMAKE_INSTALL_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
+   :variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH` to ``FALSE``:
 
    * :variable:`CMAKE_SYSTEM_PREFIX_PATH`
    * :variable:`CMAKE_SYSTEM_FRAMEWORK_PATH`

+ 1 - 0
Help/manual/cmake-variables.7.rst

@@ -206,6 +206,7 @@ Variables that Change Behavior
    /variable/CMAKE_FIND_ROOT_PATH_MODE_PACKAGE
    /variable/CMAKE_FIND_ROOT_PATH_MODE_PROGRAM
    /variable/CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH
+   /variable/CMAKE_FIND_USE_INSTALL_PREFIX
    /variable/CMAKE_FIND_USE_CMAKE_PATH
    /variable/CMAKE_FIND_USE_CMAKE_SYSTEM_PATH
    /variable/CMAKE_FIND_USE_PACKAGE_REGISTRY

+ 12 - 0
Help/release/dev/find-calls-search-install-prefix.rst

@@ -0,0 +1,12 @@
+find-calls-search-install-prefix
+--------------------------------
+
+* The :command:`find_file`, :command:`find_library`, :command:`find_path`,
+  :command:`find_package`, and :command:`find_program` commands have gained
+  the `NO_CMAKE_INSTALL_PREFIX` option to control searching
+  `CMAKE_INSTALL_PREFIX`.
+
+* Adds support for :variable:`CMAKE_FIND_USE_INSTALL_PREFIX` to toggle
+  behavior of the :command:`find_file`, :command:`find_library`, :command:`find_path`,
+  :command:`find_package`, and :command:`find_program` commands new
+  `NO_CMAKE_INSTALL_PREFIX` option.

+ 1 - 0
Help/variable/CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH.rst

@@ -20,6 +20,7 @@ take precedence over this variable.
 
 See also the :variable:`CMAKE_FIND_USE_CMAKE_PATH`,
 :variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH`,
+:variable:`CMAKE_FIND_USE_INSTALL_PREFIX`,
 :variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH`,
 :variable:`CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY`,
 :variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY`,

+ 1 - 0
Help/variable/CMAKE_FIND_USE_CMAKE_SYSTEM_PATH.rst

@@ -20,6 +20,7 @@ take precedence over this variable.
 
 See also the :variable:`CMAKE_FIND_USE_CMAKE_PATH`,
 :variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH`,
+:variable:`CMAKE_FIND_USE_INSTALL_PREFIX`,
 :variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH`,
 :variable:`CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY`,
 :variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY`,

+ 39 - 0
Help/variable/CMAKE_FIND_USE_INSTALL_PREFIX.rst

@@ -0,0 +1,39 @@
+CMAKE_FIND_USE_INSTALL_PREFIX
+-----------------------------------
+
+.. versionadded:: 3.24
+
+Controls the default behavior of the following commands for whether or not to
+search the install location:
+
+* :command:`find_program`
+* :command:`find_library`
+* :command:`find_file`
+* :command:`find_path`
+* :command:`find_package`
+
+This is useful in cross-compiling environments.
+
+Due to backwards compatibility with :variable:`CMAKE_FIND_NO_INSTALL_PREFIX`,
+the behavior of the find command change based on if this variable exists.
+
+============================== ============================ ===========
+ CMAKE_FIND_USE_INSTALL_PREFIX CMAKE_FIND_NO_INSTALL_PREFIX   Search
+============================== ============================ ===========
+ Not Defined                      On                          NO
+ Not Defined                      Off || Not Defined          YES
+ Off                              On                          NO
+ Off                              Off || Not Defined          NO
+ On                               On                          YES
+ On                               Off || Not Defined          YES
+============================== ============================ ===========
+
+By default this variable is not defined. Explicit options given to the above
+commands take precedence over this variable.
+
+See also the :variable:`CMAKE_FIND_USE_CMAKE_PATH`,
+:variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH`,
+:variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH`,
+:variable:`CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY`,
+:variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY`,
+and :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` variables.

+ 1 - 0
Help/variable/CMAKE_FIND_USE_PACKAGE_REGISTRY.rst

@@ -26,6 +26,7 @@ the :ref:`User Package Registry` as if they were called with the
 See also :ref:`Disabling the Package Registry` and the
 :variable:`CMAKE_FIND_USE_CMAKE_PATH`,
 :variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH`,
+:variable:`CMAKE_FIND_USE_INSTALL_PREFIX`,
 :variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH`,
 :variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH`,
 :variable:`CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY`,

+ 1 - 0
Help/variable/CMAKE_FIND_USE_PACKAGE_ROOT_PATH.rst

@@ -18,6 +18,7 @@ take precedence over this variable.
 
 See also the :variable:`CMAKE_FIND_USE_CMAKE_PATH`,
 :variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH`,
+:variable:`CMAKE_FIND_USE_INSTALL_PREFIX`,
 :variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH`,
 :variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH`,
 :variable:`CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY`,

+ 1 - 0
Help/variable/CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH.rst

@@ -20,6 +20,7 @@ take precedence over this variable.
 
 See also the :variable:`CMAKE_FIND_USE_CMAKE_PATH`,
 :variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH`,
+:variable:`CMAKE_FIND_USE_INSTALL_PREFIX`,
 :variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH`,
 :variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY`,
 :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH`,

+ 1 - 0
Help/variable/CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY.rst

@@ -27,6 +27,7 @@ See also :ref:`Disabling the Package Registry`.
 
 See also the :variable:`CMAKE_FIND_USE_CMAKE_PATH`,
 :variable:`CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH`,
+:variable:`CMAKE_FIND_USE_INSTALL_PREFIX`,
 :variable:`CMAKE_FIND_USE_CMAKE_SYSTEM_PATH`,
 :variable:`CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH`,
 :variable:`CMAKE_FIND_USE_PACKAGE_REGISTRY`,

+ 10 - 0
Modules/CMakeSystemSpecificInformation.cmake

@@ -17,6 +17,16 @@ set(CYGWIN )
 set(MSYS )
 set(WIN32  )
 
+function(_cmake_record_install_prefix )
+  set(_CMAKE_SYSTEM_PREFIX_PATH_INSTALL_PREFIX_VALUE "${CMAKE_INSTALL_PREFIX}" PARENT_SCOPE)
+  set(count 0)
+  foreach(value IN LISTS CMAKE_SYSTEM_PREFIX_PATH)
+    if(value STREQUAL CMAKE_INSTALL_PREFIX)
+      math(EXPR count "${count}+1")
+    endif()
+  endforeach()
+  set(_CMAKE_SYSTEM_PREFIX_PATH_INSTALL_PREFIX_COUNT "${count}" PARENT_SCOPE)
+endfunction()
 
 # include Generic system information
 include(CMakeGenericSystem)

+ 1 - 0
Modules/Platform/CrayLinuxEnvironment.cmake

@@ -68,6 +68,7 @@ if (NOT CMAKE_FIND_NO_INSTALL_PREFIX)
     )
   endif()
 endif()
+_cmake_record_install_prefix()
 
 list(APPEND CMAKE_SYSTEM_INCLUDE_PATH
   $ENV{SYSROOT_DIR}/usr/include/X11

+ 1 - 0
Modules/Platform/UnixPaths.cmake

@@ -44,6 +44,7 @@ if (NOT CMAKE_FIND_NO_INSTALL_PREFIX)
     )
   endif()
 endif()
+_cmake_record_install_prefix()
 
 # Non "standard" but common install prefixes
 list(APPEND CMAKE_SYSTEM_PREFIX_PATH

+ 1 - 0
Modules/Platform/WindowsPaths.cmake

@@ -67,6 +67,7 @@ if (NOT CMAKE_FIND_NO_INSTALL_PREFIX)
     )
   endif()
 endif()
+_cmake_record_install_prefix()
 
 if(CMAKE_CROSSCOMPILING AND NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
   # MinGW (useful when cross compiling from linux with CMAKE_FIND_ROOT_PATH set)

+ 57 - 2
Source/cmFindBase.cxx

@@ -267,8 +267,61 @@ void cmFindBase::FillCMakeSystemVariablePath()
 {
   cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeSystem];
 
+  const bool install_prefix_in_list =
+    !this->Makefile->IsOn("CMAKE_FIND_NO_INSTALL_PREFIX");
+  const bool remove_install_prefix = this->NoCMakeInstallPath;
+  const bool add_install_prefix = !this->NoCMakeInstallPath &&
+    this->Makefile->IsDefinitionSet("CMAKE_FIND_USE_INSTALL_PREFIX");
+
+  // We have 3 possible states for `CMAKE_SYSTEM_PREFIX_PATH` and
+  // `CMAKE_INSTALL_PREFIX`.
+  // Either we need to remove `CMAKE_INSTALL_PREFIX`, add
+  // `CMAKE_INSTALL_PREFIX`, or do nothing.
+  //
+  // When we need to remove `CMAKE_INSTALL_PREFIX` we remove the Nth occurrence
+  // of `CMAKE_INSTALL_PREFIX` from `CMAKE_SYSTEM_PREFIX_PATH`, where `N` is
+  // 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;
+  }
+
+  if (remove_install_prefix && install_prefix_in_list &&
+      install_prefix_count > 0 && !install_path_to_remove.empty()) {
+    cmValue prefix_paths =
+      this->Makefile->GetDefinition("CMAKE_SYSTEM_PREFIX_PATH");
+
+    // remove entry 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);
+    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_SYSTEM_PREFIX_PATH");
+  } else {
+    // Otherwise the current setup of `CMAKE_SYSTEM_PREFIX_PATH` is correct
+    paths.AddCMakePrefixPath("CMAKE_SYSTEM_PREFIX_PATH");
+  }
+
   std::string var = cmStrCat("CMAKE_SYSTEM_", this->CMakePathName, "_PATH");
-  paths.AddCMakePrefixPath("CMAKE_SYSTEM_PREFIX_PATH");
   paths.AddCMakePath(var);
 
   if (this->CMakePathName == "PROGRAM") {
@@ -496,7 +549,9 @@ cmFindBaseDebugState::~cmFindBaseDebugState()
         "  CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH: ",
         !this->FindCommand->NoSystemEnvironmentPath, "\n",
         "  CMAKE_FIND_USE_CMAKE_SYSTEM_PATH: ",
-        !this->FindCommand->NoCMakeSystemPath, "\n");
+        !this->FindCommand->NoCMakeSystemPath, "\n",
+        "  CMAKE_FIND_USE_INSTALL_PREFIX: ",
+        !this->FindCommand->NoCMakeInstallPath, "\n");
     }
 
     buffer +=

+ 6 - 2
Source/cmFindCommon.cxx

@@ -39,6 +39,7 @@ cmFindCommon::cmFindCommon(cmExecutionStatus& status)
   this->NoCMakeEnvironmentPath = false;
   this->NoSystemEnvironmentPath = false;
   this->NoCMakeSystemPath = false;
+  this->NoCMakeInstallPath = false;
 
 // OS X Bundle and Framework search policy.  The default is to
 // search frameworks first on apple.
@@ -179,14 +180,15 @@ void cmFindCommon::SelectDefaultMacMode()
 
 void cmFindCommon::SelectDefaultSearchModes()
 {
-  const std::array<std::pair<bool&, std::string>, 5> search_paths = {
+  const std::array<std::pair<bool&, std::string>, 6> search_paths = {
     { { this->NoPackageRootPath, "CMAKE_FIND_USE_PACKAGE_ROOT_PATH" },
       { this->NoCMakePath, "CMAKE_FIND_USE_CMAKE_PATH" },
       { this->NoCMakeEnvironmentPath,
         "CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH" },
       { this->NoSystemEnvironmentPath,
         "CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH" },
-      { this->NoCMakeSystemPath, "CMAKE_FIND_USE_CMAKE_SYSTEM_PATH" } }
+      { this->NoCMakeSystemPath, "CMAKE_FIND_USE_CMAKE_SYSTEM_PATH" },
+      { this->NoCMakeInstallPath, "CMAKE_FIND_USE_INSTALL_PREFIX" } }
   };
 
   for (auto const& path : search_paths) {
@@ -348,6 +350,8 @@ bool cmFindCommon::CheckCommonArgument(std::string const& arg)
     this->NoSystemEnvironmentPath = true;
   } else if (arg == "NO_CMAKE_SYSTEM_PATH") {
     this->NoCMakeSystemPath = true;
+  } else if (arg == "NO_CMAKE_INSTALL_PREFIX") {
+    this->NoCMakeInstallPath = true;
   } else if (arg == "NO_CMAKE_FIND_ROOT_PATH") {
     this->FindRootPathMode = RootPathModeNever;
   } else if (arg == "ONLY_CMAKE_FIND_ROOT_PATH") {

+ 1 - 0
Source/cmFindCommon.h

@@ -130,6 +130,7 @@ protected:
   bool NoCMakeEnvironmentPath;
   bool NoSystemEnvironmentPath;
   bool NoCMakeSystemPath;
+  bool NoCMakeInstallPath;
 
   std::vector<std::string> SearchPathSuffixes;
 

+ 51 - 1
Source/cmFindPackageCommand.cxx

@@ -1682,7 +1682,57 @@ void cmFindPackageCommand::FillPrefixesCMakeSystemVariable()
 {
   cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeSystem];
 
-  paths.AddCMakePath("CMAKE_SYSTEM_PREFIX_PATH");
+  const bool install_prefix_in_list =
+    !this->Makefile->IsOn("CMAKE_FIND_NO_INSTALL_PREFIX");
+  const bool remove_install_prefix = this->NoCMakeInstallPath;
+  const bool add_install_prefix = !this->NoCMakeInstallPath &&
+    this->Makefile->IsDefinitionSet("CMAKE_FIND_USE_INSTALL_PREFIX");
+
+  // We have 3 possible states for `CMAKE_SYSTEM_PREFIX_PATH` and
+  // `CMAKE_INSTALL_PREFIX`.
+  // Either we need to remove `CMAKE_INSTALL_PREFIX`, add
+  // `CMAKE_INSTALL_PREFIX`, or do nothing.
+  //
+  // When we need to remove `CMAKE_INSTALL_PREFIX` we remove the Nth occurrence
+  // of `CMAKE_INSTALL_PREFIX` from `CMAKE_SYSTEM_PREFIX_PATH`, where `N` is
+  // 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;
+  }
+
+  if (remove_install_prefix && install_prefix_in_list &&
+      install_prefix_count > 0 && !install_path_to_remove.empty()) {
+
+    cmValue prefix_paths =
+      this->Makefile->GetDefinition("CMAKE_SYSTEM_PREFIX_PATH");
+    // remove entry from CMAKE_SYSTEM_PREFIX_PATH
+    std::vector<std::string> expanded = cmExpandedList(*prefix_paths);
+    long count = 0;
+    for (const auto& path : expanded) {
+      bool to_add =
+        !(path == install_path_to_remove && ++count == install_prefix_count);
+      if (to_add) {
+        paths.AddPath(path);
+      }
+    }
+  } else if (add_install_prefix && !install_prefix_in_list) {
+    paths.AddCMakePath("CMAKE_INSTALL_PREFIX");
+    paths.AddCMakePath("CMAKE_SYSTEM_PREFIX_PATH");
+  } else {
+    // Otherwise the current setup of `CMAKE_SYSTEM_PREFIX_PATH` is correct
+    paths.AddCMakePath("CMAKE_SYSTEM_PREFIX_PATH");
+  }
+
   paths.AddCMakePath("CMAKE_SYSTEM_FRAMEWORK_PATH");
   paths.AddCMakePath("CMAKE_SYSTEM_APPBUNDLE_PATH");
 

+ 2 - 0
Tests/RunCMake/find_file/FromPATHEnvDebugVar-stderr.txt

@@ -8,6 +8,7 @@
     CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH: 1
     CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH: 0
     CMAKE_FIND_USE_CMAKE_SYSTEM_PATH: 1
+    CMAKE_FIND_USE_INSTALL_PREFIX: 1
 
   find_file considered the following locations:.*
   The item was not found.*
@@ -21,5 +22,6 @@
     CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH: 1
     CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH: 0
     CMAKE_FIND_USE_CMAKE_SYSTEM_PATH: 1
+    CMAKE_FIND_USE_INSTALL_PREFIX: 1
 
   find_file considered the following locations:.*

+ 1 - 0
Tests/RunCMake/find_file/PrefixInPATH-stderr.txt

@@ -8,6 +8,7 @@
     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_file considered the following locations:.*
 .*include/PrefixInPATH.*

+ 2 - 0
Tests/RunCMake/find_library/FromPATHEnv-stderr.txt

@@ -9,6 +9,7 @@
     CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH: 1
     CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH: 0
     CMAKE_FIND_USE_CMAKE_SYSTEM_PATH: 1
+    CMAKE_FIND_USE_INSTALL_PREFIX: 1
 
   find_library considered the following locations:.*
   The item was not found.*
@@ -22,6 +23,7 @@
     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.*

+ 2 - 0
Tests/RunCMake/find_library/FromPATHEnvDebugVar-stderr.txt

@@ -9,6 +9,7 @@
     CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH: 1
     CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH: 0
     CMAKE_FIND_USE_CMAKE_SYSTEM_PATH: 1
+    CMAKE_FIND_USE_INSTALL_PREFIX: 1
 
   find_library considered the following locations:.*
   The item was not found.*
@@ -22,6 +23,7 @@
     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.*

+ 43 - 0
Tests/RunCMake/find_library/IgnoreInstallPrefix-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.*
+  .*IgnoreInstallPrefix-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.*

+ 3 - 0
Tests/RunCMake/find_library/IgnoreInstallPrefix-stdout.txt

@@ -0,0 +1,3 @@
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'
+-- CREATED_LIBRARY='[^']*/Tests/RunCMake/find_library/IgnoreInstallPrefix-build/lib/libcreated.a'
+-- CREATED_LIBRARY='CREATED_LIBRARY-NOTFOUND'

+ 32 - 0
Tests/RunCMake/find_library/IgnoreInstallPrefix.cmake

@@ -0,0 +1,32 @@
+set(ENV_PATH "$ENV{PATH}")
+set(ENV_CMAKE_PREFIX_PATH "$ENV{CMAKE_PREFIX_PATH}")
+set(ENV{PATH} "")
+set(ENV{CMAKE_PREFIX_PATH} "")
+
+list(APPEND CMAKE_FIND_LIBRARY_PREFIXES lib)
+list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES .a)
+
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib)
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib/libcreated.a" "created")
+
+set(CMAKE_FIND_DEBUG_MODE 1)
+set(CMAKE_FIND_USE_INSTALL_PREFIX OFF)
+
+find_library(CREATED_LIBRARY NAMES created)
+message(STATUS "CREATED_LIBRARY='${CREATED_LIBRARY}'")
+
+set(CMAKE_FIND_USE_INSTALL_PREFIX ON)
+find_library(CREATED_LIBRARY NAMES created)
+message(STATUS "CREATED_LIBRARY='${CREATED_LIBRARY}'")
+
+unset(CREATED_LIBRARY)
+unset(CREATED_LIBRARY CACHE)
+
+unset(CMAKE_FIND_USE_INSTALL_PREFIX)
+find_library(CREATED_LIBRARY NAMES created NO_CMAKE_INSTALL_PREFIX)
+message(STATUS "CREATED_LIBRARY='${CREATED_LIBRARY}'")
+
+set(CMAKE_FIND_DEBUG_MODE 0)
+
+set(ENV{PATH} "${ENV_PATH}")
+set(ENV{CMAKE_PREFIX_PATH} "${ENV_CMAKE_PREFIX_PATH}")

+ 1 - 0
Tests/RunCMake/find_library/PrefixInPATH-stderr.txt

@@ -8,6 +8,7 @@
     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:.*
 .*/does_not_exist.*

+ 1 - 0
Tests/RunCMake/find_library/RunCMakeTest.cmake

@@ -3,6 +3,7 @@ include(RunCMake)
 run_cmake(Created)
 run_cmake(FromPrefixPath)
 run_cmake(FromPATHEnv)
+run_cmake_with_options(IgnoreInstallPrefix "-DCMAKE_INSTALL_PREFIX=${RunCMake_BINARY_DIR}/IgnoreInstallPrefix-build/")
 if(UNIX AND NOT CYGWIN)
   run_cmake(LibArchLink)
   run_cmake(LibSymLink)

+ 17 - 0
Tests/RunCMake/find_package/IgnoreInstallPrefix.cmake

@@ -0,0 +1,17 @@
+
+find_package(Bar QUIET CONFIG NO_CMAKE_INSTALL_PREFIX)
+if(Bar_FOUND)
+  message(SEND_ERROR "Bar should not be found, was found in ${Bar_DIR}")
+endif()
+
+set(CMAKE_FIND_USE_INSTALL_PREFIX OFF)
+find_package(Bar QUIET CONFIG)
+if(Bar_FOUND)
+  message(SEND_ERROR "Bar should not be found, was found in ${Bar_DIR}")
+endif()
+
+set(CMAKE_FIND_USE_INSTALL_PREFIX ON)
+find_package(Bar QUIET CONFIG)
+if(NOT Bar_FOUND)
+  message(SEND_ERROR "Bar should be found via CMAKE_INSTALL_PREFIX")
+endif()

+ 1 - 0
Tests/RunCMake/find_package/RunCMakeTest.cmake

@@ -48,6 +48,7 @@ run_cmake(VersionRangeConfig2)
 run_cmake(VersionRangeConfig02)
 run_cmake(VersionRangeConfigStd)
 run_cmake(VersionRangeConfigStd2)
+run_cmake_with_options(IgnoreInstallPrefix  "-DCMAKE_INSTALL_PREFIX=${RunCMake_SOURCE_DIR}/PackageRoot/foo/cmake_root")
 run_cmake(IgnorePath)
 run_cmake(IgnorePrefixPath)
 if(UNIX

+ 2 - 0
Tests/RunCMake/find_path/FromPATHEnv-stderr.txt

@@ -8,6 +8,7 @@
     CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH: 1
     CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH: 0
     CMAKE_FIND_USE_CMAKE_SYSTEM_PATH: 1
+    CMAKE_FIND_USE_INSTALL_PREFIX: 1
 
   find_path considered the following locations:.*
   The item was not found.*
@@ -21,6 +22,7 @@
     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_path considered the following locations:.*
   The item was found at.*

+ 2 - 0
Tests/RunCMake/find_path/FromPATHEnvDebugVar-stderr.txt

@@ -8,6 +8,7 @@
     CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH: 1
     CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH: 0
     CMAKE_FIND_USE_CMAKE_SYSTEM_PATH: 1
+    CMAKE_FIND_USE_INSTALL_PREFIX: 1
 
   find_path considered the following locations:.*
   The item was not found.*
@@ -21,6 +22,7 @@
     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_path considered the following locations:.*
   The item was found at.*

+ 2 - 0
Tests/RunCMake/find_program/EnvAndHints-stderr.txt

@@ -8,6 +8,7 @@
     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_program considered the following locations:.*
   The item was found at.*
@@ -23,6 +24,7 @@
     CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH: 1
     CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH: 0
     CMAKE_FIND_USE_CMAKE_SYSTEM_PATH: 1
+    CMAKE_FIND_USE_INSTALL_PREFIX: 1
 
   find_program considered the following locations:.*
   The item was not found.*

+ 2 - 0
Tests/RunCMake/find_program/EnvAndHintsDebugVar-stderr.txt

@@ -8,6 +8,7 @@
     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_program considered the following locations:.*
   The item was found at.*
@@ -23,6 +24,7 @@
     CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH: 1
     CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH: 0
     CMAKE_FIND_USE_CMAKE_SYSTEM_PATH: 1
+    CMAKE_FIND_USE_INSTALL_PREFIX: 1
 
   find_program considered the following locations:.*
   The item was not found.*

+ 1 - 1
Tests/RunCMake/no_install_prefix/RunCMakeTest.cmake

@@ -11,5 +11,5 @@ run_cmake(with_install_prefix)
 file(REMOVE_RECURSE "${RunCMake_BINARY_DIR}/prefix")
 file(MAKE_DIRECTORY "${RunCMake_BINARY_DIR}/prefix/NoPrefix")
 file(WRITE "${RunCMake_BINARY_DIR}/prefix/NoPrefix/NoPrefixConfig.cmake" "")
-list(APPEND RunCMake_TEST_OPTIONS "-DCMAKE_FIND_NO_INSTALL_PREFIX=1")
+list(APPEND RunCMake_TEST_OPTIONS "-DCMAKE_FIND_NO_INSTALL_PREFIX=1" "-DCMAKE_INSTALL_PREFIX:PATH=${RunCMake_BINARY_DIR}/prefix")
 run_cmake(no_install_prefix)

+ 14 - 0
Tests/RunCMake/no_install_prefix/do_test.cmake

@@ -1,2 +1,16 @@
 
+find_package(NoPrefix NO_CMAKE_INSTALL_PREFIX)
+if(NoPrefix_FOUND)
+  message(FATAL_ERROR "Should not find package when NO_CMAKE_INSTALL_PREFIX specified")
+endif()
+
+set(CMAKE_FIND_USE_INSTALL_PREFIX ON)
+find_package(NoPrefix)
+if(NOT NoPrefix_FOUND)
+  message(FATAL_ERROR "Should always find package when CMAKE_FIND_USE_INSTALL_PREFIX is enabled")
+endif()
+
+unset(CMAKE_FIND_USE_INSTALL_PREFIX)
+unset(NoPrefix_DIR CACHE)
+
 find_package(NoPrefix REQUIRED)

+ 1 - 1
Tests/RunCMake/no_install_prefix/no_install_prefix-stderr.txt

@@ -1,4 +1,4 @@
-CMake Error at do_test.cmake:2 \(find_package\):
+CMake Error at do_test.cmake:16 \(find_package\):
   By not providing "FindNoPrefix.cmake" in CMAKE_MODULE_PATH this project has
   asked CMake to find a package configuration file provided by "NoPrefix",
   but CMake did not find one.