【问题标题】:Why program linked against Qt 5.9 cannot run under Qt 5.6?为什么链接到 Qt 5.9 的程序不能在 Qt 5.6 下运行?
【发布时间】:2021-04-30 04:10:41
【问题描述】:

我有一个在 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 确实存在,它是指向 libQt5Core.so.5.6.1 的链接。

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

【问题讨论】:

  • 你是如何配置/链接你的程序的?您是否使用了一些 Qt 5.6 中没有的功能?
  • 我认为 .so 文件的次要版本不会破坏兼容性。 对于 Qt 5.6 中已经存在的函数,这是正确的。但是,即使是次要版本也可能会引入可能在应用程序中使用的新功能。此类应用程序无法在旧版本上运行。
  • 我认为这与 Qt5.6 和 Qt 5.9 之间的代码更改无关,因为由于找不到.so,程序甚至还没有启动。我认为也许 .so 加载器决定不加载 libQt5Core.so.5.6.1,因为它不包含程序所需的标志“Qt_5.9”。我不清楚 .so 加载程序如何加载 .so。它不只是按文件名加载吗?

标签: c++ qt qt5 shared-libraries dynamic-linking


【解决方案1】:

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 及更高版本的库都应该是这种情况。

【讨论】:

  • 感谢您的回答。你能解释一下objdump -p输出的含义吗?为什么“required from libQt5Core.so.5”下有两个版本:Qt_5.15和Qt_5? qtcreator 是否需要 Qt_5.15 或 Qt_5,或两者都需要?
  • @William:我用您询问的其他解释编辑了我的答案。我发现只有一个带有Qt_5.15标签的符号,也就是“qtbase/src/corelib/global/qversiontagging.h”中定义的qt_version_tag,其他都使用Qt_5标签,所以这只是一个防止版本不匹配的方法,而不是确定在特定次要版本中引入了哪个符号(函数、类、类成员......)的方法,与例如 /usr/lib64/libc.so.6 不同,其中每个符号似乎都标有首次引入它们的库的次要版本。
【解决方案2】:

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

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

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

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

所以你不能在qt 5.6下运行qt 5.9

【讨论】:

    猜你喜欢
    • 2018-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-22
    • 2012-01-05
    • 2016-05-25
    • 2019-01-02
    相关资源
    最近更新 更多