Skip to content

GitLab

  • Menu
Projects Groups Snippets
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • Community Community
  • Project information
    • Project information
    • Activity
    • Members
  • Analytics
    • Analytics
    • Value stream
  • Wiki
    • Wiki
  • Activity
Collapse sidebar
  • CMake
  • CommunityCommunity
  • Wiki
  • Contrib
  • Macros
  • CompareVersionStrings

CompareVersionStrings · Changes

Page history
Organize page layout after conversion from mediawiki authored Apr 27, 2018 by Kitware Robot's avatar Kitware Robot
Organize pages into directories and shorter file names.  Use lower-case
names for directories and capitalized names for files.  This produces a
pleasing sort order in the GitLab Wiki navigation page.

Also rename entry page `CMake.md` to `Home.md` to match GitLab Wiki
conventions.
Hide whitespace changes
Inline Side-by-side
contrib/macros/CompareVersionStrings.md 0 → 100644
View page @ d523de26
**CAUTION: The contents of this page may be obsolete**
![120px-Old_finnish_stop_sign.svg](/uploads/521180f925eeefd545a3a7a761185c2e/120px-Old_finnish_stop_sign.svg.png)
----
Please see the **VERSION_LESS**, **VERSION_EQUAL**, and
**VERSION_GREATER** options to the IF() command.
-----
I needed a way to compare two version strings to make sure that I had a
version of a package that was sufficient for my needs. The first go
around I used regular expressions to pull out all the dot versions,
create a number, and finally compare the number.
SET(THREE_PART_VERSION_REGEX "[0-9]+\\.[0-9]+\\.[0-9]+")
# Breaks up a string in the form n1.n2.n3 into three parts and stores
# them in major, minor, and patch. version should be a value, not a
# variable, while major, minor and patch should be variables.
MACRO(THREE_PART_VERSION_TO_VARS version major minor patch)
IF(${version} MATCHES ${THREE_PART_VERSION_REGEX})
STRING(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+" "\\1" ${major} "${version}")
STRING(REGEX REPLACE "^[0-9]+\\.([0-9])+\\.[0-9]+" "\\1" ${minor} "${version}")
STRING(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+)" "\\1" ${patch} "${version}")
ELSE(${version} MATCHES ${THREE_PART_VERSION_REGEX})
MESSAGE("MACRO(THREE_PART_VERSION_TO_VARS ${version} ${major} ${minor} ${patch}")
MESSAGE(FATAL_ERROR "Problem parsing version string, I can't parse it properly.")
ENDIF(${version} MATCHES ${THREE_PART_VERSION_REGEX})
ENDMACRO(THREE_PART_VERSION_TO_VARS)
THREE_PART_VERSION_TO_VARS(${version-string} major_vers minor_vers patch_vers)
MESSAGE("version = ${major_vers}.${minor_vers}.${patch_vers}")
# Compute a version number
MATH(EXPR version_number "${major_vers} * 1000000 + ${minor_vers} * 1000 + ${patch_vers}" )
MESSAGE("version_number = ${version_number}")
This was somewhat cumbersome, and was hard coded for three dot versions
(x.y.z). I wanted to be able to use a single macro for version strings
with 1 to any number of dot versions. In addition I wanted to be able to
compare version strings with different number of dot versions (i.e.
0.99.1 and 0.99.1.2).
# Computes the realtionship between two version strings. A version
# string is a number delineated by '.'s such as 1.3.2 and 0.99.9.1.
# You can feed version strings with different number of dot versions,
# and the shorter version number will be padded with zeros: 9.2 <
# 9.2.1 will actually compare 9.2.0 < 9.2.1.
#
# Input: a_in - value, not variable
# b_in - value, not variable
# result_out - variable with value:
# -1 : a_in < b_in
# 0 : a_in == b_in
# 1 : a_in > b_in
#
# Written by James Bigler.
MACRO(COMPARE_VERSION_STRINGS a_in b_in result_out)
# Since SEPARATE_ARGUMENTS using ' ' as the separation token,
# replace '.' with ' ' to allow easy tokenization of the string.
STRING(REPLACE "." " " a ${a_in})
STRING(REPLACE "." " " b ${b_in})
SEPARATE_ARGUMENTS(a)
SEPARATE_ARGUMENTS(b)
# Check the size of each list to see if they are equal.
LIST(LENGTH a a_length)
LIST(LENGTH b b_length)
# Pad the shorter list with zeros.
# Note that range needs to be one less than the length as the for
# loop is inclusive (silly CMake).
IF(a_length LESS b_length)
# a is shorter
SET(shorter a)
MATH(EXPR range "${b_length} - 1")
MATH(EXPR pad_range "${b_length} - ${a_length} - 1")
ELSE(a_length LESS b_length)
# b is shorter
SET(shorter b)
MATH(EXPR range "${a_length} - 1")
MATH(EXPR pad_range "${a_length} - ${b_length} - 1")
ENDIF(a_length LESS b_length)
# PAD out if we need to
IF(NOT pad_range LESS 0)
FOREACH(pad RANGE ${pad_range})
# Since shorter is an alias for b, we need to get to it by by dereferencing shorter.
LIST(APPEND ${shorter} 0)
ENDFOREACH(pad RANGE ${pad_range})
ENDIF(NOT pad_range LESS 0)
SET(result 0)
FOREACH(index RANGE ${range})
IF(result EQUAL 0)
# Only continue to compare things as long as they are equal
LIST(GET a ${index} a_version)
LIST(GET b ${index} b_version)
# LESS
IF(a_version LESS b_version)
SET(result -1)
ENDIF(a_version LESS b_version)
# GREATER
IF(a_version GREATER b_version)
SET(result 1)
ENDIF(a_version GREATER b_version)
ENDIF(result EQUAL 0)
ENDFOREACH(index)
# Copy out the return result
SET(${result_out} ${result})
ENDMACRO(COMPARE_VERSION_STRINGS)
I tested it with the following input:
# a and b need to be passed in by value
MACRO(COMPARE_VERSION a b)
COMPARE_VERSION_STRINGS(${a} ${b} result)
IF(result LESS 0)
MESSAGE("${a} < ${b}")
ELSE(result LESS 0)
IF(result GREATER 0)
MESSAGE("${a} > ${b}")
ELSE(result GREATER 0)
MESSAGE("${a} == ${b}")
ENDIF(result GREATER 0)
ENDIF(result LESS 0)
ENDMACRO(COMPARE_VERSION)
SET(version-string "1.3.31")
COMPARE_VERSION(${version-string} "1.3.30")
COMPARE_VERSION(${version-string} "1.3.31")
COMPARE_VERSION(${version-string} "1.3.32")
COMPARE_VERSION(${version-string} "1.2.32")
COMPARE_VERSION(${version-string} "1.10.1")
COMPARE_VERSION("9.2" "9.1")
COMPARE_VERSION("9.2" "9.2")
COMPARE_VERSION("9.2" "9.3")
COMPARE_VERSION("9.1" "9.2")
COMPARE_VERSION("9.2" "9.2")
COMPARE_VERSION("9.3" "9.2")
COMPARE_VERSION("9.10" "9.2")
COMPARE_VERSION("9.2" "9.10")
COMPARE_VERSION("0.92.1.0" "0.92.1.1")
COMPARE_VERSION("0.92.1.1" "0.92.1.1")
COMPARE_VERSION("0.92.1.2" "0.92.1.1")
COMPARE_VERSION("0.92.1.2" "0.99.1.1")
COMPARE_VERSION("0.99.1.2" "0.92.1.1")
COMPARE_VERSION("0.92.1.2" "0.99.1")
COMPARE_VERSION("0.99.1" "0.92.1.1")
COMPARE_VERSION("0.99.1.2" "0.99.1")
COMPARE_VERSION("0.99.1" "0.99.1.1")
COMPARE_VERSION( "1" "10")
COMPARE_VERSION("10" "1")
Here's the output:
1.3.31 > 1.3.30
1.3.31 == 1.3.31
1.3.31 < 1.3.32
1.3.31 > 1.2.32 (note this is 1.2 not 1.3)
1.3.31 < 1.10.1
9.2 > 9.1
9.2 == 9.2
9.2 < 9.3
9.1 < 9.2
9.2 == 9.2
9.3 > 9.2
9.10 > 9.2
9.2 < 9.10
0.92.1.0 < 0.92.1.1
0.92.1.1 == 0.92.1.1
0.92.1.2 > 0.92.1.1
0.92.1.2 < 0.99.1.1
0.99.1.2 > 0.92.1.1
0.92.1.2 < 0.99.1
0.99.1 > 0.92.1.1
0.99.1.2 > 0.99.1
0.99.1 < 0.99.1.1
1 < 10
10 > 1
----
This page was initially populated by conversion from its [original location](https://public.kitware.com/Wiki/CMakeCompareVersionStrings) in another wiki.
Clone repository
  • CMake Versions on Linux Distros
  • Contrib
  • Editing Guidelines
  • FAQ
  • Home
  • contrib
    • macros
      • AddCxxTest
      • CompareVersionStrings
      • CopyIfDifferent
      • CreateFinalFile
      • FilterOut
      • ForceAddFlags
      • GatherProjectFiles
      • GenerateProject
      • LibtoolFile
      • ListOperations
View All Pages