Browse Source

Merge topic 'find-package-required'

857a039d66 find_*: Add variable to default calls to REQUIRED

Acked-by: Kitware Robot <[email protected]>
Acked-by: buildbot <[email protected]>
Merge-request: !10364
Brad King 9 months ago
parent
commit
75da788360
38 changed files with 337 additions and 22 deletions
  1. 13 1
      Help/command/FIND_XXX.txt
  2. 12 2
      Help/command/find_package.rst
  3. 1 0
      Help/manual/cmake-variables.7.rst
  4. 8 0
      Help/release/dev/cmake-find-required.rst
  5. 27 0
      Help/variable/CMAKE_FIND_REQUIRED.rst
  6. 18 0
      Source/cmFindBase.cxx
  7. 53 17
      Source/cmFindPackageCommand.cxx
  8. 12 2
      Source/cmFindPackageCommand.h
  9. 1 0
      Tests/RunCMake/find_file/Optional-result.txt
  10. 10 0
      Tests/RunCMake/find_file/Optional-stderr.txt
  11. 14 0
      Tests/RunCMake/find_file/Optional.cmake
  12. 1 0
      Tests/RunCMake/find_file/RunCMakeTest.cmake
  13. 1 0
      Tests/RunCMake/find_library/Optional-result.txt
  14. 10 0
      Tests/RunCMake/find_library/Optional-stderr.txt
  15. 13 0
      Tests/RunCMake/find_library/Optional.cmake
  16. 1 0
      Tests/RunCMake/find_library/RunCMakeTest.cmake
  17. 4 0
      Tests/RunCMake/find_package/MissingNormalForceRequired-stderr.txt
  18. 1 0
      Tests/RunCMake/find_package/PackageVarOverridesOptional-result.txt
  19. 20 0
      Tests/RunCMake/find_package/PackageVarOverridesOptional-stderr.txt
  20. 2 0
      Tests/RunCMake/find_package/PackageVarOverridesOptional.cmake
  21. 1 0
      Tests/RunCMake/find_package/RequiredOptionalKeywordsClash-result.txt
  22. 4 0
      Tests/RunCMake/find_package/RequiredOptionalKeywordsClash-stderr.txt
  23. 1 0
      Tests/RunCMake/find_package/RequiredOptionalKeywordsClash.cmake
  24. 18 0
      Tests/RunCMake/find_package/RequiredVarNested-stderr.txt
  25. 3 0
      Tests/RunCMake/find_package/RequiredVarNested.cmake
  26. 8 0
      Tests/RunCMake/find_package/RequiredVarNestedConfig.cmake
  27. 1 0
      Tests/RunCMake/find_package/RequiredVarOptional-result.txt
  28. 21 0
      Tests/RunCMake/find_package/RequiredVarOptional-stderr.txt
  29. 4 0
      Tests/RunCMake/find_package/RequiredVarOptional.cmake
  30. 4 0
      Tests/RunCMake/find_package/RunCMakeTest.cmake
  31. 1 0
      Tests/RunCMake/find_path/Optional-result.txt
  32. 10 0
      Tests/RunCMake/find_path/Optional-stderr.txt
  33. 13 0
      Tests/RunCMake/find_path/Optional.cmake
  34. 1 0
      Tests/RunCMake/find_path/RunCMakeTest.cmake
  35. 1 0
      Tests/RunCMake/find_program/Optional-result.txt
  36. 10 0
      Tests/RunCMake/find_program/Optional-stderr.txt
  37. 13 0
      Tests/RunCMake/find_program/Optional.cmake
  38. 1 0
      Tests/RunCMake/find_program/RunCMakeTest.cmake

+ 13 - 1
Help/command/FIND_XXX.txt

@@ -18,7 +18,7 @@ The general signature is:
              [VALIDATOR function]
              [DOC "cache documentation string"]
              [NO_CACHE]
-             [REQUIRED]
+             [REQUIRED|OPTIONAL]
              [NO_DEFAULT_PATH]
              [NO_PACKAGE_ROOT_PATH]
              [NO_CMAKE_PATH]
@@ -118,6 +118,18 @@ Options include:
   the search will be attempted again the next time |FIND_XXX| is invoked
   with the same variable.
 
+  .. versionadded:: 4.1
+
+    Every |FIND_XXX| command will be treated as ``REQUIRED`` when the
+    :variable:`CMAKE_FIND_REQUIRED` variable is enabled.
+
+``OPTIONAL``
+  .. versionadded:: 4.1
+
+  Ignore the value of :variable:`CMAKE_FIND_REQUIRED` and
+  continue without an error message if nothing is found.
+  Incompatible with ``REQUIRED``.
+
 If ``NO_DEFAULT_PATH`` is specified, then no additional paths are
 added to the search.
 If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows:

+ 12 - 2
Help/command/find_package.rst

@@ -132,7 +132,7 @@ Basic Signature
 .. code-block:: cmake
 
   find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE]
-               [REQUIRED] [[COMPONENTS] [components...]]
+               [REQUIRED|OPTIONAL] [[COMPONENTS] [components...]]
                [OPTIONAL_COMPONENTS components...]
                [REGISTRY_VIEW  (64|32|64_32|32_64|HOST|TARGET|BOTH)]
                [GLOBAL]
@@ -159,6 +159,13 @@ otherwise execution still continues.  As a form of shorthand, if the
 ``REQUIRED`` option is present, the ``COMPONENTS`` keyword can be omitted
 and the required components can be listed directly after ``REQUIRED``.
 
+The :variable:`CMAKE_FIND_REQUIRED` variable can be enabled to make this call
+``REQUIRED`` by default. This behavior can be overridden by providing the
+``OPTIONAL`` keyword. As with the ``REQUIRED`` option, a list of components
+can be listed directly after ``OPTIONAL``, which is equivalent to listing
+them after the ``COMPONENTS`` keyword. When the ``OPTIONAL`` keyword is given,
+the warning output when a package is not found is suppressed.
+
 Additional optional components may be listed after
 ``OPTIONAL_COMPONENTS``.  If these cannot be satisfied, the package overall
 can still be considered found, as long as all required components are
@@ -249,7 +256,7 @@ Full Signature
 .. code-block:: cmake
 
   find_package(<PackageName> [version] [EXACT] [QUIET]
-               [REQUIRED] [[COMPONENTS] [components...]]
+               [REQUIRED|OPTIONAL] [[COMPONENTS] [components...]]
                [OPTIONAL_COMPONENTS components...]
                [CONFIG|NO_MODULE]
                [GLOBAL]
@@ -635,6 +642,9 @@ Every non-REQUIRED ``find_package`` call can be disabled or made REQUIRED:
 
 Setting both variables to ``TRUE`` simultaneously is an error.
 
+The :variable:`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>` variable takes priority
+over the ``OPTIONAL`` keyword in determining whether a package is required.
+
 .. _`version selection`:
 
 Config Mode Version Selection

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

@@ -61,6 +61,7 @@ Variables that Provide Information
    /variable/CMAKE_FIND_PACKAGE_REDIRECTS_DIR
    /variable/CMAKE_FIND_PACKAGE_SORT_DIRECTION
    /variable/CMAKE_FIND_PACKAGE_SORT_ORDER
+   /variable/CMAKE_FIND_REQUIRED
    /variable/CMAKE_GENERATOR
    /variable/CMAKE_GENERATOR_INSTANCE
    /variable/CMAKE_GENERATOR_PLATFORM

+ 8 - 0
Help/release/dev/cmake-find-required.rst

@@ -0,0 +1,8 @@
+cmake-find-required
+-------------------
+
+* The :variable:`CMAKE_FIND_REQUIRED` variable was added to tell
+  :command:`find_package`, :command:`find_path`, :command:`find_file`,
+  :command:`find_library`, and :command:`find_program` to be ``REQUIRED``
+  by default.  The commands also gained an ``OPTIONAL`` keyword to ignore
+  the variable for a specific call.

+ 27 - 0
Help/variable/CMAKE_FIND_REQUIRED.rst

@@ -0,0 +1,27 @@
+CMAKE_FIND_REQUIRED
+-------------------
+
+.. versionadded:: 4.1
+
+If enabled, the following commands are treated as having the ``REQUIRED``
+keyword unless provided with the ``OPTIONAL`` keyword:
+
+* :command:`find_package`
+* :command:`find_program`
+* :command:`find_library`
+* :command:`find_path`
+* :command:`find_file`
+
+When :command:`find_package` loads a ``Find<PackageName>.cmake``
+or ``<PackageName>Config.cmake`` module, the ``CMAKE_FIND_REQUIRED``
+variable is automatically unset within it to restore the default
+behavior for nested find operations.  The module is free to set the
+``CMAKE_FIND_REQUIRED`` variable itself to opt-in to the behavior.
+
+Note that enabling this variable breaks some commonly used patterns.
+Multiple calls to :command:`find_package` are sometimes used to obtain a
+different search order to the default.
+
+See also the :variable:`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>` for making
+a :command:`find_package` call ``REQUIRED``, and for additional information on
+how enabling these variables can break commonly used patterns.

+ 18 - 0
Source/cmFindBase.cxx

@@ -94,6 +94,7 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
   this->SelectDefaultMacMode();
 
   bool newStyle = false;
+  bool haveRequiredOrOptional = false;
   enum Doing
   {
     DoingNone,
@@ -129,8 +130,21 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
       this->NoDefaultPath = true;
     } else if (args[j] == "REQUIRED") {
       doing = DoingNone;
+      if (haveRequiredOrOptional && !this->Required) {
+        this->SetError("cannot be both REQUIRED and OPTIONAL");
+        return false;
+      }
       this->Required = true;
       newStyle = true;
+      haveRequiredOrOptional = true;
+    } else if (args[j] == "OPTIONAL") {
+      doing = DoingNone;
+      if (haveRequiredOrOptional && this->Required) {
+        this->SetError("cannot be both REQUIRED and OPTIONAL");
+        return false;
+      }
+      newStyle = true;
+      haveRequiredOrOptional = true;
     } else if (args[j] == "REGISTRY_VIEW") {
       if (++j == args.size()) {
         this->SetError("missing required argument for REGISTRY_VIEW");
@@ -187,6 +201,10 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
     }
   }
 
+  if (!haveRequiredOrOptional) {
+    this->Required = this->Makefile->IsOn("CMAKE_FIND_REQUIRED");
+  }
+
   if (this->VariableDocumentation.empty()) {
     this->VariableDocumentation = "Where can ";
     if (this->Names.empty()) {

+ 53 - 17
Source/cmFindPackageCommand.cxx

@@ -747,7 +747,18 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
       configArgs.push_back(i);
       doing = DoingNone;
     } else if (args[i] == "REQUIRED") {
-      this->Required = true;
+      if (this->Required == RequiredStatus::OptionalExplicit) {
+        this->SetError("cannot be both REQUIRED and OPTIONAL");
+        return false;
+      }
+      this->Required = RequiredStatus::RequiredExplicit;
+      doing = DoingComponents;
+    } else if (args[i] == "OPTIONAL") {
+      if (this->Required == RequiredStatus::RequiredExplicit) {
+        this->SetError("cannot be both REQUIRED and OPTIONAL");
+        return false;
+      }
+      this->Required = RequiredStatus::OptionalExplicit;
       doing = DoingComponents;
     } else if (args[i] == "COMPONENTS") {
       doing = DoingComponents;
@@ -844,6 +855,11 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args)
     }
   }
 
+  if (this->Required == RequiredStatus::Optional &&
+      this->Makefile->IsOn("CMAKE_FIND_REQUIRED")) {
+    this->Required = RequiredStatus::RequiredFromFindVar;
+  }
+
   if (!this->GlobalScope) {
     cmValue value(
       this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_TARGETS_GLOBAL"));
@@ -978,21 +994,21 @@ bool cmFindPackageCommand::FindPackage(
   bool const makePackageRequiredSet =
     this->Makefile->IsOn(makePackageRequiredVar);
   if (makePackageRequiredSet) {
-    if (this->Required) {
+    if (this->IsRequired()) {
       this->Makefile->IssueMessage(
         MessageType::WARNING,
         cmStrCat("for module ", this->Name,
                  " already called with REQUIRED, thus ",
                  makePackageRequiredVar, " has no effect."));
     } else {
-      this->Required = true;
+      this->Required = RequiredStatus::RequiredFromPackageVar;
     }
   }
 
   std::string const disableFindPackageVar =
     cmStrCat("CMAKE_DISABLE_FIND_PACKAGE_", this->Name);
   if (this->Makefile->IsOn(disableFindPackageVar)) {
-    if (this->Required) {
+    if (this->IsRequired()) {
       this->SetError(
         cmStrCat("for module ", this->Name,
                  (makePackageRequiredSet
@@ -1310,6 +1326,9 @@ void cmFindPackageCommand::SetModuleVariables()
 {
   this->AddFindDefinition("CMAKE_FIND_PACKAGE_NAME", this->Name);
 
+  // Nested find calls are not automatically required.
+  this->AddFindDefinition("CMAKE_FIND_REQUIRED", ""_s);
+
   // Store the list of components and associated variable definitions.
   std::string components_var = this->Name + "_FIND_COMPONENTS";
   this->AddFindDefinition(components_var, this->Components);
@@ -1329,7 +1348,7 @@ void cmFindPackageCommand::SetModuleVariables()
     this->AddFindDefinition(quietly, "1"_s);
   }
 
-  if (this->Required) {
+  if (this->IsRequired()) {
     // Tell the module that is about to be read that it should report
     // a fatal error if the package is not found.
     std::string req = cmStrCat(this->Name, "_FIND_REQUIRED");
@@ -1575,11 +1594,13 @@ bool cmFindPackageCommand::HandlePackageMode(
 
   // package not found
   if (result && !found) {
-    // warn if package required or neither quiet nor in config mode
-    if (this->Required ||
-        !(this->Quiet ||
-          (this->UseConfigFiles && !this->UseFindModules &&
-           this->ConsideredConfigs.empty()))) {
+    // warn if package required or
+    // (neither quiet nor in config mode and not explicitly optional)
+    if (this->IsRequired() ||
+        (!(this->Quiet ||
+           (this->UseConfigFiles && !this->UseFindModules &&
+            this->ConsideredConfigs.empty())) &&
+         this->Required != RequiredStatus::OptionalExplicit)) {
       // The variable is not set.
       std::ostringstream e;
       std::ostringstream aw;
@@ -1675,11 +1696,19 @@ bool cmFindPackageCommand::HandlePackageMode(
                "without ensuring that it is actually available.\n";
         }
       }
+      if (this->Required == RequiredStatus::RequiredFromFindVar) {
+        e << "\nThis package is considered required because the "
+             "CMAKE_FIND_REQUIRED variable has been enabled.\n";
+      } else if (this->Required == RequiredStatus::RequiredFromPackageVar) {
+        e << "\nThis package is considered required because the "
+          << cmStrCat("CMAKE_REQUIRE_FIND_PACKAGE_", this->Name)
+          << " variable has been enabled.\n";
+      }
 
-      this->Makefile->IssueMessage(this->Required ? MessageType::FATAL_ERROR
-                                                  : MessageType::WARNING,
-                                   e.str());
-      if (this->Required) {
+      this->Makefile->IssueMessage(
+        this->IsRequired() ? MessageType::FATAL_ERROR : MessageType::WARNING,
+        e.str());
+      if (this->IsRequired()) {
         cmSystemTools::SetFatalErrorOccurred();
       }
 
@@ -1912,7 +1941,7 @@ bool cmFindPackageCommand::ReadPackage()
   // Loop over appendices.
   auto iter = this->CpsAppendices.begin();
   while (iter != this->CpsAppendices.end()) {
-    bool required = false;
+    RequiredStatus required = RequiredStatus::Optional;
     bool important = false;
 
     // Check if this appendix provides any requested components.
@@ -1972,7 +2001,7 @@ bool cmFindPackageCommand::ReadPackage()
 
 bool cmFindPackageCommand::FindPackageDependencies(
   std::string const& fileName, cmPackageInfoReader const& reader,
-  bool required)
+  RequiredStatus required)
 {
   // Get package requirements.
   for (cmPackageRequirement const& dep : reader.GetRequirements()) {
@@ -2110,7 +2139,7 @@ void cmFindPackageCommand::AppendSuccessInformation()
   }
   this->Makefile->GetState()->SetGlobalProperty(versionInfoPropName,
                                                 versionInfo);
-  if (this->Required) {
+  if (this->IsRequired()) {
     std::string const requiredInfoPropName =
       cmStrCat("_CMAKE_", this->Name, "_TYPE");
     this->Makefile->GetState()->SetGlobalProperty(requiredInfoPropName,
@@ -3265,6 +3294,13 @@ bool cmFindPackageCommand::SearchEnvironmentPrefix(std::string const& prefix)
   return TryGeneratedPaths(searchFn, pdt::Cps, prefix, pkgDirGen);
 }
 
+bool cmFindPackageCommand::IsRequired() const
+{
+  return this->Required == RequiredStatus::RequiredExplicit ||
+    this->Required == RequiredStatus::RequiredFromPackageVar ||
+    this->Required == RequiredStatus::RequiredFromFindVar;
+}
+
 // TODO: Debug cmsys::Glob double slash problem.
 
 bool cmFindPackage(std::vector<std::string> const& args,

+ 12 - 2
Source/cmFindPackageCommand.h

@@ -151,9 +151,17 @@ private:
   using AppendixMap = std::map<std::string, Appendix>;
   AppendixMap FindAppendices(std::string const& base,
                              cmPackageInfoReader const& baseReader) const;
+  enum RequiredStatus
+  {
+    Optional,
+    OptionalExplicit,
+    RequiredExplicit,
+    RequiredFromPackageVar,
+    RequiredFromFindVar
+  };
   bool FindPackageDependencies(std::string const& fileName,
                                cmPackageInfoReader const& reader,
-                               bool required);
+                               RequiredStatus required);
 
   bool ImportPackageTargets(std::string const& fileName,
                             cmPackageInfoReader& reader);
@@ -194,6 +202,8 @@ private:
   bool SearchAppBundlePrefix(std::string const& prefix);
   bool SearchEnvironmentPrefix(std::string const& prefix);
 
+  bool IsRequired() const;
+
   struct OriginalDef
   {
     bool exists;
@@ -234,7 +244,7 @@ private:
   unsigned int VersionFoundCount = 0;
   KWIML_INT_uint64_t RequiredCMakeVersion = 0;
   bool Quiet = false;
-  bool Required = false;
+  RequiredStatus Required = RequiredStatus::Optional;
   bool UseCpsFiles = false;
   bool UseConfigFiles = true;
   bool UseFindModules = true;

+ 1 - 0
Tests/RunCMake/find_file/Optional-result.txt

@@ -0,0 +1 @@
+1

+ 10 - 0
Tests/RunCMake/find_file/Optional-stderr.txt

@@ -0,0 +1,10 @@
+CMake Error at Optional.cmake:[0-9]+ \(find_file\):
+  find_file cannot be both REQUIRED and OPTIONAL
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)
+
+
+CMake Error at Optional\.cmake:[0-9]+ \(find_file\):
+  Could not find FILE_doNotExists using the following files: doNotExists.h
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)

+ 14 - 0
Tests/RunCMake/find_file/Optional.cmake

@@ -0,0 +1,14 @@
+set(CMAKE_FIND_REQUIRED ON)
+find_file(FILE_doNotExists_Optional
+  NAMES doNotExists.h
+  OPTIONAL
+)
+find_file(FILE_doNotExists_OptionalRequired
+  NAMES doNotExists.h
+  OPTIONAL
+  REQUIRED
+)
+find_file(FILE_doNotExists
+  NAMES doNotExists.h
+  REQUIRED
+)

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

@@ -4,6 +4,7 @@ run_cmake(FromPATHEnv)
 run_cmake(FromPrefixPath)
 run_cmake(PrefixInPATH)
 run_cmake(Required)
+run_cmake(Optional)
 run_cmake(NO_CACHE)
 run_cmake(REGISTRY_VIEW-no-view)
 run_cmake(REGISTRY_VIEW-wrong-view)

+ 1 - 0
Tests/RunCMake/find_library/Optional-result.txt

@@ -0,0 +1 @@
+1

+ 10 - 0
Tests/RunCMake/find_library/Optional-stderr.txt

@@ -0,0 +1,10 @@
+CMake Error at Optional.cmake:[0-9]+ \(find_library\):
+  find_library cannot be both REQUIRED and OPTIONAL
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)
+
+
+CMake Error at Optional\.cmake:[0-9]+ \(find_library\):
+  Could not find LIB_doNotExists using the following names: doNotExists
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)

+ 13 - 0
Tests/RunCMake/find_library/Optional.cmake

@@ -0,0 +1,13 @@
+set(CMAKE_FIND_REQUIRED ON)
+find_library(LIB_doNotExists_Optional
+  NAMES doNotExists
+  OPTIONAL
+)
+find_library(LIB_doNotExists_OptionalRequired
+  NAMES doNotExists
+  OPTIONAL
+  REQUIRED
+)
+find_library(LIB_doNotExists
+  NAMES doNotExists
+)

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

@@ -12,6 +12,7 @@ if(UNIX AND NOT CYGWIN)
 endif()
 run_cmake(PrefixInPATH)
 run_cmake(Required)
+run_cmake(Optional)
 run_cmake(NO_CACHE)
 run_cmake(REGISTRY_VIEW-no-view)
 run_cmake(REGISTRY_VIEW-wrong-view)

+ 4 - 0
Tests/RunCMake/find_package/MissingNormalForceRequired-stderr.txt

@@ -1,5 +1,9 @@
 CMake Error at MissingNormalForceRequired.cmake:2 \(find_package\):
   No "FindNotHere.cmake" found in CMAKE_MODULE_PATH\.
+
+  This package is considered required because the
+  CMAKE_REQUIRE_FIND_PACKAGE_NotHere variable has been enabled.
+
 Call Stack \(most recent call first\):
   CMakeLists.txt:3 \(include\)
 +

+ 1 - 0
Tests/RunCMake/find_package/PackageVarOverridesOptional-result.txt

@@ -0,0 +1 @@
+1

+ 20 - 0
Tests/RunCMake/find_package/PackageVarOverridesOptional-stderr.txt

@@ -0,0 +1,20 @@
+CMake Error at PackageVarOverridesOptional.cmake:[0-9]+ \(find_package\):
+  By not providing "FindFoo.cmake" in CMAKE_MODULE_PATH this project has
+  asked CMake to find a package configuration file provided by "Foo", but
+  CMake did not find one.
+
+  Could not find a package configuration file provided by "Foo" with any of
+  the following names:
+
+    FooConfig.cmake
+    foo-config.cmake
+
+  Add the installation prefix of "Foo" to CMAKE_PREFIX_PATH or set "Foo_DIR"
+  to a directory containing one of the above files.  If "Foo" provides a
+  separate development package or SDK, be sure it has been installed.
+
+  This package is considered required because the
+  CMAKE_REQUIRE_FIND_PACKAGE_Foo variable has been enabled.
+
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)

+ 2 - 0
Tests/RunCMake/find_package/PackageVarOverridesOptional.cmake

@@ -0,0 +1,2 @@
+set(CMAKE_REQUIRE_FIND_PACKAGE_Foo ON)
+find_package(Foo OPTIONAL)

+ 1 - 0
Tests/RunCMake/find_package/RequiredOptionalKeywordsClash-result.txt

@@ -0,0 +1 @@
+1

+ 4 - 0
Tests/RunCMake/find_package/RequiredOptionalKeywordsClash-stderr.txt

@@ -0,0 +1,4 @@
+CMake Error at RequiredOptionalKeywordsClash.cmake:[0-9]+ \(find_package\):
+  find_package cannot be both REQUIRED and OPTIONAL
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)

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

@@ -0,0 +1 @@
+find_package(Foo OPTIONAL REQUIRED)

+ 18 - 0
Tests/RunCMake/find_package/RequiredVarNested-stderr.txt

@@ -0,0 +1,18 @@
+CMake Warning at RequiredVarNestedConfig\.cmake:[0-9]+ \(find_package\):
+  By not providing "FindDoesNotExist\.cmake" in CMAKE_MODULE_PATH this project
+  has asked CMake to find a package configuration file provided by
+  "DoesNotExist", but CMake did not find one\.
+
+  Could not find a package configuration file provided by "DoesNotExist" with
+  any of the following names:
+
+    DoesNotExistConfig.cmake
+    doesnotexist-config.cmake
+
+  Add the installation prefix of "DoesNotExist" to CMAKE_PREFIX_PATH or set
+  "DoesNotExist_DIR" to a directory containing one of the above files\.  If
+  "DoesNotExist" provides a separate development package or SDK, be sure it
+  has been installed\.
+Call Stack \(most recent call first\):
+  RequiredVarNested.cmake:[0-9]+ \(find_package\)
+  CMakeLists\.txt:[0-9]+ \(include\)

+ 3 - 0
Tests/RunCMake/find_package/RequiredVarNested.cmake

@@ -0,0 +1,3 @@
+set(CMAKE_FIND_REQUIRED ON CACHE BOOL "") # The cache entry must be shadowed by a nested definition.
+set(RequiredVarNested_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
+find_package(RequiredVarNested CONFIG)

+ 8 - 0
Tests/RunCMake/find_package/RequiredVarNestedConfig.cmake

@@ -0,0 +1,8 @@
+if (CMAKE_FIND_REQUIRED)
+  message(FATAL_ERROR "CMAKE_FIND_REQUIRED enabled in Config.cmake")
+endif()
+find_package(DoesNotExist)
+find_library(library DoesNotExist)
+find_program(program DoesNotExist)
+find_path(path DoesNotExist)
+find_file(file DoesNotExist)

+ 1 - 0
Tests/RunCMake/find_package/RequiredVarOptional-result.txt

@@ -0,0 +1 @@
+1

+ 21 - 0
Tests/RunCMake/find_package/RequiredVarOptional-stderr.txt

@@ -0,0 +1,21 @@
+CMake Error at RequiredVarOptional.cmake:[0-9]+ \(find_package\):
+  By not providing "FindDoesNotExist.cmake" in CMAKE_MODULE_PATH this project
+  has asked CMake to find a package configuration file provided by
+  "DoesNotExist", but CMake did not find one.
+
+  Could not find a package configuration file provided by "DoesNotExist" with
+  any of the following names:
+
+    DoesNotExistConfig.cmake
+    doesnotexist-config.cmake
+
+  Add the installation prefix of "DoesNotExist" to CMAKE_PREFIX_PATH or set
+  "DoesNotExist_DIR" to a directory containing one of the above files.  If
+  "DoesNotExist" provides a separate development package or SDK, be sure it
+  has been installed.
+
+  This package is considered required because the CMAKE_FIND_REQUIRED
+  variable has been enabled.
+
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)

+ 4 - 0
Tests/RunCMake/find_package/RequiredVarOptional.cmake

@@ -0,0 +1,4 @@
+set(CMAKE_FIND_REQUIRED ON)
+find_package(DoesNotExist-Optional OPTIONAL CompA CompB CompC)
+find_package(DoesNotExist)
+message(FATAL_ERROR "This error must not be reachable.")

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

@@ -27,9 +27,13 @@ run_cmake_with_options(ModuleModeDebugPkg --debug-find-pkg=Foo,Zot)
 run_cmake(PackageRoot)
 run_cmake(PackageRootNestedConfig)
 run_cmake(PackageRootNestedModule)
+run_cmake(PackageVarOverridesOptional)
 run_cmake(PolicyPush)
 run_cmake(PolicyPop)
 run_cmake(RequiredOptionValuesClash)
+run_cmake(RequiredOptionalKeywordsClash)
+run_cmake(RequiredVarOptional)
+run_cmake(RequiredVarNested)
 run_cmake(FindRootPathAndPrefixPathAreEqual)
 run_cmake(SetFoundFALSE)
 run_cmake(WrongVersion)

+ 1 - 0
Tests/RunCMake/find_path/Optional-result.txt

@@ -0,0 +1 @@
+1

+ 10 - 0
Tests/RunCMake/find_path/Optional-stderr.txt

@@ -0,0 +1,10 @@
+CMake Error at Optional.cmake:[0-9]+ \(find_path\):
+  find_path cannot be both REQUIRED and OPTIONAL
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)
+
+
+CMake Error at Optional\.cmake:[0-9]+ \(find_path\):
+  Could not find PATH_doNotExists using the following files: doNotExists.h
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)

+ 13 - 0
Tests/RunCMake/find_path/Optional.cmake

@@ -0,0 +1,13 @@
+set(CMAKE_FIND_REQUIRED ON)
+find_path(PATH_doNotExists_Optional
+  NAMES doNotExists.h
+  OPTIONAL
+)
+find_path(PATH_doNotExists_OptionalRequired
+  NAMES doNotExists.h
+  OPTIONAL
+  REQUIRED
+)
+find_path(PATH_doNotExists
+  NAMES doNotExists.h
+)

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

@@ -4,6 +4,7 @@ run_cmake(EmptyOldStyle)
 run_cmake(FromPATHEnv)
 run_cmake(PrefixInPATH)
 run_cmake(Required)
+run_cmake(Optional)
 run_cmake(NO_CACHE)
 run_cmake(REGISTRY_VIEW-no-view)
 run_cmake(REGISTRY_VIEW-wrong-view)

+ 1 - 0
Tests/RunCMake/find_program/Optional-result.txt

@@ -0,0 +1 @@
+1

+ 10 - 0
Tests/RunCMake/find_program/Optional-stderr.txt

@@ -0,0 +1,10 @@
+CMake Error at Optional.cmake:[0-9]+ \(find_program\):
+  find_program cannot be both REQUIRED and OPTIONAL
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)
+
+
+CMake Error at Optional\.cmake:[0-9]+ \(find_program\):
+  Could not find PROG_AandB using the following names: testAandB
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)

+ 13 - 0
Tests/RunCMake/find_program/Optional.cmake

@@ -0,0 +1,13 @@
+set(CMAKE_FIND_REQUIRED ON)
+find_program(PROG_AandB_Optional
+  NAMES testAandB
+  OPTIONAL
+)
+find_program(PROG_AandB_OptionalRequired
+  NAMES testAandB
+  OPTIONAL
+  REQUIRED
+)
+find_program(PROG_AandB
+  NAMES testAandB
+)

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

@@ -5,6 +5,7 @@ run_cmake(DirsPerName)
 run_cmake(NamesPerDir)
 run_cmake(RelAndAbsPath)
 run_cmake(Required)
+run_cmake(Optional)
 run_cmake(NO_CACHE)
 run_cmake(IgnorePrefixPath)
 run_cmake(REGISTRY_VIEW-no-view)