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

Michael Jackson mike.jackson at bluequartz.net
Thu Oct 11 08:54:59 EDT 2018


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
    




More information about the CMake mailing list