tags:

views:

357

answers:

3

In a Makefile this would be done with something like:

g++ -DGIT_SHA1="`git log -1 | head -n 1`" ...

This is very useful, because the binary knows exact commit SHA1 so it can dump it in case of segfault.

How can I achieve the same with CMake?

+1  A: 

If CMake doesn't have a built-in capability to do this substitution, then you could write a wrapper shell script that reads a template file, substitutes the SHA1 hash as above in the correct location (using sed, for example), creates the real CMake build file, and then calls CMake to build your project.

A slightly different approach might be to make the SHA1 substitution optional. You would create the CMake file with a dummy hash value such as "NO_OFFICIAL_SHA1_HASH". When developers build their own builds from their working directories, the built code would not include a SHA1 hash value (only the dummy value) because the code from the working directory doesn't even have a corresponding SHA1 hash value yet.

On the other hand, when an official build is made by your build server, from sources pulled from a central repository, then you know the SHA1 hash value for the source code. At that point, you can substitute the hash value in the CMake file and then run CMake.

Greg Hewgill
+1  A: 

I can't help you with the CMake side, but with respect to Git side I would recommend taking a look how Linux kernel and Git project itself does it, via GIT-VERSION-GEN script, or how tig does it in its Makefile, by using git describe if there is git repository present, falling back to "version" / "VERSION" / "GIT-VERSION-FILE" generated and present in tarballs, finally falling back to default value hardcoded in script (or Makefile).

The first part (using git describe) requires that you tag releases using annotated (and possibly GPG signed) tags. Or use git describe --tags to use also lightweight tags.

Jakub Narębski
+2  A: 

I'd use sth. like this in my CMakeLists.txt:

exec_program(
    "git"
    ${CMAKE_CURRENT_SOURCE_DIR}
    ARGS "describe"
    OUTPUT_VARIABLE VERSION )

string( REGEX MATCH "-g.*$" VERSION_SHA1 ${VERSION} )
string( REGEX REPLACE "[-g]" "" VERSION_SHA1 ${VERSION_SHA1} )

add_definitions( -DGIT_SHA1="${VERSION_SHA1}" )
the Ritz