CMake实战3步搞定Windows程序版本号设置附完整rc模板在Windows平台开发中程序版本号不仅是软件迭代的标识更是用户识别和信任的重要依据。对于从MFC转向CMake的开发者来说如何在CMake项目中优雅地实现类似MFC的文件属性版本信息配置是一个常见痛点。本文将提供一个开箱即用的解决方案只需3步即可完成版本号设置并附带完整可复用的rc模板文件。1. 版本号配置基础版本号在Windows程序中通常以MAJOR.MINOR.PATCH格式呈现例如1.2.3。在CMake中我们可以通过简单的变量定义来管理这些值# 定义主版本号 set(PROJECT_VERSION_MAJOR 2) # 定义次版本号 set(PROJECT_VERSION_MINOR 3) # 定义修订号 set(PROJECT_VERSION_PATCH 5)注意版本号应遵循语义化版本规范MAJOR表示不兼容的API修改MINOR表示向下兼容的功能新增PATCH表示向下兼容的问题修正。Windows资源文件(.rc)中还需要一个额外的构建号(Build Number)通常设置为0。完整的版本号在资源文件中会表现为四段式MAJOR.MINOR.PATCH.BUILD。2. 创建可配置的rc模板文件version.rc.in是一个模板文件CMake会将其中的变量替换为实际值生成最终的.rc文件。以下是完整的模板内容#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 BEGIN BLOCK StringFileInfo BEGIN BLOCK 040904E4 BEGIN VALUE FileVersion, PROJECT_VERSION_MAJOR.PROJECT_VERSION_MINOR.PROJECT_VERSION_PATCH VALUE ProductVersion, PROJECT_VERSION_MAJOR.PROJECT_VERSION_MINOR.PROJECT_VERSION_PATCH VALUE CompanyName, Your Company Name VALUE FileDescription, Your Application Description VALUE ProductName, Your Product Name VALUE LegalCopyright, Copyright © 2023 Your Company VALUE OriginalFilename, YourApp.exe END END BLOCK VarFileInfo BEGIN VALUE Translation, 0x409, 1252 END END模板中各关键部分的含义FILEVERSION和PRODUCTVERSION二进制版本号必须为四段式StringFileInfo块包含用户可见的字符串信息VarFileInfo块指定语言和字符集(这里是美式英语和Windows多语言)FILEFLAGS区分Debug和Release版本3. 集成到CMake项目将模板文件集成到CMake项目只需三个步骤定义版本变量在CMakeLists.txt中设置版本号配置资源文件使用configure_file生成最终.rc文件添加到目标将资源文件包含到可执行文件中完整实现如下# 步骤1定义版本号 set(PROJECT_VERSION_MAJOR 1) set(PROJECT_VERSION_MINOR 0) set(PROJECT_VERSION_PATCH 0) # 步骤2配置资源文件 configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc ONLY ) # 步骤3添加到可执行文件 add_executable(MyApp main.cpp ${CMAKE_CURRENT_BINARY_DIR}/version.rc )提示对于GUI应用程序使用WIN32关键字控制台程序使用CONSOLE这与MFC项目中的设置类似。4. 高级配置技巧4.1 自动化版本号管理手动维护版本号容易出错可以考虑从外部文件或Git标签自动获取版本号# 从VERSION文件读取版本号 file(STRINGS VERSION PROJECT_VERSION) string(REGEX MATCH ([0-9])\\.([0-9])\\.([0-9]) _ ${PROJECT_VERSION}) set(PROJECT_VERSION_MAJOR ${CMAKE_MATCH_1}) set(PROJECT_VERSION_MINOR ${CMAKE_MATCH_2}) set(PROJECT_VERSION_PATCH ${CMAKE_MATCH_3})4.2 多项目统一版本号对于包含多个子项目的大型解决方案可以在根CMakeLists.txt中定义版本号子项目共享# 根CMakeLists.txt set(PROJECT_VERSION_MAJOR 1) set(PROJECT_VERSION_MINOR 2) set(PROJECT_VERSION_PATCH 3) add_subdirectory(subproject1) add_subdirectory(subproject2)4.3 条件编译不同配置根据构建类型(Debug/Release)设置不同的文件描述#ifdef _DEBUG VALUE FileDescription, Debug Build of Your Application #else VALUE FileDescription, Release Build of Your Application #endif4.4 版本信息国际化支持多语言版本信息只需添加额外的StringFileInfo块BEGIN BLOCK StringFileInfo BEGIN BLOCK 040904E4 // 英语(美国) BEGIN VALUE FileDescription, English Description END BLOCK 040404B0 // 中文(简体) BEGIN VALUE FileDescription, 中文描述 END END END5. 常见问题解决5.1 版本信息未显示如果生成的EXE文件属性中看不到版本信息检查确保.rc文件被正确包含在add_executable中确认资源编译器没有报错检查.rc文件是否被正确生成在构建目录5.2 版本号格式错误Windows资源文件要求版本号必须为四段式即使产品版本号显示为三段式在FILEVERSION和PRODUCTVERSION中仍需补充第四段(通常为0)。5.3 与MFC资源冲突如果项目同时使用MFC和CMake生成的资源文件可能会遇到资源冲突。解决方案将版本信息合并到主资源文件中使用RC_INCLUDES指定额外包含目录确保资源ID不重复set(CMAKE_RC_INCLUDES ${CMAKE_CURRENT_BINARY_DIR})5.4 64位构建问题对于64位应用程序确保资源编译器目标架构正确if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(CMAKE_RC_COMPILE_OBJECT ${CMAKE_RC_COMPILE_OBJECT} --targetpe-x86-64) endif()在实际项目中这套方案已经帮助多个团队平滑地从MFC迁移到CMake同时保持了版本信息的一致性和可维护性。特别是在持续集成环境中通过自动化脚本更新版本号大大减少了人为错误。
CMake实战:3步搞定Windows程序版本号设置(附完整rc模板)
CMake实战3步搞定Windows程序版本号设置附完整rc模板在Windows平台开发中程序版本号不仅是软件迭代的标识更是用户识别和信任的重要依据。对于从MFC转向CMake的开发者来说如何在CMake项目中优雅地实现类似MFC的文件属性版本信息配置是一个常见痛点。本文将提供一个开箱即用的解决方案只需3步即可完成版本号设置并附带完整可复用的rc模板文件。1. 版本号配置基础版本号在Windows程序中通常以MAJOR.MINOR.PATCH格式呈现例如1.2.3。在CMake中我们可以通过简单的变量定义来管理这些值# 定义主版本号 set(PROJECT_VERSION_MAJOR 2) # 定义次版本号 set(PROJECT_VERSION_MINOR 3) # 定义修订号 set(PROJECT_VERSION_PATCH 5)注意版本号应遵循语义化版本规范MAJOR表示不兼容的API修改MINOR表示向下兼容的功能新增PATCH表示向下兼容的问题修正。Windows资源文件(.rc)中还需要一个额外的构建号(Build Number)通常设置为0。完整的版本号在资源文件中会表现为四段式MAJOR.MINOR.PATCH.BUILD。2. 创建可配置的rc模板文件version.rc.in是一个模板文件CMake会将其中的变量替换为实际值生成最终的.rc文件。以下是完整的模板内容#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 BEGIN BLOCK StringFileInfo BEGIN BLOCK 040904E4 BEGIN VALUE FileVersion, PROJECT_VERSION_MAJOR.PROJECT_VERSION_MINOR.PROJECT_VERSION_PATCH VALUE ProductVersion, PROJECT_VERSION_MAJOR.PROJECT_VERSION_MINOR.PROJECT_VERSION_PATCH VALUE CompanyName, Your Company Name VALUE FileDescription, Your Application Description VALUE ProductName, Your Product Name VALUE LegalCopyright, Copyright © 2023 Your Company VALUE OriginalFilename, YourApp.exe END END BLOCK VarFileInfo BEGIN VALUE Translation, 0x409, 1252 END END模板中各关键部分的含义FILEVERSION和PRODUCTVERSION二进制版本号必须为四段式StringFileInfo块包含用户可见的字符串信息VarFileInfo块指定语言和字符集(这里是美式英语和Windows多语言)FILEFLAGS区分Debug和Release版本3. 集成到CMake项目将模板文件集成到CMake项目只需三个步骤定义版本变量在CMakeLists.txt中设置版本号配置资源文件使用configure_file生成最终.rc文件添加到目标将资源文件包含到可执行文件中完整实现如下# 步骤1定义版本号 set(PROJECT_VERSION_MAJOR 1) set(PROJECT_VERSION_MINOR 0) set(PROJECT_VERSION_PATCH 0) # 步骤2配置资源文件 configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc ONLY ) # 步骤3添加到可执行文件 add_executable(MyApp main.cpp ${CMAKE_CURRENT_BINARY_DIR}/version.rc )提示对于GUI应用程序使用WIN32关键字控制台程序使用CONSOLE这与MFC项目中的设置类似。4. 高级配置技巧4.1 自动化版本号管理手动维护版本号容易出错可以考虑从外部文件或Git标签自动获取版本号# 从VERSION文件读取版本号 file(STRINGS VERSION PROJECT_VERSION) string(REGEX MATCH ([0-9])\\.([0-9])\\.([0-9]) _ ${PROJECT_VERSION}) set(PROJECT_VERSION_MAJOR ${CMAKE_MATCH_1}) set(PROJECT_VERSION_MINOR ${CMAKE_MATCH_2}) set(PROJECT_VERSION_PATCH ${CMAKE_MATCH_3})4.2 多项目统一版本号对于包含多个子项目的大型解决方案可以在根CMakeLists.txt中定义版本号子项目共享# 根CMakeLists.txt set(PROJECT_VERSION_MAJOR 1) set(PROJECT_VERSION_MINOR 2) set(PROJECT_VERSION_PATCH 3) add_subdirectory(subproject1) add_subdirectory(subproject2)4.3 条件编译不同配置根据构建类型(Debug/Release)设置不同的文件描述#ifdef _DEBUG VALUE FileDescription, Debug Build of Your Application #else VALUE FileDescription, Release Build of Your Application #endif4.4 版本信息国际化支持多语言版本信息只需添加额外的StringFileInfo块BEGIN BLOCK StringFileInfo BEGIN BLOCK 040904E4 // 英语(美国) BEGIN VALUE FileDescription, English Description END BLOCK 040404B0 // 中文(简体) BEGIN VALUE FileDescription, 中文描述 END END END5. 常见问题解决5.1 版本信息未显示如果生成的EXE文件属性中看不到版本信息检查确保.rc文件被正确包含在add_executable中确认资源编译器没有报错检查.rc文件是否被正确生成在构建目录5.2 版本号格式错误Windows资源文件要求版本号必须为四段式即使产品版本号显示为三段式在FILEVERSION和PRODUCTVERSION中仍需补充第四段(通常为0)。5.3 与MFC资源冲突如果项目同时使用MFC和CMake生成的资源文件可能会遇到资源冲突。解决方案将版本信息合并到主资源文件中使用RC_INCLUDES指定额外包含目录确保资源ID不重复set(CMAKE_RC_INCLUDES ${CMAKE_CURRENT_BINARY_DIR})5.4 64位构建问题对于64位应用程序确保资源编译器目标架构正确if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(CMAKE_RC_COMPILE_OBJECT ${CMAKE_RC_COMPILE_OBJECT} --targetpe-x86-64) endif()在实际项目中这套方案已经帮助多个团队平滑地从MFC迁移到CMake同时保持了版本信息的一致性和可维护性。特别是在持续集成环境中通过自动化脚本更新版本号大大减少了人为错误。