1 背景
随着实际项目的完善,可维护变的更加重要。在日志中保存项目的版本或是构建信息是一个非常有用的方法。
CMake提供了configure_file()
命令,可以帮助开发者在构建项目时,自动生成版本或是构建信息,便于开发者在代码中直接引用。
2 configure_file()
命令介绍
2.1 参数说明
configure_file()
命令的完整签名如下:
configure_file(<input> <output>
[NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS |
FILE_PERMISSIONS <permissions>...]
[COPYONLY] [ESCAPE_QUOTES] [@ONLY]
[NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF]])
复制<input>
文件到<output>
文件,同时根据命令的参数对复制的文件内容进行替换,同时也可以修改<output>
文件的权限。
<input>
输入文件的路径,相对于CMAKE_CURRENT_SOURCE_DIR的路径。输入路径必须是文件,而不是目录。
<output>
输出文件或目录的路径,相对于CMAKE_CURRENT_BINARY_DIR的路径。如果路径包含不存在的目录,则会创建这些目录。如果路径指定一个现有目录,则输出文件将放置在该目录中,文件名与输入文件相同。
NO_SOURCE_PERMISSIONS
不要将输入文件的权限转移到输出文件。复制文件的权限默认为标准的644值 (-rw-r–r–)。
USE_SOURCE_PERMISSIONS
将输入文件的权限转移到输出文件。如果未给出三个与权限相关的关键字(NO_SOURCE_PERMISSIONS、USE_SOURCE_PERMISSIONS或FILE_PERMISSIONS),这就是默认行为。USE_SOURCE_PERMISSIONS关键字主要用于使调用的预期行为更清晰。
FILE_PERMISSIONS <permissions>...
忽略输入文件的权限,并为输出文件使用指定的 <permissions>。
COPYONLY
复制文件,不替换任何变量引用或其他内容。此选项不能与NEWLINE_STYLE一起使用。
ESCAPE_QUOTES
使用反斜杠(C风格)转义任何替换的引号。
@ONLY
将变量替换限制为@VAR@
形式的引用。 CMake支持@VAR@
和 ${VAR}
形式的的替换。推荐使用这个参数,避免与CMake脚本中的 ${VAR}
混淆。
NEWLINE_STYLE <style>
指定输出文件的换行符样式。指定UNIX或LF表示\n换行符,或指定DOS、WIN32或CRLF表示\r\n换行符。此选项不能与COPYONLY一起使用。
实际项目中使用不会那么复杂,一般只使用基础签名
configure_file(<input> <output> [@ONLY])
2.2 常见用法
将<input>
文件理解为模板文件,CMakeLists.txt中的变量替换模板文件中相应的变量,生成一个新的文件。
项目中的常见用法是用构建时的版本号或是git的commit id替换模板文件。调用execute_process()
命令查询git的commit id,并将其保存在versin.h头文件中。
cmake_minimum_required(VERSION 3.10)
project(my_app)
# 执行git命令获取短哈希值
execute_process(
COMMAND git rev-parse --short HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} # 指定Git仓库根目录
OUTPUT_VARIABLE GIT_SHORT_COMMIT_ID
OUTPUT_STRIP_TRAILING_WHITESPACE # 去除末尾空白字符
ERROR_VARIABLE GIT_ERROR
RESULT_VARIABLE GIT_RESULT
)
# 错误处理
if(NOT GIT_RESULT EQUAL 0)
message(FATAL_ERROR "Failed to get git commit ID: ${GIT_ERROR}")
endif()
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/version.h.in
${CMAKE_CURRENT_SOURCE_DIR}/version.h
@ONLY
)
add_executable(my_app main.cpp)
# 包含头文件路径
target_include_directories(my_app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
version.h.in文件内容如下
#include <string>
// 被替换的变量(此处为GIT_SHORT_COMMIT_ID)需要与CMakeLists.txt中定义的变量一致
const std::string git_short_commit_id = "@GIT_SHORT_COMMIT_ID@";
替换后的version.h文件内容如下:
#include <string>
const std::string git_short_commit_id = "5171b09";
main.cpp文件中引用version.h文件中的git_short_commit_id变量。
#include <iostream>
#include "version.h"
int main()
{
std::cout << "git short commit-id: " << git_short_commit_id << std::endl;
return 1;
}
3 参考资料
https://cmake.org/cmake/help/latest/command/configure_file.html
4 最后
分享CMake使用中的小技巧。如果文章对您有帮助,不妨关注、收藏和转发,感谢。