cmake扩展(2)——windows下动态设置输出文件(dll/exe)版本

准备

windows下设置文件的版本需要通过VERSIONINFO接口,详情参考VERSIONINFO resource。这里我们根据模板做了一定的修改。

1 VERSIONINFOFILEVERSION ${GIT_VERSION}	//文件版本号,必填。以,分隔,输出以.分隔。这里是取CMakeLists里的GIT_VERSION变量PRODUCTVERSION ${GIT_VERSION} //产品版本号,必填。以,分隔。虽然没起作用,见下面的"ProductVersion"FILEFLAGSMASK 0x17L
#ifdef _DEBUGFILEFLAGS 0x1L
#elseFILEFLAGS 0x0L
#endifFILEOS 0x4LFILETYPE 0x0LFILESUBTYPE 0x0L
BEGINBLOCK "StringFileInfo"BEGINBLOCK "040904b0"BEGINVALUE "FileDescription", "MyLibrary Binary" //文件说明VALUE "FileVersion", "1.1.1"                //文件版本,好像没啥用,只与FILEVERSION相关VALUE "InternalName", ""           //VALUE "LegalCopyright", "Copyright (C) 2019"VALUE "OriginalFilename", ""VALUE "ProductName", "1234" //产品名称VALUE "ProductVersion", "1.3.4.5.6"  //产品版本,与PRODUCTVERSION无关,直接输出 //${PROJECT_VERSION_MAJOR},${PROJECT_VERSION_MINOR},${PROJECT_VERSION_PATCH},${PROJECT_VERSION_TWEAK}ENDENDBLOCK "VarFileInfo"BEGINVALUE "Translation", 0x409, 1200END
END

注意事项

  1. FILEVERSION和PRODUCTVERSION为必填项。内容以','分隔,输出以'.'分隔(如设置为1,1,3,5,则实际输出版本为1.1.3.5)。可以直接是一整个变量,也可以是多个变量以','隔开。
  2. 而后面BLOCK块中内容都是全量输出,不做调整。
  3. 目前实验显示FILEVERSION内容管理实际输出的文件版本号,而产品版本号不由PRODUCTVERSION管理,反而由后面BLOK块中的"ProductVersion"控制。不知道是为啥。

调用versioninfo

前面已经准备号了versioninfo.接下来需要在CMakeLists中接入versioninfo。

  1. 首先将上面的versioninfo模板内容写入到文件中,并命名为versioninfo.rc(名字不重要,只要后续引用这个文件即可)
  2. 先在CMakeLists中手动写一个版本号(动态获取后面介绍),GIT_VERSION与versioninfo.rc中引用的变量名保持一致
set(GIT_VERSION 1,2,0,4)
  1. 通过config_file()命令将文件拷贝到指定文件或目录下。这里使用的时MSVC编译器,所以对MSVC进行判断了。
if(MSVC)set(VERSIONINFO_RC "${CMAKE_BINARY_DIR}/versioninfo.rc")configure_file("${CMAKE_SOURCE_DIR}/versioninfo.rc""${VERSIONINFO_RC}")
endif()
  1. 创建输出文件(dll/exe)时包含versioninfo.rc资源
add_executable(${PROJECT_NAME} ${SOURCES} ${VERSIONINFO_RC})
  1. cmake之后编译,查看生成的可执行文件详细信息内容。

动态获取版本号

这里采用的是cmake的execute_process运行git命令获取版本,并对结果进行截取组合达到我们想要的内容。

execute_process表示运行命令,可以与git其他命令结合获取其他信息。


#######################
####获取git版本#########
#######################
#设置默认版本
set(GIT_VERSION 1.0.0)
#通过git命令获取版本
execute_process(COMMAND git describe --tags
OUTPUT_VARIABLE GIT_DESCRIBE)# set(GIT_DESCRIBE "${GIT_DESCRIBE}-8-")
#查找版本
string(REGEX MATCH "[0-9]\\.[0-9]\\.[0-9]" GIT_DESCRIBE_VERSION ${GIT_DESCRIBE})
message(STATUS "GIT_DESCRIBE_VERSION=${GIT_DESCRIBE_VERSION}")
if(NOT ${GIT_DESCRIBE_VERSION} EQUAL "")
set(GIT_VERSION "${GIT_DESCRIBE_VERSION}")
endif()#查找提交次数
string(REGEX MATCHALL "-([0-9]+)-" MATCH_COMMIT_RET ${GIT_DESCRIBE})
message(STATUS "MATCH_COMMIT_RET=${MATCH_COMMIT_RET}")
list(LENGTH MATCH_COMMIT_RET MATCH_COMMIT_RET_LEN)message(STATUS "MATCH_COMMIT_RET_LEN=${MATCH_COMMIT_RET_LEN}")if(${MATCH_COMMIT_RET_LEN} GREATER 0)
#拿到最后一个匹配项
math(EXPR MATCH_COMMIT_RET_LEN "${MATCH_COMMIT_RET_LEN} - 1")
message(STATUS "MATCH_COMMIT_RET_LEN=${MATCH_COMMIT_RET_LEN}")
list(GET MATCH_COMMIT_RET ${MATCH_COMMIT_RET_LEN} MATCH_LAST)
#获取
string(REGEX REPLACE "-(.+)-" "\\1" GIT_COMMIT_COUNT ${MATCH_LAST})
set(GIT_VERSION "${GIT_VERSION}.${GIT_COMMIT_COUNT}")
else()#没有则默认写0
set(GIT_VERSION "${GIT_VERSION}.0")
endif()string(REPLACE "." ","  GIT_VERSION ${GIT_VERSION})
# set(GIT_VERSION 1,2,0)
# message(STATUS "final version is ${GIT_VERSION}")
##################################END#######################################

缺陷

这里因为是按照我们设想的git tag版本格式(x.x.x),并根据git describe会自动返回"version-提交次数-g当前提交hash"内容所写的。目的就是提炼成"version.提交次数",也就是x.x.x.x形式。所以这就要求在打tag的时候需要注意一定的格式否则这个代码将不起作用。

此外,git describe对于轻量标签不起作用,只有附注标签生效。

完整代码

cmake_minimum_required(VERSION 3.10)project(gitversion)#######################
####获取git版本#########
#######################
#设置默认版本
set(GIT_VERSION 1.0.0)
#通过git命令获取版本
execute_process(COMMAND git describe --tagsOUTPUT_VARIABLE GIT_DESCRIBE)# set(GIT_DESCRIBE "${GIT_DESCRIBE}-8-")
#查找版本
string(REGEX MATCH "[0-9]\\.[0-9]\\.[0-9]" GIT_DESCRIBE_VERSION ${GIT_DESCRIBE})
message(STATUS "GIT_DESCRIBE_VERSION=${GIT_DESCRIBE_VERSION}")
if(NOT ${GIT_DESCRIBE_VERSION} EQUAL "")set(GIT_VERSION "${GIT_DESCRIBE_VERSION}")
endif()#查找提交次数
string(REGEX MATCHALL "-([0-9]+)-" MATCH_COMMIT_RET ${GIT_DESCRIBE})
message(STATUS "MATCH_COMMIT_RET=${MATCH_COMMIT_RET}")
list(LENGTH MATCH_COMMIT_RET MATCH_COMMIT_RET_LEN)message(STATUS "MATCH_COMMIT_RET_LEN=${MATCH_COMMIT_RET_LEN}")if(${MATCH_COMMIT_RET_LEN} GREATER 0)#拿到最后一个匹配项math(EXPR MATCH_COMMIT_RET_LEN "${MATCH_COMMIT_RET_LEN} - 1")message(STATUS "MATCH_COMMIT_RET_LEN=${MATCH_COMMIT_RET_LEN}")list(GET MATCH_COMMIT_RET ${MATCH_COMMIT_RET_LEN} MATCH_LAST)#获取string(REGEX REPLACE "-(.+)-" "\\1" GIT_COMMIT_COUNT ${MATCH_LAST})set(GIT_VERSION "${GIT_VERSION}.${GIT_COMMIT_COUNT}")
else()#没有则默认写0set(GIT_VERSION "${GIT_VERSION}.0")
endif()string(REPLACE "." ","  GIT_VERSION ${GIT_VERSION})
# set(GIT_VERSION 1,2,0)
# message(STATUS "final version is ${GIT_VERSION}")
##################################END########################################这里需要注意按顺序
if(MSVC)set(VERSIONINFO_RC "${CMAKE_BINARY_DIR}/versioninfo.rc")configure_file("${CMAKE_SOURCE_DIR}/versioninfo.rc""${VERSIONINFO_RC}")
endif()file(GLOB SOURCES "*.cpp")
add_executable(${PROJECT_NAME} ${SOURCES} ${VERSIONINFO_RC})target_include_directories(${PROJECT_NAME} PRIVATE${CMAKE_SOURCE_DIR})

注意事项

  • 需要注意这里add_executable中引用了versioninfo.rc文件,而versioninfo.rc文件中引用了GIT_VERSION变量,所以GIT_VERSION变量的获取需要放在最前面,然后是引入versioninfo.rc,最后是add_executable,否则会导致编译时,GIT_VERSION变量内容为空编译不过。

其他

另一种方式是通过cmake的PROJECT_VERSION,PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR, PROJECT_VERSION_PATCH, PROJECT_VERSION_TWEAK来获取,但是无法动态调整版本号,需要手动修改。

代码如下:

cmake_minimum_required(VERSION 3.10)project(cmakeversion VERSION 1.2.5.8)#这里需要注意按顺序
if(MSVC)set(VERSIONINFO_RC "${CMAKE_BINARY_DIR}/versioninfo.rc")configure_file("${CMAKE_SOURCE_DIR}/versioninfo.rc""${VERSIONINFO_RC}")
endif()file(GLOB SOURCES "*.cpp")
add_executable(${PROJECT_NAME} ${SOURCES} ${VERSIONINFO_RC})target_include_directories(${PROJECT_NAME} PRIVATE${CMAKE_SOURCE_DIR})include(CMakePackageConfigHelpers)
configure_package_config_file(Config.cmake.in${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmakeINSTALL_DESTINATION lib/cmake/${PROJECT_NAME})
write_basic_package_version_file(${PROJECT_NAME}ConfigVersion.cmakeVERSION ${PACKAGE_VERSION} COMPATIBILITY AnyNewerVersion )install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmakeDESTINATION lib/cmake/${PROJECT_NAME} )message(status "version=${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.${PROJECT_VERSION_TWEAK}")

此外需要引用Config.cmake.in

@PACKAGE_INIT@set_and_check(CMAKEVERSION_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")
set_and_check(CMAKEVERSION_SYSCONFIG_DIR "@PACKAGE_SYSCONFIG_INSTALL_DIR@")check_required_components(Cmakeversion)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/33361.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java】异常处理 之 自定义异常

Java标准库定义的常用异常包括: Exception │ ├─ RuntimeException │ │ │ ├─ NullPointerException │ │ │ ├─ IndexOutOfBoundsException │ │ │ ├─ SecurityException │ │ │ └─ IllegalArgumentException │ │ │ └─ Num…

idea如何上传项目到github(超详细)

idea如何上传项目到github 1、IDEA配置2、项目上传到本地仓库2.1、创建本地git仓库2.2、Add操作2.3、Commit操作 3、项目上传到Github4、拿到登录Github的token 1、IDEA配置 File-Settings-VersionControl-Git Git的安装路径下bin目录下的git.exe可执行文件 可以直接点 Gene…

QGIS3.28的二次开发六:VS不借助QT插件创建UI界面

上一篇博客我们说了在VS中如何使用QT插件来创建UI界面,但是我们二次开发QGIS的第一篇博客就说了,最好使用OSGeo4W中自动下载的QT进行QGIS二次开发,这样兼容性是最好的,那么该如何在VS中不使用外部安装的QT以及QT的VS插件情况下进行…

【vue3】vue3中父子组件传参:

文章目录 一、父传子:二、父调用子方法:三、子组件发送emit方法给父组件: 一、父传子: 【1】父组件传值: 【2】子组件接收: 二、父调用子方法: 【1】父组件调用: 【2】子组件暴…

RabbitMQ在CentOS下的安装

RabbitMQ的版本是3.8.2 1.环境配置:CentOs 7.6以上版本,我的版本是7.9,不要对yum换源,否则可能会安装失败。 echo "export LC_ALLen_US.UTF-8" >> /etc/profile source /etc/profile 以上命令,是…

vue使用ElementUI

1.安装 npm i element-ui -S 2.引入 2.1完整引入 import Vue from vue; import ElementUI from element-ui; import element-ui/lib/theme-chalk/index.css; import App from ./App.vue;Vue.use(ElementUI); 2.2按需引入 说明:为了输入时候有提示,建…

变形金刚在图像识别方面比CNN更好吗?

链接到文 — https://arxiv.org/pdf/2010.11929.pdf 一、说明 如今,在自然语言处理(NLP)任务中,转换器已成为goto架构(例如BERT,GPT-3等)。另一方面,变压器在计算机视觉任务中的使用…

vue3 基础知识 01

加油! 😘 文章目录 一、vue3 带来的变化(源码)二、vue3 带来的变化(性能)三、vue3 带来的变化(新的API)四、声明式 和 命令式五、template六、data七、methods 一、vue3 带来的变化&…

Practices9(双指针)|283. 移动零、11. 盛最多水的容器、15. 三数之和

283. 移动零 1.题目: 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 请注意 ,必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,…

chrome、edge、Firefox关闭音量提醒控件显示

文章目录 1. Chrome2. edge3. firefox 1. Chrome 在地址栏输入: chrome://flags/#hardware-media-key-handling 将Hardware Media Key Handling的状态设为Disabled 2. edge 在地址栏输入 edge://flags/#hardware-media-key-handling 将Hardware Media Key Handling的状态…

第二十三章 原理篇:Pix2Seq

大夏天我好像二阳了真是要命啊。 现在找到工作了,感觉很快乐,但是也有了压力。 《论你靠吹牛混进公司后该怎么熬过试用期》 希望自己能保持学习的习惯!加油! 参考教程: https://arxiv.org/pdf/2109.10852.pdf https://…

高级进阶多线程——多任务处理、线程状态(生命周期)、三种创建多线程的方式

Java多线程 Java中的多线程是一个同时执行多个线程的进程。线程是一个轻量级的子进程,是最小的处理单元。多进程和多线程都用于实现多任务处理。 但是,一般使用多线程而不是多进程,这是因为线程使用共享内存区域。它们不分配单独的内存区域…

Nginx负载均衡以及keepalived高可用实验

Vip 10.1.122 Keepalived-master 10.1.1.132Keepalied-backup 10.1.1.133Realserver_1 10.1.1.136Realserver_2 10.1.1.137 四台机器上安装nginx,编译安装的话需要另外安装pcre包支持,安装在/usr/local/nginx Keepalived-master 和backu…

【网络编程·网络层】IP协议

目录 一、IP协议的概念 二、IP协议的报头 1、四位首部长度 2、16位总长度(解包) 3、8位协议(分用) 4、16位首部校验和 5、8位生存时间 6、32位源IP和32位目的IP 7、4位版本/8位服务类型 8、16位标识 9、3位标志 10、1…

go练习 day02

go中使用mongodb实现增删改查 连接mongodb yaml配置 mongodb:uri: mongodb://localhost:27017初始化连接 package confimport ("context""fmt""time""github.com/spf13/viper""go.mongodb.org/mongo-driver/mongo""…

基于kettle实现pg数据定时转存mongodb

mogodb 待创建 基于kettle实现pg数据定时转存mongodb_kettle 实时迁移 mongodb_呆呆的私房菜的博客-CSDN博客

MFC29-30天 补充中间遇到的一些小问题

宏定义中的#和##的含义&#xff1a; #include <Windows.h> #include <tchar.h> #include <iostream> #define Test(x,y) x##y //自动连接 xy #define T2(x) #x //自动转为字符串 "x"int main() {auto p Test(Message, Box);(*p)(NULL, _T(T2(Hel…

SQLSTATE[42000]: this is incompatible with sql_mode=only_full_group_by in

执行 SELECT *FROM test WHERE id>1 GROUP BY name having AVG(age)>10 ORDER BY id desc limit 1 提示错误 Fatal error: Uncaught PDOException: SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #1 of SELECT list is not in GROUP BY clause…

C# winform 布局操作组件介绍

Winform布局 布局的2个属性 Anchor:锁定位置 Dock&#xff1a;填充位置 一般Dock是与容器控件配合使用 布局的一些控件 TableLayoutPanel&#xff1a;表格容器 每个表格只能放一个控件 要放置多个时可以在每个表格里面添加一个Panel&#xff08;也可以是其他的容器&#x…

git一次错误merge的回滚

场景&#xff1a;提交到sit的代码&#xff0c;结果解决冲突merge了DEV的代码&#xff0c;所以要回滚到合并之前的代码 &#xff08;原因是我再网页上处理了冲突&#xff0c;他就自动merge了,如图—所以还是idea处理冲突&#xff0c;可控&#xff09; 方式二&#xff1a; &…