diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst index 4dc9696b30..40733458f5 100644 --- a/Help/command/find_package.rst +++ b/Help/command/find_package.rst @@ -581,12 +581,12 @@ Paths are searched in the order described above. The first viable package configuration file found is used, even if a newer version of the package resides later in the list of search paths. -For search paths which contain glob expressions (``*``), the order in which -directories matching the glob are searched is unspecified unless the -:variable:`CMAKE_FIND_PACKAGE_SORT_ORDER` variable is set. This variable, -along with the :variable:`CMAKE_FIND_PACKAGE_SORT_DIRECTION` variable, -determines the order in which CMake considers glob matches. For example, if -the file system contains the package configuration files +For search paths which contain glob expressions (``*``), directories matching +the glob are searched in natural, descending order by default. This behavior +can be overridden by setting variables :variable:`CMAKE_FIND_PACKAGE_SORT_ORDER` +and :variable:`CMAKE_FIND_PACKAGE_SORT_DIRECTION` accordingly. Those variables +determine the order in which CMake considers glob matches. For example, if the +file system contains the package configuration files :: @@ -594,21 +594,21 @@ the file system contains the package configuration files /example-1.10/example-config.cmake /share/example-2.0/example-config.cmake -it is unspecified (when the aforementioned variables are unset) whether -``find_package(example)`` will find ``example-1.2`` or ``example-1.10`` -(assuming that both are viable), but ``find_package`` will *not* find -``example-2.0``, because one of the other two will be found first. +then ``find_package(example)`` will (when the aforementioned variables are +unset) pick ``example-1.10`` (assuming both ``example-1.2`` and ``example-1.10`` +are viable). Note however that ``find_package`` will *not* find ``example-2.0``, +because one of the other two will be found first. To control the order in which ``find_package`` searches directories that match a glob expression, use :variable:`CMAKE_FIND_PACKAGE_SORT_ORDER` and :variable:`CMAKE_FIND_PACKAGE_SORT_DIRECTION`. -For instance, to cause the above example to select ``example-1.10``, +For instance, to cause the above example to select ``example-1.2``, one can set .. code-block:: cmake set(CMAKE_FIND_PACKAGE_SORT_ORDER NATURAL) - set(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC) + set(CMAKE_FIND_PACKAGE_SORT_DIRECTION ASC) before calling ``find_package``. @@ -624,6 +624,15 @@ before calling ``find_package``. and ``/.framework/Versions/*/Resources/CMake``. In previous versions of CMake, this order was unspecified. +.. versionchanged:: 4.2 + When encountering multiple viable matches, ``find_package`` now picks the + one with the most recent version by default. In previous versions of CMake, + the result was unspecified. Accordingly, the default of + :variable:`CMAKE_FIND_PACKAGE_SORT_ORDER` has changed from ``NONE`` to + ``NATURAL`` and :variable:`CMAKE_FIND_PACKAGE_SORT_DIRECTION` + now defaults to ``DEC`` (descending) instead of ``ASC`` (ascending). + + .. include:: include/FIND_XXX_ROOT.rst .. include:: include/FIND_XXX_ORDER.rst diff --git a/Help/variable/CMAKE_FIND_PACKAGE_SORT_DIRECTION.rst b/Help/variable/CMAKE_FIND_PACKAGE_SORT_DIRECTION.rst index 92758fd02d..033748aa1e 100644 --- a/Help/variable/CMAKE_FIND_PACKAGE_SORT_DIRECTION.rst +++ b/Help/variable/CMAKE_FIND_PACKAGE_SORT_DIRECTION.rst @@ -3,16 +3,21 @@ CMAKE_FIND_PACKAGE_SORT_DIRECTION .. versionadded:: 3.7 +.. versionchanged:: 4.2 + + The default sort direction has changed from ``DEC`` to ``ASC``. + + The sorting direction used by :variable:`CMAKE_FIND_PACKAGE_SORT_ORDER`. It can assume one of the following values: ``ASC`` - Default. Ordering is done in ascending mode. + Ordering is done in ascending mode. The lowest folder found will be tested first. ``DEC`` - Ordering is done in descending mode. + Default. Ordering is done in descending mode. The highest 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. +If :variable:`CMAKE_FIND_PACKAGE_SORT_ORDER` is set to ``NONE`` this variable +has no effect. diff --git a/Help/variable/CMAKE_FIND_PACKAGE_SORT_ORDER.rst b/Help/variable/CMAKE_FIND_PACKAGE_SORT_ORDER.rst index f1016d9cf5..524b2ef469 100644 --- a/Help/variable/CMAKE_FIND_PACKAGE_SORT_ORDER.rst +++ b/Help/variable/CMAKE_FIND_PACKAGE_SORT_ORDER.rst @@ -3,39 +3,40 @@ CMAKE_FIND_PACKAGE_SORT_ORDER .. versionadded:: 3.7 +.. versionchanged:: 4.2 + + The default sort order has changed from ``NONE`` to ``NATURAL``. + + The default order for sorting directories which match a search path containing a glob expression found using :command:`find_package`. It can assume one of the following values: ``NONE`` - Default. No attempt is done to sort directories. + No attempt is done to sort directories. The first valid package found will be selected. ``NAME`` Sort directories lexicographically before searching. ``NATURAL`` - Sort directories using natural order (see ``strverscmp(3)`` manual), + Default. Sort directories 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 available to be found by -:command:`find_package`. For example suppose that the following libraries -have package configuration files on disk, in a directory of the same name, -with all such directories residing in the same parent directory: +Natural sorting is employed by default to return the highest version when +multiple versions of the same library are available to be found by +:command:`find_package`. For example suppose that the following libraries have +package configuration files on disk, in a directory of the same name, with all +such directories residing in the same parent directory: -* libX-1.1.0 -* libX-1.2.9 -* libX-1.2.10 +* ``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 default order of ``NATURAL`` will select the one with the highest version +number, i.e. ``libX-1.2.10``. The sort direction can be controlled using the -:variable:`CMAKE_FIND_PACKAGE_SORT_DIRECTION` variable -(by default descending, e.g. lib-B will be tested before lib-A). +:variable:`CMAKE_FIND_PACKAGE_SORT_DIRECTION` variable (by default descending, +i.e. ``libX-1.2`` will be tested before ``libX-1.0`` and ``lib-B`` will be +tested before ``lib-A``). diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index 10448a8a3e..4d5da755a7 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -334,10 +334,10 @@ private: class FlushDebugBufferOnExit; - /*! the selected sortOrder (None by default)*/ - SortOrderType SortOrder = None; - /*! the selected sortDirection (Asc by default)*/ - SortDirectionType SortDirection = Asc; + /*! the selected sortOrder (Natural by default)*/ + SortOrderType SortOrder = Natural; + /*! the selected sortDirection (Dec by default)*/ + SortDirectionType SortDirection = Dec; struct ConfigFileInfo { diff --git a/Tests/FindPackageCMakeTest/CMakeLists.txt b/Tests/FindPackageCMakeTest/CMakeLists.txt index bd1887a28e..37a63eb7a1 100644 --- a/Tests/FindPackageCMakeTest/CMakeLists.txt +++ b/Tests/FindPackageCMakeTest/CMakeLists.txt @@ -117,7 +117,7 @@ foreach(p ${PACKAGES}) endforeach() # Enable framework and bundle searching. Make sure bundles are found -# before unix-syle packages. +# before unix-style packages. set(CMAKE_FIND_FRAMEWORK LAST) set(CMAKE_FIND_APPBUNDLE FIRST) @@ -584,6 +584,17 @@ endif() unset(SortLib_VERSION) +set(SortLib_DIR "" CACHE FILEPATH "Wipe out find results for testing." FORCE) +# Expected to default to 'NATURAL' and 'DEC' +unset(CMAKE_FIND_PACKAGE_SORT_ORDER) +unset(CMAKE_FIND_PACKAGE_SORT_DIRECTION) +FIND_PACKAGE(SortLib CONFIG) +IF (NOT "${SortLib_VERSION}" STREQUAL "3.10.1") + message(SEND_ERROR "FIND_PACKAGE_SORT_ORDER Default! ${SortLib_VERSION}") +endif() +unset(SortLib_VERSION) + + set(SortFramework_DIR "" CACHE FILEPATH "Wipe out find results for testing." FORCE) SET(CMAKE_FIND_PACKAGE_SORT_ORDER NAME) SET(CMAKE_FIND_PACKAGE_SORT_DIRECTION ASC) diff --git a/Tests/FindPackageCpsTest/CMakeLists.txt b/Tests/FindPackageCpsTest/CMakeLists.txt index 574f5a7b9f..43caab4575 100644 --- a/Tests/FindPackageCpsTest/CMakeLists.txt +++ b/Tests/FindPackageCpsTest/CMakeLists.txt @@ -90,6 +90,7 @@ foreach(CMAKE_FIND_PACKAGE_SORT_DIRECTION IN ITEMS "" ASC Bogus) unset(SortLib_VERSION) endforeach() + 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) @@ -100,6 +101,7 @@ endif() set(SortLib_DIR "" CACHE FILEPATH "Wipe out find results for testing." FORCE) unset(SortLib_VERSION) + set(SortLib_DIR "" CACHE FILEPATH "Wipe out find results for testing." FORCE) FIND_PACKAGE(SortLib 4.0 CONFIG) IF (NOT "${SortLib_VERSION}" STREQUAL "4.0.0") @@ -107,6 +109,18 @@ IF (NOT "${SortLib_VERSION}" STREQUAL "4.0.0") endif() unset(SortLib_VERSION) + +set(SortLib_DIR "" CACHE FILEPATH "Wipe out find results for testing." FORCE) +# Expected to default to 'NATURAL' and 'DEC' +unset(CMAKE_FIND_PACKAGE_SORT_ORDER) +unset(CMAKE_FIND_PACKAGE_SORT_DIRECTION) +FIND_PACKAGE(SortLib CONFIG) +IF (NOT "${SortLib_VERSION}" STREQUAL "3.10.1") + message(SEND_ERROR "FIND_PACKAGE_SORT_ORDER Default! ${SortLib_VERSION}") +endif() +unset(SortLib_VERSION) + + set(SortFramework_DIR "" CACHE FILEPATH "Wipe out find results for testing." FORCE) set(CMAKE_FIND_PACKAGE_SORT_ORDER NAME) set(CMAKE_FIND_PACKAGE_SORT_DIRECTION ASC) @@ -117,6 +131,7 @@ endif() set(SortLib_DIR "" CACHE FILEPATH "Wipe out find results for testing." FORCE) unset(SortFramework_VERSION) + set(SortFramework_DIR "" CACHE FILEPATH "Wipe out find results for testing." FORCE) set(CMAKE_FIND_PACKAGE_SORT_ORDER NATURAL) set(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC) @@ -127,6 +142,7 @@ endif() set(SortLib_DIR "" CACHE FILEPATH "Wipe out find results for testing." FORCE) unset(SortFramework_VERSION) + unset(CMAKE_FIND_PACKAGE_SORT_ORDER) unset(CMAKE_FIND_PACKAGE_SORT_DIRECTION) diff --git a/Tests/RunCMake/find_package/ConfigureLog.cmake b/Tests/RunCMake/find_package/ConfigureLog.cmake index 49e785c183..3b304a969d 100644 --- a/Tests/RunCMake/find_package/ConfigureLog.cmake +++ b/Tests/RunCMake/find_package/ConfigureLog.cmake @@ -6,6 +6,7 @@ list(INSERT CMAKE_PREFIX_PATH 0 set(CMAKE_FIND_DEBUG_MODE 1) # Stable sorting for predictable behaviors. set(CMAKE_FIND_PACKAGE_SORT_ORDER NAME) +set(CMAKE_FIND_PACKAGE_SORT_DIRECTION ASCENDING) # Unset search variables for more predictable output. unset(CMAKE_FRAMEWORK_PATH)