[CMake] Putting the git commit hash in a cmake variable
Elvis Stansvik
elvis.stansvik at orexplore.com
Thu Oct 11 13:38:23 EDT 2018
Den tors 11 okt. 2018 kl 18:28 skrev Matt Schulte <schultetwin1 at gmail.com>:
>
> Thanks Isaiah and Michael.
>
> Both solutions work great if you just want to generate a header file
> that contains the git commit hash. I have seen these solutions before.
> I'd like to go a little farther and have the current commit hash
> available in a CMake variable. This means CMake must re-configure if
> the commit hash changes. That's what I have setup in my example above,
> but it only works with cmake 3.12 and ninja 1.8.2. I was curious if
> anyone else has tried to store the results of an command line tool in
> a variable and make sure its always up to date by forcing cmake to
> reconfigure if the output of the command no longer matches what is
> stored in that variable.
We have something like this in MyAppVersion.cmake:
find_package(Git QUIET REQUIRED)
execute_process(
COMMAND "${GIT_EXECUTABLE}" describe --always HEAD
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE MYAPP_VERSION
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
set_property(GLOBAL APPEND
PROPERTY CMAKE_CONFIGURE_DEPENDS
"${CMAKE_SOURCE_DIR}/.git/index")
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+).*$"
"\\1;\\2;\\3" _ver_parts "${MYAPP_VERSION}")
list(GET _ver_parts 0 MYAPP_VERSION_MAJOR)
list(GET _ver_parts 1 MYAPP_VERSION_MINOR)
list(GET _ver_parts 2 MYAPP_VERSION_PATCH)
if("${MYAPP_VERSION}" MATCHES "^.*-(.*)-g.*$")
string(REGEX REPLACE "^.*-(.*)-g.*$" "\\1" MYAPP_VERSION_MICRO
"${MYAPP_VERSION}")
else()
set(MYAPP_VERSION_MICRO "0")
endif()
and include it in our CMakeLists.txt.
That makes the output of `git describe` availabe in the MYAPP_VERSION
CMake variable.
The trick to make it always current is to append to
CMAKE_CONFIGURE_DEPENDS the .git/index file, so that the project is
re-configured if the Git index file is touched.
Can't remember where I found this trick, but it has worked fine for us
ever since.
Elvis
> On Thu, Oct 11, 2018 at 5:55 AM Michael Jackson
> <mike.jackson at bluequartz.net> wrote:
> >
> > You could use a custom_target() instead, where that target is a simple shell/batch file that runs the needed git command and creates a simple header file. Then your main executable/library targets are dependent on that custom_target() so that it is run every time. We do something similar in our project. I added some "smarts" to it to at least compare the new output with the old output and only over write if they are different.
> >
> > --
> > Michael Jackson | Owner, President
> > BlueQuartz Software
> > [e] mike.jackson at bluequartz.net
> > [w] www.bluequartz.net <http://www.bluequartz.net>
> >
> > On 10/10/18, 5:05 PM, "CMake on behalf of Matt Schulte" <cmake-bounces at cmake.org on behalf of schultetwin1 at gmail.com> wrote:
> >
> > Hi all,
> >
> > 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.
> >
> > ```cmake
> > execute_process(
> > COMMAND
> > git rev-parse --short HEAD
> > RESULT_VARIABLE
> > SHORT_HASH_RESULT
> > OUTPUT_VARIABLE
> > SHORT_HASH)
> >
> > # If running in script mode (this runs on every build)
> > if (CMAKE_SCRIPT_MODE_FILE)
> > if (EXISTS "${SHORT_HASH_FILE}")
> > file(READ ${SHORT_HASH_FILE} READ_IN_SHORT_HASH)
> > else()
> > set(READ_IN_SHORT_HASH "")
> > endif()
> >
> > if (NOT ("${READ_IN_SHORT_HASH}" STREQUAL "${SHORT_HASH}"))
> > message(STATUS "Short hash is out of date")
> > # This will update short_hash.txt, causing cmake to reconfigure
> > file(WRITE ${SHORT_HASH_FILE} ${SHORT_HASH})
> > endif()
> >
> > # Else running as part of cmake configure
> > else()
> > set(SHORT_HASH_FILE ${CMAKE_CURRENT_BINARY_DIR}/short_hash.txt)
> > file(WRITE ${SHORT_HASH_FILE} ${SHORT_HASH})
> >
> > # The trick here is to make sure short_hash.txt is listed as a byproduct
> > add_custom_target(
> > git_short_hash
> > BYPRODUCTS
> > ${SHORT_HASH_FILE}
> > COMMAND
> > ${CMAKE_COMMAND}
> > "-DSHORT_HASH_FILE=${SHORT_HASH_FILE}"
> > "-P" "${CMAKE_CURRENT_LIST_FILE}"
> > COMMENT
> > "Re-checking short hash..."
> > VERBATIM
> > USES_TERMINAL)
> >
> > # This configure_file makes cmake reconfigure dependent on short_hash.txt
> > configure_file(${SHORT_HASH_FILE} ${SHORT_HASH_FILE}.junk COPYONLY)
> >
> > message(STATUS "Short Hash: ${SHORT_HASH}")
> > endif()
> > ```
> >
> > This works great with cmake 3.12 and ninja 1.8.2! (I was really happy
> > with how well it worked. I tip my hat to the cmake developers for
> > this). However, it doesn't work with Makefiles, and causes ninja 1.7.2
> > to get stuck in an infinite loop. On CMake 3.10 this will cause ninja
> > 1.8.2 to generate a warning about a loop.
> >
> > Has anyone run into this issue before and have a better solution? Or
> > is trying to execute a command before cmake checks if it should
> > reconfigure a hack that should never be done?
> >
> > Thanks for the help!
> > Matt
> > --
> >
> > Powered by www.kitware.com
> >
> > Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ
> >
> > Kitware offers various services to support the CMake community. For more information on each offering, please visit:
> >
> > CMake Support: http://cmake.org/cmake/help/support.html
> > CMake Consulting: http://cmake.org/cmake/help/consulting.html
> > CMake Training Courses: http://cmake.org/cmake/help/training.html
> >
> > Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html
> >
> > Follow this link to subscribe/unsubscribe:
> > https://cmake.org/mailman/listinfo/cmake
> >
> >
> >
> --
>
> Powered by www.kitware.com
>
> Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ
>
> Kitware offers various services to support the CMake community. For more information on each offering, please visit:
>
> CMake Support: http://cmake.org/cmake/help/support.html
> CMake Consulting: http://cmake.org/cmake/help/consulting.html
> CMake Training Courses: http://cmake.org/cmake/help/training.html
>
> Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html
>
> Follow this link to subscribe/unsubscribe:
> https://cmake.org/mailman/listinfo/cmake
More information about the CMake
mailing list