소스 검색

FPHSA: when EXACT version match is requested only compare the components given

Given that you have a foobar that identifies itself as 1.2.3 from now on a

  find_package(foobar 1.2 EXACT)

will succeed, as 1.2.3 will now be considered as being 1.2. Until now this was
only the case for version 1.2.0.
Rolf Eike Beer 11 년 전
부모
커밋
4f9bf4468b

+ 32 - 4
Modules/FindPackageHandleStandardArgs.cmake

@@ -290,12 +290,40 @@ function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
     if(VERSION)
 
       if(${_NAME}_FIND_VERSION_EXACT)       # exact version required
-        if (NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}")
-          set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
-          set(VERSION_OK FALSE)
+        # count the dots in the version string
+        string(REGEX REPLACE "[^.]" "" _VERSION_DOTS "${VERSION}")
+        # add one dot because there is one dot more than there are components
+        string(LENGTH "${_VERSION_DOTS}." _VERSION_DOTS)
+        if (_VERSION_DOTS GREATER ${_NAME}_FIND_VERSION_COUNT)
+          # Because of the C++ implementation of find_package() ${_NAME}_FIND_VERSION_COUNT
+          # is at most 4 here. Therefore a simple lookup table is used.
+          if (${_NAME}_FIND_VERSION_COUNT EQUAL 1)
+            set(_VERSION_REGEX "[^.]*")
+          elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 2)
+            set(_VERSION_REGEX "[^.]*\\.[^.]*")
+          elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 3)
+            set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*")
+          else ()
+            set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*\\.[^.]*")
+          endif ()
+          string(REGEX REPLACE "^(${_VERSION_REGEX})\\..*" "\\1" _VERSION_HEAD "${VERSION}")
+          unset(_VERSION_REGEX)
+          if (NOT ${_NAME}_FIND_VERSION VERSION_EQUAL _VERSION_HEAD)
+            set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
+            set(VERSION_OK FALSE)
+          else ()
+            set(VERSION_MSG "(found suitable exact version \"${VERSION}\")")
+          endif ()
+          unset(_VERSION_HEAD)
         else ()
-          set(VERSION_MSG "(found suitable exact version \"${VERSION}\")")
+          if (NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}")
+            set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"")
+            set(VERSION_OK FALSE)
+          else ()
+            set(VERSION_MSG "(found suitable exact version \"${VERSION}\")")
+          endif ()
         endif ()
+        unset(_VERSION_DOTS)
 
       else()     # minimum version specified:
         if ("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}")

+ 6 - 0
Tests/RunCMake/FPHSA/FindPseudo.cmake

@@ -0,0 +1,6 @@
+# pseudo find_module
+
+set(FOOBAR TRUE)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Pseudo REQUIRED_VARS FOOBAR VERSION_VAR Pseudo_VERSION)

+ 20 - 0
Tests/RunCMake/FPHSA/RunCMakeTest.cmake

@@ -1,3 +1,23 @@
 include(RunCMake)
 
 run_cmake(BadFoundVar)
+
+# The pseudo module will "find" a package with the given version. Check if the
+# version selection code in FPHSA works correctly.
+set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" "-DPseudo_VERSION=1.2.3.4.5")
+run_cmake(any_version)
+
+# test EXACT mode with every subcomponent
+run_cmake(exact_1)
+run_cmake(exact_1.2)
+run_cmake(exact_1.2.3)
+run_cmake(exact_1.2.3.4)
+
+# now test every component with an invalid version
+run_cmake(exact_2)
+run_cmake(exact_1.1)
+run_cmake(exact_1.3)
+run_cmake(exact_1.2.2)
+run_cmake(exact_1.2.4)
+run_cmake(exact_1.2.3.3)
+run_cmake(exact_1.2.3.5)

+ 1 - 0
Tests/RunCMake/FPHSA/any_version.cmake

@@ -0,0 +1 @@
+find_package(Pseudo REQUIRED)

+ 1 - 0
Tests/RunCMake/FPHSA/exact_1.1-result.txt

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

+ 1 - 0
Tests/RunCMake/FPHSA/exact_1.1.cmake

@@ -0,0 +1 @@
+find_package(Pseudo 1.1 EXACT REQUIRED)

+ 1 - 0
Tests/RunCMake/FPHSA/exact_1.2.2-result.txt

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

+ 1 - 0
Tests/RunCMake/FPHSA/exact_1.2.2.cmake

@@ -0,0 +1 @@
+find_package(Pseudo 1.2.2 EXACT REQUIRED)

+ 1 - 0
Tests/RunCMake/FPHSA/exact_1.2.3.3-result.txt

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

+ 1 - 0
Tests/RunCMake/FPHSA/exact_1.2.3.3.cmake

@@ -0,0 +1 @@
+find_package(Pseudo 1.2.3.3 EXACT REQUIRED)

+ 1 - 0
Tests/RunCMake/FPHSA/exact_1.2.3.4.cmake

@@ -0,0 +1 @@
+find_package(Pseudo 1.2.3.4 EXACT REQUIRED)

+ 1 - 0
Tests/RunCMake/FPHSA/exact_1.2.3.5-result.txt

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

+ 1 - 0
Tests/RunCMake/FPHSA/exact_1.2.3.5.cmake

@@ -0,0 +1 @@
+find_package(Pseudo 1.2.3.5 EXACT REQUIRED)

+ 1 - 0
Tests/RunCMake/FPHSA/exact_1.2.3.cmake

@@ -0,0 +1 @@
+find_package(Pseudo 1.2.3 EXACT REQUIRED)

+ 1 - 0
Tests/RunCMake/FPHSA/exact_1.2.4-result.txt

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

+ 1 - 0
Tests/RunCMake/FPHSA/exact_1.2.4.cmake

@@ -0,0 +1 @@
+find_package(Pseudo 1.2.4 EXACT REQUIRED)

+ 1 - 0
Tests/RunCMake/FPHSA/exact_1.2.cmake

@@ -0,0 +1 @@
+find_package(Pseudo 1.2 EXACT REQUIRED)

+ 1 - 0
Tests/RunCMake/FPHSA/exact_1.3-result.txt

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

+ 1 - 0
Tests/RunCMake/FPHSA/exact_1.3.cmake

@@ -0,0 +1 @@
+find_package(Pseudo 1.3 EXACT REQUIRED)

+ 1 - 0
Tests/RunCMake/FPHSA/exact_1.cmake

@@ -0,0 +1 @@
+find_package(Pseudo 1 EXACT REQUIRED)

+ 1 - 0
Tests/RunCMake/FPHSA/exact_2-result.txt

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

+ 1 - 0
Tests/RunCMake/FPHSA/exact_2.cmake

@@ -0,0 +1 @@
+find_package(Pseudo 2 EXACT REQUIRED)