[CMake] Revision header

Michael Hertling mhertling at online.de
Tue Jan 24 00:05:01 EST 2012


On 01/21/2012 10:51 PM, Oliver Smith wrote:
> I have a script that generates a revision.h file, I've spent the morning 
> trying to figure out how to make it so that ... any time CMake rebuilds 
> any of the other targets, it starts by running the make-new-revision script.
> 
> The idea is, I use the script manually to upversion, but anytime I type 
> "make" and /anything/ has to be done (even just a relink), it will do 
> the upversion first.
> 
> I've only managed to make it either source dependent or always build, 
> which forces the versionNo file to recompile and forces all executables 
> to relink, so if you type:
> 
> make ; make ... it will have to relink the executables the second time 
> because of an pointless upversion :)
> 
> - Oliver

There might be a solution for your concern, but it's probably somewhat
fragile; look at the following exemplary project for a demonstration:

# CMakeLists.txt:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(P C)
SET(CMAKE_VERBOSE_MAKEFILE ON)
SET(VERSIONHEADERIN ${CMAKE_SOURCE_DIR}/version.h.in)
SET(VERSIONHEADER ${CMAKE_BINARY_DIR}/version.h)
SET(VERSIONFILE ${CMAKE_BINARY_DIR}/version.txt)
IF(NOT EXISTS ${VERSIONFILE})
    FILE(WRITE ${VERSIONFILE} "0\n")
ENDIF()
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR})
ADD_EXECUTABLE(main main.c)
ADD_CUSTOM_TARGET(version
    ${CMAKE_COMMAND}
        -DVERSIONHEADERIN=${VERSIONHEADERIN}
        -DVERSIONHEADER=${VERSIONHEADER}
        -DVERSIONFILE=${VERSIONFILE}
        -P ${CMAKE_SOURCE_DIR}/version.cmake)
ADD_DEPENDENCIES(main version)
ADD_CUSTOM_TARGET(upversion
    ${CMAKE_COMMAND}
        -DVERSIONFILE=${VERSIONFILE}
        -P ${CMAKE_SOURCE_DIR}/upversion.cmake)

# version.cmake:
FILE(STRINGS ${VERSIONFILE} VERSION)
EXECUTE_PROCESS(
    COMMAND make -n VERBOSE=
    COMMAND grep "Linking"
    RESULT_VARIABLE GREPPED
)
IF(GREPPED EQUAL 0)
    # Something will be done, thus:
    MATH(EXPR VERSION "${VERSION}+1")
    FILE(WRITE ${VERSIONFILE} "${VERSION}\n")
ENDIF()
CONFIGURE_FILE(${VERSIONHEADERIN} ${VERSIONHEADER} @ONLY)

# upversion.cmake:
FILE(STRINGS ${VERSIONFILE} VERSION)
MATH(EXPR VERSION "${VERSION}+1")
FILE(WRITE ${VERSIONFILE} "${VERSION}\n")

/* version.h.in: */
#define VERSION @VERSION@

/* main.c: */
#include "version.h"
#include <stdio.h>
int main(void)
{
    printf("VERSION: %d\n",VERSION);
}

The basic idea is to run "make -n" (version.cmake), scan the output for
strings indicating an upcoming rebuild ("Linking"), increment a version
number accordingly (version.txt) and generate a version header in the
end (version.h.in). Anything else is done via the usual dependency
tracking. Additionally, the upversion.cmake script allows for
incrementing the version number manually.

Perhaps, you can adapt the approach to your needs. However, the critical
moment is how to detect if any actions which require the version number
to be incremented are going to happen. The example uses "make -n" and
"grep" for this purpose, but that's fragile, of course, as I remarked
at the outset.

Regards,

Michael


More information about the CMake mailing list