ENH: Improve find_package version numbering

Make the number of version components specified explicitly available.
Set variables for unspecified version components to "0" instead of
leaving them unset.  This simplifies version number handling for find-
and config-modules.  Also support a fourth "tweak" version component
since some packages use them.
This commit is contained in:
Brad King 2008-09-10 10:11:48 -04:00
parent 4eaac32db6
commit 994262e5cc
8 changed files with 123 additions and 104 deletions

View File

@ -67,20 +67,25 @@ line.
A FindXXX.cmake module will typically be loaded by the command
FIND_PACKAGE(XXX [major[.minor[.patch]]] [EXACT]
FIND_PACKAGE(XXX [major[.minor[.patch[.tweak]]]] [EXACT]
[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. The variable XXX_FIND_VERSION_EXACT
will indicate whether an exact version is requested.
following variables before loading the module:
XXX_FIND_VERSION = full requested version string
XXX_FIND_VERSION_MAJOR = major version if requested, else 0
XXX_FIND_VERSION_MINOR = minor version if requested, else 0
XXX_FIND_VERSION_PATCH = patch version if requested, else 0
XXX_FIND_VERSION_TWEAK = tweak version if requested, else 0
XXX_FIND_VERSION_COUNT = number of version components, 0 to 4
XXX_FIND_VERSION_EXACT = true if EXACT option was given
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.
in "XXX_VERSION..." version variables docmented by the module.
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

View File

@ -67,14 +67,16 @@ cmFindPackageCommand::cmFindPackageCommand()
this->VersionMajor = 0;
this->VersionMinor = 0;
this->VersionPatch = 0;
this->VersionTweak = 0;
this->VersionCount = 0;
this->VersionExact = false;
this->VersionFoundMajor = 0;
this->VersionFoundMinor = 0;
this->VersionFoundPatch = 0;
this->VersionFoundTweak = 0;
this->VersionFoundCount = 0;
this->CommandDocumentation =
" find_package(<package> [major[.minor[.patch]]] [EXACT] [QUIET]\n"
" find_package(<package> [version] [EXACT] [QUIET]\n"
" [[REQUIRED|COMPONENTS] [components...]])\n"
"Finds and loads settings from an external project. "
"<package>_FOUND will be set to indicate whether the package was found. "
@ -86,8 +88,8 @@ cmFindPackageCommand::cmFindPackageCommand()
"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[.patch]]]\" version argument specifies a desired "
"version with which the package found should be compatible. "
"The [version] argument requests a version with which the package found "
"should be compatible (format is major[.minor[.patch[.tweak]]]). "
"The EXACT option requests that the version be matched exactly. "
"Version support is currently provided only on a package-by-package "
"basis (details below).\n"
@ -109,7 +111,7 @@ cmFindPackageCommand::cmFindPackageCommand()
"check the module documentation. "
"If no module is found the command proceeds to Config mode.\n"
"The complete Config mode command signature is:\n"
" find_package(<package> [major[.minor[.patch]]] [EXACT] [QUIET]\n"
" find_package(<package> [version] [EXACT] [QUIET]\n"
" [[REQUIRED|COMPONENTS] [components...]] [NO_MODULE]\n"
" [NAMES name1 [name2 ...]]\n"
" [CONFIGS config1 [config2 ...]]\n"
@ -153,9 +155,9 @@ cmFindPackageCommand::cmFindPackageCommand()
"a configuration file a fatal error is always generated because user "
"intervention is required."
"\n"
"When the \"[major[.minor[.patch]]]\" version argument is specified "
"Config mode will only find a version of the package that claims "
"compatibility with the requested version. "
"When the [version] argument is given Config mode will only find a "
"version of the package that claims compatibility with the requested "
"version (format is major[.minor[.patch[.tweak]]]). "
"If the EXACT option is given only a version of the package claiming "
"an exact match of the requested version may be found. "
"CMake does not establish any convention for the meaning of version "
@ -173,22 +175,26 @@ cmFindPackageCommand::cmFindPackageCommand()
"variables have been defined:\n"
" PACKAGE_FIND_NAME = the <package> name\n"
" PACKAGE_FIND_VERSION = full requested version string\n"
" PACKAGE_FIND_VERSION_MAJOR = requested major version, if any\n"
" PACKAGE_FIND_VERSION_MINOR = requested minor version, if any\n"
" PACKAGE_FIND_VERSION_PATCH = requested patch version, if any\n"
" PACKAGE_FIND_VERSION_MAJOR = major version if requested, else 0\n"
" PACKAGE_FIND_VERSION_MINOR = minor version if requested, else 0\n"
" PACKAGE_FIND_VERSION_PATCH = patch version if requested, else 0\n"
" PACKAGE_FIND_VERSION_TWEAK = tweak version if requested, else 0\n"
" PACKAGE_FIND_VERSION_COUNT = number of version components, 0 to 4\n"
"The version file checks whether it satisfies the requested version "
"and sets these variables:\n"
" PACKAGE_VERSION = package version (major[.minor[.patch]])\n"
" PACKAGE_VERSION = full provided version string\n"
" PACKAGE_VERSION_EXACT = true if version is exact match\n"
" PACKAGE_VERSION_COMPATIBLE = true if version is compatible\n"
"These variables are checked by the find_package command to determine "
"whether the configuration file provides an acceptable version. "
"They are not available after the find_package call returns. "
"If the version is acceptable the following variables are set:\n"
" <package>_VERSION = package version (major[.minor[.patch]])\n"
" <package>_VERSION_MAJOR = major from major[.minor[.patch]], if any\n"
" <package>_VERSION_MINOR = minor from major[.minor[.patch]], if any\n"
" <package>_VERSION_PATCH = patch from major[.minor[.patch]], if any\n"
" <package>_VERSION = full provided version string\n"
" <package>_VERSION_MAJOR = major version if provided, else 0\n"
" <package>_VERSION_MINOR = minor version if provided, else 0\n"
" <package>_VERSION_PATCH = patch version if provided, else 0\n"
" <package>_VERSION_TWEAK = tweak version if provided, else 0\n"
" <package>_VERSION_COUNT = number of version components, 0 to 4\n"
"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 "
@ -469,10 +475,13 @@ bool cmFindPackageCommand
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);
unsigned int parsed_tweak;
this->VersionCount = sscanf(this->Version.c_str(), "%u.%u.%u.%u",
&parsed_major, &parsed_minor,
&parsed_patch, &parsed_tweak);
switch(this->VersionCount)
{
case 4: this->VersionTweak = parsed_tweak; // no break!
case 3: this->VersionPatch = parsed_patch; // no break!
case 2: this->VersionMinor = parsed_minor; // no break!
case 1: this->VersionMajor = parsed_major; // no break!
@ -565,25 +574,16 @@ void cmFindPackageCommand::SetModuleVariables(const std::string& components)
ver += "_FIND_VERSION";
this->Makefile->AddDefinition(ver.c_str(), this->Version.c_str());
char buf[64];
switch(this->VersionCount)
{
case 3:
{
sprintf(buf, "%u", this->VersionPatch);
this->Makefile->AddDefinition((ver+"_PATCH").c_str(), buf);
} // no break
case 2:
{
sprintf(buf, "%u", this->VersionMinor);
this->Makefile->AddDefinition((ver+"_MINOR").c_str(), buf);
} // no break
case 1:
{
sprintf(buf, "%u", this->VersionMajor);
this->Makefile->AddDefinition((ver+"_MAJOR").c_str(), buf);
} // no break
default: break;
}
sprintf(buf, "%u", this->VersionMajor);
this->Makefile->AddDefinition((ver+"_MAJOR").c_str(), buf);
sprintf(buf, "%u", this->VersionMinor);
this->Makefile->AddDefinition((ver+"_MINOR").c_str(), buf);
sprintf(buf, "%u", this->VersionPatch);
this->Makefile->AddDefinition((ver+"_PATCH").c_str(), buf);
sprintf(buf, "%u", this->VersionTweak);
this->Makefile->AddDefinition((ver+"_TWEAK").c_str(), buf);
sprintf(buf, "%u", this->VersionCount);
this->Makefile->AddDefinition((ver+"_COUNT").c_str(), buf);
// Tell the module whether an exact version has been requested.
std::string exact = this->Name;
@ -1234,36 +1234,17 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file)
this->Makefile->AddDefinition("PACKAGE_FIND_NAME", this->Name.c_str());
this->Makefile->AddDefinition("PACKAGE_FIND_VERSION",
this->Version.c_str());
if(this->VersionCount >= 3)
{
char buf[64];
sprintf(buf, "%u", this->VersionPatch);
this->Makefile->AddDefinition("PACKAGE_FIND_VERSION_PATCH", buf);
}
else
{
this->Makefile->RemoveDefinition("PACKAGE_FIND_VERSION_PATCH");
}
if(this->VersionCount >= 2)
{
char buf[64];
sprintf(buf, "%u", this->VersionMinor);
this->Makefile->AddDefinition("PACKAGE_FIND_VERSION_MINOR", buf);
}
else
{
this->Makefile->RemoveDefinition("PACKAGE_FIND_VERSION_MINOR");
}
if(this->VersionCount >= 1)
{
char buf[64];
sprintf(buf, "%u", this->VersionMajor);
this->Makefile->AddDefinition("PACKAGE_FIND_VERSION_MAJOR", buf);
}
else
{
this->Makefile->RemoveDefinition("PACKAGE_FIND_VERSION_MAJOR");
}
char buf[64];
sprintf(buf, "%u", this->VersionMajor);
this->Makefile->AddDefinition("PACKAGE_FIND_VERSION_MAJOR", buf);
sprintf(buf, "%u", this->VersionMinor);
this->Makefile->AddDefinition("PACKAGE_FIND_VERSION_MINOR", buf);
sprintf(buf, "%u", this->VersionPatch);
this->Makefile->AddDefinition("PACKAGE_FIND_VERSION_PATCH", buf);
sprintf(buf, "%u", this->VersionTweak);
this->Makefile->AddDefinition("PACKAGE_FIND_VERSION_TWEAK", buf);
sprintf(buf, "%u", this->VersionCount);
this->Makefile->AddDefinition("PACKAGE_FIND_VERSION_COUNT", buf);
// Load the version check file.
bool found = false;
@ -1286,11 +1267,14 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file)
unsigned int parsed_major;
unsigned int parsed_minor;
unsigned int parsed_patch;
unsigned int parsed_tweak;
this->VersionFoundCount =
sscanf(this->VersionFound.c_str(), "%u.%u.%u",
&parsed_major, &parsed_minor, &parsed_patch);
sscanf(this->VersionFound.c_str(), "%u.%u.%u.%u",
&parsed_major, &parsed_minor,
&parsed_patch, &parsed_tweak);
switch(this->VersionFoundCount)
{
case 4: this->VersionFoundTweak = parsed_tweak; // no break!
case 3: this->VersionFoundPatch = parsed_patch; // no break!
case 2: this->VersionFoundMinor = parsed_minor; // no break!
case 1: this->VersionFoundMajor = parsed_major; // no break!
@ -1321,27 +1305,18 @@ void cmFindPackageCommand::StoreVersionFound()
this->Makefile->AddDefinition(ver.c_str(), this->VersionFound.c_str());
}
// Store the portions that could be parsed.
// Store the version components.
char buf[64];
switch(this->VersionFoundCount)
{
case 3:
{
sprintf(buf, "%u", this->VersionFoundPatch);
this->Makefile->AddDefinition((ver+"_PATCH").c_str(), buf);
} // no break
case 2:
{
sprintf(buf, "%u", this->VersionFoundMinor);
this->Makefile->AddDefinition((ver+"_MINOR").c_str(), buf);
} // no break
case 1:
{
sprintf(buf, "%u", this->VersionFoundMajor);
this->Makefile->AddDefinition((ver+"_MAJOR").c_str(), buf);
} // no break
default: break;
}
sprintf(buf, "%u", this->VersionFoundMajor);
this->Makefile->AddDefinition((ver+"_MAJOR").c_str(), buf);
sprintf(buf, "%u", this->VersionFoundMinor);
this->Makefile->AddDefinition((ver+"_MINOR").c_str(), buf);
sprintf(buf, "%u", this->VersionFoundPatch);
this->Makefile->AddDefinition((ver+"_PATCH").c_str(), buf);
sprintf(buf, "%u", this->VersionFoundTweak);
this->Makefile->AddDefinition((ver+"_TWEAK").c_str(), buf);
sprintf(buf, "%u", this->VersionFoundCount);
this->Makefile->AddDefinition((ver+"_COUNT").c_str(), buf);
}
//----------------------------------------------------------------------------

View File

@ -111,6 +111,7 @@ private:
unsigned int VersionMajor;
unsigned int VersionMinor;
unsigned int VersionPatch;
unsigned int VersionTweak;
unsigned int VersionCount;
bool VersionExact;
cmStdString FileFound;
@ -118,6 +119,7 @@ private:
unsigned int VersionFoundMajor;
unsigned int VersionFoundMinor;
unsigned int VersionFoundPatch;
unsigned int VersionFoundTweak;
unsigned int VersionFoundCount;
bool Quiet;
bool Required;

View File

@ -27,6 +27,7 @@ LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
FIND_PACKAGE(VersionTestA 1)
FIND_PACKAGE(VersionTestB 1.2)
FIND_PACKAGE(VersionTestC 1.2.3)
FIND_PACKAGE(VersionTestD 1.2.3.4)
#-----------------------------------------------------------------------------

View File

@ -4,9 +4,15 @@ 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)
IF(NOT "${VersionTestA_FIND_VERSION_MINOR}" STREQUAL "0")
MESSAGE(SEND_ERROR "VersionTestA_FIND_VERSION_MINOR=${VersionTestA_FIND_VERSION_MINOR} is not 0")
ENDIF(NOT "${VersionTestA_FIND_VERSION_MINOR}" STREQUAL "0")
IF(NOT "${VersionTestA_FIND_VERSION_PATCH}" STREQUAL "0")
MESSAGE(SEND_ERROR "VersionTestA_FIND_VERSION_PATCH=${VersionTestA_FIND_VERSION_PATCH} is not 0")
ENDIF(NOT "${VersionTestA_FIND_VERSION_PATCH}" STREQUAL "0")
IF(NOT "${VersionTestA_FIND_VERSION_TWEAK}" STREQUAL "0")
MESSAGE(SEND_ERROR "VersionTestA_FIND_VERSION_TWEAK=${VersionTestA_FIND_VERSION_TWEAK} is not 0")
ENDIF(NOT "${VersionTestA_FIND_VERSION_TWEAK}" STREQUAL "0")
IF(NOT "${VersionTestA_FIND_VERSION_COUNT}" STREQUAL "1")
MESSAGE(SEND_ERROR "VersionTestA_FIND_VERSION_COUNT=${VersionTestA_FIND_VERSION_COUNT} is not 1")
ENDIF(NOT "${VersionTestA_FIND_VERSION_COUNT}" STREQUAL "1")

View File

@ -7,6 +7,12 @@ 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)
IF(NOT "${VersionTestB_FIND_VERSION_PATCH}" STREQUAL "0")
MESSAGE(SEND_ERROR "VersionTestB_FIND_VERSION_PATCH=${VersionTestB_FIND_VERSION_PATCH} is not 0")
ENDIF(NOT "${VersionTestB_FIND_VERSION_PATCH}" STREQUAL "0")
IF(NOT "${VersionTestB_FIND_VERSION_TWEAK}" STREQUAL "0")
MESSAGE(SEND_ERROR "VersionTestB_FIND_VERSION_TWEAK=${VersionTestB_FIND_VERSION_TWEAK} is not 0")
ENDIF(NOT "${VersionTestB_FIND_VERSION_TWEAK}" STREQUAL "0")
IF(NOT "${VersionTestB_FIND_VERSION_COUNT}" STREQUAL "2")
MESSAGE(SEND_ERROR "VersionTestB_FIND_VERSION_COUNT=${VersionTestB_FIND_VERSION_COUNT} is not 2")
ENDIF(NOT "${VersionTestB_FIND_VERSION_COUNT}" STREQUAL "2")

View File

@ -10,3 +10,9 @@ 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")
IF(NOT "${VersionTestC_FIND_VERSION_TWEAK}" STREQUAL "0")
MESSAGE(SEND_ERROR "VersionTestC_FIND_VERSION_TWEAK=${VersionTestC_FIND_VERSION_TWEAK} is not 0")
ENDIF(NOT "${VersionTestC_FIND_VERSION_TWEAK}" STREQUAL "0")
IF(NOT "${VersionTestC_FIND_VERSION_COUNT}" STREQUAL "3")
MESSAGE(SEND_ERROR "VersionTestC_FIND_VERSION_COUNT=${VersionTestC_FIND_VERSION_COUNT} is not 3")
ENDIF(NOT "${VersionTestC_FIND_VERSION_COUNT}" STREQUAL "3")

View File

@ -0,0 +1,18 @@
IF(NOT "${VersionTestD_FIND_VERSION}" STREQUAL "1.2.3.4")
MESSAGE(SEND_ERROR "VersionTestD_FIND_VERSION=${VersionTestD_FIND_VERSION} is not 1.2.3.4")
ENDIF(NOT "${VersionTestD_FIND_VERSION}" STREQUAL "1.2.3.4")
IF(NOT "${VersionTestD_FIND_VERSION_MAJOR}" STREQUAL "1")
MESSAGE(SEND_ERROR "VersionTestD_FIND_VERSION_MAJOR=${VersionTestD_FIND_VERSION_MAJOR} is not 1")
ENDIF(NOT "${VersionTestD_FIND_VERSION_MAJOR}" STREQUAL "1")
IF(NOT "${VersionTestD_FIND_VERSION_MINOR}" STREQUAL "2")
MESSAGE(SEND_ERROR "VersionTestD_FIND_VERSION_MINOR=${VersionTestD_FIND_VERSION_MINOR} is not 2")
ENDIF(NOT "${VersionTestD_FIND_VERSION_MINOR}" STREQUAL "2")
IF(NOT "${VersionTestD_FIND_VERSION_PATCH}" STREQUAL "3")
MESSAGE(SEND_ERROR "VersionTestD_FIND_VERSION_PATCH=${VersionTestD_FIND_VERSION_PATCH} is not 3")
ENDIF(NOT "${VersionTestD_FIND_VERSION_PATCH}" STREQUAL "3")
IF(NOT "${VersionTestD_FIND_VERSION_TWEAK}" STREQUAL "4")
MESSAGE(SEND_ERROR "VersionTestD_FIND_VERSION_TWEAK=${VersionTestD_FIND_VERSION_TWEAK} is not 4")
ENDIF(NOT "${VersionTestD_FIND_VERSION_TWEAK}" STREQUAL "4")
IF(NOT "${VersionTestD_FIND_VERSION_COUNT}" STREQUAL "4")
MESSAGE(SEND_ERROR "VersionTestD_FIND_VERSION_COUNT=${VersionTestD_FIND_VERSION_COUNT} is not 4")
ENDIF(NOT "${VersionTestD_FIND_VERSION_COUNT}" STREQUAL "4")