Phil CK

CMake - Bash Commands

Last updated on

In my main hobby project I store some information that gets used for logging, I’m not a huge fan of leaning on the build system for a bunch of reasons but this info I’ve found useful from time to time.

# Git Hash
set(CMD_GIT_HASH git log -1 --format=%h)
execute_process(
        COMMAND ${CMD_GIT_HASH}
        WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
        OUTPUT_VARIABLE GIT_HASH
        RESULT_VARIABLE ENV_RES
        ERROR_VARIABLE ENV_ERR
        OUTPUT_STRIP_TRAILING_WHITESPACE)

if(NOT ${ENV_RES} EQUAL 0)
    set(GIT_HASH "deadbeef")
    # We use deadbeef as it can be used as a hash.
    # This is mostly likely happed becasue dev has git installed on a different
    # bash, and the IDE regenerated the project with a different bash.
    # We also don't treat as error as this shouldn't be something to hold you up
    # on.
    message(STATUS "ENV: Error - Failed to get git hash, maybe git not installed on this bash")
endif()

message(STATUS "ENV: GIT HASH=${GIT_HASH}")
set_property(GLOBAL PROPERTY GIT_HASH_PROP ${GIT_HASH})

# Whoami

set(CMD_WHO whoami)
execute_process(
        COMMAND ${CMD_WHO}
        WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
        OUTPUT_VARIABLE WHO
        RESULT_VARIABLE ENV_RES
        ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)

if(NOT ${ENV_RES} EQUAL 0)
    set(WHO "unknown user")
    # This path shouldn't really ever happen. On both nix and windows 'whoami'
    # exists. This is just to honor the return variable.
    # We also don't treat as error as this shouldn't be something to hold you up
    # on.
    message(STATUS "ERR: Failed to get 'whoami' - maybe doesn't exist on this platform")
endif()

string(REPLACE "\\" "/" WHO ${WHO}) # Windows issue
message(STATUS "ENV: WHOAMI=${WHO}")
set_property(GLOBAL PROPERTY WHO_PROP ${WHO})

After I’ve got this information inside a CMakeLists that is generating a project I pass this information down in the form of a preprocessor command.

# Get the info
get_property(GIT_HASH_COMMIT GLOBAL PROPERTY GIT_HASH_PROP)
get_property(WHOAMI GLOBAL PROPERTY WHO_PROP)

target_compile_definitions(
        ${TARGET}
        PRIVATE
        "BUILD_NAME=\"${TARGET}\""
        "BUILD_STR=\"${WHOAMI}-${GIT_HASH_COMMIT}\""
        "BUILD_NUM=0x${GIT_HASH_COMMIT}")

I can then log this information out at runtime.

One word of caution, if you use something like git bash on Windows, then alter a CMakeLists.txt inside Visual Studio, Visual Studio will regenerate the project with a different Command Line, if git is not on that system default command line then this will fail, so you need to protect against that.