为了便于自动化版本管理,在C\C++项目中通常会考虑使用 Git 标识的版本作为程序版本号,本文介绍如何在 CMake 构建的项目中加入此项功能支持。
核心思路是,利用 CMake 调用 Git 命令获取仓库版本状态,然后将信息输出到一个头文件中,程序需要使用版本信息的,包含头文件并使用对应宏即可。
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
31
32
|
cmake_minimum_required(VERSION 2.8)
project(Foo)
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
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"
)
# 包含引用目录,源文件可以直接用 #include "repo_version.h" 包含
include_directories(${PROJECT_BINARY_DIR})
aux_source_directory(. SRC)
# 添加头文件依赖,保证更改后重新编译
add_executable(foo ${SRC} ${PROJECT_BINARY_DIR}/repo_version.h)
|
程序示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
#include <stdio.h>
#include "repo_version.h"
int main(int argc, char** argv)
{
printf("version: %s\n", REPO_VERSION);
printf("date: %s\n", REPO_DATE);
printf("hash: %s\n", REPO_HASH);
return 0;
}
|
如果项目小,可以不使用头文件方式,而是直接在 CMake 传入宏定义。宏定义方法不适合中大型项目,因为每次都会导致项目重编译,编译时间又长,影响效率。