如何使用CMake生成Windows DLL版本信息

36
我正在使用CMake构建共享库,但是对于Windows DLL,我需要版本信息,例如:
  • 文件描述
  • 文件版本
  • 内部名称
  • 版权所有
  • 原始文件名
  • 产品名称
  • 产品版本
到目前为止,我只有VERSION和SOVERSION属性,但这些似乎与我预期的FileVersion信息不相关。
set(LIC_TARGET MySharedLib)
add_library(${LIC_TARGET} SHARED ${SOURCES} )

SET_TARGET_PROPERTIES(${LIC_TARGET}
    PROPERTIES
    VERSION ${MY_PRODUCT_NUMBER}.${MY_PRODUCT_VERSION}.${MY_BUILD_NUMBER}
    SOVERSION ${MY_PRODUCT_NUMBER})

我找到了手动方法(请参见底部示例),但更希望将其包含在CMake中。
求助?

1
“手动方法”链接中的示例缺少一行重要代码:#include <windows.h> - Patrick
3个回答

29

你可以使用CMake变量值与 version.rc.in 文件以及 configure_file 命令相结合。

// version.rc.in
#define VER_FILEVERSION             @MY_PRODUCT_NUMBER@,@MY_PRODUCT_VERSION@,@MY_BUILD_NUMBER@,0
#define VER_FILEVERSION_STR         "@MY_PRODUCT_NUMBER@.@MY_PRODUCT_VERSION@.@MY_BUILD_NUMBER@.0\0"

#define VER_PRODUCTVERSION          @MY_PRODUCT_NUMBER@,@MY_PRODUCT_VERSION@,@MY_BUILD_NUMBER@,0
#define VER_PRODUCTVERSION_STR      "@MY_PRODUCT_NUMBER@.@MY_PRODUCT_VERSION@.@MY_BUILD_NUMBER@\0"
//
// ...along with the rest of the file from your "manual methods" reference

然后,在你的CMakeLists.txt文件中:

# CMakeLists.txt
set(MY_PRODUCT_NUMBER 3)
set(MY_PRODUCT_VERSION 5)
set(MY_BUILD_NUMBER 49)

configure_file(
  ${CMAKE_CURRENT_SOURCE_DIR}/version.rc.in
  ${CMAKE_CURRENT_BINARY_DIR}/version.rc
  @ONLY)

set(LIC_TARGET MySharedLib)
add_library(${LIC_TARGET} SHARED ${SOURCES}
  ${CMAKE_CURRENT_BINARY_DIR}/version.rc)

# Alternatively you could simply include version.rc in another rc file
# if there already is one in one of the files in ${SOURCES}

1
非常感谢!这比手动准备rc文件更加集成化。 - lellobot

17

我曾经遇到过同样的问题,并为我的项目自动生成了版本号。你需要从GitHub下载三个文件:

将它们放在你项目的 cmake 子目录下,并确保将其包含在 CMAKE_MODULE_PATH 中,例如:

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)

在添加您的目标之前,使用add_executable()或add_library(SHARED):

include(generate_product_version)
generate_product_version(
   VersionFilesOutputVariable
   NAME "My Great Project"
   ICON ${PATH_TO_APPLICATION_ICON}
   VERSION_MAJOR 1
   VERSION_MINOR 3
   VERSION_PATCH ${BUILD_COUNTER}
   VERSION_REVISION ${BUILD_REVISION}
)

完整支持的资源字符串列表请参见generate_product_version.cmake

VersionInfo.h和VersionResource.rc将生成到CMake二进制文件夹中。变量VersionFilesOutputVariable将保存指向这些文件的路径。只需将此列表添加到您的目标即可:

add_executable(MyGreatProject ${your-target-sources} ${VersionFilesOutputVariable})

更新: 将 generate_product_version 脚本的参数从 VERSION_PATH 改为 VERSION_PATCH。


4
这将生成带有“俄语”作为语言的二进制文件,可能不合适。BLOCK "040904b0" 将其更改为英语。如果您在一个 CmakeList.txt 中有多个目标,则无法使用它,我已经在这里添加了我们使用的内容:https://github.com/arangodb/arangodb/commit/2d23ce989c1247708fba0640d48b52b04ece175c - dothebart
据我所知,要生成非本地化版本信息,我们应该将VersionResource.rc中的翻译值更改为:VALUE "Translation", 0x409, 1252。否则,某些信息无法正确生成,例如公司名称。同样,除非进行此更改,否则我们无法从PowerShell获取正确的版本信息。 - simon_tulia

8

有一种比已接受的答案更简单的方法。它不涉及转换输入资源.rc.in。只需按照这里所述创建一个通用版本的.rc文件,然后从您的CMakeLists.txt中执行以下操作:

#CMakeLists.txt

add_definitions(-DVER_COMPANYNAME_STR="MyCompany")
add_definitions(-DVER_FILEVERSION_STR="1,1,0.0")
# ...
# add all the other defines here

set(LIC_TARGET MySharedLib)
add_library(${LIC_TARGET} SHARED ${SOURCES} version.rc)

这样做的额外好处是,您的源代码也可以访问这些定义,因此您可以以编程方式访问您的版本信息。

1
我喜欢这个想法,但请注意更新.rc文件只需要重新链接。 更新-D定义需要重新链接以及重建任何受影响的源文件...可能会慢得多。 - elegant dice
还要注意,通过Microsoft的GetFileVersionInfo API,您可以以编程方式获取版本号。在Microsoft平台上不需要#define。但这种方法仍然非常适用于跨平台灵活性。 - elegant dice
2
虽然您可以在CMake中使用set_source_files_properties()仅在.rc文件上设置这些定义。 - elegant dice
这是cmake对nmake的一个功能,还是cmake对Visual Studio的一个功能(因此在mingw上不可用)? - Groostav
@Groostav .rc文件仅适用于Windows。定义只是C定义,因此跨平台。 - Alf
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接