当前位置: 首页 > news >正文

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)

相关文章:

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

准备 windows下设置文件的版本需要通过VERSIONINFO接口,详情参考VERSIONINFO resource。这里我们根据模板做了一定的修改。 1 VERSIONINFOFILEVERSION ${GIT_VERSION} //文件版本号,必填。以,分隔,输出以.分隔。这里是取CMakeLists里的GIT_…...

Python-OpenCV中的图像处理-颜色空间转换

Python-OpenCV中的图像处理-颜色空间转换 颜色空间转换获取HSV的值 颜色空间转换 在 OpenCV 中有超过 150 中进行颜色空间转换的方法。但是你以后就会 发现我们经常用到的也就两种: BGR G r a y 和 B G R Gray 和 BGR Gray和BGRHSV。 注意:在 OpenCV 的…...

yolov5目标检测多线程Qt界面

上一篇文章&#xff1a;yolov5目标检测多线程C部署 V1 基本功能实现 mainwindow.h #pragma once#include <iostream>#include <QMainWindow> #include <QFileDialog> #include <QThread>#include <opencv2/opencv.hpp>#include "yolov5.…...

[ubuntu]创建root权限的用户 该用户登录后自动切换为root用户

一、创建新用户 1、创建新用户 sudo useradd -r -m -s /bin/bash 用户名 # -r&#xff1a;建立系统账号 -m&#xff1a;自动建立用户的登入目录 -s&#xff1a;指定用户登入后所使用的shell2、手动为用户设置密码 passwd 用户名 二、为用户增加root权限 1、添加写权限 ch…...

大连交通大学813软件工程考研习题

1.什么是软件生存周期模型?有哪些主要模型? 生存周期模型&#xff1a;描述软件开发过程中各种活动如何执行的模型。对软件开发提供强有力的支持&#xff0c;为开发过程中的活动提供统一的政策保证&#xff0c;为参与开发的人员提供帮助和指导&#xff0c;是软件生存周期模型…...

分布式协议与算法——Paxos算法

目录 Paxos算法Basic Paxos算法三种角色如何达成共识&#xff08;协商过程&#xff09;小结&#xff1a; Multi-Paxos算法关于 Multi-Paxos 的思考领导者优化Basic PaxosChubby 的 Multi-Paxos 实现小结 参考 Paxos算法 Paxos论文 Paxos Made Simple 、author&#xff1a;Lesli…...

Spring中的Websocket身份验证和授权

目录 一、需要了解的事项二、依赖三、WebSocket 配置3.1 、简单的消息代理3.2 、Spring安全配置 一、需要了解的事项 http和WebSocket的安全链和安全配置是完全独立的。SpringAuthenticationProvider根本不参与 Websocket 身份验证。将要给出的示例中&#xff0c;身份验证不会…...

【果树农药喷洒机器人】Part7:静态PWM变量喷药实验

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…...

C++ 网络编程项目fastDFS分布是文件系统(一)

目录 1.项目架构图 1. 项目架构图 1.1 一些概念 1.2 项目架构图 2. 分布式文件系统 2.1 传统文件系统 2.2 分布式文件系统 3. FastDFS 3.1 fastDFS介绍 3.2 fastDFS安装 3.3 fastDFS配置文件 3.4 fastDFS的启动 4. fastDFS状态检测 4.1 对file_id的解释 4. 2上传…...

PoseiSwap 开启“Poseidon”池,治理体系或将全面开启

PoseiSwap 曾在前不久分别以 IDO、IEO 的方式推出了 POSE 通证&#xff0c;但 PoseiSwap DEX 中并未向除 Zepoch 节点外的角色开放 POSE 资产的交易。而在前不久&#xff0c;PoseiSwap 推出了全新的“Poseidon”池&#xff0c;该池将向所有用户开放&#xff0c;并允许用户自由的…...

【C/C++】重载运算符特性

重载运算符是 C 中的一个重要特性&#xff0c;它允许程序员自定义类类型的运算符行为。重载运算符的使用场景包括&#xff1a; 使类类型的对象能够像内置类型一样进行运算&#xff1a;例如&#xff0c;可以重载加号运算符&#xff0c;使两个对象相加时能够像两个整数相加一样。…...

HTML+JavaScript构建一个将C/C++定义的ANSI字符串转换为MASM32定义的DWUniCode字符串的工具

公文一键排版系统基本完成&#xff0c;准备继续完善SysInfo&#xff0c;增加用户帐户信息&#xff0c;其中涉及到Win32_Account结构&#xff0c;其C定义如下&#xff1a; [Dynamic, Provider("CIMWin32"), UUID("{8502C4CC-5FBB-11D2-AAC1-006008C78BC7}"…...

24届近3年南京信息工程大学自动化考研院校分析

今天给大家带来的是南京信息工程大学控制考研分析 满满干货&#xff5e;还不快快点赞收藏 一、南京信息工程大学 学校简介 南京信息工程大学位于南京江北新区&#xff0c;是一所以大气科学为特色的全国重点大学&#xff0c;由江苏省人民政府、中华人民共和国教育部、中国气…...

【LeetCode】1572.矩阵对角线元素的和

题目 给你一个正方形矩阵 mat&#xff0c;请你返回矩阵对角线元素的和。 请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。 示例 1&#xff1a; 输入&#xff1a;mat [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;25 解释&#xff1a;对角线的和为&a…...

2023-08-08 Ubuntu 挂载U盘 fdisk -l 、sudo mount /dev/sdb1 /mnt/mydisk

一、基本命令 1、插入U盘&#xff0c;查看U盘是否被系统识别&#xff1a; 打开终端&#xff0c;输入&#xff1a; sudo fdisk -l 查看系统是否识别U盘&#xff0c;如果识别&#xff0c;会显示U盘的相关信息&#xff0c;如果没有识别&#xff0c;则说明系统没有识别U盘。 2…...

make/makefile/cmake/nmake

最近&#xff0c;有没有被make、cmake、makefile... ... 这些东西绕晕了&#xff0c;看看下面的文章&#xff0c;也许就可以理解清楚了。 1. gcc 它是GNU Compiler Collection&#xff08;就是GNU编译器套件&#xff09;&#xff0c;也可以简单认为是编译器&#xff0c;它可以…...

实用的开源应用全新开源源码Vue3+TS的前后台分离的开发平台源码开源技术社区平台

开源全新开源源码Vue3TS的前后台分离的开发平台源码。创意、新奇、有趣、实用的开源应用、系统、软件、硬件及技术&#xff0c;一个探索、发现、分享、使用与互动交流的开源技术社区平台。致力于打造活力开源社区&#xff0c;共建开源新生态&#xff01; 功能简介 个人办公&a…...

C++复习笔记——primer第五版

文章目录 一、引用和指针1.引用2.指针2.1利用指针访问对象2.2指针的值或指针所指对象的值的改变 3.赋值和指针4.指向指针的引用 二、String1.初始化String对象的方式2. string对象上的操作3.使用getline读取一整行4.字面值和字符串相加5.使用for循环改变字符串中的字符 三、Vec…...

ElasticSearch:项目实战(2)

ElasticSearch: 项目实战 (1) 需求&#xff1a; 新增文章审核通过后同步数据到es索引库 1、文章服务中添加消息发送方法 在service层文章新增成功后&#xff0c;将数据通过kafka消息同步发送到搜索服务 Autowiredprivate KafkaTemplate<String,String> kafkaTemplate;/…...

Eleastisearch5.2.2利用镜像迁移构建实例后ES非健康状态

正常迁移完成后启动服务&#xff0c;查看ES非健康状态 此时观察ES集群状态&#xff1a;curl -XGET -u elastic:xxx localhost:9200/_cluster/health?pretty 注意到"active_shards_percent_as_number" : 88.8888 该项的值不产生变化;集群状态"status" : “…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

用鸿蒙HarmonyOS5实现中国象棋小游戏的过程

下面是一个基于鸿蒙OS (HarmonyOS) 的中国象棋小游戏的实现代码。这个实现使用Java语言和鸿蒙的Ability框架。 1. 项目结构 /src/main/java/com/example/chinesechess/├── MainAbilitySlice.java // 主界面逻辑├── ChessView.java // 游戏视图和逻辑├──…...

jdbc查询mysql数据库时,出现id顺序错误的情况

我在repository中的查询语句如下所示&#xff0c;即传入一个List<intager>的数据&#xff0c;返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致&#xff0c;会导致返回的id是从小到大排列的&#xff0c;但我不希望这样。 Query("SELECT NEW com…...