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?
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?
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.
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.
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}" )