Introduction
Deploying Qt applications in embedded Linux systems is a common requirement in scenarios such as industrial control, smart terminals, and in-vehicle systems. However, unlike desktop environments, embedded devices often lack a complete graphics stack (such as X11 or Wayland) and may not even have a window manager. Therefore, Qt provides various platform plugins to adapt to different underlying display and input systems.
This article will delve into how to correctly run Qt applications in an embedded Linux environment, covering:
- The
<span>-qws</span>mode from the Qt4 era - The
<span>--platform</span>parameter mechanism in Qt5/6 - The principles and usage of major platform plugins (
<span>xcb</span>,<span>linuxfb</span>,<span>eglfs</span>,<span>wayland</span>,<span>vnc</span>) - A complete cross-compilation and deployment example
- A common issues troubleshooting guide
1. Differences in Architecture Between Qt4 and Qt5+: Why No Longer Use <span>-qws</span>
1.1 QWS (Qt Window System) in Qt4
During the Qt4 era, embedded systems widely used the QWS (Qt Window System) mode. QWS is a lightweight window system implemented by Qt itself, independent of X11. Applications directly manipulate the framebuffer or hardware video memory.
The running method is very simple:
./HelloQt -qws&
Where:
<span>-qws</span>indicates starting in QWS Server mode (the first process acts as the server)- Other processes can connect as clients (using
<span>-qws -display :0</span>, etc.)
⚠️ Disadvantage: QWS is unique to Qt4, with a closed architecture, making it difficult to integrate with modern graphics stacks.
1.2 Platform Abstraction Layer (QPA) in Qt5+
Starting from Qt5, Qt introduced the QPA (Qt Platform Abstraction) architecture, abstracting the underlying graphics, input, and window management into “platform plugins”. Developers specify the backend to use at runtime through <span>--platform <plugin></span>.
This approach is more modular, extensible, and can seamlessly interface with mainstream Linux graphics technologies (such as DRM/KMS, Wayland, X11).
2. Detailed Explanation of Qt5/6 Platform Plugins
The basic command format for running Qt5/6 applications is:
./HelloQt --platform <plugin_name>[options]
Below are descriptions of commonly used plugins:
| Plugin Name | Applicable Scenarios | Dependencies | Features |
|---|---|---|---|
<span>xcb</span> |
Desktop Linux (with X11) | libxcb, X server | Standard desktop backend |
<span>linuxfb</span> |
No GPU, direct framebuffer writing | /dev/fb0 | Most straightforward solution, no acceleration |
<span>eglfs</span> |
Embedded devices with GPU (e.g., Raspberry Pi, i.MX6) | EGL, OpenGL ES, DRM/KMS | High performance, fullscreen exclusive |
<span>wayland</span> |
Systems supporting the Wayland protocol | wayland-client, compositor | Modern, supports multiple windows |
<span>vnc</span> |
Remote debugging or virtual display | libvncserver | Output to VNC service |
Next, we will introduce the usage of each plugin one by one.
3. Specific Code and Deployment Examples
3.1 Example Program: HelloQt
Create a simple Qt Quick or Widgets program.
main.cpp (Widgets Version):
#include <QApplication>
#include <QLabel>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QLabel label("Hello, Embedded Qt!");
label.setAlignment(Qt::AlignCenter);
label.resize(480, 272);
label.show();
return app.exec();
}
CMakeLists.txt:
cmake_minimum_required(VERSION 3.16)
project(HelloQt)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
find_package(Qt6 REQUIRED COMPONENTS Widgets)
add_executable(HelloQt main.cpp)
target_link_libraries(HelloQt Qt6::Widgets)
💡 Note: Actual embedded deployment requires cross-compilation, the compilation details are omitted here, assuming the
<span>HelloQt</span>executable has been generated.
4. Detailed Usage of Each Platform Plugin
4.1 <span>xcb</span>: X11 Backend (for testing only)
Suitable for simulating an embedded environment on desktop Linux during the development phase.
./HelloQt --platform xcb
✅ Advantage: Easy to debug❌ Disadvantage: Depends on X server, not suitable for GUI-less embedded devices
4.2 <span>linuxfb</span>: Directly Write to Framebuffer
Suitable for simple devices without GPU and window systems (e.g., microcontroller + LCD screen).
Usage Conditions:
<span>/dev/fb0</span>must exist and be readable/writable- The user must have permission to access the framebuffer (temporary authorization can be done via
<span>chmod 666 /dev/fb0</span>)
Startup Command:
./HelloQt --platform linuxfb
Advanced Options (via environment variables):
export QT_QPA_FB_TSLIB=1 # Enable tslib touch
export QT_QPA_GENERIC_PLUGINS=tslib:/dev/input/event0
./HelloQt --platform linuxfb:fb=/dev/fb0
⚠️ Note:
<span>linuxfb</span>does not support OpenGL, only software rendering.
4.3 <span>eglfs</span>: Preferred for Embedded GPU Acceleration
eglfs (EGL Full Screen) is the recommended backend for most embedded SoCs with GPU (e.g., NXP i.MX6/8, Raspberry Pi, Rockchip).
Features:
- Directly uses DRM/KMS or Broadcom Dispmanx for display
- Fullscreen exclusive, no window management
- Supports OpenGL ES hardware acceleration
Startup Command:
./HelloQt --platform eglfs
Common Sub-Plugins (auto-detected):
<span>eglfs_kms</span>: Based on DRM/KMS (generic)<span>eglfs_brcm</span>: Specific to Raspberry Pi<span>eglfs_viv</span>: NXP Vivante GPU
Debugging Tips:
# View eglfs initialization logs
QT_LOGGING_RULES="qt.qpa.*=true" ./HelloQt --platform eglfs
# Specify resolution (if auto-detection fails)
./HelloQt --platform eglfs --width 800 --height 480
Permission Issues:
Ensure the user belongs to the <span>video</span> group, or has permission to access <span>/dev/dri/card0</span>, <span>/dev/galcore</span>, and other device nodes.
4.4 <span>wayland</span>: Modern Compositor Protocol
Suitable for systems with a deployed Wayland compositor (e.g., Weston, wlroots).
Startup Command:
# Assuming Weston is running
./HelloQt --platform wayland
Advantages:
- Supports multiple windows and compositing effects
- Aligns with the development direction of the Linux graphics stack
Disadvantages:
- Requires an additional compositor to run
- Higher memory and CPU overhead
4.5 <span>vnc</span>: Remote Debugging Tool
Outputs the Qt program to a VNC server, facilitating debugging without a screen.
Startup Command:
./HelloQt --platform vnc
By default, it listens on <span>:0</span> (i.e., port 5900), and can be connected to using a VNC client.
Custom Port:
./HelloQt --platform vnc --display :1 # Listen on 5901
🔧 The
<span>vnc</span>plugin must be enabled during Qt compilation (<span>-feature-vnc</span>)
5. How to Choose the Right Platform Plugin?
| Device Type | Recommended Plugin | Description |
|---|---|---|
| Raspberry Pi (with desktop) | <span>xcb</span> or <span>eglfs</span> |
Use xcb for desktop, eglfs for bare metal |
| NXP i.MX6 (without X11) | <span>eglfs</span> |
Utilize Vivante GPU |
| Simple LCD + Touchscreen | <span>linuxfb</span> + <span>tslib</span> |
Low-cost solution |
| Deployed Weston | <span>wayland</span> |
Modern multitasking |
| No screen debugging | <span>vnc</span> |
Remote UI viewing |
Practical Suggestions: Try the following in order on the target device:
./HelloQt --platform eglfs # Preferred
./HelloQt --platform linuxfb # Backup
./HelloQt --platform vnc # Debugging
Observe for errors (e.g., <span>Could not find a suitable platform plugin</span>), which will help determine which plugin is available.
6. Cross-Compilation Considerations
Ensure that Qt is custom compiled for the embedded target platform and includes the required plugins.
For example, to compile Qt with support for <span>eglfs</span>:
./configure -release -opengl es2 -device linux-imx6-g++ \
-device-option CROSS_COMPILE=arm-linux-gnueabihf- \
-sysroot /path/to/sysroot \
-prefix /usr/local/qt5-embedded \
-no-xcb -no-pch -nomake examples -nomake tests
After compilation, the plugins are located at:
$QTDIR/plugins/platforms/libqeglfs.so
$QTDIR/plugins/platforms/libqlinuxfb.so
...
During deployment, these <span>.so</span> files need to be copied to the <span>./platforms/</span> directory on the target device, or set the <span>QT_QPA_PLATFORM_PLUGIN_PATH</span>:
export QT_QPA_PLATFORM_PLUGIN_PATH=./platforms
./HelloQt --platform eglfs
7. Common Errors and Solutions
Error 1: <span>This application failed to start because no Qt platform plugin could be initialized.</span>
Cause: Missing platform plugin or incorrect path.
Solution:
- Check if the corresponding
<span>.so</span>exists in the<span>./platforms/</span>directory - Set
<span>QT_DEBUG_PLUGINS=1</span>to view the loading process
Error 2: <span>eglfs: OpenGL windows cannot be mixed with others.</span>
Cause: Attempting to create non-OpenGL windows (e.g., mixing QWidget + QQuickWidget) under <span>eglfs</span>
Solution: Use either Qt Quick or pure Widgets consistently
Error 3: Touch Not Responding
Solution:
export QT_QPA_GENERIC_PLUGINS=evdevtouch:/dev/input/event1
export QT_QPA_EGLFS_DISABLE_INPUT=1 # If using tslib
8. Conclusion
Running Qt applications on embedded Linux hinges on understanding and correctly selecting the platform plugins. From Qt4’s <span>-qws</span> to Qt5/6’s <span>--platform</span> mechanism, Qt provides flexible and powerful adaptation capabilities.
Key points to review:
- Qt4: Use
<span>-qws</span>(deprecated) - Qt5/6: Use
<span>--platform <name></span> - Recommended Order:
<span>eglfs</span>→<span>linuxfb</span>→<span>vnc</span> - Deployment Essentials: Platform plugin
<span>.so</span>files + device permissions + input configuration
Others
- Domestic Open Source: https://gitee.com/feiyangqingyun
- International Open Source: https://github.com/feiyangqingyun
- Project Collection: https://qtchina.blog.csdn.net/article/details/97565652
- Contact: WeChat feiyangqingyun
- Official Store: https://shop114595942.taobao.com/