From 87b71eec6257b0d9c43b446205d61f334278fe7d Mon Sep 17 00:00:00 2001
From: Marc Chevrier <marc.chevrier@gmail.com>
Date: Tue, 1 Jun 2021 16:05:34 +0200
Subject: find_*: Add support for option NO_CACHE

Request that find result is stored in a normal variable rather than a
cache entry.

Fixes: #20687
Issue: #20743
---
 Help/command/FIND_XXX.txt                       |  21 +++-
 Help/release/dev/find_item-NO_CACHE.rst         |   6 ++
 Source/cmFindBase.cxx                           | 115 ++++++++++++--------
 Source/cmFindBase.h                             |   7 +-
 Source/cmFindLibraryCommand.cxx                 |   2 +-
 Source/cmFindPathCommand.cxx                    |   2 +-
 Source/cmFindProgramCommand.cxx                 |   2 +-
 Tests/RunCMake/find_file/NO_CACHE-stdout.txt    |  18 ++++
 Tests/RunCMake/find_file/NO_CACHE.cmake         | 129 +++++++++++++++++++++++
 Tests/RunCMake/find_file/RunCMakeTest.cmake     |   1 +
 Tests/RunCMake/find_library/NO_CACHE-stdout.txt |  18 ++++
 Tests/RunCMake/find_library/NO_CACHE.cmake      | 133 ++++++++++++++++++++++++
 Tests/RunCMake/find_library/RunCMakeTest.cmake  |   1 +
 Tests/RunCMake/find_path/NO_CACHE-stdout.txt    |  18 ++++
 Tests/RunCMake/find_path/NO_CACHE.cmake         | 131 +++++++++++++++++++++++
 Tests/RunCMake/find_path/RunCMakeTest.cmake     |   1 +
 Tests/RunCMake/find_program/NO_CACHE-stdout.txt |  18 ++++
 Tests/RunCMake/find_program/NO_CACHE.cmake      | 130 +++++++++++++++++++++++
 Tests/RunCMake/find_program/RunCMakeTest.cmake  |   1 +
 19 files changed, 700 insertions(+), 54 deletions(-)
 create mode 100644 Help/release/dev/find_item-NO_CACHE.rst
 create mode 100644 Tests/RunCMake/find_file/NO_CACHE-stdout.txt
 create mode 100644 Tests/RunCMake/find_file/NO_CACHE.cmake
 create mode 100644 Tests/RunCMake/find_library/NO_CACHE-stdout.txt
 create mode 100644 Tests/RunCMake/find_library/NO_CACHE.cmake
 create mode 100644 Tests/RunCMake/find_path/NO_CACHE-stdout.txt
 create mode 100644 Tests/RunCMake/find_path/NO_CACHE.cmake
 create mode 100644 Tests/RunCMake/find_program/NO_CACHE-stdout.txt
 create mode 100644 Tests/RunCMake/find_program/NO_CACHE.cmake

diff --git a/Help/command/FIND_XXX.txt b/Help/command/FIND_XXX.txt
index aae1c38..5b63e1c 100644
--- a/Help/command/FIND_XXX.txt
+++ b/Help/command/FIND_XXX.txt
@@ -15,6 +15,7 @@ The general signature is:
              [PATHS [path | ENV var]... ]
              [PATH_SUFFIXES suffix1 [suffix2 ...]]
              [DOC "cache documentation string"]
+             [NO_CACHE]
              [REQUIRED]
              [NO_DEFAULT_PATH]
              [NO_PACKAGE_ROOT_PATH]
@@ -28,8 +29,8 @@ The general signature is:
             )
 
 This command is used to find a |SEARCH_XXX_DESC|.
-A cache entry named by ``<VAR>`` is created to store the result
-of this command.
+A cache entry, or a normal variable if ``NO_CACHE`` is specified,
+named by ``<VAR>`` is created to store the result of this command.
 If the |SEARCH_XXX| is found the result is stored in the variable
 and the search will not be repeated unless the variable is cleared.
 If nothing is found, the result will be ``<VAR>-NOTFOUND``.
@@ -56,6 +57,22 @@ Options include:
 ``DOC``
   Specify the documentation string for the ``<VAR>`` cache entry.
 
+``NO_CACHE``
+  .. versionadded:: 3.21
+
+  The result of the search will be stored in a normal variable rather than
+  a cache entry.
+
+  .. note::
+
+    If the variable is already set before the call (as a normal or cache
+    variable) then the search will not occur.
+
+  .. warning::
+
+    This option should be used with caution because it can greatly increase
+    the cost of repeated configure steps.
+
 ``REQUIRED``
   .. versionadded:: 3.18
 
diff --git a/Help/release/dev/find_item-NO_CACHE.rst b/Help/release/dev/find_item-NO_CACHE.rst
new file mode 100644
index 0000000..be5258c
--- /dev/null
+++ b/Help/release/dev/find_item-NO_CACHE.rst
@@ -0,0 +1,6 @@
+find_item-NO_CACHE
+------------------
+
+* The :command:`find_file`, :command:`find_path`, :command:`find_program`,
+  and :command:`find_library` commands gained the option ``NO_CACHE`` to store
+  find result in normal variable.
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx
index c1281e3..1038ac2 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -39,12 +39,15 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
 
   // copy argsIn into args so it can be modified,
   // in the process extract the DOC "documentation"
+  // and handle options NO_CACHE and ENV
   size_t size = argsIn.size();
   std::vector<std::string> args;
   bool foundDoc = false;
   for (unsigned int j = 0; j < size; ++j) {
     if (foundDoc || argsIn[j] != "DOC") {
-      if (argsIn[j] == "ENV") {
+      if (argsIn[j] == "NO_CACHE") {
+        this->StoreResultInCache = false;
+      } else if (argsIn[j] == "ENV") {
         if (j + 1 < size) {
           j++;
           cmSystemTools::GetPath(args, argsIn[j].c_str());
@@ -68,11 +71,10 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
     return false;
   }
   this->VariableName = args[0];
-  if (this->CheckForVariableInCache()) {
-    this->AlreadyInCache = true;
+  if (this->CheckForVariableDefined()) {
+    this->AlreadyDefined = true;
     return true;
   }
-  this->AlreadyInCache = false;
 
   // Find what search path locations have been enabled/disable
   this->SelectDefaultSearchModes();
@@ -297,12 +299,12 @@ void cmFindBase::FillUserGuessPath()
   paths.AddSuffixes(this->SearchPathSuffixes);
 }
 
-bool cmFindBase::CheckForVariableInCache()
+bool cmFindBase::CheckForVariableDefined()
 {
-  if (cmProp cacheValue = this->Makefile->GetDefinition(this->VariableName)) {
+  if (cmProp value = this->Makefile->GetDefinition(this->VariableName)) {
     cmState* state = this->Makefile->GetState();
     cmProp cacheEntry = state->GetCacheEntryValue(this->VariableName);
-    bool found = !cmIsNOTFOUND(*cacheValue);
+    bool found = !cmIsNOTFOUND(*value);
     bool cached = cacheEntry != nullptr;
     auto cacheType = cached ? state->GetCacheEntryType(this->VariableName)
                             : cmStateEnums::UNINITIALIZED;
@@ -350,41 +352,53 @@ void cmFindBase::NormalizeFindResult()
       }
     }
 
-    // If the user specifies the entry on the command line without a
-    // type we should add the type and docstring but keep the original
-    // value.
-    if (value != *existingValue || this->AlreadyInCacheWithoutMetaInfo) {
-      this->Makefile->GetCMakeInstance()->AddCacheEntry(
-        this->VariableName, value.c_str(), this->VariableDocumentation.c_str(),
-        this->VariableType);
-      if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) ==
-          cmPolicies::NEW) {
-        if (this->Makefile->IsNormalDefinitionSet(this->VariableName)) {
-          this->Makefile->AddDefinition(this->VariableName, value);
+    if (this->StoreResultInCache) {
+      // If the user specifies the entry on the command line without a
+      // type we should add the type and docstring but keep the original
+      // value.
+      if (value != *existingValue || this->AlreadyInCacheWithoutMetaInfo) {
+        this->Makefile->GetCMakeInstance()->AddCacheEntry(
+          this->VariableName, value.c_str(),
+          this->VariableDocumentation.c_str(), this->VariableType);
+        if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) ==
+            cmPolicies::NEW) {
+          if (this->Makefile->IsNormalDefinitionSet(this->VariableName)) {
+            this->Makefile->AddDefinition(this->VariableName, value);
+          }
+        } else {
+          // if there was a definition then remove it
+          // This is required to ensure same behavior as
+          // cmMakefile::AddCacheDefinition.
+          this->Makefile->RemoveDefinition(this->VariableName);
         }
-      } else {
-        // if there was a definition then remove it
-        // This is required to ensure same behavior as
-        // cmMakefile::AddCacheDefinition.
-        this->Makefile->RemoveDefinition(this->VariableName);
       }
+    } else {
+      // ensure a normal variable is defined.
+      this->Makefile->AddDefinition(this->VariableName, value);
     }
   } else {
     // If the user specifies the entry on the command line without a
     // type we should add the type and docstring but keep the original
     // value.
-    if (this->AlreadyInCacheWithoutMetaInfo) {
-      this->Makefile->AddCacheDefinition(this->VariableName, "",
-                                         this->VariableDocumentation.c_str(),
-                                         this->VariableType);
-      if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) ==
-            cmPolicies::NEW &&
-          this->Makefile->IsNormalDefinitionSet(this->VariableName)) {
-        this->Makefile->AddDefinition(
-          this->VariableName,
-          *this->Makefile->GetCMakeInstance()->GetCacheDefinition(
-            this->VariableName));
+    if (this->StoreResultInCache) {
+      if (this->AlreadyInCacheWithoutMetaInfo) {
+        this->Makefile->AddCacheDefinition(this->VariableName, "",
+                                           this->VariableDocumentation.c_str(),
+                                           this->VariableType);
+        if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) ==
+              cmPolicies::NEW &&
+            this->Makefile->IsNormalDefinitionSet(this->VariableName)) {
+          this->Makefile->AddDefinition(
+            this->VariableName,
+            *this->Makefile->GetCMakeInstance()->GetCacheDefinition(
+              this->VariableName));
+        }
       }
+    } else {
+      // ensure a normal variable is defined.
+      this->Makefile->AddDefinition(
+        this->VariableName,
+        this->Makefile->GetSafeDefinition(this->VariableName));
     }
   }
 }
@@ -397,23 +411,32 @@ void cmFindBase::StoreFindResult(const std::string& value)
     this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) == cmPolicies::NEW;
 
   if (!value.empty()) {
-    this->Makefile->AddCacheDefinition(this->VariableName, value,
-                                       this->VariableDocumentation.c_str(),
-                                       this->VariableType, force);
-    if (updateNormalVariable &&
-        this->Makefile->IsNormalDefinitionSet(this->VariableName)) {
+    if (this->StoreResultInCache) {
+      this->Makefile->AddCacheDefinition(this->VariableName, value,
+                                         this->VariableDocumentation.c_str(),
+                                         this->VariableType, force);
+      if (updateNormalVariable &&
+          this->Makefile->IsNormalDefinitionSet(this->VariableName)) {
+        this->Makefile->AddDefinition(this->VariableName, value);
+      }
+    } else {
       this->Makefile->AddDefinition(this->VariableName, value);
     }
+
     return;
   }
 
-  this->Makefile->AddCacheDefinition(
-    this->VariableName, cmStrCat(this->VariableName, "-NOTFOUND"),
-    this->VariableDocumentation.c_str(), this->VariableType, force);
-  if (updateNormalVariable &&
-      this->Makefile->IsNormalDefinitionSet(this->VariableName)) {
-    this->Makefile->AddDefinition(this->VariableName,
-                                  cmStrCat(this->VariableName, "-NOTFOUND"));
+  auto notFound = cmStrCat(this->VariableName, "-NOTFOUND");
+  if (this->StoreResultInCache) {
+    this->Makefile->AddCacheDefinition(this->VariableName, notFound,
+                                       this->VariableDocumentation.c_str(),
+                                       this->VariableType, force);
+    if (updateNormalVariable &&
+        this->Makefile->IsNormalDefinitionSet(this->VariableName)) {
+      this->Makefile->AddDefinition(this->VariableName, notFound);
+    }
+  } else {
+    this->Makefile->AddDefinition(this->VariableName, notFound);
   }
 
   if (this->Required) {
diff --git a/Source/cmFindBase.h b/Source/cmFindBase.h
index c2a9288..d197424 100644
--- a/Source/cmFindBase.h
+++ b/Source/cmFindBase.h
@@ -35,10 +35,10 @@ protected:
   friend class cmFindBaseDebugState;
   void ExpandPaths();
 
-  // see if the VariableName is already set in the cache,
+  // see if the VariableName is already set,
   // also copy the documentation from the cache to VariableDocumentation
   // if it has documentation in the cache
-  bool CheckForVariableInCache();
+  bool CheckForVariableDefined();
 
   void NormalizeFindResult();
   void StoreFindResult(const std::string& value);
@@ -57,8 +57,9 @@ protected:
   // CMAKE_*_PATH CMAKE_SYSTEM_*_PATH FRAMEWORK|LIBRARY|INCLUDE|PROGRAM
   std::string EnvironmentPath; // LIB,INCLUDE
 
-  bool AlreadyInCache = false;
+  bool AlreadyDefined = false;
   bool AlreadyInCacheWithoutMetaInfo = false;
+  bool StoreResultInCache = true;
 
   bool Required = false;
 
diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx
index b1f4275..0cbe637 100644
--- a/Source/cmFindLibraryCommand.cxx
+++ b/Source/cmFindLibraryCommand.cxx
@@ -39,7 +39,7 @@ bool cmFindLibraryCommand::InitialPass(std::vector<std::string> const& argsIn)
     return false;
   }
 
-  if (this->AlreadyInCache) {
+  if (this->AlreadyDefined) {
     this->NormalizeFindResult();
     return true;
   }
diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx
index 126cc2f..3d21167 100644
--- a/Source/cmFindPathCommand.cxx
+++ b/Source/cmFindPathCommand.cxx
@@ -36,7 +36,7 @@ bool cmFindPathCommand::InitialPass(std::vector<std::string> const& argsIn)
     return false;
   }
 
-  if (this->AlreadyInCache) {
+  if (this->AlreadyDefined) {
     this->NormalizeFindResult();
     return true;
   }
diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx
index 76fc4a4..1c87625 100644
--- a/Source/cmFindProgramCommand.cxx
+++ b/Source/cmFindProgramCommand.cxx
@@ -165,7 +165,7 @@ bool cmFindProgramCommand::InitialPass(std::vector<std::string> const& argsIn)
     return false;
   }
 
-  if (this->AlreadyInCache) {
+  if (this->AlreadyDefined) {
     this->NormalizeFindResult();
     return true;
   }
diff --git a/Tests/RunCMake/find_file/NO_CACHE-stdout.txt b/Tests/RunCMake/find_file/NO_CACHE-stdout.txt
new file mode 100644
index 0000000..e786321
--- /dev/null
+++ b/Tests/RunCMake/find_file/NO_CACHE-stdout.txt
@@ -0,0 +1,18 @@
+-- FILE_exists='.+/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- FILE_doNotExists='FILE_doNotExists-NOTFOUND'
+--[ ]+
+-- Policy CMP0125 = OLD
+-- CACHED FILE_cache='unknown'
+-- FILE_cache='unknown'
+-- CACHED FILE_cache='PrefixInPATH.h'
+-- FILE_cache='PrefixInPATH.h'
+-- CACHED FILE_cache='PrefixInPATH.h'
+-- FILE_cache='PrefixInPATH.h'
+--[ ]+
+-- Policy CMP0125 = NEW
+-- CACHED FILE_cache='unknown'
+-- FILE_cache='unknown'
+-- CACHED FILE_cache='PrefixInPATH.h'
+-- FILE_cache='PrefixInPATH.h'
+-- CACHED FILE_cache='PrefixInPATH.h'
+-- FILE_cache='.+/Tests/RunCMake/find_file/NO_CACHE-build/PrefixInPATH.h'
diff --git a/Tests/RunCMake/find_file/NO_CACHE.cmake b/Tests/RunCMake/find_file/NO_CACHE.cmake
new file mode 100644
index 0000000..65156b9
--- /dev/null
+++ b/Tests/RunCMake/find_file/NO_CACHE.cmake
@@ -0,0 +1,129 @@
+find_file(FILE_exists
+  NAMES PrefixInPATH.h
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (DEFINED CACHE{FILE_exists})
+  message(SEND_ERROR "Cache variable defined: FILE_exists")
+endif()
+message(STATUS "FILE_exists='${FILE_exists}'")
+
+
+find_file(FILE_doNotExists
+  NAMES doNotExists.h
+  NO_CACHE
+  )
+if (DEFINED CACHE{FILE_doNotExists})
+  message(SEND_ERROR "Cache variable defined: FILE_doNotExists")
+endif()
+message(STATUS "FILE_doNotExists='${FILE_doNotExists}'")
+
+
+cmake_policy(SET CMP0125 OLD)
+message(STATUS "")
+message(STATUS "Policy CMP0125 = OLD")
+file(REMOVE "${CMAKE_BINARY_DIR}/PrefixInPATH.h")
+
+set(FILE_cache "unknown" CACHE FILEPATH "")
+find_file(FILE_cache
+  NAMES PrefixInPATH.h
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{FILE_cache})
+  message(SEND_ERROR "Cache variable not defined: FILE_cache")
+endif()
+message(STATUS "CACHED FILE_cache='$CACHE{FILE_cache}'")
+unset(FILE_cache CACHE)
+message(STATUS "FILE_cache='${FILE_cache}'")
+
+
+set(FILE_cache "PrefixInPATH.h" CACHE FILEPATH "")
+unset(FILE_cache)
+find_file(FILE_cache
+  NAMES PrefixInPATH.h
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{FILE_cache})
+  message(SEND_ERROR "Cache variable not defined: FILE_cache")
+endif()
+message(STATUS "CACHED FILE_cache='$CACHE{FILE_cache}'")
+unset(FILE_cache CACHE)
+message(STATUS "FILE_cache='${FILE_cache}'")
+
+
+set(FILE_cache "PrefixInPATH.h" CACHE FILEPATH "")
+unset(FILE_cache)
+# simulate cache variable defined in command line
+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/include/PrefixInPATH.h" DESTINATION "${CMAKE_BINARY_DIR}")
+set_property(CACHE FILE_cache PROPERTY TYPE UNINITIALIZED)
+find_file(FILE_cache
+  NAMES PrefixInPATH.h
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{FILE_cache})
+  message(SEND_ERROR "Cache variable not defined: FILE_cache")
+endif()
+message(STATUS "CACHED FILE_cache='$CACHE{FILE_cache}'")
+unset(FILE_cache CACHE)
+message(STATUS "FILE_cache='${FILE_cache}'")
+
+
+cmake_policy(SET CMP0125 NEW)
+message(STATUS "")
+message(STATUS "Policy CMP0125 = NEW")
+file(REMOVE "${CMAKE_BINARY_DIR}/PrefixInPATH.h")
+
+set(FILE_cache "unknown" CACHE FILEPATH "")
+unset(FILE_cache)
+find_file(FILE_cache
+  NAMES PrefixInPATH.h
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{FILE_cache})
+  message(SEND_ERROR "Cache variable not defined: FILE_cache")
+endif()
+message(STATUS "CACHED FILE_cache='$CACHE{FILE_cache}'")
+unset(FILE_cache CACHE)
+message(STATUS "FILE_cache='${FILE_cache}'")
+
+
+set(FILE_cache "PrefixInPATH.h" CACHE FILEPATH "")
+unset(FILE_cache)
+find_file(FILE_cache
+  NAMES PrefixInPATH.h
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{FILE_cache})
+  message(SEND_ERROR "Cache variable not defined: FILE_cache")
+endif()
+message(STATUS "CACHED FILE_cache='$CACHE{FILE_cache}'")
+unset(FILE_cache CACHE)
+message(STATUS "FILE_cache='${FILE_cache}'")
+
+
+set(FILE_cache "PrefixInPATH.h" CACHE FILEPATH "")
+unset(FILE_cache)
+# simulate cache variable defined in command line
+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/include/PrefixInPATH.h" DESTINATION "${CMAKE_BINARY_DIR}")
+set_property(CACHE FILE_cache PROPERTY TYPE UNINITIALIZED)
+find_file(FILE_cache
+  NAMES PrefixInPATH.h
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{FILE_cache})
+  message(SEND_ERROR "Cache variable not defined: FILE_cache")
+endif()
+message(STATUS "CACHED FILE_cache='$CACHE{FILE_cache}'")
+unset(FILE_cache CACHE)
+message(STATUS "FILE_cache='${FILE_cache}'")
diff --git a/Tests/RunCMake/find_file/RunCMakeTest.cmake b/Tests/RunCMake/find_file/RunCMakeTest.cmake
index 93dfb78..95f55a5 100644
--- a/Tests/RunCMake/find_file/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_file/RunCMakeTest.cmake
@@ -4,3 +4,4 @@ run_cmake(FromPATHEnv)
 run_cmake(FromPrefixPath)
 run_cmake(PrefixInPATH)
 run_cmake(Required)
+run_cmake(NO_CACHE)
diff --git a/Tests/RunCMake/find_library/NO_CACHE-stdout.txt b/Tests/RunCMake/find_library/NO_CACHE-stdout.txt
new file mode 100644
index 0000000..1b4c2a9
--- /dev/null
+++ b/Tests/RunCMake/find_library/NO_CACHE-stdout.txt
@@ -0,0 +1,18 @@
+-- LIB_exists='.+/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
+-- LIB_doNotExists='LIB_doNotExists-NOTFOUND'
+--[ ]+
+-- Policy CMP0125 = OLD
+-- CACHED LIB_cache='unknown'
+-- LIB_cache='unknown'
+-- CACHED LIB_cache='libPrefixInPATH.a'
+-- LIB_cache='libPrefixInPATH.a'
+-- CACHED LIB_cache='libPrefixInPATH.a'
+-- LIB_cache='libPrefixInPATH.a'
+--[ ]+
+-- Policy CMP0125 = NEW
+-- CACHED LIB_cache='unknown'
+-- LIB_cache='unknown'
+-- CACHED LIB_cache='libPrefixInPATH.a'
+-- LIB_cache='libPrefixInPATH.a'
+-- CACHED LIB_cache='libPrefixInPATH.a'
+-- LIB_cache='.+/Tests/RunCMake/find_library/NO_CACHE-build/libPrefixInPATH.a'
diff --git a/Tests/RunCMake/find_library/NO_CACHE.cmake b/Tests/RunCMake/find_library/NO_CACHE.cmake
new file mode 100644
index 0000000..a94b828
--- /dev/null
+++ b/Tests/RunCMake/find_library/NO_CACHE.cmake
@@ -0,0 +1,133 @@
+list(APPEND CMAKE_FIND_LIBRARY_PREFIXES lib)
+list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES .a)
+
+find_library(LIB_exists
+  NAMES PrefixInPATH
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (DEFINED CACHE{LIB_exists})
+  message(SEND_ERROR "Cache variable defined: LIB_exists")
+endif()
+message(STATUS "LIB_exists='${LIB_exists}'")
+
+
+find_library(LIB_doNotExists
+  NAMES doNotExists
+  NO_CACHE
+  )
+if (DEFINED CACHE{LIB_doNotExists})
+  message(SEND_ERROR "Cache variable defined: LIB_doNotExists")
+endif()
+message(STATUS "LIB_doNotExists='${LIB_doNotExists}'")
+
+
+cmake_policy(SET CMP0125 OLD)
+message(STATUS "")
+message(STATUS "Policy CMP0125 = OLD")
+file(REMOVE "${CMAKE_BINARY_DIR}/libPrefixInPATH.a")
+
+set(LIB_cache "unknown" CACHE FILEPATH "")
+find_library(LIB_cache
+  NAMES PrefixInPATH
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{LIB_cache})
+  message(SEND_ERROR "Cache variable not defined: LIB_cache")
+endif()
+message(STATUS "CACHED LIB_cache='$CACHE{LIB_cache}'")
+unset(LIB_cache CACHE)
+message(STATUS "LIB_cache='${LIB_cache}'")
+
+
+set(LIB_cache "libPrefixInPATH.a" CACHE FILEPATH "")
+unset(LIB_cache)
+find_library(LIB_cache
+  NAMES PrefixInPATH
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{LIB_cache})
+  message(SEND_ERROR "Cache variable not defined: LIB_cache")
+endif()
+message(STATUS "CACHED LIB_cache='$CACHE{LIB_cache}'")
+unset(LIB_cache CACHE)
+message(STATUS "LIB_cache='${LIB_cache}'")
+
+
+set(LIB_cache "libPrefixInPATH.a" CACHE FILEPATH "")
+unset(LIB_cache)
+# simulate cache variable defined in command line
+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/lib/libPrefixInPATH.a" DESTINATION "${CMAKE_BINARY_DIR}")
+set_property(CACHE LIB_cache PROPERTY TYPE UNINITIALIZED)
+find_library(LIB_cache
+  NAMES PrefixInPATH
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{LIB_cache})
+  message(SEND_ERROR "Cache variable not defined: LIB_cache")
+endif()
+message(STATUS "CACHED LIB_cache='$CACHE{LIB_cache}'")
+unset(LIB_cache CACHE)
+message(STATUS "LIB_cache='${LIB_cache}'")
+
+
+cmake_policy(SET CMP0125 NEW)
+message(STATUS "")
+message(STATUS "Policy CMP0125 = NEW")
+file(REMOVE "${CMAKE_BINARY_DIR}/libPrefixInPATH.a")
+
+set(LIB_cache "unknown" CACHE FILEPATH "")
+find_library(LIB_cache
+  NAMES PrefixInPATH
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{LIB_cache})
+  message(SEND_ERROR "Cache variable not defined: LIB_cache")
+endif()
+message(STATUS "CACHED LIB_cache='$CACHE{LIB_cache}'")
+unset(LIB_cache CACHE)
+message(STATUS "LIB_cache='${LIB_cache}'")
+
+
+set(LIB_cache "libPrefixInPATH.a" CACHE FILEPATH "")
+unset(LIB_cache)
+find_library(LIB_cache
+  NAMES PrefixInPATH
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{LIB_cache})
+  message(SEND_ERROR "Cache variable not defined: LIB_cache")
+endif()
+message(STATUS "CACHED LIB_cache='$CACHE{LIB_cache}'")
+unset(LIB_cache CACHE)
+message(STATUS "LIB_cache='${LIB_cache}'")
+
+
+set(LIB_cache "libPrefixInPATH.a" CACHE FILEPATH "")
+unset(LIB_cache)
+# simulate cache variable defined in command line
+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/lib/libPrefixInPATH.a" DESTINATION "${CMAKE_BINARY_DIR}")
+set_property(CACHE LIB_cache PROPERTY TYPE UNINITIALIZED)
+find_library(LIB_cache
+  NAMES PrefixInPATH
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/lib
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{LIB_cache})
+  message(SEND_ERROR "Cache variable not defined: LIB_cache")
+endif()
+message(STATUS "CACHED LIB_cache='$CACHE{LIB_cache}'")
+unset(LIB_cache CACHE)
+message(STATUS "LIB_cache='${LIB_cache}'")
diff --git a/Tests/RunCMake/find_library/RunCMakeTest.cmake b/Tests/RunCMake/find_library/RunCMakeTest.cmake
index c7d69e4..e297173 100644
--- a/Tests/RunCMake/find_library/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_library/RunCMakeTest.cmake
@@ -9,3 +9,4 @@ if(UNIX AND NOT CYGWIN)
 endif()
 run_cmake(PrefixInPATH)
 run_cmake(Required)
+run_cmake(NO_CACHE)
diff --git a/Tests/RunCMake/find_path/NO_CACHE-stdout.txt b/Tests/RunCMake/find_path/NO_CACHE-stdout.txt
new file mode 100644
index 0000000..a41454e
--- /dev/null
+++ b/Tests/RunCMake/find_path/NO_CACHE-stdout.txt
@@ -0,0 +1,18 @@
+-- PATH_exists='.+/Tests/RunCMake/find_path/include/'
+-- PATH_exists='PATH_doNotExists-NOTFOUND'
+--[ ]+
+-- Policy CMP0125 = OLD
+-- CACHED PATH_cache='unknown'
+-- PATH_cache='unknown'
+-- CACHED PATH_cache='include'
+-- PATH_cache='include'
+-- CACHED PATH_cache='include'
+-- PATH_cache='include'
+--[ ]+
+-- Policy CMP0125 = NEW
+-- CACHED PATH_cache='unknown'
+-- PATH_cache='unknown'
+-- CACHED PATH_cache='include'
+-- PATH_cache='include'
+-- CACHED PATH_cache='include'
+-- PATH_cache='.+/Tests/RunCMake/find_path/NO_CACHE-build/include'
diff --git a/Tests/RunCMake/find_path/NO_CACHE.cmake b/Tests/RunCMake/find_path/NO_CACHE.cmake
new file mode 100644
index 0000000..4779ac8
--- /dev/null
+++ b/Tests/RunCMake/find_path/NO_CACHE.cmake
@@ -0,0 +1,131 @@
+find_path(PATH_exists
+  NAMES PrefixInPATH.h
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (DEFINED CACHE{PATH_exists})
+  message(SEND_ERROR "Cache variable defined: PATH_exists")
+endif()
+message(STATUS "PATH_exists='${PATH_exists}'")
+
+
+find_path(PATH_doNotExists
+  NAMES doNotExists.h
+  NO_CACHE
+  )
+if (DEFINED CACHE{PATH_doNotExists})
+  message(SEND_ERROR "Cache variable defined: PATH_doNotExists")
+endif()
+message(STATUS "PATH_exists='${PATH_doNotExists}'")
+
+
+cmake_policy(SET CMP0125 OLD)
+message(STATUS "")
+message(STATUS "Policy CMP0125 = OLD")
+file(REMOVE "${CMAKE_BINARY_DIR}/PrefixInPATH.h")
+
+set(PATH_cache "unknown" CACHE PATH "")
+find_path(PATH_cache
+  NAMES PrefixInPATH.h
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{PATH_cache})
+  message(SEND_ERROR "Cache variable defined: PATH_cache")
+endif()
+message(STATUS "CACHED PATH_cache='$CACHE{PATH_cache}'")
+unset(PATH_cache CACHE)
+message(STATUS "PATH_cache='${PATH_cache}'")
+
+
+set(PATH_cache "include" CACHE PATH "")
+unset(PATH_cache)
+find_path(PATH_cache
+  NAMES PrefixInPATH.h
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{PATH_cache})
+  message(SEND_ERROR "Cache variable defined: PATH_cache")
+endif()
+message(STATUS "CACHED PATH_cache='$CACHE{PATH_cache}'")
+unset(PATH_cache CACHE)
+message(STATUS "PATH_cache='${PATH_cache}'")
+
+
+set(PATH_cache "include" CACHE PATH "")
+unset(PATH_cache)
+# simulate cache variable defined in command line
+file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include")
+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/include/PrefixInPATH.h" DESTINATION "${CMAKE_BINARY_DIR}/include")
+set_property(CACHE PATH_cache PROPERTY TYPE UNINITIALIZED)
+find_path(PATH_cache
+  NAMES PrefixInPATH.h
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{PATH_cache})
+  message(SEND_ERROR "Cache variable not defined: PATH_cache")
+endif()
+message(STATUS "CACHED PATH_cache='$CACHE{PATH_cache}'")
+unset(PATH_cache CACHE)
+message(STATUS "PATH_cache='${PATH_cache}'")
+
+
+cmake_policy(SET CMP0125 NEW)
+message(STATUS "")
+message(STATUS "Policy CMP0125 = NEW")
+file(REMOVE_RECURSE "${CMAKE_BINARY_DIR}/include")
+
+set(PATH_cache "unknown" CACHE PATH "")
+unset(PATH_cache)
+find_path(PATH_cache
+  NAMES PrefixInPATH.h
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{PATH_cache})
+  message(SEND_ERROR "Cache variable defined: PATH_cache")
+endif()
+message(STATUS "CACHED PATH_cache='$CACHE{PATH_cache}'")
+unset(PATH_cache CACHE)
+message(STATUS "PATH_cache='${PATH_cache}'")
+
+
+set(PATH_cache "include" CACHE PATH "")
+unset(PATH_cache)
+find_path(PATH_cache
+  NAMES PrefixInPATH.h
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{PATH_cache})
+  message(SEND_ERROR "Cache variable defined: PATH_cache")
+endif()
+message(STATUS "CACHED PATH_cache='$CACHE{PATH_cache}'")
+unset(PATH_cache CACHE)
+message(STATUS "PATH_cache='${PATH_cache}'")
+
+
+set(PATH_cache "include" CACHE PATH "")
+unset(PATH_cache)
+# simulate cache variable defined in command line
+file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include")
+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/include/PrefixInPATH.h" DESTINATION "${CMAKE_BINARY_DIR}/include")
+set_property(CACHE PATH_cache PROPERTY TYPE UNINITIALIZED)
+find_path(PATH_cache
+  NAMES PrefixInPATH.h
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{PATH_cache})
+  message(SEND_ERROR "Cache variable not defined: PATH_cache")
+endif()
+message(STATUS "CACHED PATH_cache='$CACHE{PATH_cache}'")
+unset(PATH_cache CACHE)
+message(STATUS "PATH_cache='${PATH_cache}'")
diff --git a/Tests/RunCMake/find_path/RunCMakeTest.cmake b/Tests/RunCMake/find_path/RunCMakeTest.cmake
index 5c919bb..90ee768 100644
--- a/Tests/RunCMake/find_path/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_path/RunCMakeTest.cmake
@@ -4,6 +4,7 @@ run_cmake(EmptyOldStyle)
 run_cmake(FromPATHEnv)
 run_cmake(PrefixInPATH)
 run_cmake(Required)
+run_cmake(NO_CACHE)
 
 if(APPLE)
   run_cmake(FrameworksWithSubdirs)
diff --git a/Tests/RunCMake/find_program/NO_CACHE-stdout.txt b/Tests/RunCMake/find_program/NO_CACHE-stdout.txt
new file mode 100644
index 0000000..c235d81
--- /dev/null
+++ b/Tests/RunCMake/find_program/NO_CACHE-stdout.txt
@@ -0,0 +1,18 @@
+-- PROG_A='.+/Tests/RunCMake/find_program/A/testA'
+-- PROG_AandB='PROG_AandB-NOTFOUND'
+--[ ]+
+-- Policy CMP0125 = OLD
+-- CACHED PROG_cache='unknown'
+-- PROG_cache='unknown'
+-- CACHED PROG_cache='testA'
+-- PROG_cache='testA'
+-- CACHED PROG_cache='testA'
+-- PROG_cache='testA'
+--[ ]+
+-- Policy CMP0125 = NEW
+-- CACHED PROG_cache='unknown'
+-- PROG_cache='unknown'
+-- CACHED PROG_cache='testA'
+-- PROG_cache='testA'
+-- CACHED PROG_cache='testA'
+-- PROG_cache='.+/Tests/RunCMake/find_program/NO_CACHE-build/testA'
diff --git a/Tests/RunCMake/find_program/NO_CACHE.cmake b/Tests/RunCMake/find_program/NO_CACHE.cmake
new file mode 100644
index 0000000..77a0582
--- /dev/null
+++ b/Tests/RunCMake/find_program/NO_CACHE.cmake
@@ -0,0 +1,130 @@
+find_program(PROG_A
+  NAMES testA
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (DEFINED CACHE{PROG_A})
+  message(SEND_ERROR "Cache variable defined: PROG_A")
+endif()
+message(STATUS "PROG_A='${PROG_A}'")
+
+
+find_program(PROG_AandB
+  NAMES testAandB
+  NO_CACHE
+  )
+if (DEFINED CACHE{PROG_AandB})
+  message(SEND_ERROR "Cache variable defined: PROG_AandN")
+endif()
+message(STATUS "PROG_AandB='${PROG_AandB}'")
+
+
+cmake_policy(SET CMP0125 OLD)
+message(STATUS "")
+message(STATUS "Policy CMP0125 = OLD")
+file(REMOVE "${CMAKE_BINARY_DIR}/testA")
+
+set(PROG_cache "unknown" CACHE FILEPATH "")
+find_program(PROG_cache
+  NAMES testA
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{PROG_cache})
+  message(SEND_ERROR "Cache variable not defined: PROG_cache")
+endif()
+message(STATUS "CACHED PROG_cache='$CACHE{PROG_cache}'")
+unset(PROG_cache CACHE)
+message(STATUS "PROG_cache='${PROG_cache}'")
+
+
+set(PROG_cache "testA" CACHE FILEPATH "")
+unset(PROG_cache)
+find_program(PROG_cache
+  NAMES testA
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{PROG_cache})
+  message(SEND_ERROR "Cache variable not defined: PROG_cache")
+endif()
+message(STATUS "CACHED PROG_cache='$CACHE{PROG_cache}'")
+unset(PROG_cache CACHE)
+message(STATUS "PROG_cache='${PROG_cache}'")
+
+
+set(PROG_cache "testA" CACHE FILEPATH "")
+unset(PROG_cache)
+# simulate cache variable defined in command line
+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/A/testA" DESTINATION "${CMAKE_BINARY_DIR}")
+set_property(CACHE PROG_cache PROPERTY TYPE UNINITIALIZED)
+find_program(PROG_cache
+  NAMES testA
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{PROG_cache})
+  message(SEND_ERROR "Cache variable not defined: PROG_cache")
+endif()
+message(STATUS "CACHED PROG_cache='$CACHE{PROG_cache}'")
+unset(PROG_cache CACHE)
+message(STATUS "PROG_cache='${PROG_cache}'")
+
+
+cmake_policy(SET CMP0125 NEW)
+message(STATUS "")
+message(STATUS "Policy CMP0125 = NEW")
+file(REMOVE "${CMAKE_BINARY_DIR}/testA")
+
+set(PROG_cache "unknown" CACHE FILEPATH "")
+find_program(PROG_cache
+  NAMES testA
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{PROG_cache})
+  message(SEND_ERROR "Cache variable not defined: PROG_cache")
+endif()
+message(STATUS "CACHED PROG_cache='$CACHE{PROG_cache}'")
+unset(PROG_cache CACHE)
+message(STATUS "PROG_cache='${PROG_cache}'")
+
+
+set(PROG_cache "testA" CACHE FILEPATH "")
+unset(PROG_cache)
+find_program(PROG_cache
+  NAMES testA
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{PROG_cache})
+  message(SEND_ERROR "Cache variable not defined: PROG_cache")
+endif()
+message(STATUS "CACHED PROG_cache='$CACHE{PROG_cache}'")
+unset(PROG_cache CACHE)
+message(STATUS "PROG_cache='${PROG_cache}'")
+
+
+set(PROG_cache "testA" CACHE FILEPATH "")
+unset(PROG_cache)
+# simulate cache variable defined in command line
+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/A/testA" DESTINATION "${CMAKE_BINARY_DIR}")
+set_property(CACHE PROG_cache PROPERTY TYPE UNINITIALIZED)
+find_program(PROG_cache
+  NAMES testA
+  PATHS ${CMAKE_CURRENT_SOURCE_DIR}/A
+  NO_CACHE
+  NO_DEFAULT_PATH
+  )
+if (NOT DEFINED CACHE{PROG_cache})
+  message(SEND_ERROR "Cache variable not defined: PROG_cache")
+endif()
+message(STATUS "CACHED PROG_cache='$CACHE{PROG_cache}'")
+unset(PROG_cache CACHE)
+message(STATUS "PROG_cache='${PROG_cache}'")
diff --git a/Tests/RunCMake/find_program/RunCMakeTest.cmake b/Tests/RunCMake/find_program/RunCMakeTest.cmake
index 77c021d..34edc19 100644
--- a/Tests/RunCMake/find_program/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_program/RunCMakeTest.cmake
@@ -5,6 +5,7 @@ run_cmake(DirsPerName)
 run_cmake(NamesPerDir)
 run_cmake(RelAndAbsPath)
 run_cmake(Required)
+run_cmake(NO_CACHE)
 
 if(CMAKE_SYSTEM_NAME MATCHES "^(Windows|CYGWIN|MSYS)$")
   run_cmake(WindowsCom)
-- 
cgit v0.12