tags:

views:

78

answers:

3

With CMake I can get the svn revision using Subversion_WC_INFO. However, this only happens at configure time-- every subsequent make will use this cached revision.

I'd like to get the svn revision at build time (ie, every time make is run). How can I do this?

+1  A: 

I don't know of any CMake-specific functionality to do this, but it's easy enough to do yourself, as one of your build steps. Run svnversion from a script and parse its output, or (easier) run TortoiseSVN's subwcrev program (which has also been ported to other operating systems, so it's not Windows-specific).

Josh Kelley
+2  A: 

This is more of a pain to do than it needs to be. You can run a program at build time to extract the version information from subversion. CMake itself can be used as this program using its scripting language. You can run any CMake script using the -P command line flag. The piece of code to do this would be:

# the FindSubversion.cmake module is part of the standard distribution
include(FindSubversion)
# extract working copy information for SOURCE_DIR into MY_XXX variables
Subversion_WC_INFO(${SOURCE_DIR} MY)
# write a file with the SVNVERSION define
file(WRITE svnversion.h.txt "#define SVNVERSION ${MY_WC_REVISION}\n")
# copy the file to the final header only if the version changes
# reduces needless rebuilds
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different
                        svnversion.h.txt svnversion.h)

This extracts the subversion revision information and writes it to a header file. This header file is only updated when needed to avoid recompiling all the time. In your program, you would include that header file to get at the SVNVERSION define.

The CMakeLists.txt file that you would need to run the script would be something like this:

# boilerplate
cmake_minimum_required(VERSION 2.8)
project(testsvn)

# the test executable
add_executable(test main.c ${CMAKE_CURRENT_BINARY_DIR}/svnversion.h)

# include the output directory, where the svnversion.h file is generated
include_directories(${CMAKE_CURRENT_BINARY_DIR})

# a custom target that is always built
add_custom_target(svnheader ALL
    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/svnheader.h)

# creates svnheader.h using cmake script
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/svnheader.h
    COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}
                         -P ${CMAKE_CURRENT_SOURCE_DIR}/getsvn.cmake)

# svnversion.h is a generated file
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/svnversion.h
    PROPERTIES GENERATED TRUE
    HEADER_FILE_ONLY TRUE)

# explicitly say that the executable depends on the svnheader
add_dependencies(test svnheader)

You need to use add_custom_target and add_custom_command since there are no inputs to the svnheader.h file, it "appears from nowhere" to cmake. I already dealt with the issue of needless rebuilds in the getsvn.cmake file though, so rebuilding the "svnheader" target is basically a no-op if the subversion revision has not changed.

Finally, an example main.c file:

#include "svnversion.h"

int main(int argc, const char *argv[])
{
    printf("%d\n", SVNVERSION);
    return 0;
}
rq
Awesome answer. Didn't know that cmake scripts could be executed at build-time.
paleozogt
A: 

I'm actually looking for the same thing and I found this: howto-use-cmake-with-cc-projects It seems much simpler but I'm wondering if it is as efficient as rq's answer.

FBaralli