Qt 和 Windows 可执行版本信息

Qt and Windows Executable Version Information

我的 Windows Qt 小部件应用程序使用 "version.h" 文件和 "RC" 文件来填充可执行文件的版本信息字符串。

version.h 看起来像这样...

#ifndef VERSION_H
#define VERSION_H

#define VERSION_MAJOR                           1
#define VERSION_MINOR                           0
#define VERSION_BUILD                           3

#define VER_FILEVERSION           VERSION_MAJOR,VERSION_MINOR,VERSION_BUILD,0
#define STR_FILEVERSION                     VERSION_MAJOR##"."##VERSION_MINOR##"."VERSION_BUILD##".0"

// Keep the product version as fixed
#define VER_PRODUCTVERSION        1.0.0.0
#define STR_PRODUCTVERSION          "1.0.0.0[=11=]"

#define STR_COMPANYNAME                     "MyCompany"
#define STR_FILEDESCRIPTION             "MyFile"
#define STR_INTERNALNAME                    "MyFile"
#define STR_LEGALCOPYRIGHT              "Copyright © 2017 MyCompany"
#define STR_LEGALTRADEMARKS1            "All Rights Reserved"
#define STR_LEGALTRADEMARKS2            STR_LEGALTRADEMARKS1
#define STR_ORIGINALFILENAME            "MyApp.exe"
#define STR_PRODUCTNAME                     "MyApp"

#define STR_COMPANYDOMAIN                   "mywebsite.com"

#endif // VERSION_H

RC 文件如下所示:

IDI_APP_ICON    ICON    DISCARDABLE     "MyApp.ico"

#include <windows.h>
#include "version.h"

VS_VERSION_INFO VERSIONINFO
FILEVERSION     VER_FILEVERSION
PRODUCTVERSION  VER_PRODUCTVERSION
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904E4"
        BEGIN
            VALUE "CompanyName",        STR_COMPANYNAME
            VALUE "FileDescription",    STR_FILEDESCRIPTION
            VALUE "FileVersion",        STR_FILEVERSION
            VALUE "InternalName",       STR_INTERNALNAME
            VALUE "LegalCopyright",     STR_LEGALCOPYRIGHT
            VALUE "LegalTrademarks1",   STR_LEGALTRADEMARKS1
            VALUE "LegalTrademarks2",   STR_LEGALTRADEMARKS2
            VALUE "OriginalFilename",   STR_ORIGINALFILENAME
            VALUE "ProductName",        STR_PRODUCTNAME
            VALUE "ProductVersion",     STR_PRODUCTVERSION
        END
    END

    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1252
    END
END

为了完整起见,“.pro”文件中包含以下行:

RC_FILE    = MyApp.rc

这一切似乎工作正常:当我右键单击 exe 并转到详细信息选项卡时,我可以看到版本信息和合并的 version.h 和 RC 文件中的所有其他字符串。

但是,如果我增加任何一个 VERSION_XXX #define 值并构建应用程序,我注意到报告的 "File version" 没有改变 - 只有当我执行"rebuild"版本有变化吗

我真的不想每次增加版本信息(目前主要是VERSION_BUILD)都必须完全重建,所以我需要做什么才能更新这些信息每次生成exe?

问题是 qmake 不支持 RC_FILE 的依赖项。那么对此可以做些什么呢?

1) 最简单和最快捷的方法是使用 touch:如果 MyApp.rc(几乎)永远不会改变,我们可以强制其时间戳遵循 version.h 之一。然后是这样的:

MyApp.pro

TARGET = MyApp
win*:RC_FILE = $${TARGET}.rc
win*:!build_pass:touch($$RC_FILE, version.h)
# ... more to follow

配合 qmake && make 就可以了。

2) 另一个看似简单的解决方案是 完全使用 RC_FILE,但让 qmake 从预定义变量自动生成资源脚本:VERSIONQMAKE_TARGET_COMPANYQMAKE_TARGET_DESCRIPTION 等。有关完整列表,请参阅 qmake Platform Notes

只需将 VERSION = x.y.z.n(并删除 RC_FILE = MyApp.rc)添加到您的 .pro 文件即可启用此功能。

这对大多数 Qt 应用程序来说已经足够了,只要它们使用自己的 Qt 资源系统,而 Windows .rc 脚本只需要应用程序 ICON(s) 和 VERSIONINFO。

上面的例子:

version.pri

RC_ICONS = MyApp.ico
VERSION = 1.0.3.0
QMAKE_TARGET_COMPANY = MyCompany
QMAKE_TARGET_DESCRIPTION = MyFile
QMAKE_TARGET_COPYRIGHT = "Copyright © 2017 MyCompany"
QMAKE_TARGET_PRODUCT = MyApp
RC_CODEPAGE = 1252
RC_LANG = 0x0409

MyApp.pro

TARGET = MyApp
#win*:RC_FILE = $${TARGET}.rc
win*:include(version.pri)
# ... more to follow

不幸的是,这会带来另一个问题:如果您的 C++ 源代码树中仍然需要 version.h,则必须以某种方式将其与 version.pri 同步。我认为使用 QMAKE_SUBSTITUTES 来自动生成 version.h 是最好的选择。不过加一堆DEFINES+=...也是个思路。

3) 您可以在 .pro 文件中创建自定义目标并自行编译资源脚本。例如:

MyApp.pro

TARGET = MyApp
#win*:RC_FILE = $${TARGET}.rc
win* {
    QMAKE_EXTRA_TARGETS += windows_resource
    windows_resource.target = $${TARGET}_res$${first(QMAKE_EXT_OBJ)}
    windows_resource.depends = $${TARGET}.rc version.h
    msvc:windows_resource.commands = $$QMAKE_RC /fo $$windows_resource.target $${TARGET}.rc
    else:windows_resource.commands = $$QMAKE_RC $${TARGET}.rc $$windows_resource.target
    PRE_TARGETDEPS += $$windows_resource.target
    LIBS += $$windows_resource.target
}
# ... more to follow