在CMAKE中使用git命令获取版本信息
Charles Chan @ 2022-10-12 #CMake #Git @Program
基本代码
if(EXISTS "${PROJECT_SOURCE_DIR}/.git/logs/HEAD")
find_program(GIT_PROGRAM NAMES git)
if(${GIT_PROGRAM} STREQUAL GIT_PROGRAM-NOTFOUND)
set(BUILD_GIT_ID "[unknown]unknown\(built from non-git or tarball\)")
else()
execute_process(COMMAND git -c core.fileMode=false describe --always --dirty
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE BUILD_GIT_ID_1T)
execute_process(COMMAND git log -1 --format=%s
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE BUILD_GIT_ID_2T)
execute_process(COMMAND git branch --show-current
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE BUILD_GIT_BRANCH_T)
string(REPLACE "\n" "" BUILD_GIT_ID_1 ${BUILD_GIT_ID_1T})
string(REPLACE "\n" "" BUILD_GIT_ID_2 ${BUILD_GIT_ID_2T})
string(REPLACE "\"" "\\\"" BUILD_GIT_ID_1 ${BUILD_GIT_ID_1})
string(REPLACE "\"" "\\\"" BUILD_GIT_ID_2 ${BUILD_GIT_ID_2})
string(REPLACE "\n" "" BUILD_GIT_BRANCH ${BUILD_GIT_BRANCH_T})
set(BUILD_GIT_ID "[${BUILD_GIT_BRANCH}]${BUILD_GIT_ID_1}\(${BUILD_GIT_ID_2}\)")
execute_process(COMMAND git rev-list --count HEAD
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE BUILD_GIT_REV_CNT)
string(REPLACE "\n" "" BUILD_GIT_REV_CNT ${BUILD_GIT_REV_CNT})
set(NPATCH_VERSION ${BUILD_GIT_REV_CNT})
endif()
else ()
set(BUILD_GIT_ID "[unknown]unknown\(built from non-git or tarball\)")
endif()
if("${BUILD_GIT_ID}" MATCHES ".*dirty.*")
string(ASCII 27 Esc)
install(CODE "MESSAGE(\"${Esc}[31mDIRTY CODES : ${BUILD_GIT_ID}${Esc}[m\")")
endif("${BUILD_GIT_ID}" MATCHES ".*dirty.*")
这样做之后,可以得到几个有用的宏:
BUILD_GIT_ID_1
: 也就是git commit log的前7位。这是一个字符串。BUILD_GIT_ID_2
: 也就是git commit message。这是一个字符串。BUILD_GIT_REV_CNT
: 也就是git commit count。这是一个数字,可以用来给so添加版本号。
同时,一旦目录内存在修改,那么在make install
时,会有一行红颜色的提示。
并且编译的结果中会存在“–dirty”的标记。表示代码和git版本号并不完全相同。
连接库中带版本号
注意,将其中的“PKG”替换成你喜欢的内容。
set (NMAJOR_VERSION 1)
set (NMINOR_VERSION 0)
set (NPATCH_VERSION 0)
set (NHOTFIX_VERSION 0)
SET (PKG_VERSION ${NMAJOR_VERSION}.${NMINOR_VERSION}.${NPATCH_VERSION})
set_target_properties(PKG PROPERTIES SOVERSION ${PKG_VERSION })
让程序可以输出信息
创建一个类似下面的头文件,取名叫做config.h.in
/*****************************************************************************
* *
* CAUTION : This file was generated by the cmake, never modify it manually. *
* *
*****************************************************************************/
#ifndef __CONFIG_H__
#define __CONFIG_H__
#define BUILD_GIT_ID ("@BUILD_GIT_ID@")
#define PKG_VERSION ("@PKG_VERSION@")
#define PKG_VERSION_MAJOR (@NMAJOR_VERSION@)
#define PKG_VERSION_MINOR (@NMINOR_VERSION@)
#define PKG_VERSION_PATCH (@NPATCH_VERSION@)
#define PKG_VERSION_HOTFIX (@NHOTFIX_VERSION@)
#define PKG_VERSION_REV ("@BUILD_GIT_ID_1@")
#define PKG_COMPILE_OPT ("@CMAKE_ARGS@")
#endif
然后在CMakeLists.txt
中添加:
configure_file (
"${PROJECT_SOURCE_DIR}/config.h.in"
"${PROJECT_BINARY_DIR}/config.h"
)
之后,就可以在需要的源文件中包含这个头文件,并使用这些宏定义。
编译参数
更极端的情况下,我们可能还希望知道二进制生成时使用的编译参数是什么。
get_cmake_property(CACHE_VARS CACHE_VARIABLES)
foreach(CACHE_VAR ${CACHE_VARS})
get_property(CACHE_VAR_HELPSTRING CACHE ${CACHE_VAR} PROPERTY HELPSTRING)
#message("CACHE_VAR: ${CACHE_VAR} ${CACHE_VAR_HELPSTRING}")
if(NOT CACHE_VAR_HELPSTRING STREQUAL "")
string(SUBSTRING ${CACHE_VAR_HELPSTRING} 0 11 HELPSTRING_OVERHEAD)
if(HELPSTRING_OVERHEAD STREQUAL "Build with ")
get_property(CACHE_VAR_TYPE CACHE ${CACHE_VAR} PROPERTY TYPE)
if(CACHE_VAR_TYPE STREQUAL "UNINITIALIZED")
set(CACHE_VAR_TYPE)
else()
set(CACHE_VAR_TYPE :${CACHE_VAR_TYPE})
endif()
set(CMAKE_ARGS "${CMAKE_ARGS} -D${CACHE_VAR}=${${CACHE_VAR}}")
endif()
endif()
endforeach()
string(REPLACE "cmake . " "" CMAKE_ARGS ${CMAKE_ARGS})
使用
(void)fprintf(stderr, "Version %d.%d.%d.%s\n",
PKG_VERSION_MAJOR, PKG_VERSION_MINOR,
PKG_VERSION_PATCH, PKG_VERSION_REV);
(void)fprintf(stderr, "Compile options: %s\n\n", PKG_COMPILE_OPT);
效果
Version 1.0.134.d8ba08e
Compile options: -DBUILD_TESTCASES=OFF -DWITH_WARN_TO_ERR=ON
在CMAKE中使用git命令获取版本信息
基本代码
if(EXISTS "${PROJECT_SOURCE_DIR}/.git/logs/HEAD")
find_program(GIT_PROGRAM NAMES git)
if(${GIT_PROGRAM} STREQUAL GIT_PROGRAM-NOTFOUND)
set(BUILD_GIT_ID "[unknown]unknown\(built from non-git or tarball\)")
else()
execute_process(COMMAND git -c core.fileMode=false describe --always --dirty
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE BUILD_GIT_ID_1T)
execute_process(COMMAND git log -1 --format=%s
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE BUILD_GIT_ID_2T)
execute_process(COMMAND git branch --show-current
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE BUILD_GIT_BRANCH_T)
string(REPLACE "\n" "" BUILD_GIT_ID_1 ${BUILD_GIT_ID_1T})
string(REPLACE "\n" "" BUILD_GIT_ID_2 ${BUILD_GIT_ID_2T})
string(REPLACE "\"" "\\\"" BUILD_GIT_ID_1 ${BUILD_GIT_ID_1})
string(REPLACE "\"" "\\\"" BUILD_GIT_ID_2 ${BUILD_GIT_ID_2})
string(REPLACE "\n" "" BUILD_GIT_BRANCH ${BUILD_GIT_BRANCH_T})
set(BUILD_GIT_ID "[${BUILD_GIT_BRANCH}]${BUILD_GIT_ID_1}\(${BUILD_GIT_ID_2}\)")
execute_process(COMMAND git rev-list --count --first-parent HEAD
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE BUILD_GIT_REV_CNT)
string(REPLACE "\n" "" BUILD_GIT_REV_CNT ${BUILD_GIT_REV_CNT})
set(NPATCH_VERSION ${BUILD_GIT_REV_CNT})
endif()
else ()
set(BUILD_GIT_ID "[unknown]unknown\(built from non-git or tarball\)")
endif()
if("${BUILD_GIT_ID}" MATCHES ".*dirty.*")
string(ASCII 27 Esc)
install(CODE "MESSAGE(\"${Esc}[31mDIRTY CODES : ${BUILD_GIT_ID}${Esc}[m\")")
endif("${BUILD_GIT_ID}" MATCHES ".*dirty.*")
这样做之后,可以得到几个有用的宏:
BUILD_GIT_ID_1
: 也就是git commit log的前7位。这是一个字符串。BUILD_GIT_ID_2
: 也就是git commit message。这是一个字符串。BUILD_GIT_REV_CNT
: 也就是git commit count。这是一个数字,可以用来给so添加版本号。
同时,一旦目录内存在修改,那么在make install
时,会有一行红颜色的提示。
并且编译的结果中会存在“–dirty”的标记。表示代码和git版本号并不完全相同。
连接库中带版本号
注意,将其中的“PKG”替换成你喜欢的内容。
set (NMAJOR_VERSION 1)
set (NMINOR_VERSION 0)
set (NPATCH_VERSION 0)
set (NHOTFIX_VERSION 0)
SET (PKG_VERSION ${NMAJOR_VERSION}.${NMINOR_VERSION}.${NPATCH_VERSION})
set_target_properties(PKG PROPERTIES SOVERSION ${PKG_VERSION })
编译参数
更极端的情况下,我们可能还希望知道二进制生成时使用的编译参数是什么。
get_cmake_property(CACHE_VARS CACHE_VARIABLES)
foreach(CACHE_VAR ${CACHE_VARS})
get_property(CACHE_VAR_HELPSTRING CACHE ${CACHE_VAR} PROPERTY HELPSTRING)
#message("CACHE_VAR: ${CACHE_VAR} ${CACHE_VAR_HELPSTRING}")
if(NOT CACHE_VAR_HELPSTRING STREQUAL "")
string(SUBSTRING ${CACHE_VAR_HELPSTRING} 0 11 HELPSTRING_OVERHEAD)
if(HELPSTRING_OVERHEAD STREQUAL "Build with ")
get_property(CACHE_VAR_TYPE CACHE ${CACHE_VAR} PROPERTY TYPE)
if(CACHE_VAR_TYPE STREQUAL "UNINITIALIZED")
set(CACHE_VAR_TYPE)
else()
set(CACHE_VAR_TYPE :${CACHE_VAR_TYPE})
endif()
set(CMAKE_ARGS "${CMAKE_ARGS} -D${CACHE_VAR}=${${CACHE_VAR}}")
endif()
endif()
endforeach()
string(REPLACE "cmake . " "" CMAKE_ARGS ${CMAKE_ARGS})
让程序可以输出信息
创建一个类似下面的头文件,取名叫做config.h.in
/*****************************************************************************
* *
* CAUTION : This file was generated by the cmake, never modify it manually. *
* *
*****************************************************************************/
#ifndef __CONFIG_H__
#define __CONFIG_H__
#define BUILD_GIT_ID ("@BUILD_GIT_ID@")
#define PKG_VERSION ("@PKG_VERSION@")
#define PKG_VERSION_MAJOR (@NMAJOR_VERSION@)
#define PKG_VERSION_MINOR (@NMINOR_VERSION@)
#define PKG_VERSION_PATCH (@NPATCH_VERSION@)
#define PKG_VERSION_HOTFIX (@NHOTFIX_VERSION@)
#define PKG_VERSION_REV ("@BUILD_GIT_ID_1@")
#define PKG_COMPILE_OPT ("@CMAKE_ARGS@")
#endif
然后在CMakeLists.txt
中添加:
configure_file (
"${PROJECT_SOURCE_DIR}/config.h.in"
"${PROJECT_BINARY_DIR}/config.h"
)
之后,就可以在需要的源文件中包含这个头文件,并使用这些宏定义。
使用
#include <config.h>
...
(void)fprintf(stderr, "Version %d.%d.%d.%s\n",
PKG_VERSION_MAJOR, PKG_VERSION_MINOR,
PKG_VERSION_PATCH, PKG_VERSION_REV);
(void)fprintf(stderr, "Compile options: %s\n\n", PKG_COMPILE_OPT);
...
效果示意
Version 1.0.123.d8ba08e
Compile options: -DBUILD_TESTCASES=OFF -DWITH_WARN_TO_ERR=ON