【问题标题】:Runtime errors in trivial static build of Qt hello world application in MSYS2/MinGWMSYS2/MinGW 中 Qt hello world 应用程序的简单静态构建中的运行时错误
【发布时间】:2020-11-25 03:31:05
【问题描述】:

我正在尝试使用 MSYS2/MinGW 为 Windows 构建一个简单的 Qt 应用程序,如下所示。

你好.cpp:

#include <QApplication>
#include <QWidget>

int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    QWidget window;
    window.setWindowTitle("Hello world");
    window.show();
    return app.exec();
}

我可以使用下面的命令构建它,它构建并运行成功:

g++ $(pkg-config Qt5Widgets Qt5Core --cflags) hello.cpp $(pkg-config Qt5Widgets --libs) -o hello

现在我想静态构建应用程序,以便可以将其作为独立的可执行文件部署/运行。 mingw-w64-x86_64-qt5-static 包似乎正是为了这个目的而存在的,所以我用pacman 安装了它(版本 5.15.1-1)。

默认情况下,静态 Qt 构建的 pkg-config 文件不在 PKG_CONFIG_PATH 中,所以我更新了 PKG_CONFIG_PATH 以首先搜索 qt5-static 中的文件:

PKG_CONFIG_PATH=/mingw64/qt5-static/lib/pkgconfig:$PKG_CONFIG_PATH

我还相应地更新了我的构建命令,以请求库的静态依赖项。但是,这会导致一堆错误:

$ g++ $(pkg-config Qt5Widgets Qt5Core --cflags) hello.cpp $(pkg-config Qt5Widgets --static --libs) -o hello
g++.exe: error: D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libQt5Gui.a: No such file or directory
g++.exe: error: D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtlibpng.a: No such file or directory
g++.exe: error: D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtharfbuzz.a: No such file or directory
g++.exe: error: D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libQt5Core.a: No such file or directory
g++.exe: error: D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtpcre2.a: No such file or directory
g++.exe: error: D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libQt5Core.a: No such file or directory
g++.exe: error: D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtpcre2.a: No such file or directory
g++.exe: error: D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtlibpng.a: No such file or directory
g++.exe: error: D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtharfbuzz.a: No such file or directory
g++.exe: error: D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtpcre2.a: No such file or directory

有问题的文件路径直接来自包中.pc 文件的Libs.private 部分。看起来他们可能正在使用包维护者的机器路径?

无论如何,由于我应该拥有所有这些库,因此我尝试通过将 pkg-config 输出通过管道传输到 sed 以将绝对路径替换为相应的 -l 标志来解决此问题,如下所示(对于例如,这会将D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtharfbuzz.a 替换为-lqtharfbuzz 等)。这会导致构建成功,但是当我尝试运行生成的可执行文件时,会显示运行时失败:

$ g++ --static -static-libstdc++ $(pkg-config Qt5Widgets Qt5Core --cflags) hello.cpp $(pkg-config Qt5Widgets --static --libs | sed 's/D:\/\S\+\/lib\(\S\+\)\.a\b/-l\1/g') -o hello
$ ./hello
qt.qpa.plugin: Could not find the Qt platform plugin "windows" in ""
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

那么,我的问题是,如何使用 MSYS2/MinGWmingw-w64-x86_64-qt5-static 构建静态 Qt 可执行文件?

编辑:为了提供更多的透明度,以防它有助于理解/调试问题,我在 bash 中使用set -x 运行相同的静态构建命令,以便您可以看到pkg-config 命令如何扩展。

没有sed 过滤器:

$ g++ --static -static-libstdc++ $(pkg-config Qt5Widgets Qt5Core --cflags) hello.cpp $(pkg-config Qt5Widgets --static --libs) -o hello
++ pkg-config Qt5Widgets Qt5Core --cflags
++ pkg-config Qt5Widgets --static --libs
+ g++ --static -static-libstdc++ -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -IC:/msys64/mingw64/qt5-static/include/QtWidgets -IC:/msys64/mingw64/qt5-static/include -IC:/msys64/mingw64/qt5-static/include/QtGui -IC:/msys64/mingw64/qt5-static/include -IC:/msys64/mingw64/qt5-static/include/QtCore -IC:/msys64/mingw64/qt5-static/include hello.cpp -LC:/msys64/mingw64/qt5-static/lib -lQt5Widgets D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libQt5Gui.a -ld3d11 -ldxgi -ldxguid D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtlibpng.a D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtharfbuzz.a -lcomdlg32 -loleaut32 -limm32 -lglu32 -lopengl32 -lgdi32 D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libQt5Core.a -lmpr -luserenv -lversion -lz D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtpcre2.a -lzstd -lnetapi32 -lws2_32 -ladvapi32 -lkernel32 -lole32 -lshell32 -luuid -luser32 -lwinmm -luxtheme -ldwmapi -lshell32 -lcomdlg32 -loleaut32 -limm32 -lwinmm -lws2_32 -lole32 -luuid -ladvapi32 -lglu32 -lopengl32 -lgdi32 -luser32 -lQt5Gui -ld3d11 -ldxgi -ldxguid D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libQt5Core.a -lmpr -luserenv -lversion -lz D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtpcre2.a -lzstd -lnetapi32 -lws2_32 -ladvapi32 -lkernel32 -lole32 -lshell32 -luuid -luser32 -lwinmm D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtlibpng.a D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtharfbuzz.a -lz -lcomdlg32 -loleaut32 -limm32 -lwinmm -lws2_32 -lole32 -luuid -ladvapi32 -lglu32 -lopengl32 -lgdi32 -luser32 -lQt5Core -lmpr -luserenv -lversion -lz D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtpcre2.a -lzstd -lnetapi32 -lws2_32 -ladvapi32 -lkernel32 -lole32 -lshell32 -luuid -luser32 -lwinmm -o hello
g++.exe: error: D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libQt5Gui.a: No such file or directory
g++.exe: error: D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtlibpng.a: No such file or directory
g++.exe: error: D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtharfbuzz.a: No such file or directory
g++.exe: error: D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libQt5Core.a: No such file or directory
g++.exe: error: D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtpcre2.a: No such file or directory
g++.exe: error: D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libQt5Core.a: No such file or directory
g++.exe: error: D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtpcre2.a: No such file or directory
g++.exe: error: D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtlibpng.a: No such file or directory
g++.exe: error: D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtharfbuzz.a: No such file or directory
g++.exe: error: D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/libqtpcre2.a: No such file or directory

使用sed 过滤器:

$ g++ --static -static-libstdc++ $(pkg-config Qt5Widgets Qt5Core --cflags) hello.cpp $(pkg-config Qt5Widgets --static --libs | sed 's/D:\/\S\+\/lib\(\S\+\)\.a\b/-l\1/g') -o hello
++ pkg-config Qt5Widgets Qt5Core --cflags
++ pkg-config Qt5Widgets --static --libs
++ sed 's/D:\/\S\+\/lib\(\S\+\)\.a\b/-l\1/g'
+ g++ --static -static-libstdc++ -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -IC:/msys64/mingw64/qt5-static/include/QtWidgets -IC:/msys64/mingw64/qt5-static/include -IC:/msys64/mingw64/qt5-static/include/QtGui -IC:/msys64/mingw64/qt5-static/include -IC:/msys64/mingw64/qt5-static/include/QtCore -IC:/msys64/mingw64/qt5-static/include hello.cpp -LC:/msys64/mingw64/qt5-static/lib -lQt5Widgets -lQt5Gui -ld3d11 -ldxgi -ldxguid -lqtlibpng -lqtharfbuzz -lcomdlg32 -loleaut32 -limm32 -lglu32 -lopengl32 -lgdi32 -lQt5Core -lmpr -luserenv -lversion -lz -lqtpcre2 -lzstd -lnetapi32 -lws2_32 -ladvapi32 -lkernel32 -lole32 -lshell32 -luuid -luser32 -lwinmm -luxtheme -ldwmapi -lshell32 -lcomdlg32 -loleaut32 -limm32 -lwinmm -lws2_32 -lole32 -luuid -ladvapi32 -lglu32 -lopengl32 -lgdi32 -luser32 -lQt5Gui -ld3d11 -ldxgi -ldxguid -lQt5Core -lmpr -luserenv -lversion -lz -lqtpcre2 -lzstd -lnetapi32 -lws2_32 -ladvapi32 -lkernel32 -lole32 -lshell32 -luuid -luser32 -lwinmm -lqtlibpng -lqtharfbuzz -lz -lcomdlg32 -loleaut32 -limm32 -lwinmm -lws2_32 -lole32 -luuid -ladvapi32 -lglu32 -lopengl32 -lgdi32 -luser32 -lQt5Core -lmpr -luserenv -lversion -lz -lqtpcre2 -lzstd -lnetapi32 -lws2_32 -ladvapi32 -lkernel32 -lole32 -lshell32 -luuid -luser32 -lwinmm -o hello

另外,目前我只是想了解如何使用现有的包 MSYS2 包从 MSYS2/Mingw 中的命令行构建这个简单的示例。我还没有对使用 Qt Creator/QMake/etc 感兴趣。管理构建。

【问题讨论】:

    标签: qt qt5 mingw static-libraries msys2


    【解决方案1】:

    为了避免qt.qpa.plugin: Could not find the Qt platform plugin "windows" in "",您需要静态链接到 Windows 平台插件。很可能您还希望静态链接到其他插件,例如用于 Qt Widgets 样式或 SVG 图标支持。

    建议阅读官方文档:https://doc.qt.io/qt-5/plugins-howto.html#static-plugins

    “创建静态插件”下的步骤很重要。由于您可能只使用 Qt 提供的插件,您当然可以跳过第一步。由于您没有使用 QMake,因此您不能遵循最后一步,而是需要手动将插件的相应静态库添加到链接器调用(以及它依赖的库)中。使用pacman -Ql mingw-w64-x86_64-qt5-static 查找安装中插件的路径。

    【讨论】:

    • 静态插件似乎是缺失的部分!有很多障碍要跳过,但我最终得到了一个独立的静态可执行文件。具体来说,我必须定义预处理器宏QT_STATICPLUGIN,在我的源文件中添加Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin) 宏,然后使用nm 进行依赖项搜索,以跟踪解决缺失引用所需的所有库。我有点惊讶我需要为此引入多少额外的库。我想这就是人们使用 qmake 的原因。
    • 不要期望使用 qmake 时会有流畅的体验。我想上游不支持使用 GCC/mingw-w64 进行静态构建,例如我不得不修补很多 (github.com/Martchus/PKGBUILDs/tree/master/qt5-base/…)。但是,我已经测试过使用 Qt 6 和 CMake 制作一个静态链接的可执行文件,这不那么老套了 (github.com/Martchus/PKGBUILDs/tree/master/qt6-base/…)。
    【解决方案2】:

    您必须构建 Qt 库的静态版本(它们只分发动态库)。

    本页:

    static Qt

    并不完全准确(我已经编辑了几次),但这是一个好的开始。

    【讨论】:

    • 我希望留在 MSYS2/MinGW64 外壳中并使用现有的 mingw-w64-x86_64-qt5-static 包,但由于这种方法似乎不起作用,也许我将不得不求助于生成我的正如您所指出的,拥有静态库并使用 Qt Creator 构建我的应用程序。不过,我仍然有兴趣了解我的方法存在什么问题。
    • 我真的不熟悉 mingw-w64-x86_64-qt5-static。我想知道它是否是一个不完整的构建,恰好缺少您需要的一些库。无论如何,我仍然建议您考虑构建自己的库。只需几个步骤,如果您愿意,我可以为您提供详细信息。
    【解决方案3】:

    看起来它正在寻找绝对位置 D:/mingwbuild/mingw-w64-qt5-static/src/x86_64/qtbase/lib/ 中的库。那不是您拥有库文件的位置是否正确?

    一个肮脏的解决方法是将它们复制到这个确切的位置。

    您也可以尝试添加 pkg-config 选项 --define-prefix 以查看是否修复了库文件的报告路径。

    要自己构建静态 Qt,请参阅我之前的说明: how to statically compile Qt using MinGW compiler and SSL support

    【讨论】:

    • 正确 - 这不是我机器上库文件的位置。我尝试了您的 --define-prefix 建议,但并没有解决问题。 .pc 文件中的 prefix 值似乎对于我的安装 (prefix=/mingw64/qt5-static) 是正确的,但 .pc 文件中的一些(不是全部)Libs.private 值使用这些绝对路径。正如你所建议的,我可能不得不自己构建一个静态 Qt,尽管我最初希望利用现有的 MSYS2 包。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-14
    • 2022-07-13
    • 1970-01-01
    • 2011-03-03
    • 1970-01-01
    • 2012-01-23
    • 2016-08-01
    相关资源
    最近更新 更多