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

这篇具有很好参考价值的文章主要介绍了cmake扩展(2)——windows下动态设置输出文件(dll/exe)版本。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

准备

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

1 VERSIONINFO
 FILEVERSION ${GIT_VERSION}	//文件版本号,必填。以,分隔,输出以.分隔。这里是取CMakeLists里的GIT_VERSION变量
 PRODUCTVERSION ${GIT_VERSION} //产品版本号,必填。以,分隔。虽然没起作用,见下面的"ProductVersion"
 FILEFLAGSMASK 0x17L
#ifdef _DEBUG
 FILEFLAGS 0x1L
#else
 FILEFLAGS 0x0L
#endif
 FILEOS 0x4L
 FILETYPE 0x0L
 FILESUBTYPE 0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904b0"
        BEGIN
            VALUE "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}
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200
    END
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 --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#######################################

#这里需要注意按顺序
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.cmake
    INSTALL_DESTINATION lib/cmake/${PROJECT_NAME})
write_basic_package_version_file(${PROJECT_NAME}ConfigVersion.cmake
    VERSION ${PACKAGE_VERSION} COMPATIBILITY AnyNewerVersion )



install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
        ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
        DESTINATION lib/cmake/${PROJECT_NAME} )

message(status "version=${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.${PROJECT_VERSION_TWEAK}")

此外需要引用Config.cmake.in文章来源地址https://www.toymoban.com/news/detail-645113.html

@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)版本的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • windows系统cmake生成c++动态库无lib文件解决方法 && bat文件批处理cmd命令

    作为cmake初学者,在windows系统下使用cmake生成c++动态库时出现了下图所示问题,是关于lib文件的。找了一圈,也没发现生成有lib文件。 在google上查,才发现windows系统下动态库生成lib文件,还需要添加以下命令: 生成动态库Demo(链接在此) 文件目录架构: ——源文件目录 —

    2023年04月25日
    浏览(44)
  • 浅谈Kernel32.dll(Windows平台下必有的动态库文件)

            今天听了前辈的黑客攻击的知识分享,里面比较基础的元素就是Kernel32.dll,我对它感兴趣好久了,今天搜集一些资料,有关Kernel32的。   目录 ​编辑 一、Kernel32介绍 二、Kernel32内存管理 三、引起Kernel32出错的主要元凶 四、解决方案 五、总结         Kernel32.dll是

    2024年02月04日
    浏览(41)
  • Windows使用cmake编译dll

    CMake MinGW CMake工具负责将CMakeLists.txt配置文件转换成相关的MakeFile脚本,本身并不参与编译,而是使用MinGW工具进行编译。 在Linux系统使用CMake编译需要执行以下命令即可编译出相关产物,但在Windows要使用MinGW工具编译需要在执行cmake命令时,添加相关的参数,即 -G \\\"MinGW Makefil

    2024年02月11日
    浏览(64)
  • exe/dll 文件依赖查询工具

    windows下开发exe后,本机运行正常,一旦准备部署到其他机器上,就会出现一堆问题。其中主要问题就是不知道自己缺了哪些库。一般的做法是使用depend.exe工具查看PE文件的依赖库,并进行打包。 但有时因为本机多个目录都存在相同名字的库,也不知道应该用哪个版本…等等

    2024年02月10日
    浏览(44)
  • Exe合并压缩:将dll等文件依赖压缩到一个exe中

    如果exe对某些dll有依赖,并且dll无法打包进原始exe时(比如没有该exe的工程源码,或者懒得搭建一套 VS或Python环境),可以优化将exe文件和依赖的dll文件合并成一个最终的release.exe, 通常的简便做法是直接将exe与dll放入同一目录下作为软件发布,但是相关dll依赖会直接暴露出

    2024年02月06日
    浏览(47)
  • python 打包项目(包含.ui文件,.dll文件)为exe可执行文件

    目录 1. 背景 2. 生成.spec文件: 3. 编辑.spec文件: 4. 最后生成单个可执行文件.exe:  5 补充: 1. 背景         最近在项目中想做一个用于烧录MCU的上位机给工厂用。于是在某工程模板上简单开发了一个基于python 和pyQt5的上位机软件。项目包含多个.py文件,多个.dll文件,一

    2024年02月16日
    浏览(45)
  • 创建傀儡进程svchost.exe并注入DLL文件(Shellcode)

    本文主要利用 SetThreadContext 修改进程中的线程上下文来实现Dll注入(ShellCode)。 实现原理 首先,使用 CreateProcess 函数创建svchost.exe进程,并且设置创建进程的标志为 CREATE_SUSPENDED,即表示新进程的主线程被挂起。 使用 GetThreadContext,设置标志为 CONTEXT_ALL,获取新进程中所有的

    2024年02月02日
    浏览(50)
  • C++开发实战(二):打开已有工程,并编译生成dll、exe等文件

    1、如下几张图,提示很友好,但我都点击了确定,并进行了运行,提示: 此项目需要 MFC 库。从 Visual Studio 安装程序(单个组件选项卡)为正在使用的任何。。。 2、根据提示安装依赖库 (1)搜索栏搜索应用Visual Studio Installer (2)双击打开,选择单个组件安装,选择 MFC 库(

    2024年02月06日
    浏览(97)
  • visual studio 生成dll文件以及修改输出dll文件名称操作

    Windows系统下Visual Studio可以通过.def文件创建dll。 1.确定需要导出的函数,test.cpp文件中定义如下 2. 添加 .def文件,一般添加到源文件下面。 * 在代码栏下面有一个“模块定义文件”,即我们的.def文件 3.编写test.def文件 文件添加完成,下一步即可设置一些导出规则。 4.在我们的

    2024年02月14日
    浏览(44)
  • Android JNI系列详解之CMake配置库文件的输出目录

    一、前提 阅读上一篇文章Android JNI系列详解之CMake编译工具的使用,里面讲到了需要配置两个文件:CMakeList.txt和build.gradle 二、配置CMake编译工具输出库文件的路径 1.默认的库文件输出路径:app/build/intermediates/cmake/debug/obj 由此可见不便于每次查找,因此我们需要将这个路径配置

    2024年02月10日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包