如何在CMake项目中实现类似MFC的版本信息配置:详解VS_VERSION_INFO的应用

张开发
2026/4/10 10:22:20 15 分钟阅读

分享文章

如何在CMake项目中实现类似MFC的版本信息配置:详解VS_VERSION_INFO的应用
1. 为什么需要版本信息配置在Windows平台上开发应用程序时版本信息是一个非常重要的元数据。它不仅能帮助用户识别软件版本还能在系统管理、错误报告和更新检查中发挥关键作用。如果你用过MFC开发一定对资源文件中的版本信息配置非常熟悉。右键点击一个exe文件选择属性在详细信息标签页看到的那些版本号、公司名称等信息就是通过VS_VERSION_INFO资源实现的。传统MFC项目直接在.rc资源文件中硬编码这些信息但对于现代CMake项目来说我们需要更灵活的配置方式。想象一下每次发布新版本都要手动修改资源文件既容易出错又不便于自动化构建。我在实际项目中就遇到过因为忘记更新版本号导致测试混乱的情况后来改用CMake动态生成才彻底解决了这个问题。2. 准备工作理解VS_VERSION_INFO结构2.1 VS_VERSION_INFO资源详解VS_VERSION_INFO是Windows定义的标准资源类型它采用了一种特殊的结构体格式。这个结构包含了两类信息固定信息包括文件版本、产品版本、文件类型等字符串信息包含可读的版本字符串、公司名称、版权信息等在资源脚本(.rc)中它通常长这样VS_VERSION_INFO VERSIONINFO FILEVERSION 1,0,0,0 PRODUCTVERSION 1,0,0,0 FILEFLAGSMASK 0x3fL FILEFLAGS 0x0L FILEOS VOS__WINDOWS32 FILETYPE VFT_APP { BLOCK StringFileInfo { BLOCK 040904E4 { VALUE FileVersion, 1.0.0 VALUE ProductName, 我的应用 } } BLOCK VarFileInfo { VALUE Translation, 0x409, 1252 } }2.2 版本号的组成规则Windows版本号通常由4个数字组成格式为主版本.次版本.修订号.构建号。在实际项目中我建议这样使用主版本重大功能更新次版本新增功能修订号bug修复构建号持续集成系统的自动递增编号3. CMake项目中的实现方案3.1 创建模板文件version.rc.in首先我们需要创建一个模板文件让CMake能够动态填充版本信息。在项目根目录下新建version.rc.in#include windows.h VS_VERSION_INFO VERSIONINFO FILEVERSION PROJECT_VERSION_MAJOR,PROJECT_VERSION_MINOR,PROJECT_VERSION_PATCH,0 PRODUCTVERSION PROJECT_VERSION_MAJOR,PROJECT_VERSION_MINOR,PROJECT_VERSION_PATCH,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS VOS__WINDOWS32 FILETYPE VFT_APP { BLOCK StringFileInfo { BLOCK 040904E4 { VALUE FileVersion, PROJECT_VERSION_MAJOR.PROJECT_VERSION_MINOR.PROJECT_VERSION_PATCH VALUE ProductVersion, PROJECT_VERSION_MAJOR.PROJECT_VERSION_MINOR.PROJECT_VERSION_PATCH VALUE CompanyName, PROJECT_COMPANY_NAME VALUE FileDescription, PROJECT_DESCRIPTION VALUE ProductName, PROJECT_NAME VALUE LegalCopyright, PROJECT_COPYRIGHT } } BLOCK VarFileInfo { VALUE Translation, 0x409, 1252 } }这个模板使用了CMake的变量替换语法VAR_NAME稍后我们会在CMakeLists.txt中定义这些变量。3.2 配置CMakeLists.txt接下来修改你的CMakeLists.txt添加版本信息配置# 设置版本号 set(PROJECT_VERSION_MAJOR 1) set(PROJECT_VERSION_MINOR 0) set(PROJECT_VERSION_PATCH 0) # 设置其他元数据 set(PROJECT_NAME 我的应用) set(PROJECT_COMPANY_NAME 我的公司) set(PROJECT_DESCRIPTION 这是一个使用CMake构建的应用程序) set(PROJECT_COPYRIGHT 版权所有 © 2023) # 生成版本资源文件 configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc ONLY ) # 添加资源文件到项目 add_executable(MyApp WIN32 src/main.cpp ${CMAKE_CURRENT_BINARY_DIR}/version.rc )这里有几个关键点需要注意configure_file命令会将模板中的变量替换为实际值生成的文件放在CMAKE_CURRENT_BINARY_DIR保持源码目录干净资源文件必须添加到可执行文件的源文件列表中4. 高级配置技巧4.1 自动生成构建号手动维护构建号很麻烦我们可以利用CMake的脚本功能自动生成# 获取当前日期作为构建号 string(TIMESTAMP BUILD_DATE %Y%m%d) set(PROJECT_BUILD_NUMBER ${BUILD_DATE}) # 在模板中使用 FILEVERSION PROJECT_VERSION_MAJOR,PROJECT_VERSION_MINOR,PROJECT_VERSION_PATCH,${PROJECT_BUILD_NUMBER}4.2 支持多语言如果你的应用需要支持多语言可以修改StringFileInfo块BLOCK StringFileInfo { BLOCK 040904E4 # 英语(美国) { VALUE FileDescription, English description } BLOCK 040404E4 # 中文(简体) { VALUE FileDescription, 中文描述 } }4.3 从外部文件读取版本号对于大型项目建议将版本信息单独放在一个文件中比如version.cmake# version.cmake set(PROJECT_VERSION_MAJOR 1) set(PROJECT_VERSION_MINOR 2) set(PROJECT_VERSION_PATCH 3)然后在主CMakeLists.txt中包含它include(version.cmake)这样版本管理会更清晰也便于自动化脚本处理。5. 常见问题与解决方案5.1 版本信息不显示如果生成的exe文件没有显示版本信息检查以下几点确保资源文件被正确添加到add_executable检查生成的version.rc文件内容是否正确尝试清理并重新生成整个项目5.2 版本号格式问题Windows资源管理器显示的版本字符串有时会忽略最后的0这是正常现象。比如1.0.0.0可能显示为1.0.0。5.3 调试版与发布版的区分在模板中我们使用了预处理器判断_DEBUG宏#ifdef _DEBUG FILEFLAGS 0x1L # VS_FF_DEBUG #else FILEFLAGS 0x0L #endif这可以确保调试版和发布版有不同的版本标志。6. 实际应用案例在我最近的一个跨平台项目中我们使用这套方案管理Windows版本的版本信息同时通过Git标签自动生成版本号。具体实现如下# 从Git标签获取版本号 find_package(Git) if(GIT_FOUND) execute_process( COMMAND ${GIT_EXECUTABLE} describe --tags --abbrev0 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE GIT_TAG OUTPUT_STRIP_TRAILING_WHITESPACE ) if(GIT_TAG) string(REGEX MATCH v([0-9])\\.([0-9])\\.([0-9]) _ ${GIT_TAG}) set(PROJECT_VERSION_MAJOR ${CMAKE_MATCH_1}) set(PROJECT_VERSION_MINOR ${CMAKE_MATCH_2}) set(PROJECT_VERSION_PATCH ${CMAKE_MATCH_3}) endif() endif()这样每次打tag发布时版本号会自动更新完全不需要手动维护。

更多文章