From f41b1e8e9148c62e186e0729c5a5144c51e944e9 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 21 Jan 2008 08:48:33 -0500 Subject: ENH: Implement version support in the find_package command module mode. Version numbers provided to the command are converted to variable settings to tell the FindXXX.cmake module what version is requested. This addresses issue #1645. --- Modules/readme.txt | 18 +++++++- Source/cmFindPackageCommand.cxx | 63 ++++++++++++++++++++++++++-- Source/cmFindPackageCommand.h | 5 +++ Tests/FindPackageTest/CMakeLists.txt | 7 ++++ Tests/FindPackageTest/FindVersionTestA.cmake | 12 ++++++ Tests/FindPackageTest/FindVersionTestB.cmake | 12 ++++++ Tests/FindPackageTest/FindVersionTestC.cmake | 12 ++++++ 7 files changed, 124 insertions(+), 5 deletions(-) create mode 100644 Tests/FindPackageTest/FindVersionTestA.cmake create mode 100644 Tests/FindPackageTest/FindVersionTestB.cmake create mode 100644 Tests/FindPackageTest/FindVersionTestC.cmake diff --git a/Modules/readme.txt b/Modules/readme.txt index 632c054..f94935f 100644 --- a/Modules/readme.txt +++ b/Modules/readme.txt @@ -18,6 +18,10 @@ XXX_FOUND Set to false, or undefined, if we haven't found, or don' XXX_RUNTIME_LIBRARY_DIRS Optionally, the runtime library search path for use when running an executable linked to shared libraries. The list should be used by user code to create the PATH on windows or LD_LIBRARY_PATH on unix. This should not be a cache entry. +XXX_VERSION_STRING A human-readable string containing the version of the package found, if any. +XXX_VERSION_MAJOR The major version of the package found, if any. +XXX_VERSION_MINOR The minor version of the package found, if any. +XXX_VERSION_PATCH The patch version of the package found, if any. You do not have to provide all of the above variables. You should provide XXX_FOUND under most circumstances. If XXX is a library, then XXX_LIBRARIES, should also be defined, and XXX_INCLUDE_DIRS should usually be defined (I guess libm.a might be an exception) @@ -63,7 +67,19 @@ line. A FindXXX.cmake module will typically be loaded by the command - FIND_PACKAGE(XXX [QUIET] [REQUIRED [components...]]) + FIND_PACKAGE(XXX [major[.minor[.patch]]] + [QUIET] [REQUIRED [components...]]) + +If any version numbers are given to the command it will set the +variable XXX_FIND_VERSION to contain the whole version. The variables +XXX_FIND_VERSION_MAJOR, XXX_FIND_VERSION_MINOR, and +XXX_FIND_VERSION_PATCH will be set to contain the corresponding +portions of the version number. If the find module supports +versioning it should locate a version of the package that is +compatible with the version requested. If a compatible version of the +package cannot be found the module should not report success. The +version of the package found should be stored in the version variables +named above. If the QUIET option is given to the command it will set the variable XXX_FIND_QUIETLY to true before loading the FindXXX.cmake module. If diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index a4b7e6a..c4d7b87 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -63,8 +63,12 @@ cmFindPackageCommand::cmFindPackageCommand() this->NoBuilds = false; this->NoModule = false; this->DebugMode = false; + this->VersionMajor = 0; + this->VersionMinor = 0; + this->VersionPatch = 0; + this->VersionCount = 0; this->CommandDocumentation = - " find_package( [major.minor] [QUIET] [NO_MODULE]\n" + " find_package( [major[.minor[.patch]]] [QUIET] [NO_MODULE]\n" " [[REQUIRED|COMPONENTS] [components...]]\n" " [NAMES name1 [name2 ...]]\n" " [CONFIGS config1 [config2 ...]]\n" @@ -84,13 +88,15 @@ cmFindPackageCommand::cmFindPackageCommand() "can be used when _FOUND is true are package-specific. " "A package-specific list of components may be listed after the " "REQUIRED option, or after the COMPONENTS option if no REQUIRED " - "option is given. The \"major.minor\" version argument is currently " - "a placeholder for future use and is ignored. " + "option is given. The \"[major[.minor[.patch]]]\" version argument " + "specifies a desired version with which the package found should be " + "compatible. Version support is currently provided only on a " + "package-by-package basis and is not enforced by the command. " "The command has two modes by which it searches for packages: " "\"Module\" mode and \"Config\" mode." "\n" "Module mode has a reduced signature:\n" - " find_package( [major.minor] [QUIET]\n" + " find_package( [major[.minor[.patch]]] [QUIET]\n" " [[REQUIRED|COMPONENTS] [components...]])\n" "CMake searches for a file called \"Find.cmake\" in " "the CMAKE_MODULE_PATH followed by the CMake installation. " @@ -104,6 +110,7 @@ cmFindPackageCommand::cmFindPackageCommand() "Config mode attempts to locate a configuration file provided by the " "package to be found. A cache entry called _DIR is created to " "hold the directory containing the file. " + "Currently versioning is not implemented by Config mode. " "By default the command searches for a package with the name . " "If the NAMES option is given the names following it are used instead " "of . " @@ -338,6 +345,7 @@ bool cmFindPackageCommand::InitialPass(std::vector const& args) else if(!haveVersion && version.find(args[i].c_str())) { haveVersion = true; + this->Version = args[i]; } else { @@ -348,6 +356,24 @@ bool cmFindPackageCommand::InitialPass(std::vector const& args) } } + if(!this->Version.empty()) + { + // Try to parse the version number and store the results that were + // successfully parsed. + unsigned int parsed_major; + unsigned int parsed_minor; + unsigned int parsed_patch; + this->VersionCount = sscanf(this->Version.c_str(), "%u.%u.%u", + &parsed_major, &parsed_minor, &parsed_patch); + switch(this->VersionCount) + { + case 3: this->VersionPatch = parsed_patch; // no break! + case 2: this->VersionMinor = parsed_minor; // no break! + case 1: this->VersionMajor = parsed_major; // no break! + default: break; + } + } + // Store the list of components. std::string components_var = Name + "_FIND_COMPONENTS"; this->Makefile->AddDefinition(components_var.c_str(), components.c_str()); @@ -428,6 +454,35 @@ bool cmFindPackageCommand::FindModule(bool& found) this->Makefile->AddDefinition(req.c_str(), "1"); } + if(!this->Version.empty()) + { + // Tell the module that is about to be read what version of the + // package has been requested. + std::string ver = this->Name; + ver += "_FIND_VERSION"; + this->Makefile->AddDefinition(ver.c_str(), this->Version.c_str()); + char buf[64]; + switch(this->VersionCount) + { + case 3: + { + snprintf(buf, 64, "%u", this->VersionPatch); + this->Makefile->AddDefinition((ver+"_PATCH").c_str(), buf); + } // no break + case 2: + { + snprintf(buf, 64, "%u", this->VersionMinor); + this->Makefile->AddDefinition((ver+"_MINOR").c_str(), buf); + } // no break + case 1: + { + snprintf(buf, 64, "%u", this->VersionMajor); + this->Makefile->AddDefinition((ver+"_MAJOR").c_str(), buf); + } // no break + default: break; + } + } + // Load the module we found. found = true; return this->ReadListFile(mfile.c_str()); diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index af41048..7090eee 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -94,6 +94,11 @@ private: std::string CommandDocumentation; cmStdString Name; cmStdString Variable; + cmStdString Version; + unsigned int VersionMajor; + unsigned int VersionMinor; + unsigned int VersionPatch; + unsigned int VersionCount; cmStdString FileFound; bool Quiet; bool Required; diff --git a/Tests/FindPackageTest/CMakeLists.txt b/Tests/FindPackageTest/CMakeLists.txt index 5d21fee..8b3225e 100644 --- a/Tests/FindPackageTest/CMakeLists.txt +++ b/Tests/FindPackageTest/CMakeLists.txt @@ -22,6 +22,13 @@ IF(NOT FOO_DIR) CMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH}") ENDIF(NOT FOO_DIR) +LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}) +FIND_PACKAGE(VersionTestA 1) +FIND_PACKAGE(VersionTestB 1.2) +FIND_PACKAGE(VersionTestC 1.2.3) + +#----------------------------------------------------------------------------- + #SET(CMAKE_FIND_DEBUG_MODE 1) # For purposes of the test wipe out previous find results. diff --git a/Tests/FindPackageTest/FindVersionTestA.cmake b/Tests/FindPackageTest/FindVersionTestA.cmake new file mode 100644 index 0000000..eedf371 --- /dev/null +++ b/Tests/FindPackageTest/FindVersionTestA.cmake @@ -0,0 +1,12 @@ +IF(NOT "${VersionTestA_FIND_VERSION}" STREQUAL "1") + MESSAGE(SEND_ERROR "VersionTestA_FIND_VERSION=${VersionTestA_FIND_VERSION} is not 1") +ENDIF(NOT "${VersionTestA_FIND_VERSION}" STREQUAL "1") +IF(NOT "${VersionTestA_FIND_VERSION_MAJOR}" STREQUAL "1") + MESSAGE(SEND_ERROR "VersionTestA_FIND_VERSION_MAJOR=${VersionTestA_FIND_VERSION_MAJOR} is not 1") +ENDIF(NOT "${VersionTestA_FIND_VERSION_MAJOR}" STREQUAL "1") +IF(DEFINED VersionTestA_FIND_VERSION_MINOR) + MESSAGE(SEND_ERROR "VersionTestA_FIND_VERSION_MINOR should not be defined") +ENDIF(DEFINED VersionTestA_FIND_VERSION_MINOR) +IF(DEFINED VersionTestA_FIND_VERSION_PATCH) + MESSAGE(SEND_ERROR "VersionTestA_FIND_VERSION_PATCH should not be defined") +ENDIF(DEFINED VersionTestA_FIND_VERSION_PATCH) diff --git a/Tests/FindPackageTest/FindVersionTestB.cmake b/Tests/FindPackageTest/FindVersionTestB.cmake new file mode 100644 index 0000000..787d200 --- /dev/null +++ b/Tests/FindPackageTest/FindVersionTestB.cmake @@ -0,0 +1,12 @@ +IF(NOT "${VersionTestB_FIND_VERSION}" STREQUAL "1.2") + MESSAGE(SEND_ERROR "VersionTestB_FIND_VERSION=${VersionTestB_FIND_VERSION} is not 1.2") +ENDIF(NOT "${VersionTestB_FIND_VERSION}" STREQUAL "1.2") +IF(NOT "${VersionTestB_FIND_VERSION_MAJOR}" STREQUAL "1") + MESSAGE(SEND_ERROR "VersionTestB_FIND_VERSION_MAJOR=${VersionTestB_FIND_VERSION_MAJOR} is not 1") +ENDIF(NOT "${VersionTestB_FIND_VERSION_MAJOR}" STREQUAL "1") +IF(NOT "${VersionTestB_FIND_VERSION_MINOR}" STREQUAL "2") + MESSAGE(SEND_ERROR "VersionTestB_FIND_VERSION_MINOR=${VersionTestB_FIND_VERSION_MINOR} is not 2") +ENDIF(NOT "${VersionTestB_FIND_VERSION_MINOR}" STREQUAL "2") +IF(DEFINED VersionTestB_FIND_VERSION_PATCH) + MESSAGE(SEND_ERROR "VersionTestB_FIND_VERSION_PATCH should not be defined") +ENDIF(DEFINED VersionTestB_FIND_VERSION_PATCH) diff --git a/Tests/FindPackageTest/FindVersionTestC.cmake b/Tests/FindPackageTest/FindVersionTestC.cmake new file mode 100644 index 0000000..26ce050 --- /dev/null +++ b/Tests/FindPackageTest/FindVersionTestC.cmake @@ -0,0 +1,12 @@ +IF(NOT "${VersionTestC_FIND_VERSION}" STREQUAL "1.2.3") + MESSAGE(SEND_ERROR "VersionTestC_FIND_VERSION=${VersionTestC_FIND_VERSION} is not 1.2.3") +ENDIF(NOT "${VersionTestC_FIND_VERSION}" STREQUAL "1.2.3") +IF(NOT "${VersionTestC_FIND_VERSION_MAJOR}" STREQUAL "1") + MESSAGE(SEND_ERROR "VersionTestC_FIND_VERSION_MAJOR=${VersionTestC_FIND_VERSION_MAJOR} is not 1") +ENDIF(NOT "${VersionTestC_FIND_VERSION_MAJOR}" STREQUAL "1") +IF(NOT "${VersionTestC_FIND_VERSION_MINOR}" STREQUAL "2") + MESSAGE(SEND_ERROR "VersionTestC_FIND_VERSION_MINOR=${VersionTestC_FIND_VERSION_MINOR} is not 2") +ENDIF(NOT "${VersionTestC_FIND_VERSION_MINOR}" STREQUAL "2") +IF(NOT "${VersionTestC_FIND_VERSION_PATCH}" STREQUAL "3") + MESSAGE(SEND_ERROR "VersionTestC_FIND_VERSION_PATCH=${VersionTestC_FIND_VERSION_PATCH} is not 3") +ENDIF(NOT "${VersionTestC_FIND_VERSION_PATCH}" STREQUAL "3") -- cgit v0.12