使用静态 Qt 构建在 Linux 上部署 Qt5 应用程序

Posted

技术标签:

【中文标题】使用静态 Qt 构建在 Linux 上部署 Qt5 应用程序【英文标题】:Deploying Qt5 application on Linux using static Qt build 【发布时间】:2018-07-09 08:32:03 【问题描述】:

我已经使用以下命令在 ubuntu 上构建并安装了 Qt5.11 的静态构建:

make distclean; ./configure 
-static -release -ltcg -optimize-size -no-pch -prefix 
"/opt/qt/511-static-release" -skip webengine -nomake tools 
-nomake tests -nomake examples; make -j 8; make install;

构建成功完成。

然后我尝试将我的项目与此构建链接,但它失败了。以下是最后几行输出:

编译输出(Qt-Creator)

...

../src/config/config_dialog.h -o moc_config_dialog.cpp
g++ -c -pipe -std=c++11 -g -std=gnu++11 -Wall -W -D_REENTRANT -fPIC - 
DQT_DEPRECATED_WARNINGS -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB 
-DQT_CORE_LIB -I../../my-gui-qt -I. -I../src/view/ -I./model - 
I/opt/qt/511-static-release/include -I/opt/qt/511-static- 
release/include/QtWidgets -I/opt/qt/511-static-release/include/QtGui - 
I/opt/qt/511-static-release/include/QtNetwork -I/opt/qt/511-static- 
release/include/QtCore -I. -isystem /usr/include/libdrm -I. - 
I/opt/qt/511-static-release/mkspecs/linux-g++ -o moc_config_dialog.o 
moc_config_dialog.cpp

链接器输出

 g++ -Wl,-Bdynamic -lGL -static -fPIC -o my-gui-qt main.o 
 mainwindow.o task_status_delegate.o my-gui-qt_plugin_import.o  
 qrc_resources.o moc_mainwindow.o moc_task_table_view.o 
 moc_task_table_model.o moc_config_dialog.o 
 -L/opt/qt/511-static-release/lib -lQt5OpenGL -L/usr/lib/x86_64-linux-
 gnu -L/opt/qt/511-static-release/plugins/platforms 
 -lqxcb -L/opt/qt/511-static--release/plugins/xcbglintegrations 
 -lqxcb-glx-integration -lQt5XcbQpa -lQt5ServiceSupport 
 -lQt5ThemeSupport -lQt5EventDispatcherSupport 
 -lQt5FontDatabaseSupport -lfontconfig -lfreetype -lQt5GlxSupport - 
 lXext -lQt5EdidSupport -lxcb-glx -lX11-xcb -lX11 -lXi -lSM -lICE - 
 lXrender -lxcb-static -lxcb -L/opt/qt/511-static- 
 release/plugins/imageformats -lqgif -lqicns -lqico -lqjpeg -lqtga - 
 lqtiff -lqwbmp -lqwebp -L/opt/qt/511-static-release/plugins/bearer - 
 lqconnmanbearer -lqgenericbearer -lqnmbearer -lQt5DBus -lQt5Widgets - 
 lQt5Gui -lpng12 -lqtharfbuzz -lQt5Network -lQt5Core -lm -lz -licui18n 
 -licuuc -licudata -lqtpcre2 -ldl -lgthread-2.0 -lglib-2.0 -lGL - 
 lpthread 

链接器警告

../../include/QtCore/../../src/corelib/kernel/qobjectdefs_impl.h:163:46:警告:类型“结构函数”违反了一个定义规则 [-Wodr] .moc/qcolordialog.moc:111:57:注意:在另一个翻译单元中定义了不同的类型

dialogs/qcolordialog.cpp:1738:41: 注意:对应定义的第一个区别是字段‘__pfn’

.moc/qcolordialog.moc:111:56:注意:在另一个翻译单元中定义了同名但不同类型的字段 lto1:注意:参数 1 中的类型不匹配 dialogs/qcolordialog.cpp:179:7: 注意:匿名命名空间中定义的类型‘struct QWellArray’不能匹配类型‘struct QWellArray’

dialogs/qcolordialog.cpp:180:1:注意:在另一个翻译单元的匿名命名空间中定义的不兼容类型 qicohandler.cpp:95:3:警告:类型‘struct BMP_INFOHDR’违反了一个定义规则[-Wodr]

... 还有一些类似的警告..

链接完成并生成可执行文件,但它不可运行。我可以看到文件在那里:

$ file my-gui-qt

$ my-gui-qt: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), 
dynamically linked, interpreter /lib/ld64.so.1, for GNU/Linux 2.6.32, 
BuildID[sha1]=0e22025dfc5f4bf4dbba598a6f692607303b68c, not stripped

但是尝试运行它会报错:

me@me-Inspiron-15-7000-Gaming:~/code/my-gui-qt/build-static$ ./my-gui- 
qt 
bash: ./my-gui-qt: No such file or directory

编辑:我能够使用相同的 Qt 5.11 静态构建和使用相同库的琐碎(微小)Qt 应用程序来重现此问题。应用程序编译并运行良好,直到我添加与上面的 my-gui-qt 应用程序相同的 QMAKE 标志:

QMAKE_LFLAGS += -Wl,-Bdynamic -lGL -static

原因是不同的解释器链接到 exe:

所以没有上面的 QMAKE_LFLAGS

$file TestProject*

给予:

TestProject: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), 
dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for 
GNU/Linux 2.6.32, 
BuildID[sha1]=993c09e6977c18772569a5a6ecb452c03a884f2d, not stripped

并且运行良好。然而,它给出的标志是:

TestProject: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), 
dynamically linked, interpreter /lib/ld64.so.1, for GNU/Linux 2.6.32, 
BuildID[sha1]=29674cc4997c91b45f9c87bc53ee858b12639e3b, not stripped

并且不运行(bash: : 没有这样的文件或目录)。似乎设置 -Bdynamic 标志将使 gcc 回退到 Ubuntu16.04 中不存在的通用 Unix gcc 解释器 /lib/lib64.so.1。不知道如何解决这个问题?试过 -Wl,--dynamic-linker=/lib/ld-lsb.so.2 没有成功..

【问题讨论】:

这些是警告。它们不会导致链接失败。在问题中包含链接错误怎么样? @KubaOber 嗯,谢谢。那是愚蠢的。我看到所有这些实际上只是警告,并且可执行文件已创建但不可运行。已修改问题。 尝试在调试器下(从命令行)运行它,并确保你没有做傻事。至少,看看错误的真正来源:编写一个重现问题的bash -c 调用,然后 strace 看看究竟是什么失败了。 虽然这些警告不是一个好兆头,但我预计会崩溃。也许您没有以某种方式将它与正确的 Qt 副本链接起来。 Qt Creator 通常会正确设置,但可能有其他问题。您不会有任何机会手动弄乱包含路径,对吧?尝试使用 Qt 的副本构建一些最小的东西。在没有nomake tools 的情况下重建并检查您是否可以从 Qt 安装中运行designer @KubaOber 很酷,感谢您的想法。我会尽快这样做。有一些不相关的问题要先解决,但希望能够创建 exe 并进行这些检查 【参考方案1】:

所以事实证明这个问题之前已经回答过,我只是看不到它。

当将 Qt 应用程序链接到 Qt 的静态版本但保留一些组件 (libGL.so) 以动态链接时(即 QMAKE_LFLAGS += -Wl,-Bdynamic,- -lGL -static),ELF 解释器可能会解析为它的默认值(因为上面的命令覆盖了特定的解释器路径),所以要恢复它,你应该再次指定它(正如许多其他人所说的那样):

QMAKE_LFLAGS += -Wl,-dynamic-linker=/lib64/ld-linux-x86-64.so.2  

应用程序现在运行良好。使用这些标志的组合时,仍然存在多个定义警告(即使对于普通的 Qt 应用程序)。

【讨论】:

以上是关于使用静态 Qt 构建在 Linux 上部署 Qt5 应用程序的主要内容,如果未能解决你的问题,请参考以下文章

Linux Mint x64:Qt 5.3.1 插件部署:不兼容的 qt 库

使用 MinGW 静态构建 Qt 5.7 时,如何解决此构建错误?

在 linux 上部署 Qt5.10 App 时出错

如何建立Qt Creator交叉编译嵌入式Linux

如何将我的静态 Qt 构建与 Creator 一起使用?

Qt5 部署的 QtWebEngine 项目不播放 Html5 视频