[CMake] Putting the git commit hash in a cmake variable

Ben Boeckel ben.boeckel at kitware.com
Fri Oct 12 11:33:27 EDT 2018


Sorry if this shows up oddly on the list; I was forwarded the original
in order to reply. As such, please keep me in Cc.

> I'd like to set a CMake variable to the current git commit short hash.
> This variable will be used as part of the version string for my
> project (ex: "1.0.1+git.${SHORT_HASH}"). I can get at this short hash
> by using execute_process and setting the resulting output to a
> variable.
> 
> ```cmake
> execute_process(
>     COMMAND
>         git rev-parse --short HEAD
>     RESULT_VARIABLE
>         SHORT_HASH_RESULT
>     OUTPUT_VARIABLE
>         SHORT_HASH)
> ```
> 
> My issue is that cmake will only run execute_process once, during the
> configure step. I need cmake to run this execute_process on every
> build and, if the output has changed, reconfigure to make sure
> SHORT_HASH is up to date.
> 
> I came up with one solution to this issue: During the configure step,
> I can write the current short hash to a file named short_hash.txt. On
> every build, I'll re-compute the short hash and verify that the
> computed short hash is the same as what is in short_hash.txt. If its
> not, I'll write the new short hash to short_hash.txt. I then make
> short_hash.txt an input to configure_file. This will cause cmake to
> validate SHORT_HASH is properly set, and re-configure if its not.

I solved this a few years ago :) . Here are all the relevant files:

    https://github.com/Kitware/sprokit/blob/master/src/sprokit/version.h.in
    https://github.com/Kitware/sprokit/blob/master/src/sprokit/.gitattributes
    https://github.com/Kitware/sprokit/blob/master/src/sprokit/CMakeLists.txt
    https://github.com/Kitware/sprokit/blob/master/conf/sprokit-macro-configure.cmake

Basically the solution follows:

  - If we're in an archive (.gitattributes' export-subst), use the
    information from it. Detect this in CMake by checking if Git
    replaced substitutions for us:

        if ("$Format:$" STREQUAL "")

    If we are, just use that information (gathered using other
    `$Format:$` expansions).
  - If not, we set up some code to run at build time to extract the
    information.
  - The variables (or code) from above is injected via
    `sprokit_configure_file_always` which basically is just a
    `configure_file` done at build time. The list of variables to export
    to the script are listed as arguments. The `_always` bit just adds
    an extra output file named `${output}.noexist` which causes tools to
    always run the associated custom command (which is then attached to
    a custom target via its output file).

The file is only updated if the contents change (via `configure_file`),
so rebuilding should be minimal.

--Ben


More information about the CMake mailing list