如何在编译时确定git存储库的状态

How can the status of a git repository be determined at compile time?

本文关键字:存储 git 状态 编译      更新时间:2023-10-16

我正在开发一个用C++编写的模拟系统,该系统由git管理。我使用GNU make作为构建工具。为了使模拟结果可再现,git非常有用,因为您可以返回到创建结果的模拟程序的确切版本。

目前,git存储库的状态和SHA1是在运行时以编程方式确定的,并与结果一起写入文件。但是,如果源在程序编译后发生了更改,我的日志文件中的状态将不会反映程序的实际版本。因此,我正在寻找一种方法来确定编译时的git状态。有机会做到这一点吗?

一个解决方案是让构建系统提取该值,并让它生成一些包含该值的C++头(或源文件)。

例如,如果使用CMake,您可以使用FindGit模块来执行以下操作:

project(...)
# load module.
find_package(Git)
# create "${GIT_HEAD_HASH}" variable that contains
# the SHA-1 of the current tree.  This assumes that the
# root CMakeLists is in the root of the Git repository.
git_tree_info(${CMAKE_SOURCE_DIR} GIT_HEAD)
# generate a 'version.h' file based on the 'version.h.in'
# file.  replace all @...@ strings with variables in the
# current scope.
configure_file(
    ${CMAKE_CURRENT_SOURCE_DIR}/version.h.in
    ${CMAKE_CURRENT_SOURCE_DIR}/version.h
    @ONLY
)

然后,添加以下version.h.in文件:

#ifndef _version_h__
#define _version_h__
static const char VERSION[] = "@GIT_HEAD_HASH@";
#endif

CMake将用它使用get_tree_info()提取的值替换@GIT_HEAD_HASH@字符串。

然后,从您的常规代码:

#include "version.h"
#include <cstdlib>
#include <cstring>
#include <iostream>
int main(int argc, char ** argv)
{
    if ((argc == 2) && (std::strcmp(argv[1],"--version") == 0))
    {
        std::cerr
            << VERSION
            << std::endl;
        return (EXIT_FAILURE);
    }
    // ...
}

这是一个简化的、绝对未经测试的例子。如果您查看FindGit CMake模块的源代码,您会发现它只是在构建时运行一个execute_process()命令来提取信息。您可以根据Git命令行接口的调用对其进行修改以提取任何内容。

由于您已经在使用Makefile,因此可以在那里检查状态。

如果您想跟踪当时的HEAD是什么提交,可以使用git rev-parse HEAD来获取提交的sha1。如果在运行时需要,可以将其存储在文件中。