Putting the git commit hash in a cmake variable

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Putting the git commit hash in a cmake variable

Matt Schulte
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
Reply | Threaded
Open this post in threaded view
|

Re: Putting the git commit hash in a cmake variable

Isaiah Norton
Similar question with some suggestions in response:


Best,
Isaiah

On Wed, Oct 10, 2018 at 5:05 PM Matt Schulte <[hidden email]> 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
Reply | Threaded
Open this post in threaded view
|

Re: Putting the git commit hash in a cmake variable

Michael Jackson
In reply to this post by Matt Schulte
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] [hidden email]
[w] www.bluequartz.net <http://www.bluequartz.net>

On 10/10/18, 5:05 PM, "CMake on behalf of Matt Schulte" <[hidden email] on behalf of [hidden email]> 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
Reply | Threaded
Open this post in threaded view
|

Re: Putting the git commit hash in a cmake variable

Matt Schulte
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.
On Thu, Oct 11, 2018 at 5:55 AM Michael Jackson
<[hidden email]> 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] [hidden email]
> [w] www.bluequartz.net <http://www.bluequartz.net>
>
> On 10/10/18, 5:05 PM, "CMake on behalf of Matt Schulte" <[hidden email] on behalf of [hidden email]> 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
Reply | Threaded
Open this post in threaded view
|

Re: Putting the git commit hash in a cmake variable

Elvis Stansvik
Den tors 11 okt. 2018 kl 18:28 skrev Matt Schulte <[hidden email]>:

>
> 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
> <[hidden email]> 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] [hidden email]
> > [w] www.bluequartz.net <http://www.bluequartz.net>
> >
> > On 10/10/18, 5:05 PM, "CMake on behalf of Matt Schulte" <[hidden email] on behalf of [hidden email]> 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
--

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
Reply | Threaded
Open this post in threaded view
|

Re: Putting the git commit hash in a cmake variable

Chuck Atkins

    COMMAND "${GIT_EXECUTABLE}" describe --always HEAD

git describe is nice way to do it since you can get a monotonic-ish increasing version number

 
    string(REGEX REPLACE "^.*-(.*)-g.*$" "\\1" MYAPP_VERSION_MICRO "${MYAPP_VERSION}")
...
    set(MYAPP_VERSION_MICRO "0")

Only tangentially related, CMake commands and functions that deal with version information refer to the 4th component as _TWEAK.

- Chuck


--

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
Reply | Threaded
Open this post in threaded view
|

Re: Putting the git commit hash in a cmake variable

Matt Schulte
Ah, that's a good tip Elvis. The CONFIGURE_DEPENDS on the .git/index
would do the trick. I can set that up for now.

In the long run, its not that ideal because it forces a reconfigure on
every commit (which is annoying for developers at their desk).

My example above is actually a little more complex in real life. I
just simplified it for this e-mail. We only append the git hash to our
version string if we are on certain branches. So our version string
doesn't change on feature branches.

For now I think we'll bite the bullet and re-configure on every
commit. I'll keep mulling over the how to set this up. Thanks for the
idea!

-Matt
On Thu, Oct 11, 2018 at 12:26 PM Chuck Atkins <[hidden email]> wrote:

>
>
>>     COMMAND "${GIT_EXECUTABLE}" describe --always HEAD
>
>
> git describe is nice way to do it since you can get a monotonic-ish increasing version number
>
>
>>
>>     string(REGEX REPLACE "^.*-(.*)-g.*$" "\\1" MYAPP_VERSION_MICRO "${MYAPP_VERSION}")
>> ...
>>     set(MYAPP_VERSION_MICRO "0")
>
>
> Only tangentially related, CMake commands and functions that deal with version information refer to the 4th component as _TWEAK.
>
> - Chuck
>
--

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
Reply | Threaded
Open this post in threaded view
|

Re: Putting the git commit hash in a cmake variable

Elvis Stansvik
Den fre 12 okt. 2018 00:24Matt Schulte <[hidden email]> skrev:
Ah, that's a good tip Elvis. The CONFIGURE_DEPENDS on the .git/index
would do the trick. I can set that up for now.

In the long run, its not that ideal because it forces a reconfigure on
every commit (which is annoying for developers at their desk).

My example above is actually a little more complex in real life. I
just simplified it for this e-mail. We only append the git hash to our
version string if we are on certain branches. So our version string
doesn't change on feature branches.

For now I think we'll bite the bullet and re-configure on every
commit. I'll keep mulling over the how to set this up. Thanks for the
idea!

Yes, I should have mentioned this downside. In our case it was acceptable as our configuration step is rather quick.

Tangential note from me re. developer experience: Yesterday I tried out zapcc for local development, and it really is fast:


Takes a bit of memory of course.

Elvis

-Matt
On Thu, Oct 11, 2018 at 12:26 PM Chuck Atkins <[hidden email]> wrote:
>
>
>>     COMMAND "${GIT_EXECUTABLE}" describe --always HEAD
>
>
> git describe is nice way to do it since you can get a monotonic-ish increasing version number
>
>
>>
>>     string(REGEX REPLACE "^.*-(.*)-g.*$" "\\1" MYAPP_VERSION_MICRO "${MYAPP_VERSION}")
>> ...
>>     set(MYAPP_VERSION_MICRO "0")
>
>
> Only tangentially related, CMake commands and functions that deal with version information refer to the 4th component as _TWEAK.
>
> - Chuck
>

--

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
Reply | Threaded
Open this post in threaded view
|

Re: Putting the git commit hash in a cmake variable

Ben Boeckel-2
In reply to this post by Matt Schulte
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
--

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
Reply | Threaded
Open this post in threaded view
|

Re: Putting the git commit hash in a cmake variable

Ryan Pavlik
Fwiw, this is my single most popular stack overflow post (and presumably my most popular CMake module) https://stackoverflow.com/questions/1435953/how-can-i-pass-git-sha1-to-compiler-as-definition-using-cmake/4318642#4318642

It does incorporate the other ideas that have come up, like making a dependency on a git data file.

Ryan

On Fri, Oct 12, 2018, 10:33 AM Ben Boeckel <[hidden email]> wrote:
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
--

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