C\C++项目中使用Git仓库版本号

两种方式:

  • CMakeLists.txt文件中执行git命令获取版本号;(推荐)
  • sh脚本文件生成version.h文件,保证在执行make之前,头文件已存在;

CMakeLists.txt调用git命令

利用CMake调用Git命令获取仓库版本状态,然后将信息输出到一个头文件中(或者添加define),程序需要使用版本信息的,包含头文件并使用对应宏即可。

CMakeLists.txt添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
string (TIMESTAMP build_time %m%d%H%M)
message("build time: ${build_time})

find_package(Git)
# 生成版本描述字符串类似 TAG-X-gHASH
execute_process(COMMAND ${GIT_EXECUTABLE} describe --abbrev=6 --dirty --always --tags
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_REPO_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# 获取最新 commit 日期,YYYY-MM-DD
execute_process(COMMAND ${GIT_EXECUTABLE} log -1 --format=%cd --date=short
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_REPO_DATE
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# 获取最新 commit Hash
execute_process(COMMAND ${GIT_EXECUTABLE} log -1 --format=%H
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_REPO_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)

# 写入头文件宏定义的版本字符串,日期和 Hash,代码中#inclue "repo_version.h",即可使用REPO_DATE宏变量
file(WRITE ${PROJECT_BINARY_DIR}/repo_version.h
"#define REPO_VERSION \"${GIT_REPO_VERSION}\"\n#define REPO_DATE \"${GIT_REPO_DATE}\"\n#define REPO_HASH \"${GIT_REPO_HASH}\"\n"
)

# 或者传入宏定义APP_VERSION,在代码中直接使用APP_VERSION宏变量(推荐)
add_definitions(-DAPP_VERSION=\"${GIT_REPO_VERSION}\")

如果项目小,可以不使用头文件方式,而是直接在CMake传入宏定义。宏定义方法不适合中大型项目,因为每次都会导致项目重编译,编译时间又长,影响效率

脚本生成头文件

首先,新建脚本文件build_version.sh,添加以下内容:

1
2
3
4
5
6
7
8
9
10
11
#!/bin/sh
rm version.h

commit_ts=`git log -1 --format="%ct"`
commit_time=`date -d@$commit_ts +"%Y-%m-%d %H:%M:%S"`
current_time=`date +"%Y-%m-%d %H:%M:%S"`
git_version=`git log -1 --format="%h"`
git_tag=`git describe --abbrev=6 --dirty --always --tags`
echo "#pragma once" > version.h
echo "#define GIT_REPO_VERSION ${git_tag}\n" >> version.h

小知识
echo "abc" > file.txt # 覆盖文件内容
echo "abc" >> file.txt # 追加到末尾

其次,根据需要修改sh文件中version.h的位置,执行脚本文件./build_version.sh生成version.h,内容如下:

1
2
3
#pragma once
#define GIT_REPO_VERSION v0.1.1-e50e2f-dirty