简体   繁体   中英

Split string to 3 variables in CMake

I have a program version variable

set(MY_PROGRAM_VERSION "2.5.1")

and I want to save 2,5,1 to 3 different variables, like

MY_PROGRAM_VERSION_MAJOR=2
MY_PROGRAM_VERSION_MINOR=5
MY_PROGRAM_VERSION_PATCH=1

But I really don't know how to access single elements in a CMake list. Some idea?

According to this and this i would guess you need to transform the string to something like a list literal and use GET on your new list:

cmake_minimum_required(VERSION 2.8)

set(MY_PROGRAM_VERSION "2.5.1")

string(REPLACE "." ";" VERSION_LIST ${MY_PROGRAM_VERSION})
list(GET VERSION_LIST 0 MY_PROGRAM_VERSION_MAJOR)
list(GET VERSION_LIST 1 MY_PROGRAM_VERSION_MINOR)
list(GET VERSION_LIST 2 MY_PROGRAM_VERSION_PATCH)

You can use the following helper function to automatically have the version component variables set up:

macro (setup_package_version_variables _packageName)
    if (DEFINED ${_packageName}_VERSION)
        string (REGEX MATCHALL "[0-9]+" _versionComponents "${${_packageName}_VERSION}")
        list (LENGTH _versionComponents _len)
        if (${_len} GREATER 0)
            list(GET _versionComponents 0 ${_packageName}_VERSION_MAJOR)
        endif()
        if (${_len} GREATER 1)
            list(GET _versionComponents 1 ${_packageName}_VERSION_MINOR)
        endif()
        if (${_len} GREATER 2)
            list(GET _versionComponents 2 ${_packageName}_VERSION_PATCH)
        endif()
        if (${_len} GREATER 3)
            list(GET _versionComponents 3 ${_packageName}_VERSION_TWEAK)
        endif()
        set (${_packageName}_VERSION_COUNT ${_len})
    else()
        set (${_packageName}_VERSION_COUNT 0)
        set (${_packageName}_VERSION "")
    endif()
endmacro()

The macro can be invoked in the following way:

set(MY_PROGRAM_VERSION "2.5.1")
setup_package_version_variables(MY_PROGRAM)

The macro also sets MY_PROGRAM_VERSION_COUNT to the number of version components and MY_PROGRAM_VERSION_TWEAK if the version number has 4 components (eg, "2.5.1.0")

CMake's string command is the way to go here.

In case you set the value of the variable yourself and don't get it from some third-party source, you might want to use this approach instead:

function(SetVersionNumber PREFIX VERSION_MAJOR VERSION_MINOR VERSION_PATCH)
  set(${PREFIX}_VERSION_MAJOR ${VERSION_MAJOR} PARENT_SCOPE)
  set(${PREFIX}_VERSION_MINOR ${VERSION_MINOR} PARENT_SCOPE)
  set(${PREFIX}_VERSION_PATCH ${VERSION_PATCH} PARENT_SCOPE)
  set(${PREFIX}_VERSION
        "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}"
        PARENT_SCOPE)
endfunction()

[...]

SetVersionNumber(MY_PROGRAM 2 5 1)
message(${MY_PROGRAM_VERSION_MAJOR})
message(${MY_PROGRAM_VERSION_MINOR})
message(${MY_PROGRAM_VERSION_PATCH})
message(${MY_PROGRAM_VERSION})

Saves you from having to do regex voodoo ;)

I use this function to get package name and versions.

Text after patch level is skipped. (libA-v1.2.3-THIS_IS_SKIPPED)

function(get_versions versionstring libname major minor patch)
    string(REGEX REPLACE "([A-Za-z0-9_]*)-[vV].*" "\\1" locallibname ${versionstring} )
    set(libname ${locallibname} PARENT_SCOPE)
    string(REGEX REPLACE "^([A-Za-z0-9_]*-[vV])([0-9]*)([.][0-9]*[.][0-9]*-?.*)$" "\\2" numbers ${versionstring} )
    set(major ${numbers} PARENT_SCOPE)
    string(REGEX REPLACE "^([A-Za-z0-9_]*-[vV][0-9]*[.])([0-9]*)([.][0-9]*-?.*)$" "\\2" numbers ${versionstring} )
    set(minor ${numbers} PARENT_SCOPE)
    string(REGEX REPLACE "^([A-Za-z0-9_]*-[vV][0-9]*[.][0-9]*[.])([0-9]*)(-?.*)$" "\\2" numbers ${versionstring} )
    set(patch ${numbers} PARENT_SCOPE)
endfunction()

Usage:

get_versions("TTN9Lib-V0.1.18" libname major minor patch)

See details cmake_parse_versionstring.html

Here is one more option that is pretty clean:

string(REGEX MATCH "^([0-9]+)\\.([0-9]+)\\.([0-9]+)"
       MY_PROGRAM_VERSION_MATCH ${MY_PROGRAM_VERSION})
set(MY_PROGRAM_VERSION_MAJOR ${CMAKE_MATCH_1})
set(MY_PROGRAM_VERSION_MINOR ${CMAKE_MATCH_2})
set(MY_PROGRAM_VERSION_PATCH ${CMAKE_MATCH_3})

Note that MY_PROGRAM_VERSION_MATCH is the full match ( CMAKE_MATCH_0 ) and you can just ignore it as you don't need it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM