如何修复“即使找到了,也无法在“”中加载 Qt 平台插件“xcb”。在 fixup_bundle 宏之后?

Lui*_*Kao 7 c++ qt cmake shared-libraries qml

我正在尝试设置一个可以在大多数 Linux 发行版(例如 Blender)上运行的独立二进制存档 (.tar.gz)。我仍然不熟悉 CMake。据我所知,所有依赖项都可以在安装步骤中使用fixup_bundle宏解决。而且我假设安装目录应该成为一个独立的应用程序,可以在没有安装 Qt 的情况下复制并在其他计算机上运行?我不确定 CPack 在这里的作用。

我试过的

我的 Qt 安装路径是/home/<user>/Qt5.12.2/5.12.2/gcc_64/qmake. 我已经遵循了一些答案并复制platform/libqxcb.solibQt5XcbQpa.so.5进入了安装目录。为了测试的独立包,我改变~/Qt5.12.2~/qt。这是可执行文件运行时的错误消息:

qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: xcb.

[1]    25965 abort (core dumped)  ./<executable_name>
Run Code Online (Sandbox Code Playgroud)

我也试过qt.conf将前缀和插件路径设置为,./但这没有用。我发现的一件有趣的事情是,当我设置时Plugins = /home/<user>/qt/5.12.2/gcc_64/plugins,会显示一个小 Qt 窗口,但带有一堆错误消息:

qrc:/main.qml:4:1: module "QtQuick.Dialogs" is not installed
qrc:/main.qml:1:1: module "QtQuick" is not installed
qrc:/main.qml:3:1: module "QtQuick.Controls" is not installed
......
qrc:/main.qml:3:1: module "QtQuick.Controls" is not installed
qrc:/main.qml:5:1: module "QtQuick.Controls.Styles" is not installed
qrc:/main.qml:2:1: module "QtQuick.Layouts" is not installed
Run Code Online (Sandbox Code Playgroud)

然后,我通过测试两个 libqxcb.so 找到了一些信息ldd,尽管我不确定这是真正的原因。

ldd ~/qt/5.12.2/gcc_64/plugins/platforms/libqxcb.so 显示原始的 libqxcb.so 链接了 Qt 安装附带的库:

        libQt5XcbQpa.so.5 => /home/giokka/qt/5.12.2/gcc_64/plugins/platforms/../../lib/libQt5XcbQpa.so.5 (0x00007ff8936d7000)
        libQt5Gui.so.5 => /home/giokka/qt/5.12.2/gcc_64/plugins/platforms/../../lib/libQt5Gui.so.5 (0x00007ff892d64000)
        libQt5DBus.so.5 => /home/giokka/qt/5.12.2/gcc_64/plugins/platforms/../../lib/libQt5DBus.so.5 (0x00007ff892ad8000)
        libQt5Core.so.5 => /home/giokka/qt/5.12.2/gcc_64/plugins/platforms/../../lib/libQt5Core.so.5 (0x00007ff892343000)
......
        libicui18n.so.56 => /home/giokka/qt/5.12.2/gcc_64/plugins/platforms/../../lib/libicui18n.so.56 (0x00007ff8914ee000)
        libicuuc.so.56 => /home/giokka/qt/5.12.2/gcc_64/plugins/platforms/../../lib/libicuuc.so.56 (0x00007ff891136000)
        libicudata.so.56 => /home/giokka/qt/5.12.2/gcc_64/plugins/platforms/../../lib/libicudata.so.56 (0x00007ff88f751000)
......
Run Code Online (Sandbox Code Playgroud)

ldd <path_to_project>/build/install/platforms/libqxcb.so 显示它链接到系统 Qt 库,这不是我的项目所基于的库:

./platforms/libqxcb.so: /lib64/libQt5XcbQpa.so.5: version `Qt_5_PRIVATE_API' not found (required by ./platforms/libqxcb.so)
./platforms/libqxcb.so: /lib64/libQt5Gui.so.5: version `Qt_5_PRIVATE_API' not found (required by ./platforms/libqxcb.so)
        libQt5XcbQpa.so.5 => /lib64/libQt5XcbQpa.so.5 (0x00007f1d8ea75000)
        libQt5Gui.so.5 => /lib64/libQt5Gui.so.5 (0x00007f1d8e41e000)
        libQt5DBus.so.5 => /lib64/libQt5DBus.so.5 (0x00007f1d8e382000)
        libQt5Core.so.5 => /lib64/libQt5Core.so.5 (0x00007f1d8de62000)
......
        libicui18n.so.63 => /lib64/libicui18n.so.63 (0x00007f1d8cf37000)
        libicuuc.so.63 => /lib64/libicuuc.so.63 (0x00007f1d8cd64000)
        libicudata.so.63 => /lib64/libicudata.so.63 (0x00007f1d8afd0000)
......
Run Code Online (Sandbox Code Playgroud)

源代码

CMakeLists.txt

cmake_minimum_required(VERSION 3.10 FATAL_ERROR)

project(OpenGLUnderQML LANGUAGES CXX)

set(CMAKE_PREFIX_PATH "$ENV{HOME}/Qt5.12.2/5.12.2/gcc_64/lib/cmake")
set(qt_lib_path "$ENV{HOME}/Qt5.12.2/5.12.2/gcc_64")

list(APPEND qt_modules
    Core
    Gui
    Quick
    DBus
)

foreach(module ${qt_modules})
    list(APPEND qt_libs "Qt5::${module}")
endforeach()

include(GNUInstallDirs)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}")


find_package(Qt5 COMPONENTS ${qt_modules} REQUIRED)

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

include_directories(include/)

list(APPEND headers
    include/Scene.hpp
    include/Renderer.hpp
    include/VertexArray.hpp
    include/VertexBuffer.hpp
    include/VertexLayout.hpp
    include/IndexBuffer.hpp
    include/Shader.hpp
)

list(APPEND qrc
    qml/qml.qrc
    res/fonts.qrc
    res/shaders.qrc
)

add_executable(${PROJECT_NAME}
    src/main.cpp
    src/Scene.cpp
    src/Renderer.cpp
    src/VertexArray.cpp
    src/VertexBuffer.cpp
    src/VertexLayout.cpp
    src/IndexBuffer.cpp
    src/Shader.cpp
    ${headers}
    ${qrc}
)

target_link_libraries(${PROJECT_NAME}
    PUBLIC
        ${qt_libs}
)


file(RELATIVE_PATH _rel "${CMAKE_INSTALL_PREFIX}/install" "${CMAKE_INSTALL_PREFIX}")
set(_rpath "\$ORIGIN/${_rel}")
file(TO_NATIVE_PATH "${_rpath}/install" app_RPATH)

set_target_properties(${PROJECT_NAME}
    PROPERTIES
        SKIP_BUILD_RPATH OFF
        BUILD_WITH_INSTALL_RPATH OFF
        INSTALL_RPATH ${app_RPATH}
        INSTALL_RPATH_USE_LINK_PATH ON
)

install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_BINARY_DIR}/install)
install(
    CODE "
include(BundleUtilities)
fixup_bundle(\"${CMAKE_BINARY_DIR}/install/${PROJECT_NAME}\" \"\" \"\")
"
    DESTINATION ${CMAKE_BINARY_DIR}/install
    COMPONENT Runtime
)

install(FILES "$<TARGET_FILE:Qt5::QXcbIntegrationPlugin>" DESTINATION ${CMAKE_BINARY_DIR}/install/platforms)

Run Code Online (Sandbox Code Playgroud)

配置文件

[Paths]
Prefix = ./
Plugins = /home/giokka/qt/5.12.2/gcc_64/plugins
Run Code Online (Sandbox Code Playgroud)

更新01:

这是我的qt.conf文件,但它不起作用。

[Paths]
Prefix = .
Libraries = lib
Qml2Imports = qml
Plugins = plugins
Run Code Online (Sandbox Code Playgroud)

但是,此脚本在我的编译计算机上有效,但在另一台计算机上无效:

export LD_LIBRARY_PATH=`pwd`/lib
export QML_IMPORT_PATH=`pwd`/qml
export QML2_IMPORT_PATH=`pwd`/qml
export QT_QPA_PLATFORM_PLUGIN_PATH=`pwd`/plugins/platforms
./OpenGLUnderQML
Run Code Online (Sandbox Code Playgroud)

我的捆绑包内容:

lib
OpenGLUnderQML (the executable)
plugins
qml
qt.conf
startapp.sh (the script above)
Run Code Online (Sandbox Code Playgroud)

libpluginsqml完全从 QTDIR(约 500 MB)复制,因此应该不会遗漏任何库或插件。

Sch*_*der 13

我遇到了一个非常相似的问题,并具有相同的错误消息。首先,通过打开调试一些

导出 QT_DEBUG_PLUGINS=1

并重新运行应用程序。对我来说,这揭示了以下内容:

“无法加载库/home/.../miniconda3/lib/python3.7/site-packages/PyQt5/Qt/plugins/platforms/libqxcb.so:(libxkbcommon-x11.so.0:无法打开共享对象文件:没有这样的文件或目录)”

“无法加载库/home/.../miniconda3/lib/python3.7/site-packages/PyQt5/Qt/plugins/platforms/libqxcb.so:(libxkbcommon-x11.so.0:无法打开共享对象文件:没有这样的文件或目录)”

事实上,我缺少 libxkbcommon-x11.so.0 和 libxkbcommon-x11.so.0。接下来,从 Linux 命令行使用 dpkg 检查您的体系结构。(对我来说,命令“arch”给出了不同且无益的结果)

dpkg --print-architecture #结果对我来说:amd64

然后我用谷歌搜索“libxkbcommon-x11.so.0 ubuntu 18.04 amd64”,同样搜索libxkbcommon-x11.so.0,它在packages.ubuntu.com上生成这些包。这告诉我,回想起来,毫不奇怪,我缺少名为 libxkbcommon-x11-0 和 libxkbcommon-0 的软件包,并且安装这些软件包将包含所需的文件,但开发版本不会。那么解决办法:

sudo apt-get 更新

sudo apt-get install libxkbcommon0

sudo apt-get install libxkbcommon-x11-0


tei*_*vaz 2

您在这里有多个问题,所以我将分别解决它们。

1. CMake使用了错误的Qt安装。

这里 CMake 的入口点是函数find_package。该函数在搜索库时使用启发式方法。这是文档的片段:

<prefix>/(lib/<arch>|lib*|share)/cmake/<name>*/                 (U)
<prefix>/(lib/<arch>|lib*|share)/<name>*/                       (U)
<prefix>/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/         (U)
<prefix>/<name>*/(lib/<arch>|lib*|share)/cmake/<name>*/         (W/U)
<prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/               (W/U)
<prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/ (W/U)
Run Code Online (Sandbox Code Playgroud)

所以你的前缀路径应该是

set(CMAKE_PREFIX_PATH "$ENV{HOME}/Qt5.12.2/5.12.2/gcc_64")
Run Code Online (Sandbox Code Playgroud)

大多数情况下,这应该足够了。如果这还不够,那么 goto 方法是PATH在执行 CMake 命令之前修改变量,如下所示:

export PATH=~/Qt5.12.2/5.12.2/gcc_64:$PATH
cmake .. # do your cmake stuff
Run Code Online (Sandbox Code Playgroud)

这里的一个好习惯是有一个名为的系统范围环境变量,QTDIR指向 Qt 的正确安装(例如export QTDIR=/Qt5.12.2/5.12.2/gcc_64在您的 中.bash_profile)并使用它。

2. CMake找不到插件。

fixup_bundle模块中的命令仅BundleUtilities更改动态库加载路径并将必要的内容复制到捆绑包中。构建可分发的 Qt 应用程序不仅仅是更改库 - 请参阅文档。对于 Windows 和 MacOS Qt 提供了特殊的工具:windeployqtmacdeployqt. 然而,对于 Linux,没有官方工具,但您可以查看非官方的linuxdeployqt. 无论如何,对您来说最重要的指南是“Qt for Linux/X11 - 部署”。无法fixup_bundle修复插件,因为加载插件的机制不同 - 它们是从代码动态加载并按需加载的。

简而言之,您需要知道您使用哪些插件以及 Qt 模块除了它们之外还需要哪些资源。一旦你弄清楚了 - 将它们复制到你的包中。上述工具正是这样做的(除了修复动态库之外)。