From 4fa96dbf95bb3689fb1c3283c38713ec5275f262 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 10 Sep 2008 11:58:40 -0400 Subject: ENH: Add version comparison to if() command Provide VERSION_LESS, VERSION_EQUAL, and VERSION_GREATER operators in the if() command. This simplifies component-wise comparison of version numbers in the form "major[.minor[.patch[.tweak]]]". --- Source/cmIfCommand.cxx | 48 ++++++++++++++++++++++++++++++++++++ Source/cmIfCommand.h | 5 ++++ Tests/FindPackageTest/CMakeLists.txt | 17 +++++++++++++ 3 files changed, 70 insertions(+) diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx index e82a8fb..8c22602 100644 --- a/Source/cmIfCommand.cxx +++ b/Source/cmIfCommand.cxx @@ -285,6 +285,34 @@ namespace } //========================================================================= + enum Op { OpLess, OpEqual, OpGreater }; + bool HandleVersionCompare(Op op, const char* lhs_str, const char* rhs_str) + { + // Parse out up to 4 components. + unsigned int lhs[4] = {0,0,0,0}; + unsigned int rhs[4] = {0,0,0,0}; + sscanf(lhs_str, "%u.%u.%u.%u", &lhs[0], &lhs[1], &lhs[2], &lhs[3]); + sscanf(rhs_str, "%u.%u.%u.%u", &rhs[0], &rhs[1], &rhs[2], &rhs[3]); + + // Do component-wise comparison. + for(unsigned int i=0; i < 4; ++i) + { + if(lhs[i] < rhs[i]) + { + // lhs < rhs, so true if operation is LESS + return op == OpLess; + } + else if(lhs[i] > rhs[i]) + { + // lhs > rhs, so true if operation is GREATER + return op == OpGreater; + } + } + // lhs == rhs, so true if operation is EQUAL + return op == OpEqual; + } + + //========================================================================= // level 0 processes parenthetical expressions bool HandleLevel0(std::list &newArgs, cmMakefile *makefile, @@ -552,6 +580,26 @@ namespace reducible, arg, newArgs, argP1, argP2); } + if (argP1 != newArgs.end() && argP2 != newArgs.end() && + (*(argP1) == "VERSION_LESS" || *(argP1) == "VERSION_GREATER" || + *(argP1) == "VERSION_EQUAL")) + { + def = cmIfCommand::GetVariableOrString(arg->c_str(), makefile); + def2 = cmIfCommand::GetVariableOrString((argP2)->c_str(), makefile); + Op op = OpEqual; + if(*argP1 == "VERSION_LESS") + { + op = OpLess; + } + else if(*argP1 == "VERSION_GREATER") + { + op = OpGreater; + } + bool result = HandleVersionCompare(op, def, def2); + HandleBinaryOp(result, + reducible, arg, newArgs, argP1, argP2); + } + // is file A newer than file B if (argP1 != newArgs.end() && argP2 != newArgs.end() && *(argP1) == "IS_NEWER_THAN") diff --git a/Source/cmIfCommand.h b/Source/cmIfCommand.h index 6c23aa0..bc84e56 100644 --- a/Source/cmIfCommand.h +++ b/Source/cmIfCommand.h @@ -177,6 +177,11 @@ public: " if(string STREQUAL string)\n" "True if the given string or variable's value is lexicographically " "less (or greater, or equal) than the string on the right.\n" + " if(version1 VERSION_LESS version2)\n" + " if(version1 VERSION_EQUAL version2)\n" + " if(version1 VERSION_GREATER version2)\n" + "Component-wise integer version number comparison (version format is " + "major[.minor[.patch[.tweak]]]).\n" " if(DEFINED variable)\n" "True if the given variable is defined. It does not matter if the " "variable is true or false just if it has been set."; diff --git a/Tests/FindPackageTest/CMakeLists.txt b/Tests/FindPackageTest/CMakeLists.txt index a3e24bb..1703fe7 100644 --- a/Tests/FindPackageTest/CMakeLists.txt +++ b/Tests/FindPackageTest/CMakeLists.txt @@ -145,3 +145,20 @@ IF(NOT "${Special_VERSION_MINOR}" STREQUAL "2") MESSAGE(SEND_ERROR "Package Special is minor version [${Special_VERSION_MINOR}], not [2]") ENDIF(NOT "${Special_VERSION_MINOR}" STREQUAL "2") + +# Test version number comparison. +IF(NOT "1.2.3.4" VERSION_LESS "1.2.3.5") + MESSAGE(SEND_ERROR "1.2.3.4 VERSION_LESS 1.2.3.5 is not true!") +ENDIF() +IF(NOT "1.2" VERSION_LESS "1.10") + MESSAGE(SEND_ERROR "1.2 VERSION_LESS 1.10 is not true!") +ENDIF() +IF(NOT "1.02" VERSION_GREATER "1.1") + MESSAGE(SEND_ERROR "1.02 VERSION_GREATER 1.1 is not true!") +ENDIF() +IF("1.2.3" VERSION_GREATER "1.2.3.4") + MESSAGE(SEND_ERROR "1.2.3 VERSION_GREATER 1.2.3.4 is not false!") +ENDIF() +IF(NOT "1.2" VERSION_EQUAL "1.2.0.0") + MESSAGE(SEND_ERROR "1.2 VERSION_EQUAL 1.2.0.0 is not true!") +ENDIF() -- cgit v0.12