在C / C ++源代码中包含Git提交哈希和/或分支名称
我想知道如何将Git提交哈希和/或其他信息添加到已编译二进制文件中的C ++变量的内容中,而不必将其作为Git跟踪的源代码的一部分。
我需要在嵌入式处理器上运行的已编译可执行文件中跟踪固件发布信息。 识别固件二进制文件的特定版本的方法,例如有意义的文件名,MD5校验和甚至日期/时间戳,在这个封闭的环境中是不可用的(即,没有文件系统)。
一种方法是让设备的控制台输出产生识别文本,例如“版本1.2.3”,“提交哈希1bc123 ……”或类似文本。 固件发布信息仅供维护人员使用,因此经过培训的操作员可以检查控制台输出。 为了实现这一点,它可能涉及手动编辑版本字符串,然后将其编译为代码并在程序启动时输出到控制台。
对于使用签核工作流程来仔细检查版本信息是否正确的主要版本,这是可以接受的。 然而,这是一个手动过程,它本质上是不可靠的。 例如,如果开发人员忘记更新版本信息怎么办? – 现在编译的代码与其报告的版本字符串之间存在脱节。
每次用户想要测试硬件时新编译和下载代码的工作流程在所讨论的情况下是不实际的,即,更新固件是相当繁重的。
因此需要一种识别代码版本的自动方法。 在这种情况下,使用Git,开发人员定期将他们的工作提交给function分支。 显示Git提交哈希,以及可能还有未分级更改,将是一种识别用于编译固件的源代码状态的方法。
要求是我希望我的应用程序可以获得信息,以便它能够显示:“Git commit:[01abcdef … etc],branch:experimentalStuffDoNotRelease”
因此,我想在编译的C和/或C ++代码中自动包含Git信息,例如提交哈希和分支。
开发环境使开发人员同时使用Windows和Linux,并使用Eclipse CDT,其工作流程相对简单:check out; 编译; 下载到硬件。
我使用makefile,如下所示:
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)
运行makefile时,git哈希和编译时间都被加载到源中可访问的宏中,如下所示:
#include int main(){ std::cerr<<"hash="<
在Eclipse CDT中,使用预构建步骤生成包含相关信息的包含文件,并使用条件包含来检查文件是否已创建:
- 右键单击该项目
- 选择属性
- 展开C / C ++ Build
- 选择设置在构建步骤选项卡中
-
在命令文本框中输入以下内容:
git log --pretty=format:'#define GIT_INFO_PRESENT%n static const char*
GIT_INFO =“版本信息= [%H,%d] \ r \ n”;” -n 1> ../src/gitcommit.h
这将在构建时创建一个将包含在源代码中的文件gitcommit.h
。 要自定义它,请根据需要调整字符串。 (参见https://git-scm.com/docs/pretty-formats )
作为一个例子,我在主例程的开头生成一个调试输出,以通知用户提交和分支(不是严格需要知道提交,但肯定有帮助):
-
把它放在文件中,可能在顶部
#if __has_include("gitcommit.h") #include "gitcommit.h" #else static const char* GIT_INFO = "Git version information not present.\r\n"; #endif
-
要在代码中的某处显示信息,请执行以下操作:
printf(GIT_INFO);
请注意,在这种情况下,我没有将预构建步骤作为shell脚本或Windows / DOS .bat
文件,因为我经常在Linux或Windows中工作。
请注意,这不是在Windows中测试的。
在这两种情况下,’git’必须可以从标准命令行执行。
依赖于__has_include
。 这旨在提供简单性,以便不需要提供默认包含文件。
请注意,编译器应该可以发现gitcommit.h
文件的路径。
通常作为构建的一部分,您运行一些生成类似命令的命令。 例如, git describe
为您提供了一些可以使用的东西:
echo // auto generated version: > version.h git describe > echo // auto generated version: > version.h echo -e "#define VERSION " >> version.h git describe >> version.h
例如x264使用这个简单的脚本来生成它:
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\""
这将产生类似于:
#define X264_VERSION " r2708 86b7198" #define X264_POINTVER "0.148.2708 86b7198"