How can I pass git SHA1 to compiler as definition using cmake?

Łukasz Lew picture Łukasz Lew · Sep 17, 2009 · Viewed 24.2k times · Source

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?

Answer

Ryan Pavlik picture Ryan Pavlik · Nov 30, 2010

I've made some CMake modules that peer into a git repo for versioning and similar purposes - they're all in my repository at https://github.com/rpavlik/cmake-modules

The good thing about these functions is, they will force a re-configure (a rerun of cmake) before a build every time the HEAD commit changes. Unlike doing something just once with execute_process, you don't need to remember to re-cmake to update the hash definition.

For this specific purpose, you'd need at least the GetGitRevisionDescription.cmake and GetGitRevisionDescription.cmake.in files. Then, in your main CMakeLists.txt file, you'd have something like this

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/whereYouPutMyModules/")
include(GetGitRevisionDescription)
get_git_head_revision(GIT_REFSPEC GIT_SHA1)

Then, you could either add it as a system-wide definition (which unfortunately would cause lots of rebuilding)

add_definitions("-DGIT_SHA1=${GIT_SHA1}")

or, my suggested alternative: Make a generated source file. Create these two files in your source:

GitSHA1.cpp.in:

#define GIT_SHA1 "@GIT_SHA1@"
const char g_GIT_SHA1[] = GIT_SHA1;

GitSHA1.h:

extern const char g_GIT_SHA1[];

Add this to your CMakeLists.txt (assuming you have a list of source files in SOURCES):

configure_file("${CMAKE_CURRENT_SOURCE_DIR}/GitSHA1.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/GitSHA1.cpp" @ONLY)
list(APPEND SOURCES "${CMAKE_CURRENT_BINARY_DIR}/GitSHA1.cpp" GitSHA1.h)

Then, you have a global variable containing your SHA string - the header with the extern doesn't change when the SHA does, so you can just include that any place you want to refer to the string, and then only the generated CPP needs to be recompiled on every commit to give you access to the SHA everywhere.