浏览代码

find_package: Optionally sort globbed directories in a meaningful order

Add `CMAKE_FIND_PACKAGE_SORT_{ORDER,DIRECTION}` variables to specify
sort order and direction.

When multiple package with the same name have been found in the same
location sorting option can be used to force a specific version to be
loaded (e.g. libA_1.12.0 instead of libA_1.1.0).  Currently sorting by
NAME and by NATURAL order have been implemented.

Natural ordering makes use of the `strverscmp(3)` ordering.
Pierluigi Taddei 9 年之前
父节点
当前提交
31be918b0b

+ 14 - 4
Help/command/find_package.rst

@@ -170,11 +170,21 @@ is acceptable the following variables are set:
 ``<package>_VERSION_COUNT``
 ``<package>_VERSION_COUNT``
   number of version components, 0 to 4
   number of version components, 0 to 4
 
 
-and the corresponding package configuration file is loaded.  When
-multiple package configuration files are available whose version files
+and the corresponding package configuration file is loaded.
+When multiple package configuration files are available whose version files
 claim compatibility with the version requested it is unspecified which
 claim compatibility with the version requested it is unspecified which
-one is chosen.  No attempt is made to choose a highest or closest
-version number.
+one is chosen: unless the variable :variable:`CMAKE_FIND_PACKAGE_SORT_ORDER`
+is set no attempt is made to choose a highest or closest version number.
+
+To control the order in which ``find_package`` checks for compatibiliy use
+the two variables :variable:`CMAKE_FIND_PACKAGE_SORT_ORDER` and
+:variable:`CMAKE_FIND_PACKAGE_SORT_DIRECTION`.
+For instance in order to select the highest version one can set::
+
+  SET(CMAKE_FIND_PACKAGE_SORT_ORDER NATURAL)
+  SET(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC)
+
+before calling ``find_package``.
 
 
 Config mode provides an elaborate interface and search procedure.
 Config mode provides an elaborate interface and search procedure.
 Much of the interface is provided for completeness and for use
 Much of the interface is provided for completeness and for use

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

@@ -38,6 +38,8 @@ Variables that Provide Information
    /variable/CMAKE_EXTRA_GENERATOR
    /variable/CMAKE_EXTRA_GENERATOR
    /variable/CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES
    /variable/CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES
    /variable/CMAKE_FIND_PACKAGE_NAME
    /variable/CMAKE_FIND_PACKAGE_NAME
+   /variable/CMAKE_FIND_PACKAGE_SORT_DIRECTION
+   /variable/CMAKE_FIND_PACKAGE_SORT_ORDER
    /variable/CMAKE_GENERATOR
    /variable/CMAKE_GENERATOR
    /variable/CMAKE_GENERATOR_PLATFORM
    /variable/CMAKE_GENERATOR_PLATFORM
    /variable/CMAKE_GENERATOR_TOOLSET
    /variable/CMAKE_GENERATOR_TOOLSET

+ 13 - 0
Help/release/dev/find_package-dir-sort.rst

@@ -0,0 +1,13 @@
+find_package-dir-sort
+---------------------
+
+* The :command:`find_package` command gained the possibility of
+  sorting compatible libraries by ``NAME`` or by ``NATURAL`` sorting by
+  setting the two new variables :variable:`CMAKE_FIND_PACKAGE_SORT_ORDER`
+  and :variable:`CMAKE_FIND_PACKAGE_SORT_DIRECTION`.
+
+* Variable :variable:`CMAKE_FIND_PACKAGE_SORT_ORDER` was added to control
+  the sorting mode of the :command:`find_package` command.
+
+* Variable :variable:`CMAKE_FIND_PACKAGE_SORT_DIRECTION` was added to control
+  the sorting direction the :command:`find_package` command.

+ 16 - 0
Help/variable/CMAKE_FIND_PACKAGE_SORT_DIRECTION.rst

@@ -0,0 +1,16 @@
+CMAKE_FIND_PACKAGE_SORT_DIRECTION
+---------------------------------
+
+The sorting direction used by :variable:`CMAKE_FIND_PACKAGE_SORT_ORDER`.
+It can assume one of the following values:
+
+``DEC``
+  Default.  Ordering is done in descending mode.
+  The highest folder found will be tested first.
+
+``ASC``
+  Ordering is done in ascending mode.
+  The lowest folder found will be tested first.
+
+If :variable:`CMAKE_FIND_PACKAGE_SORT_ORDER` is not set or is set to ``NONE``
+this variable has no effect.

+ 36 - 0
Help/variable/CMAKE_FIND_PACKAGE_SORT_ORDER.rst

@@ -0,0 +1,36 @@
+CMAKE_FIND_PACKAGE_SORT_ORDER
+-----------------------------
+
+The default order for sorting packages found using :command:`find_package`.
+It can assume one of the following values:
+
+``NONE``
+  Default.  No attempt is done to sort packages.
+  The first valid package found will be selected.
+
+``NAME``
+  Sort packages lexicographically before selecting one.
+
+``NATURAL``
+  Sort packages using natural order (see ``strverscmp(3)`` manual),
+  i.e. such that contiguous digits are compared as whole numbers.
+
+Natural sorting can be employed to return the highest version when multiple
+versions of the same library are found by :command:`find_package`.  For
+example suppose that the following libraries have been found:
+
+* libX-1.1.0
+* libX-1.2.9
+* libX-1.2.10
+
+By setting ``NATURAL`` order we can select the one with the highest
+version number ``libX-1.2.10``.
+
+.. code-block:: cmake
+
+  set(CMAKE_FIND_PACKAGE_SORT_ORDER NATURAL)
+  find_package(libX CONFIG)
+
+The sort direction can be controlled using the
+:variable:`CMAKE_FIND_PACKAGE_SORT_DIRECTION` variable
+(by default decrescent, e.g. lib-B will be tested before lib-A).

+ 105 - 13
Source/cmFindPackageCommand.cxx

@@ -12,6 +12,7 @@
 #include "cmFindPackageCommand.h"
 #include "cmFindPackageCommand.h"
 
 
 #include "cmAlgorithms.h"
 #include "cmAlgorithms.h"
+#include <cmSystemTools.h>
 #include <cmsys/Directory.hxx>
 #include <cmsys/Directory.hxx>
 #include <cmsys/Encoding.hxx>
 #include <cmsys/Encoding.hxx>
 #include <cmsys/RegularExpression.hxx>
 #include <cmsys/RegularExpression.hxx>
@@ -33,6 +34,45 @@ cmFindPackageCommand::PathLabel cmFindPackageCommand::PathLabel::Builds(
 cmFindPackageCommand::PathLabel
 cmFindPackageCommand::PathLabel
   cmFindPackageCommand::PathLabel::SystemRegistry("SYSTEM_PACKAGE_REGISTRY");
   cmFindPackageCommand::PathLabel::SystemRegistry("SYSTEM_PACKAGE_REGISTRY");
 
 
+struct StrverscmpGreater
+{
+  bool operator()(const std::string& lhs, const std::string& rhs) const
+  {
+    return cmSystemTools::strverscmp(lhs, rhs) > 0;
+  }
+};
+
+struct StrverscmpLesser
+{
+  bool operator()(const std::string& lhs, const std::string& rhs) const
+  {
+    return cmSystemTools::strverscmp(lhs, rhs) < 0;
+  }
+};
+
+void cmFindPackageCommand::Sort(std::vector<std::string>::iterator begin,
+                                std::vector<std::string>::iterator end,
+                                SortOrderType order, SortDirectionType dir)
+{
+  if (order == Name_order) {
+    if (dir == Dec) {
+      std::sort(begin, end, std::greater<std::string>());
+    } else {
+      std::sort(begin, end);
+    }
+  } else if (order == Natural)
+  // natural order uses letters and numbers (contiguous numbers digit are
+  // compared such that e.g. 000  00 < 01 < 010 < 09 < 0 < 1 < 9 < 10
+  {
+    if (dir == Dec) {
+      std::sort(begin, end, StrverscmpGreater());
+    } else {
+      std::sort(begin, end, StrverscmpLesser());
+    }
+  }
+  // else do not sort
+}
+
 cmFindPackageCommand::cmFindPackageCommand()
 cmFindPackageCommand::cmFindPackageCommand()
 {
 {
   this->CMakePathName = "PACKAGE";
   this->CMakePathName = "PACKAGE";
@@ -58,7 +98,8 @@ cmFindPackageCommand::cmFindPackageCommand()
   this->VersionFoundTweak = 0;
   this->VersionFoundTweak = 0;
   this->VersionFoundCount = 0;
   this->VersionFoundCount = 0;
   this->RequiredCMakeVersion = 0;
   this->RequiredCMakeVersion = 0;
-
+  this->SortOrder = None;
+  this->SortDirection = Asc;
   this->AppendSearchPathGroups();
   this->AppendSearchPathGroups();
 }
 }
 
 
@@ -135,6 +176,23 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
     this->NoSystemRegistry = true;
     this->NoSystemRegistry = true;
   }
   }
 
 
+  // Check if Sorting should be enabled
+  if (const char* so =
+        this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_SORT_ORDER")) {
+
+    if (strcmp(so, "NAME") == 0) {
+      this->SortOrder = Name_order;
+    } else if (strcmp(so, "NATURAL") == 0) {
+      this->SortOrder = Natural;
+    } else {
+      this->SortOrder = None;
+    }
+  }
+  if (const char* sd =
+        this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_SORT_DIRECTION")) {
+    this->SortDirection = strcmp(sd, "ASC") == 0 ? Asc : Dec;
+  }
+
   // Find the current root path mode.
   // Find the current root path mode.
   this->SelectDefaultRootPathMode();
   this->SelectDefaultRootPathMode();
 
 
@@ -1666,17 +1724,33 @@ private:
 class cmFileListGeneratorProject : public cmFileListGeneratorBase
 class cmFileListGeneratorProject : public cmFileListGeneratorBase
 {
 {
 public:
 public:
-  cmFileListGeneratorProject(std::vector<std::string> const& names)
+  cmFileListGeneratorProject(std::vector<std::string> const& names,
+                             cmFindPackageCommand::SortOrderType so,
+                             cmFindPackageCommand::SortDirectionType sd)
     : cmFileListGeneratorBase()
     : cmFileListGeneratorBase()
     , Names(names)
     , Names(names)
   {
   {
+    this->SetSort(so, sd);
   }
   }
   cmFileListGeneratorProject(cmFileListGeneratorProject const& r)
   cmFileListGeneratorProject(cmFileListGeneratorProject const& r)
     : cmFileListGeneratorBase()
     : cmFileListGeneratorBase()
     , Names(r.Names)
     , Names(r.Names)
   {
   {
+    this->SetSort(r.SortOrder, r.SortDirection);
+  }
+
+  void SetSort(cmFindPackageCommand::SortOrderType o,
+               cmFindPackageCommand::SortDirectionType d)
+  {
+    SortOrder = o;
+    SortDirection = d;
   }
   }
 
 
+protected:
+  // sort parameters
+  cmFindPackageCommand::SortOrderType SortOrder;
+  cmFindPackageCommand::SortDirectionType SortDirection;
+
 private:
 private:
   std::vector<std::string> const& Names;
   std::vector<std::string> const& Names;
   bool Search(std::string const& parent, cmFileList& lister) CM_OVERRIDE
   bool Search(std::string const& parent, cmFileList& lister) CM_OVERRIDE
@@ -1698,6 +1772,13 @@ private:
       }
       }
     }
     }
 
 
+    // before testing the matches check if there is a specific sorting order to
+    // perform
+    if (this->SortOrder != cmFindPackageCommand::None) {
+      cmFindPackageCommand::Sort(matches.begin(), matches.end(), SortOrder,
+                                 SortDirection);
+    }
+
     for (std::vector<std::string>::const_iterator i = matches.begin();
     for (std::vector<std::string>::const_iterator i = matches.begin();
          i != matches.end(); ++i) {
          i != matches.end(); ++i) {
       if (this->Consider(parent + *i, lister)) {
       if (this->Consider(parent + *i, lister)) {
@@ -1895,7 +1976,8 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
   {
   {
     cmFindPackageFileList lister(this);
     cmFindPackageFileList lister(this);
     lister / cmFileListGeneratorFixed(prefix) /
     lister / cmFileListGeneratorFixed(prefix) /
-      cmFileListGeneratorProject(this->Names);
+      cmFileListGeneratorProject(this->Names, this->SortOrder,
+                                 this->SortDirection);
     if (lister.Search()) {
     if (lister.Search()) {
       return true;
       return true;
     }
     }
@@ -1905,7 +1987,8 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
   {
   {
     cmFindPackageFileList lister(this);
     cmFindPackageFileList lister(this);
     lister / cmFileListGeneratorFixed(prefix) /
     lister / cmFileListGeneratorFixed(prefix) /
-      cmFileListGeneratorProject(this->Names) /
+      cmFileListGeneratorProject(this->Names, this->SortOrder,
+                                 this->SortDirection) /
       cmFileListGeneratorCaseInsensitive("cmake");
       cmFileListGeneratorCaseInsensitive("cmake");
     if (lister.Search()) {
     if (lister.Search()) {
       return true;
       return true;
@@ -1932,7 +2015,8 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
     lister / cmFileListGeneratorFixed(prefix) /
     lister / cmFileListGeneratorFixed(prefix) /
       cmFileListGeneratorEnumerate(common) /
       cmFileListGeneratorEnumerate(common) /
       cmFileListGeneratorFixed("cmake") /
       cmFileListGeneratorFixed("cmake") /
-      cmFileListGeneratorProject(this->Names);
+      cmFileListGeneratorProject(this->Names, this->SortOrder,
+                                 this->SortDirection);
     if (lister.Search()) {
     if (lister.Search()) {
       return true;
       return true;
     }
     }
@@ -1943,7 +2027,8 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
     cmFindPackageFileList lister(this);
     cmFindPackageFileList lister(this);
     lister / cmFileListGeneratorFixed(prefix) /
     lister / cmFileListGeneratorFixed(prefix) /
       cmFileListGeneratorEnumerate(common) /
       cmFileListGeneratorEnumerate(common) /
-      cmFileListGeneratorProject(this->Names);
+      cmFileListGeneratorProject(this->Names, this->SortOrder,
+                                 this->SortDirection);
     if (lister.Search()) {
     if (lister.Search()) {
       return true;
       return true;
     }
     }
@@ -1954,7 +2039,8 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
     cmFindPackageFileList lister(this);
     cmFindPackageFileList lister(this);
     lister / cmFileListGeneratorFixed(prefix) /
     lister / cmFileListGeneratorFixed(prefix) /
       cmFileListGeneratorEnumerate(common) /
       cmFileListGeneratorEnumerate(common) /
-      cmFileListGeneratorProject(this->Names) /
+      cmFileListGeneratorProject(this->Names, this->SortOrder,
+                                 this->SortDirection) /
       cmFileListGeneratorCaseInsensitive("cmake");
       cmFileListGeneratorCaseInsensitive("cmake");
     if (lister.Search()) {
     if (lister.Search()) {
       return true;
       return true;
@@ -1965,10 +2051,12 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
   {
   {
     cmFindPackageFileList lister(this);
     cmFindPackageFileList lister(this);
     lister / cmFileListGeneratorFixed(prefix) /
     lister / cmFileListGeneratorFixed(prefix) /
-      cmFileListGeneratorProject(this->Names) /
+      cmFileListGeneratorProject(this->Names, this->SortOrder,
+                                 this->SortDirection) /
       cmFileListGeneratorEnumerate(common) /
       cmFileListGeneratorEnumerate(common) /
       cmFileListGeneratorFixed("cmake") /
       cmFileListGeneratorFixed("cmake") /
-      cmFileListGeneratorProject(this->Names);
+      cmFileListGeneratorProject(this->Names, this->SortOrder,
+                                 this->SortDirection);
     if (lister.Search()) {
     if (lister.Search()) {
       return true;
       return true;
     }
     }
@@ -1978,9 +2066,11 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
   {
   {
     cmFindPackageFileList lister(this);
     cmFindPackageFileList lister(this);
     lister / cmFileListGeneratorFixed(prefix) /
     lister / cmFileListGeneratorFixed(prefix) /
-      cmFileListGeneratorProject(this->Names) /
+      cmFileListGeneratorProject(this->Names, this->SortOrder,
+                                 this->SortDirection) /
       cmFileListGeneratorEnumerate(common) /
       cmFileListGeneratorEnumerate(common) /
-      cmFileListGeneratorProject(this->Names);
+      cmFileListGeneratorProject(this->Names, this->SortOrder,
+                                 this->SortDirection);
     if (lister.Search()) {
     if (lister.Search()) {
       return true;
       return true;
     }
     }
@@ -1990,9 +2080,11 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in)
   {
   {
     cmFindPackageFileList lister(this);
     cmFindPackageFileList lister(this);
     lister / cmFileListGeneratorFixed(prefix) /
     lister / cmFileListGeneratorFixed(prefix) /
-      cmFileListGeneratorProject(this->Names) /
+      cmFileListGeneratorProject(this->Names, this->SortOrder,
+                                 this->SortDirection) /
       cmFileListGeneratorEnumerate(common) /
       cmFileListGeneratorEnumerate(common) /
-      cmFileListGeneratorProject(this->Names) /
+      cmFileListGeneratorProject(this->Names, this->SortOrder,
+                                 this->SortDirection) /
       cmFileListGeneratorCaseInsensitive("cmake");
       cmFileListGeneratorCaseInsensitive("cmake");
     if (lister.Search()) {
     if (lister.Search()) {
       return true;
       return true;

+ 26 - 0
Source/cmFindPackageCommand.h

@@ -24,6 +24,27 @@ class cmFindPackageFileList;
 class cmFindPackageCommand : public cmFindCommon
 class cmFindPackageCommand : public cmFindCommon
 {
 {
 public:
 public:
+  /*! A sorting order strategy to be applied to recovered package folders (see
+   * FIND_PACKAGE_SORT_ORDER)*/
+  enum /*class*/ SortOrderType
+  {
+    None,
+    Name_order,
+    Natural
+  };
+  /*! A sorting direction to be applied to recovered package folders (see
+   * FIND_PACKAGE_SORT_DIRECTION)*/
+  enum /*class*/ SortDirectionType
+  {
+    Asc,
+    Dec
+  };
+
+  /*! sorts a given list of string based on the input sort parameters */
+  static void Sort(std::vector<std::string>::iterator begin,
+                   std::vector<std::string>::iterator end, SortOrderType order,
+                   SortDirectionType dir);
+
   cmFindPackageCommand();
   cmFindPackageCommand();
 
 
   /**
   /**
@@ -156,6 +177,11 @@ private:
   std::vector<std::string> Configs;
   std::vector<std::string> Configs;
   std::set<std::string> IgnoredPaths;
   std::set<std::string> IgnoredPaths;
 
 
+  /*! the selected sortOrder (None by default)*/
+  SortOrderType SortOrder;
+  /*! the selected sortDirection (Asc by default)*/
+  SortDirectionType SortDirection;
+
   struct ConfigFileInfo
   struct ConfigFileInfo
   {
   {
     std::string filename;
     std::string filename;

+ 1 - 0
Tests/CMakeLib/CMakeLists.txt

@@ -11,6 +11,7 @@ set(CMakeLib_TESTS
   testUTF8
   testUTF8
   testXMLParser
   testXMLParser
   testXMLSafe
   testXMLSafe
+  testFindPackageCommand
   )
   )
 
 
 set(testRST_ARGS ${CMAKE_CURRENT_SOURCE_DIR})
 set(testRST_ARGS ${CMAKE_CURRENT_SOURCE_DIR})

+ 76 - 0
Tests/CMakeLib/testFindPackageCommand.cxx

@@ -0,0 +1,76 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2000-2011 Kitware, Inc., Insight Software Consortium
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#include "cmFindPackageCommand.h"
+
+#include <iostream>
+#include <string>
+
+#define cmPassed(m) std::cout << "Passed: " << (m) << "\n"
+#define cmFailed(m)                                                           \
+  std::cout << "FAILED: " << (m) << "\n";                                     \
+  failed = 1
+
+int testFindPackageCommand(int /*unused*/, char* /*unused*/ [])
+{
+  int failed = 0;
+
+  // ----------------------------------------------------------------------
+  // Test cmFindPackage::Sort
+  std::vector<std::string> testString;
+  testString.push_back("lib-0.0");
+  testString.push_back("lib-1.2");
+  testString.push_back("lib-2.0");
+  testString.push_back("lib-19.0.1");
+  testString.push_back("lib-20.01.1");
+  testString.push_back("lib-20.2.2a");
+
+  cmFindPackageCommand::Sort(testString.begin(), testString.end(),
+                             cmFindPackageCommand::Natural,
+                             cmFindPackageCommand::Asc);
+  if (!(testString[0] == "lib-0.0" && testString[1] == "lib-1.2" &&
+        testString[2] == "lib-2.0" && testString[3] == "lib-19.0.1" &&
+        testString[4] == "lib-20.01.1" && testString[5] == "lib-20.2.2a")) {
+    cmFailed("cmSystemTools::Sort fail with Natural ASC");
+  }
+
+  cmFindPackageCommand::Sort(testString.begin(), testString.end(),
+                             cmFindPackageCommand::Natural,
+                             cmFindPackageCommand::Dec);
+  if (!(testString[5] == "lib-0.0" && testString[4] == "lib-1.2" &&
+        testString[3] == "lib-2.0" && testString[2] == "lib-19.0.1" &&
+        testString[1] == "lib-20.01.1" && testString[0] == "lib-20.2.2a")) {
+    cmFailed("cmSystemTools::Sort fail with Natural ASC");
+  }
+
+  cmFindPackageCommand::Sort(testString.begin(), testString.end(),
+                             cmFindPackageCommand::Name_order,
+                             cmFindPackageCommand::Dec);
+  if (!(testString[5] == "lib-0.0" && testString[4] == "lib-1.2" &&
+        testString[3] == "lib-19.0.1" && testString[2] == "lib-2.0" &&
+        testString[1] == "lib-20.01.1" && testString[0] == "lib-20.2.2a")) {
+    cmFailed("cmSystemTools::Sort fail with Name DEC");
+  }
+
+  cmFindPackageCommand::Sort(testString.begin(), testString.end(),
+                             cmFindPackageCommand::Name_order,
+                             cmFindPackageCommand::Asc);
+  if (!(testString[0] == "lib-0.0" && testString[1] == "lib-1.2" &&
+        testString[2] == "lib-19.0.1" && testString[3] == "lib-2.0" &&
+        testString[4] == "lib-20.01.1" && testString[5] == "lib-20.2.2a")) {
+    cmFailed("cmSystemTools::Sort fail with Natural ASC");
+  }
+
+  if (!failed) {
+    cmPassed("cmSystemTools::Sort working");
+  }
+  return failed;
+}

+ 30 - 0
Tests/FindPackageTest/CMakeLists.txt

@@ -633,3 +633,33 @@ endif()
 if(PACKAGE_VERSION_UNSUITABLE)
 if(PACKAGE_VERSION_UNSUITABLE)
   message(SEND_ERROR "PACKAGE_VERSION_UNSUITABLE set, but must not be !")
   message(SEND_ERROR "PACKAGE_VERSION_UNSUITABLE set, but must not be !")
 endif()
 endif()
+
+
+############################################################################
+##Test FIND_PACKAGE using sorting
+set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR})
+SET(CMAKE_FIND_PACKAGE_SORT_ORDER NAME)
+SET(CMAKE_FIND_PACKAGE_SORT_DIRECTION ASC)
+
+set(SortLib_DIR "" CACHE FILEPATH "Wipe out find results for testing." FORCE)
+FIND_PACKAGE(SortLib CONFIG)
+IF (NOT "${SortLib_VERSION}" STREQUAL "3.1.1")
+  message(SEND_ERROR "FIND_PACKAGE_SORT_ORDER Name Asc! ${SortLib_VERSION}")
+endif()
+unset(SortLib_VERSION)
+
+
+set(SortLib_DIR "" CACHE FILEPATH "Wipe out find results for testing." FORCE)
+SET(CMAKE_FIND_PACKAGE_SORT_ORDER NATURAL)
+SET(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC)
+FIND_PACKAGE(SortLib CONFIG)
+IF (NOT "${SortLib_VERSION}" STREQUAL "3.10.1")
+  message(SEND_ERROR "FIND_PACKAGE_SORT_ORDER Natural! Dec ${SortLib_VERSION}")
+endif()
+set(SortLib_DIR "" CACHE FILEPATH "Wipe out find results for testing." FORCE)
+unset(SortLib_VERSION)
+
+
+unset(CMAKE_FIND_PACKAGE_SORT_ORDER)
+unset(CMAKE_FIND_PACKAGE_SORT_DIRECTION)
+set(CMAKE_PREFIX_PATH )

+ 2 - 0
Tests/FindPackageTest/SortLib-3.1.1/SortLibConfig.cmake

@@ -0,0 +1,2 @@
+set(SORT_LIB_VERSION 3.1.1)
+message("SortLib 3.1.1 config reached")

+ 9 - 0
Tests/FindPackageTest/SortLib-3.1.1/SortLibConfigVersion.cmake

@@ -0,0 +1,9 @@
+set(PACKAGE_VERSION 3.1.1)
+if(PACKAGE_FIND_VERSION_MAJOR EQUAL 3)
+  if(PACKAGE_FIND_VERSION_MINOR EQUAL 1)
+    set(PACKAGE_VERSION_COMPATIBLE 1)
+    if(PACKAGE_FIND_VERSION_PATCH EQUAL 1)
+      set(PACKAGE_VERSION_EXACT 1)
+    endif()
+  endif()
+endif()

+ 2 - 0
Tests/FindPackageTest/SortLib-3.10.1/SortLibConfig.cmake

@@ -0,0 +1,2 @@
+set(SORT_LIB_VERSION 3.10.1)
+message("SortLib 3.10.1 config reached")

+ 9 - 0
Tests/FindPackageTest/SortLib-3.10.1/SortLibConfigVersion.cmake

@@ -0,0 +1,9 @@
+set(PACKAGE_VERSION 3.10.1)
+if(PACKAGE_FIND_VERSION_MAJOR EQUAL 3)
+  if(PACKAGE_FIND_VERSION_MINOR EQUAL 10)
+    set(PACKAGE_VERSION_COMPATIBLE 1)
+    if(PACKAGE_FIND_VERSION_PATCH EQUAL 1)
+      set(PACKAGE_VERSION_EXACT 1)
+    endif()
+  endif()
+endif()