奇技淫巧[1]:cmake中获取git信息
1 目的
获取当前源码的git分支名及Commit Hash,将其写入头文件并生成至指定目录。
2 要点
macro
宏的使用execute_process
执行一个子进程configure_file
修改并拷贝文件
3 用法
工程结构如下:
root
├── CMakeLists.txt
├── cmake
│ └── Utility.cmake
└── include
└── git_version.h.in
首先在CMakeLists.txt中加入自定义cmake文件目录,这样在include(Utility)
时cmake会自动搜索并引入Utility.cmake
[CMakeLists.txt]:
# 添加自定义cmake文件目录
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
# 使用Utility.cmake
include(Utility)
Utility.cmake
中定义了get_git_hash
和get_git_branch
两个宏,分别用于获取当前源码的Commit Hash及git分支名
[CMakeLists.txt]:
# 获取当前的GIT_HASH
set(GIT_HASH "")
get_git_hash(GIT_HASH)
message(STATUS "Git hash is ${GIT_HASH}")
# 获取当前的分支
set(GIT_BRANCH "")
get_git_branch(GIT_BRANCH)
message(STATUS "Git branch is ${GIT_BRANCH}")
宏的定义在Utility.cmake中,以get_git_hash
为例代码如下,其中execute_process
是exec_program
的新版实现,尽量使用前者以获得更多特性支持
另:get_git_branch
只需将COMMAND
替换为${GIT_EXECUTABLE} symbolic-ref --short -q HEAD
即可
[Utility.cmake]:
# get git hash
macro(get_git_hash _git_hash) # 宏的开始
find_package(Git QUIET) # 查找Git,QUIET静默方式不报错
if(GIT_FOUND)
execute_process( # 执行一个子进程
COMMAND ${GIT_EXECUTABLE} log -1 --pretty=format:%h # 命令
OUTPUT_VARIABLE ${_git_hash} # 输出字符串存入变量
OUTPUT_STRIP_TRAILING_WHITESPACE # 删除字符串尾的换行符
ERROR_QUIET # 对执行错误静默
WORKING_DIRECTORY # 执行路径
${CMAKE_CURRENT_SOURCE_DIR}
)
endif()
endmacro() # 宏的结束
在获取GIT_HASH
和GIT_BRANCH
两个字符串变量之后,执行configure_file
,将git_version.h.in
中的@GIT_BRANCH@
和@GIT_HASH@
进行替换,并保存为指定路径下的git_version.h
[CMakeLists.txt]:
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/include/git_version.h.in # 输入
${CMAKE_BINARY_DIR}/generate/git_version.h # 输出
@ONLY # 只接受形如@VAR@的占位符
)
[http://git_version.h.in]:
#pragma once
#include <string>
const std::string git_branch = "@GIT_BRANCH@";
const std::string git_hash = "@GIT_HASH@";
执行cmake
之后build
下多了相应的文件
root
└── build
├── ...
└── generate
└── git_version.h
[git_version.h]:
#pragma once
#include <string>
const std::string git_branch = "master";
const std::string git_hash = "e40f51c";
4 源码
git clone https://github.com/zfrxiaxia/cmake_template_git.git