
奇技淫巧[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