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

Viewed 31017

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?

10 Answers

Solution

Simply adding some code to only 2 files: CMakeList.txt and main.cpp.

1. CMakeList.txt

# git commit hash macro
execute_process(
  COMMAND git log -1 --format=%h
  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
  OUTPUT_VARIABLE GIT_COMMIT_HASH
  OUTPUT_STRIP_TRAILING_WHITESPACE
)
add_definitions("-DGIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\"")

2. main.cpp

inline void LogGitCommitHash() {
#ifndef GIT_COMMIT_HASH
#define GIT_COMMIT_HASH "0000000" // 0000000 means uninitialized
#endif
    std::cout << "GIT_COMMIT_HASH[" << GIT_COMMIT_HASH << "]"; // 4f34ee8
}

Explanation

In CMakeList.txt, the CMake commandexecute_process() is used to call command git log -1 --format=%h that give you the short and unique abbreviation for your SHA-1 values in string like 4f34ee8. This string is assigned to CMake variable called GIT_COMMIT_HASH. The CMake command add_definitions() defines the macro GIT_COMMIT_HASH to the value of 4f34ee8 just before gcc compilation. The hash value is used to replace the macro in C++ code by preprocessor, and hence exists in the object file main.o and in the compiled binaries a.out.

Side Note

Another way to achieve is to use CMake command called configure_file(), but I don't like to use it because the file does not exist before CMake is run.

Related