Protobuf 版本与 Qt 冲突

Protobuf version conflicts with Qt

我正在尝试将 protobufs v 3.3.2 与 Qt 5.9.1 一起使用。这适用于某些 Qt 应用程序,但前提是它们是命令行程序。使用 Qt 和 protobufs 创建 GUI 应用程序后,出现此错误:

[libprotobuf FATAL /home/mkraus/Documents/dev/star385/build/linux-desktop-debug-libs/protobuf/src/src/google/protobuf/stubs/common.cc:78] This program was compiled against version 2.6.1 of the Protocol Buffer runtime library, which is not compatible with the installed version (3.3.2). Contact the program author for an update. If you compiled the program yourself, make sure that your headers are from the same version of Protocol Buffers as your link-time library. (Version verification failed in "/build/mir-ui6vjS/mir-0.26.3+16.04.20170605/obj-x86_64-linux-gnu/src/protobuf/mir_protobuf.pb.cc".)

我应该澄清一下,我的代码部分确实使用了 3.3.2 版(我正在从 git 源下载和编译 protobufs 并进行静态链接)。查看下面的堆栈跟踪,了解 Qt 引用的某些内容导致 protobuf 版本不匹配。

我正在 Ubuntu 16.04 上开发并使用默认桌面环境 (Unity)。

解决方法

我的故障排除揭示了这些症状和解决方法:

问题

如何将 protobufs 3.3.2 与 Qt GUI 应用程序一起使用,并且不依赖于正在使用的桌面环境? Qt是否使用2.6.1版本的protobufs,如果是,编译Qt使用protobufs 3.3.2是否可行?

调试信息

这是堆栈跟踪(程序几乎在启动时立即崩溃):

terminate called after throwing an instance of 'google::protobuf::FatalException'
  what():  This program was compiled against version 2.6.1 of the Protocol Buffer runtime library, which is not compatible with the installed version (3.3.2).  Contact the program author for an update.  If you compiled the program yourself, make sure that your headers are from the same version of Protocol Buffers as your link-time library.  (Version verification failed in "/build/mir-ui6vjS/mir-0.26.3+16.04.20170605/obj-x86_64-linux-gnu/src/protobuf/mir_protobuf.pb.cc".)

Thread 1 "scan" received signal SIGABRT, Aborted.
0x00007ffff4dff428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
54  ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  0x00007ffff4dff428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
#1  0x00007ffff4e0102a in __GI_abort () at abort.c:89
#2  0x00007ffff543984d in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007ffff54376b6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x00007ffff5437701 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x00007ffff5437919 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x0000000000603e0a in google::protobuf::internal::LogMessage::Finish (this=0x7fffffffc250)
    at /home/mkraus/Documents/dev/star385/build/linux-desktop-debug-libs/protobuf/src/src/google/protobuf/stubs/common.cc:268
#7  0x0000000000603e5a in google::protobuf::internal::LogFinisher::operator= (this=0x7fffffffc20f, other=...)
    at /home/mkraus/Documents/dev/star385/build/linux-desktop-debug-libs/protobuf/src/src/google/protobuf/stubs/common.cc:276
#8  0x0000000000603171 in google::protobuf::internal::VerifyVersion (headerVersion=2006001, minLibraryVersion=2006000, 
    filename=0x7fffde80aec0 "/build/mir-ui6vjS/mir-0.26.3+16.04.20170605/obj-x86_64-linux-gnu/src/protobuf/mir_protobuf.pb.cc")
    at /home/mkraus/Documents/dev/star385/build/linux-desktop-debug-libs/protobuf/src/src/google/protobuf/stubs/common.cc:86
#9  0x00007fffde7d490b in mir::protobuf::protobuf_AddDesc_mir_5fprotobuf_2eproto() ()
   from /usr/lib/x86_64-linux-gnu/libmirprotobuf.so.3
#10 0x00007fffde7d2409 in ?? () from /usr/lib/x86_64-linux-gnu/libmirprotobuf.so.3
#11 0x00007ffff7de76ba in call_init (l=<optimized out>, argc=argc@entry=1, argv=argv@entry=0x7fffffffd5d8, 
    env=env@entry=0x7fffffffd5e8) at dl-init.c:72
#12 0x00007ffff7de77cb in call_init (env=0x7fffffffd5e8, argv=0x7fffffffd5d8, argc=1, l=<optimized out>) at dl-init.c:30
#13 _dl_init (main_map=main_map@entry=0xa2f450, argc=1, argv=0x7fffffffd5d8, env=0x7fffffffd5e8) at dl-init.c:120
#14 0x00007ffff7dec8e2 in dl_open_worker (a=a@entry=0x7fffffffc6e0) at dl-open.c:575
#15 0x00007ffff7de7564 in _dl_catch_error (objname=objname@entry=0x7fffffffc6d0, errstring=errstring@entry=0x7fffffffc6d8, 
    mallocedp=mallocedp@entry=0x7fffffffc6cf, operate=operate@entry=0x7ffff7dec4d0 <dl_open_worker>, args=args@entry=0x7fffffffc6e0)
    at dl-error.c:187
#16 0x00007ffff7debda9 in _dl_open (file=0xa2f048 "/opt/Qt5.8.0/5.8/gcc_64/plugins/platformthemes/libqgtk3.so", mode=-2147479551, 
    caller_dlopen=0x7ffff599b7a8, nsid=-2, argc=<optimized out>, argv=<optimized out>, env=0x7fffffffd5e8) at dl-open.c:660
#17 0x00007ffff1806f09 in dlopen_doit (a=a@entry=0x7fffffffc910) at dlopen.c:66
#18 0x00007ffff7de7564 in _dl_catch_error (objname=0xa02b80, errstring=0xa02b88, mallocedp=0xa02b78, 
    operate=0x7ffff1806eb0 <dlopen_doit>, args=0x7fffffffc910) at dl-error.c:187
#19 0x00007ffff1807571 in _dlerror_run (operate=operate@entry=0x7ffff1806eb0 <dlopen_doit>, args=args@entry=0x7fffffffc910)
    at dlerror.c:163
#20 0x00007ffff1806fa1 in __dlopen (file=<optimized out>, mode=<optimized out>) at dlopen.c:87
#21 0x00007ffff599b7a8 in ?? () from /opt/Qt5.8.0/5.8/gcc_64/lib/libQt5Core.so.5
#22 0x00007ffff5994fd5 in ?? () from /opt/Qt5.8.0/5.8/gcc_64/lib/libQt5Core.so.5
#23 0x00007ffff598a647 in QFactoryLoader::instance(int) const () from /opt/Qt5.8.0/5.8/gcc_64/lib/libQt5Core.so.5
#24 0x00007ffff6b392f1 in ?? () from /opt/Qt5.8.0/5.8/gcc_64/lib/libQt5Gui.so.5
#25 0x00007ffff6b43538 in QGuiApplicationPrivate::createPlatformIntegration() () from /opt/Qt5.8.0/5.8/gcc_64/lib/libQt5Gui.so.5
#26 0x00007ffff6b43edd in QGuiApplicationPrivate::createEventDispatcher() () from /opt/Qt5.8.0/5.8/gcc_64/lib/libQt5Gui.so.5
#27 0x00007ffff59a57d6 in QCoreApplicationPrivate::init() () from /opt/Qt5.8.0/5.8/gcc_64/lib/libQt5Core.so.5
#28 0x00007ffff6b456ab in QGuiApplicationPrivate::init() () from /opt/Qt5.8.0/5.8/gcc_64/lib/libQt5Gui.so.5
#29 0x00007ffff6b46364 in QGuiApplication::QGuiApplication(int&, char**, int) () from /opt/Qt5.8.0/5.8/gcc_64/lib/libQt5Gui.so.5
#30 0x00000000005c55bd in main (argc=1, argv=0x7fffffffd5d8) at /home/mkraus/Documents/dev/star385/src/linux/ui/scan/main.cpp:35

您可以找到 here 关于同一问题的讨论,他们讨论了一个有趣的解决方法。

这个错误似乎是由位于 /opt/Qt/5.9/gcc_64/plugins/platformthemes 的库 libqgtk3.so 引起的。如果您的项目中不需要它,您可以 rename/remove 它来消除错误。

如果您使用 CMake 作为构建系统,您还需要注释文件中的所有行 /opt/Qt/5.9/gcc_64/lib/cmake/Qt5Gui/Qt5Gui_QGtk3ThemePlugin.cmake 以避免配置问题。

补充一下,真正的问题来自依赖于 libprotobuf 的库 libmir。由于这种硬依赖性,每当您尝试将最新的 tensorflow 与 libgtk3.0 一起使用时,您可能会 运行 解决此问题。由于 libmir 依赖于系统 libprotobuf,它通常落后于 tensorflow(从存储库下载自己的版本)使用的版本。

好消息,libgtk 上的这个 BUG 已报告并已修复,但要使用已修复的版本,您必须移至 libgtk3.0 3.22(请参阅 BUG 报告)。

如果您使用的是 Ubuntu 包存储库中的 Qt,您可以通过卸载 qt5-gtk-platformtheme 来删除有问题的库。这将删除 libqgtk3.so 和相应的 CMake 文件,而不必诉诸可能产生意外后果的黑客攻击。

一样,这个错误是libqgtk3插件设置GUI风格引起的。 libqgtk3 使用 libmir 系统库,它使用 protobuf 2.6.1。这会导致应用程序启动时发生冲突。

我找到了一个可以让您避免编辑 Qt 文件的解决方法:

  1. 您需要将 "plugins" 文件夹从“.../Qt/5.хх.хх/gcc_64/”复制到其他位置(例如,项目旁边构建文件夹)。
  2. 然后您必须从复制的文件夹中删除 "platformthemes/libqgtk3.so" 和 "platformthemes/libqgtk3.so.debug"。
  3. 在main()中,在创建QApplication实例之前,调用静态函数"QApplication::setLibraryPaths("path/to/copied/plugins/folder")".
  4. 最后,您必须添加变量 "LD_LIBRARY_PATH",其值为“.../Qt/5.хх.хх/gcc_64/lib”(正确路径取决于您的 Qt 版本) Qt Creator 中项目的 "environment settings"。您还可以添加值为“1”的 "QT_DEBUG_PLUGINS" 变量。它将允许您检查您的项目使用了哪些插件,并从发布版本中删除不需要的插件。

总结一下,这个错误是运行项目在Ubuntu16.04时出现的,但是当我切换到18.04版本时它就消失了。似乎在18.04版本的应用程序使用默认的Qt风格而不是GTK风格。