I'm trying to setting up a standalone binary archive (.tar.gz) that can run on most Linux distros (ex. Blender). I'm still not familiar with CMake. As far as I know, all the dependencies can be resolved at the install step with fixup_bundle
macro. And I assume that the install directory should become a standalone app that can be copied and run on other computers without Qt installed? I'm not sure about the role of CPack here.
My Qt installation path is /home/<user>/Qt5.12.2/5.12.2/gcc_64/qmake
. I've followed some answers and have copied platform/libqxcb.so
and libQt5XcbQpa.so.5
into the install directory. In order to test the standalone package, I change ~/Qt5.12.2
into ~/qt
. And this is the error message when the executable run:
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>
I've also tried qt.conf
and set the Prefix and Plugin path to ./
but that didn't work. One interesting thing I found though is that when I set Plugins = /home/<user>/qt/5.12.2/gcc_64/plugins
, a little Qt window shows, but comes with a bunch of error messages:
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
Then, I found some information by testing the two libqxcb.so with ldd
, although I'm not sure this is the actual cause.
ldd ~/qt/5.12.2/gcc_64/plugins/platforms/libqxcb.so
shows that the original libqxcb.so links the libraries that come with the Qt installation:
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)
......
ldd <path_to_project>/build/install/platforms/libqxcb.so
shows it links to the system Qt library, which is not the one my project built against on:
./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)
......
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)
qt.conf
[Paths]
Prefix = ./
Plugins = /home/giokka/qt/5.12.2/gcc_64/plugins
This is my qt.conf
file, but it doesn't work.
[Paths]
Prefix = .
Libraries = lib
Qml2Imports = qml
Plugins = plugins
However, this script works on my compiling computer but not on the other computer:
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
My bundle package content:
lib
OpenGLUnderQML (the executable)
plugins
qml
qt.conf
startapp.sh (the script above)
lib
, plugins
, and qml
are fully copied from QTDIR (about 500 MB), so there should be no library or plugin missed.
Sometimes corrupted system files can trigger various errors and issues when running your apps such as the “no Qt platform plugin could be initialized” error. So, we recommend you run an SFC scan or DISM to check system files.
On Linux, the xcb QPA (Qt Platform Abstraction) platform plugin is used. It provides the basic functionality needed by Qt GUI and Qt Widgets to run against X11. Its library dependencies are described the following table.
Qt is a C++-based framework that is designed to create applications on Windows, Android, Linux, and other platforms. While it is not a programming language on its own, apps that are based on it need to have the framework installed on their machines to be able to run.
The Qt Platform Abstraction (QPA) is the platform abstraction layer for Qt 5 and replaces Qt for Embedded Linux and the platform ports from Qt 4. QPA plugins are implemented by subclassing various QPlatform* classes.
You have multiple questions here so I'll address them separately.
The entry point for CMake here is the find_package
function. This function is using heuristics when searching for libraries. Here's a fragment of the documentation:
<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)
So your prefix path should be
set(CMAKE_PREFIX_PATH "$ENV{HOME}/Qt5.12.2/5.12.2/gcc_64")
In most cases this should be enough.
If this is not enough then the goto way is to modify the PATH
variable before executing your CMake command like so:
export PATH=~/Qt5.12.2/5.12.2/gcc_64:$PATH
cmake .. # do your cmake stuff
A good practice here is to have a system-wide environment variable called QTDIR
pointing to the proper installation of Qt (e.g. export QTDIR=/Qt5.12.2/5.12.2/gcc_64
in your .bash_profile
) and use it instead.
The fixup_bundle
command from BundleUtilities
module is only changing the dynamic library load paths and copying the necessary to the bundle.
There's more to building a distributable Qt application than just changing the libraries - see documentation. For Windows and MacOS Qt provides a special tools: windeployqt
and macdeployqt
.
For Linux however there's no official tool but you can take a look at the unofficial linuxdeployqt
. In any case the most important guide for you would be "Qt for Linux/X11 - Deployment". The fixup_bundle
can not fix the plugins because the mechanism of loading plugins is different - they are loaded dynamically from code and on demand.
To put it simple you need to know which plugins you use and which resources the Qt modules require apart from them. Once you figure that out - copy them to your bundle. The mentioned tools do exactly that (on top of fixing the dynamic libraries).
I am working on Pop!_OS a Linux variant of Ubuntu 21.04 trying to build a QT5 app in Pycharm. It took me 1 day to finally find this solution for me:
There seems to be a conflict between cv2 (opencv-python) and QT5 that causes this error. I had to uninstall opencv-python and install opencv-python-headless to resolve the issue:
pip uninstall opencv-python
pip install opencv-python-headless
I ran into a very similar problem with the same error message. First, debug some by turning on
export QT_DEBUG_PLUGINS=1
and rerun the application. For me this revealed the following:
"Cannot load library /home/.../miniconda3/lib/python3.7/site-packages/PyQt5/Qt/plugins/platforms/libqxcb.so: (libxkbcommon-x11.so.0: cannot open shared object file: No such file or directory)"
"Cannot load library /home/.../miniconda3/lib/python3.7/site-packages/PyQt5/Qt/plugins/platforms/libqxcb.so: (libxkbcommon-x11.so.0: cannot open shared object file: No such file or directory)"
Indeed, I was missing libxkbcommon-x11.so.0 and libxkbcommon-x11.so.0. Next, check your architecture using dpkg from the linux command line. (For me, the command "arch" gave a different and unhelpful result)
dpkg --print-architecture #result for me: amd64
I then googled "libxkbcommon-x11.so.0 ubuntu 18.04 amd64", and likewise for libxkbcommon-x11.so.0, which yields those packages on packages.ubuntu.com. That told me, in retrospect unsurprisingly, I'm missing packages called libxkbcommon-x11-0 and libxkbcommon-0, and that installing those packages will include the needed files, but the dev versions will not. Then the solution:
sudo apt-get update
sudo apt-get install libxkbcommon0
sudo apt-get install libxkbcommon-x11-0
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With