Qt for Embedded Linux

一、Qt 简介

二、Qt 版本对比

版本 嵌入式支持
Qt 4.8 Qt Embedded(独立)
Qt 5.x Qt5 统一(linuxfb / eglfs / wayland 后端)
Qt 6.x 推荐(Qt Quick Controls 2)

三、Qt 平台插件(QPA)

# 选择平台
./myapp -platform linuxfb
./myapp -platform eglfs

四、安装 Qt for Embedded

1. 系统包

sudo apt install qtbase5-dev qtdeclarative5-dev qtquickcontrols2-5-dev

2. 交叉编译 Qt5

wget https://download.qt.io/official_releases/qt/5.15/5.15.10/single/qt-everywhere-opensource-src-5.15.10.tar.xz
tar xf qt-everywhere-opensource-src-5.15.10.tar.xz
cd qt-everywhere-opensource-src-5.15.10

# 写 qmake 配置
cat > qtbase/mkspecs/devices/linux-imx6-g++/qmake.conf <<EOF
# 简化
EOF

# 配置
./configure -release \
    -opengl es2 \
    -device linux-imx6-g++ \
    -device-option CROSS_COMPILE=arm-linux-gnueabihf- \
    -sysroot /opt/sysroot-arm \
    -prefix /opt/qt5-arm \
    -opensource

make -j$(nproc)
make install

五、Hello Qt

// main.cpp
#include <QApplication>
#include <QLabel>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QLabel label("Hello, Embedded Linux!");
    label.resize(400, 100);
    label.show();
    return app.exec();
}
# CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(HelloQt)
set(CMAKE_CXX_STANDARD 17)
find_package(Qt5 COMPONENTS Widgets REQUIRED)
add_executable(hello main.cpp)
target_link_libraries(hello Qt5::Widgets)

六、QML(推荐)

// main.qml
import QtQuick 2.15
import QtQuick.Controls 2.15

ApplicationWindow {
    visible: true
    width: 800
    height: 480
    title: "MyApp"

    Column {
        anchors.centerIn: parent
        spacing: 10

        Label {
            text: "温度: " + temp.toFixed(1) + "°C"
            font.pixelSize: 32
        }
        Button {
            text: "刷新"
            onClicked: refresh()
        }
    }
}

七、平台插件配置

1. linuxfb

# /etc/qt5_env.conf 或命令行
export QT_QPA_PLATFORM=linuxfb
export QT_QPA_FB=/dev/fb0
export QT_QPA_FB_DEPTH=32
export QT_QPA_DISABLE_TSLIB=1

2. eglfs

export QT_QPA_PLATFORM=eglfs
export QT_QPA_EGLFS_INTEGRATION=eglfs_viv       # Vivante GPU
export QT_QPA_EGLFS_PHYSICAL_WIDTH=480
export QT_QPA_EGLFS_PHYSICAL_HEIGHT=800

3. tslib(触摸屏)

export TSLIB_TSDEVICE=/dev/input/event0
export TSLIB_CALIBFILE=/etc/pointercal

八、触摸输入

# 设备树
&tscadc {
    status = "okay";
};
// Qt 自动识别
// tslib 校准
TSLIB_CALIBFILE=/etc/pointercal

九、字体

# 部署字体
cp fonts/*.ttf /opt/qt5-arm/lib/fonts/
# 或
export QT_QPA_FONTDIR=/path/to/fonts

十、中文支持

export LANG=zh_CN.UTF-8
# 部署中文字体(文泉驿、思源)

十一、Qt5 CMake 交叉编译工具链

# toolchain-arm.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
set(CMAKE_PREFIX_PATH /opt/qt5-arm)
set(CMAKE_FIND_ROOT_PATH /opt/qt5-arm)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

十二、性能优化

QQuickWindow::setSceneGraphBackend(QSGRendererInterface::Software);  // 软件渲染
QQuickItem::setRenderTarget(QQuickItem::FramebufferObject);

十三、与硬件集成

// 读 GPIO
#include <unistd.h>
#include <fcntl.h>

int fd = open("/sys/class/gpio/gpio17/value", O_RDONLY);
char buf[2];
read(fd, buf, 1);
close(fd);

// 串口
#include <QtSerialPort>
QSerialPort serial;
serial.setPortName("/dev/ttymxc0");
serial.open(QIODevice::ReadWrite);
serial.write("hello");
// ...

十四、部署到目标板

# rsync
rsync -av output/ root@myboard:/usr/local/myapp/

# 启动脚本
#!/bin/sh
export QT_QPA_PLATFORM=linuxfb
export LD_LIBRARY_PATH=/opt/qt5-arm/lib:$LD_LIBRARY_PATH
exec /usr/local/myapp/myapp