From 027dc5bc8d01af76660628b18b8ad7dd8386fead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20S=C3=A1nchez?= Date: Tue, 23 Sep 2025 19:52:35 +0000 Subject: [PATCH] Extend the range of supported CMake package config versions --- CMakeLists.txt | 23 ++------ cmake/Eigen3ConfigVersion.cmake.in | 91 ++++++++++++++++++++++++++++++ doc/TopicCMakeGuide.dox | 25 +++++--- 3 files changed, 112 insertions(+), 27 deletions(-) create mode 100644 cmake/Eigen3ConfigVersion.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 501584fb8..928da3d9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -255,25 +255,10 @@ if(EIGEN_BUILD_CMAKE_PACKAGE) NO_CHECK_REQUIRED_COMPONENTS_MACRO # Eigen does not provide components ) - # NOTE Remove the first code path once the minimum required CMake version is - # bumped to 3.14 or above. - if (CMAKE_VERSION VERSION_LESS 3.14) - # Remove CMAKE_SIZEOF_VOID_P from Eigen3ConfigVersion.cmake since Eigen does - # not depend on architecture specific settings or libraries. More - # specifically, an Eigen3Config.cmake generated from a 64 bit target can be - # used for 32 bit targets as well (and vice versa). - set (_Eigen3_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P}) - unset (CMAKE_SIZEOF_VOID_P) - write_basic_package_version_file (Eigen3ConfigVersion.cmake - VERSION ${EIGEN_VERSION_NUMBER} - COMPATIBILITY SameMajorVersion) - set (CMAKE_SIZEOF_VOID_P ${_Eigen3_CMAKE_SIZEOF_VOID_P}) - else (CMAKE_VERSION VERSION_LESS 3.14) - write_basic_package_version_file (Eigen3ConfigVersion.cmake - VERSION ${EIGEN_VERSION_NUMBER} - COMPATIBILITY SameMajorVersion - ARCH_INDEPENDENT) - endif (CMAKE_VERSION VERSION_LESS 3.14) + set(CVF_VERSION "${EIGEN_VERSION_NUMBER}") + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/Eigen3ConfigVersion.cmake.in" + "Eigen3ConfigVersion.cmake" + @ONLY) # The Eigen target will be located in the Eigen3 namespace. Other CMake # targets can refer to it using Eigen3::Eigen. diff --git a/cmake/Eigen3ConfigVersion.cmake.in b/cmake/Eigen3ConfigVersion.cmake.in new file mode 100644 index 000000000..b680c63a0 --- /dev/null +++ b/cmake/Eigen3ConfigVersion.cmake.in @@ -0,0 +1,91 @@ +# This is a CMake version file for the Config-mode of find_package(). +# +# The version constraint is compatible with the current package under the +# following conditions: +# - If a version range is specified, the package version falls within the +# range up to the supplied version components. +# - If a single version is specified, the current package version matches +# only the requested version components. +# +# Examples: +# - 3...5 matches 3.0.0.0 to <6.0.0.0 +# - 3...<5 matches 3.0.0.0 to <5.0.0.0 +# - 3...<5.1 matches 3.0.0.0 to <5.1.0.0 +# - 3 matches 3.0.0.0 to <4.0.0.0 +# - 3.4 matches 3.4.0.0 to <3.5.0.0 + +set(PACKAGE_VERSION "@CVF_VERSION@") + +# Extract version components. +if ("${PACKAGE_VERSION}" MATCHES "^([0-9]+)(\\.([0-9]+))?(\\.([0-9]+))?(\\.([0-9]+))?$") + set(_PACKAGE_VERSION_MAJOR "${CMAKE_MATCH_1}") + if (DEFINED CMAKE_MATCH_3) + set(_PACKAGE_VERSION_MINOR "${CMAKE_MATCH_3}") + else() + set(_PACKAGE_VERSION_MINOR "0") + endif() + if (DEFINED CMAKE_MATCH_5) + set(_PACKAGE_VERSION_PATCH "${CMAKE_MATCH_5}") + else() + set(_PACKAGE_VERSION_PATCH "0") + endif() + if (DEFINED CMAKE_MATCH_7) + set(_PACKAGE_VERSION_TWEAK "${CMAKE_MATCH_7}") + else() + set(_PACKAGE_VERSION_TWEAK "0") + endif() + set(_PACKAGE_VERSION_FULL "${_PACKAGE_VERSION_MAJOR}.${_PACKAGE_VERSION_MINOR}.${_PACKAGE_VERSION_PATCH}.${_PACKAGE_VERSION_TWEAK}") +endif() + +if (PACKAGE_FIND_VERSION_RANGE) + # Create exclusive bound for the range maximum. + if (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE") + set(_PACKAGE_FIND_VERSION_UPPER "${PACKAGE_FIND_VERSION_MAX_MAJOR}.${PACKAGE_FIND_VERSION_MAX_MINOR}.${PACKAGE_FIND_VERSION_MAX_PATCH}.${PACKAGE_FIND_VERSION_MAX_TWEAK}") + else() + # Increment the last supplied version number. + if (PACKAGE_FIND_VERSION_MAX_COUNT EQUAL 1) + math(EXPR _PACKAGE_FIND_VERSION_MAX_MAJOR "${PACKAGE_FIND_VERSION_MAX_MAJOR}+1") + set(_PACKAGE_FIND_VERSION_UPPER "${_PACKAGE_FIND_VERSION_MAX_MAJOR}.0.0.0") + elseif (PACKAGE_FIND_VERSION_MAX_COUNT EQUAL 2) + math(EXPR _PACKAGE_FIND_VERSION_MAX_MINOR "${PACKAGE_FIND_VERSION_MAX_MINOR}+1") + set(_PACKAGE_FIND_VERSION_UPPER "${PACKAGE_FIND_VERSION_MAX_MAJOR}.${_PACKAGE_FIND_VERSION_MAX_MINOR}.0.0") + elseif (PACKAGE_FIND_VERSION_MAX_COUNT EQUAL 3) + math(EXPR _PACKAGE_FIND_VERSION_MAX_PATCH "${PACKAGE_FIND_VERSION_MAX_PATCH}+1") + set(_PACKAGE_FIND_VERSION_UPPER "${PACKAGE_FIND_VERSION_MAX_MAJOR}.${PACKAGE_FIND_VERSION_MAX_MINOR}.${_PACKAGE_FIND_VERSION_MAX_PATCH}.0") + elseif (PACKAGE_FIND_VERSION_MAX_COUNT EQUAL 4) + math(EXPR _PACKAGE_FIND_VERSION_MAX_TWEAK "${PACKAGE_FIND_VERSION_MAX_TWEAK}+1") + set(_PACKAGE_FIND_VERSION_UPPER "${PACKAGE_FIND_VERSION_MAX_MAJOR}.${PACKAGE_FIND_VERSION_MAX_MINOR}.${PACKAGE_FIND_VERSION_MAX_PATCH}.${_PACKAGE_FIND_VERSION_MAX_TWEAK}") + endif() + endif() + + if ((_PACKAGE_VERSION_FULL VERSION_LESS PACKAGE_FIND_VERSION_MIN) + OR (_PACKAGE_VERSION_FULL VERSION_GREATER_EQUAL _PACKAGE_FIND_VERSION_UPPER)) + set(PACKAGE_VERSION_COMPATIBLE FALSE) + else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + endif() +else() + # Create exclusive upper bound. + if (PACKAGE_FIND_VERSION_COUNT EQUAL 1) + math(EXPR _PACKAGE_FIND_VERSION_MAJOR "${PACKAGE_FIND_VERSION_MAJOR}+1") + set(_PACKAGE_FIND_VERSION_UPPER "${_PACKAGE_FIND_VERSION_MAJOR}.0.0.0") + elseif (PACKAGE_FIND_VERSION_COUNT EQUAL 2) + math(EXPR _PACKAGE_FIND_VERSION_MINOR "${PACKAGE_FIND_VERSION_MINOR}+1") + set(_PACKAGE_FIND_VERSION_UPPER "${PACKAGE_FIND_VERSION_MAJOR}.${_PACKAGE_FIND_VERSION_MINOR}.0.0") + elseif (PACKAGE_FIND_VERSION_COUNT EQUAL 3) + math(EXPR _PACKAGE_FIND_VERSION_PATCH "${PACKAGE_FIND_VERSION_PATCH}+1") + set(_PACKAGE_FIND_VERSION_UPPER "${PACKAGE_FIND_VERSION_MAJOR}.${PACKAGE_FIND_VERSION_MINOR}.${_PACKAGE_FIND_VERSION_PATCH}.0") + elseif (PACKAGE_FIND_VERSION_COUNT EQUAL 4) + math(EXPR _PACKAGE_FIND_VERSION_TWEAK "${PACKAGE_FIND_VERSION_TWEAK}+1") + set(_PACKAGE_FIND_VERSION_UPPER "${PACKAGE_FIND_VERSION_MAJOR}.${PACKAGE_FIND_VERSION_MINOR}.${PACKAGE_FIND_VERSION_PATCH}.${_PACKAGE_FIND_VERSION_TWEAK}") + endif() + + if((_PACKAGE_VERSION_FULL VERSION_LESS PACKAGE_FIND_VERSION) OR (_PACKAGE_VERSION_FULL VERSION_GREATER_EQUAL _PACKAGE_FIND_VERSION_UPPER)) + set(PACKAGE_VERSION_COMPATIBLE FALSE) + else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) + endif() + endif() +endif() diff --git a/doc/TopicCMakeGuide.dox b/doc/TopicCMakeGuide.dox index cf767d0dd..ebbc4a840 100644 --- a/doc/TopicCMakeGuide.dox +++ b/doc/TopicCMakeGuide.dox @@ -7,16 +7,16 @@ namespace Eigen { %Eigen provides native CMake support which allows the library to be easily used in CMake projects. -\note %CMake 3.0 (or later) is required to enable this functionality. +\note %CMake 3.5 (or later) is required to enable this functionality. %Eigen exports a CMake target called `Eigen3::Eigen` which can be imported using the `find_package` CMake command and used by calling `target_link_libraries` as in the following example: \code{.cmake} -cmake_minimum_required (VERSION 3.0) +cmake_minimum_required (VERSION 3.5) project (myproject) -find_package (Eigen3 3.3 REQUIRED NO_MODULE) +find_package (Eigen3 REQUIRED NO_MODULE) add_executable (example example.cpp) target_link_libraries (example Eigen3::Eigen) @@ -27,10 +27,19 @@ The above code snippet must be placed in a file called `CMakeLists.txt` alongsid \code{.sh} $ cmake path-to-example-directory \endcode -CMake will produce project files that generate an executable called `example` -which requires at least version 3.3 of %Eigen. Here, `path-to-example-directory` -is the path to the directory that contains both `CMakeLists.txt` and -`example.cpp`. +CMake will produce project files that generate an executable called `example`. +Here, `path-to-example-directory` is the path to the directory that contains +both `CMakeLists.txt` and `example.cpp`. Note that if you have multiple +instances of %Eigen installed, `find_package` will use the first one +encountered. To request a specific version of %Eigen, use the `` +option in `find_package`: +``` +find_package(Eigen3 3.4 REQUIRED NO_MODULE) # Restricts to 3.4.z +``` +or to support a range of versions: +``` +find_package(Eigen3 3.4...5 REQUIRED NO_MODULE) # Any version >=3.4.0 but <6.0.0. +``` Do not forget to set the \c CMAKE_PREFIX_PATH variable if Eigen is not installed in a default location or if you want to pick a specific version. For instance: \code{.sh} @@ -44,7 +53,7 @@ $ cmake path-to-example-directory -DEigen3_DIR=$HOME/mypackages/share/eigen3/cma If the `REQUIRED` option is omitted when locating %Eigen using `find_package`, one can check whether the package was found as follows: \code{.cmake} -find_package (Eigen3 3.3 NO_MODULE) +find_package (Eigen3 NO_MODULE) if (TARGET Eigen3::Eigen) # Use the imported target