为什么链接到 Qt 5.9 的程序不能在 Qt 5.6 下 运行?

Why program linked against Qt 5.9 cannot run under Qt 5.6?

我有一个在Qt 5.9 环境下构建的程序。当我将程序复制到安装了Qt 5.6的服务器时,程序无法启动,报如下错误:

./myapp: /usr/lib64/libQt5Core.so.5: version `Qt_5.9' not found (required by ./myapp)

但是 /usr/lib64/libQt5Core.so.5 确实存在,它是 link 到 libQt5Core.so.5.6.1.

我认为 .so 文件的次要版本不会破坏兼容性。字符串`Qt_5.9'是如何进入myapp的,对程序的加载有什么影响?

Qt 库的次要版本仅保持 向后二进制和源兼容性,这意味着较旧的可执行文件将与较新的库一起工作(参见详细信息 here ).

因此,如果您打算在装有 Qt 5.6 的服务器上部署您的程序,则应使用 Qt 5.6 或更早版本进行编译,并且只要您不使用较新的次要版本中引入的功能,就应该能够在不更改任何内容的情况下使用旧版本重新编译。

版本符号“Qt_5.9”或“Qt_5.6”同时存储在可执行文件和库中。您可以使用 objdump -p /usr/lib64/libQt5Core.so.5objdump -p ./myapp 获取与库兼容的版本列表(列出每个次要版本),在“版本定义”部分下:

$ objdump -p /usr/lib64/libQt5Core.so.5

/usr/lib64/libQt5Core.so.5:     file format elf64-x86-64

[...]
Version definitions:
1 0x01 0x00028eb5 libQt5Core.so.5
2 0x00 0x0dcbd2c9 Qt_5_PRIVATE_API
3 0x00 0x00058a25 Qt_5
4 0x00 0x058a2810 Qt_5.0
        Qt_5 
5 0x00 0x058a2811 Qt_5.1
        Qt_5.0 
[...]
19 0x00 0x08a28115 Qt_5.15
        Qt_5.14

或在“版本参考”部分下编译可执行文件所针对的库版本:

$ objdump -p /bin/qtcreator

/bin/qtcreator:     file format elf64-x86-64

[...]    
Version References:
  required from libQt5Gui.so.5:
    0x00058a25 0x00 12 Qt_5
[...]
  required from libQt5Core.so.5:
    0x08a28115 0x00 06 Qt_5.15
    0x00058a25 0x00 02 Qt_5

ELF 二进制文件中的符号可能是版本化的,这意味着版本标记可能会添加到每个符号,链接器可能希望导入带有特定版本标记的符号。 objdump 输出中的“版本”部分似乎直接来自二进制文件中的结构(这些结构描述为 here)。

对于上面的示例,qtcreator 二进制文件从 libQt5Core.so.5 导入符号,同时 Qt_5Qt_5.15 版本标签,因此二进制文件依赖于定义这两者的库,任何 5.15 及更高版本的库都应该是这种情况。

Qt 使用 major.minor.patch Qt 版本编号方案。例如,Qt 5.0.1 代表 Qt 5.0 的第一个补丁版本。每个版本对可接受的更改类型都有限制,以提供可预测和稳定的 API。这使只对某些类型的改进感兴趣的用户可以确保他们不会因升级到较新版本而受到不利影响。

主要 版本可能会破坏向后的二进制和源兼容性,尽管可能会保持源兼容性。

次要 版本向后二进制和源代码兼容。

补丁 版本向后和向前二进制和源代码兼容。

所以你不能运行 qt 5.9 under qt 5.6!