Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake: Get version from multiline text file

I have a file version.txt

VERSION_MAJOR 1
VERSION_MINOR 1
VERSION_PATCH 3

I want to use cmake to add a definition for major, minor and patch.

I've tries using

file(STRING "version.txt" myvar)

but this just puts the whole file in myvar.

How do I get the numbers?

like image 324
Maggick Avatar asked Nov 02 '17 01:11

Maggick


People also ask

How to Comment in cmakelist txt?

There is no notion of a block comment in CMake syntax. However, to comment several lines at once, select the required lines and hit CTRL + Q . If the file is a . txt file (e.g. CMakeLists.

What is ${} in CMake?

Local Variables You access a variable by using ${} , such as ${MY_VARIABLE} . 1. CMake has the concept of scope; you can access the value of the variable after you set it as long as you are in the same scope. If you leave a function or a file in a sub directory, the variable will no longer be defined.

What is a .CMake file?

A CMAKE file is a project file created by the open-source, cross-platform tool CMake. It contains source script in the CMake language for the entire program. CMake tool uses programming scripts, known as CMakeLists, to generate build files for a specific environment such as makefiles Unix machine.


1 Answers

Your use of file is incorrect, you want to use READ in order to read the contents of the file into a variable.

file(READ "version.txt" ver)

Once you have the file's contents into a variable, you can then use REGEX MATCH with a capture group, and access the capture group using CMAKE_MATCH_N

REGEX MATCH:

Create a regular expression with a capture group which will capture the numbers following "VERSION_MAJOR":

string(REGEX MATCH "VERSION_MAJOR ([0-9]*)" _ ${ver})

Note that if the regex matches the input variable, the entire match will be stored in the output variable. However, we don't want the entire match (as that includes the string "VERSION_MAJOR"), so I've just used a variable name _ as the output variable, which, by convention, tells the user I am not interested in this variable

CMAKE_MATCH_N:

If the match is successful, then the capture groups are available in CMAKE_MATCH_N. In this instance there is only one capture group, so we want to use CMAKE_MATCH_1

set(ver_major ${CMAKE_MATCH_1})

At this point ver_major contains just the major version no.

You can then repeat this for the other version components.

Full example below:

cmake_minimum_required(VERSION 3.5)

file(READ "version.txt" ver)

string(REGEX MATCH "VERSION_MAJOR ([0-9]*)" _ ${ver})
set(ver_major ${CMAKE_MATCH_1})

string(REGEX MATCH "VERSION_MINOR ([0-9]*)" _ ${ver})
set(ver_minor ${CMAKE_MATCH_1})

string(REGEX MATCH "VERSION_PATCH ([0-9]*)" _ ${ver})
set(ver_patch ${CMAKE_MATCH_1})

message("version: ${ver_major}.${ver_minor}.${ver_patch}")

Output:

$ cmake .
version: 1.1.3
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp

For production code you would obviously want to make the cmake script more robust by checking whether the match was successful, and emitting an error if not.

like image 186
Steve Lorimer Avatar answered Sep 20 '22 19:09

Steve Lorimer