注意
本文最后更新于 2024-02-01,文中内容可能已过时。
一、导言
导言
上一篇,在配置时记录了代码存储库(Git Hash
)的状态。然而,该方法方法有一个令人不满意的地方,如果在配置代码之后更改分支或提交更改,则源代码中包含的版本记录可能指向错误的Git Hash
值。本篇,我们将演示如何在构建时记录·Git Hash·(或者,执行其他操作),以确保每次构建代码时都运行这些操作,因为实际操作中可能只配置一次,但是会构建多次。 二、项目结构
1
2
3
4
5
6
| .
├── cmake
│ └── git-hash.cmake
├── CMakeLists.txt
├── example.cpp
└── version.hpp.in
|
https://gitee.com/jiangli01/tutorials/tree/master/cmake-tutorial/chapter6/05
version.hpp.in
1
2
3
4
5
| #pragma once
#include <string>
const std::string GIT_HASH = "@GIT_HASH@";
|
example.cpp
1
2
3
4
5
6
7
| #include "version.hpp"
#include <iostream>
int main() {
std::cout << "This code has been built from version " << GIT_HASH << std::endl;
}
|
git-hash.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| set(GIT_HASH "unknown")
# find Git and if available set GIT_HASH variable
find_package(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
)
endif()
message(STATUS "Git hash is ${GIT_HASH}")
configure_file(
${CMAKE_SOURCE_DIR}/version.hpp.in
${TARGET_DIR}/generated/version.hpp
@ONLY
)
|
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
33
34
35
| cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(recipe-07 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(example example.cpp)
target_include_directories(example
PRIVATE
${CMAKE_CURRENT_BINARY_DIR}/generated
)
add_custom_command(
OUTPUT
${CMAKE_CURRENT_BINARY_DIR}/generated/version.hpp
ALL
COMMAND
${CMAKE_COMMAND} -D TARGET_DIR=${CMAKE_CURRENT_BINARY_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/git-hash.cmake
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
)
# rebuild version.hpp every time
add_custom_target(
get_git_hash
ALL
DEPENDS
${CMAKE_CURRENT_BINARY_DIR}/generated/version.hpp
)
# version.hpp has to be generated before we start building example
add_dependencies(example get_git_hash)
|
tips
1
2
3
4
5
6
7
8
9
| add_custom_command(
OUTPUT
${CMAKE_CURRENT_BINARY_DIR}/generated/version.hpp
ALL
COMMAND
${CMAKE_COMMAND} -D TARGET_DIR=${CMAKE_CURRENT_BINARY_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/git-hash.cmake
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
)
|
自定义命令调用CMake
来执行git-hash.cmake
脚本。这里使用CLI
的-P
开关,通过传入脚本的位置实现的。请注意,可以像往常一样使用CLI
开关-D
传递选项。git-hash.cmake
脚本生成${TARGET_DIR}/generated/version.hpp
。自定义目标被添加到ALL
目标中,并且依赖于自定义命令的输出。换句话说,当构建默认目标时,我们确保自定义命令已经运行。此外,自定义命令将ALL
目标作为输出。这样,我们就能确保每次都会生成version.hpp
了。
三、结果展示
1
2
3
4
5
6
| $ mkdir -p build
$ cd build
$ cmake ..
$ cmake --build .
$ ./example
This code has been configured from version c66f02
|
生成git hash版本文件
四、补充内容
可以改进配置,以便在记录的Git Hash
外,包含其他的信息。检测构建环境是否污染
(即是否包含未提交的更改和未跟踪的文件),或者干净
。可以使用git describe --abbrev=7 --long --always --dirty --tags
检测这些信息。根据可重现性,甚至可以将Git
的状态,完整输出记录到头文件中。