Include Git commit hash and/or branch name in C/C++ source

…衆ロ難τιáo~ 提交于 2020-01-01 03:54:25

问题


I would like to know how you can get a Git commit hash and/or other information into the contents of a C++ variable in the compiled binary without having it be part of the source that's tracked by Git.

I need to keep track of firmware release information in a compiled executable running on an embedded processor. Means to identify the particular release of the firmware binary such as meaningful filenames, MD5 checksums or even date/time stamps are not available in this closed environment (i.e., there is no filesystem).

One approach is to have the device's console output produce identifying text, such as 'Release 1.2.3', 'commit hash 1bc123...', or similar. The firmware release information is only of interest to maintenance personnel, so a trained operator could examine the console output. To implement this it could potentially involve manual editing of a version string, which is then compiled into the code and output to the console at program startup.

This is acceptable for major releases where a signoff workflow is used to double-check that the version information is correct. However, this being a manual process it is inherently unreliable. For example, what if the developer forgets to update the version information? - There is now a disconnect between the compiled code and its reported version string.

A workflow where the code is freshly compiled and downloaded each time the user wants to test the hardware is not practical in the situation in question, ie., it is quite onerous to update the firmware.

An automatic way of identifying the version of the code is thus required. In the situation in question, Git is used, and the developers regularly commit their work to feature branches. Displaying the Git commit hash, and perhaps also whether or not there are unstaged changes, would be a way of identifying the status of the source code used to compile the firmware.

The requirement is that I would like my application to have information available to it so that it is able to display: "Git commit:[01abcdef...etc], branch: experimentalStuffDoNotRelease"

Thus, I would like to automatically include Git information, such as commit hash and branch, in the compiled C and/or C++ code.

The development environment has developers using both Windows and Linux, and uses Eclipse CDT with a relatively unsophisticated workflow of: check out; compile; download to the hardware.


回答1:


I use a makefile, like so:

GIT_HASH=`git rev-parse HEAD`
COMPILE_TIME=`date -u +'%Y-%m-%d %H:%M:%S UTC'`
GIT_BRANCH=`git branch | grep "^\*" | sed 's/^..//'`
export VERSION_FLAGS=-DGIT_HASH="\"$(GIT_HASH)\"" -DCOMPILE_TIME="\"$(COMPILE_TIME)\"" -DGIT_BRANCH="\"$(GIT_BRANCH)\""

all:
    g++ main.cpp $(VERSION_FLAGS)

When the makefile is run, the git hash and the time of compilation are both loaded into macros accessible within the source, like so:

#include <iostream>

int main(){
  std::cerr<<"hash="<<GIT_HASH<<", time="<<COMPILE_TIME<<", branch="<<GIT_BRANCH<<std::endl; 
}

Which gives output like:

hash=35f531bf1c959626e1b95f2d3e1a7d1e4c58e5ec, time=2017-05-18 04:17:25 UTC, branch=master



回答2:


In Eclipse CDT, use a pre-build step to generate an include file containing the relevant information, and a conditional inclusion to check that the file was created:

  1. Right-click the project
  2. Select Properties
  3. Expand the C/C++ Build
  4. Select Settings In the Build Steps tab
  5. Enter the following in the Command text box:

    git log --pretty=format:'#define GIT_INFO_PRESENT%n static const char*
    

    GIT_INFO = "Version Information=[%H,%d]\r\n";' -n 1 > ../src/gitcommit.h

    This will, upon build, create a file gitcommit.h that will be included in the source code. To customize it, adjust the string to your needs. (See https://git-scm.com/docs/pretty-formats)

As an example, I produce a debug output at the beginning of the main routine to inform the user of the commit and branch (not strictly needed knowing the commit, but certainly helpful):

  1. Put this in the file, probably at the top

    #if __has_include("gitcommit.h")
    #include "gitcommit.h"
    #else
    static const char* GIT_INFO = "Git version information not present.\r\n";
    #endif
    
  2. To display the information somewhere in your code, do similar to this:

    printf(GIT_INFO);
    

Note that I haven't, in this case, made the pre-build step a shell script or Windows/DOS .bat file, as I work often in Linux or Windows.

Note that this isn't tested in Windows.

In both cases, 'git' must be executable from the standard command line.

There is a dependency on provision of __has_include. This was intended to provide simplicity so that a default include file need not be provided.

Note that the gitcommit.h file's path should be discoverable by the compiler.




回答3:


Usually as part of your build you run some command that generates something like that. For example, git describe gives you something that you could use:

echo // auto generated version: > version.h
git describe > echo // auto generated version: > version.h
echo -e "#define VERSION " >> version.h
git describe >> version.h

For example x264 use this simple script to generate it:

if [ -d .git ] && command -v git >/dev/null 2>&1 ; then
    localver="$(($(git rev-list HEAD | wc -l)))"
    if [ "$localver" -gt 1 ] ; then
        ver_diff="$(($(git rev-list origin/master..HEAD | wc -l)))"
        ver="$((localver-ver_diff))"
        echo "#define X264_REV $ver"
        echo "#define X264_REV_DIFF $ver_diff"
        if [ "$ver_diff" -ne 0 ] ; then
            ver="$ver+$ver_diff"
        fi
        if git status | grep -q "modified:" ; then
            ver="${ver}M"
        fi
        ver="$ver $(git rev-list -n 1 HEAD | cut -c 1-7)"
        version=" r$ver"
    fi
fi

echo "#define X264_VERSION \"$version\""
echo "#define X264_POINTVER \"0.$ver\""

This will generate something like:

#define X264_VERSION  " r2708 86b7198"
#define X264_POINTVER "0.148.2708 86b7198"


来源:https://stackoverflow.com/questions/44038428/include-git-commit-hash-and-or-branch-name-in-c-c-source

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!