由于 RK3588 NVR 方案的内核不支持 Framebuffer 显示,没有 /dev/fb0,所以不支持 LinuxFB 平台插件。所以要编译一个 eglfs_kms 的版本。

前面的安装交叉编译工具链、安装 Qt Creator 等步骤这里都省略了,不清楚的可以看上一篇博客: RK3588 Qt 交叉编译之二:编译 LinuxFB 版本

一、交叉编译准备工作

(1)只编译 qtbase

$ cp -rdf qt-everywhere-src-5.12.2/qtbase/ qtbase-everywhere-src-5.12.2

将 qtbase 改名,只编译基础库,其它例如 qt3d、qtwebengine 之类的不需要编译,减少可能出现的报错。

(2)添加 nvr 设备

删除 qtbase-everywhere-src-5.12.2 目录下的 mkspecs ,将官方提供的 mkspecs 目录拷贝到该目录下,查看 nvr 设备的配置文件。命令如下:

接着输入命令:

$ cd qtbase-everywhere-src-5.12.2
$ rm -rf mkspecs 
$ cp -rfd xxx/mkspecs ./
$ vi devices/linux-nvr-g++/qmake.conf

可以看到原本的配置内容:

# Qt5 has a mechanism to support "device" profiles, so that people can
# specify the compiler, compiler flags and so on for a specific device.
# We leverage this mechanism in the Buildroot packaging of qt5 to
# simplify cross-compilation: we have our own "device" definition, which
# allows us to easily pass the cross-compiler paths and flags from our
# qt5.mk.
include(../common/linux_device_pre.conf)
# modifications to g++-unix.conf
QMAKE_CC                = $${CROSS_COMPILE}gcc
QMAKE_CXX               = $${CROSS_COMPILE}g++
# modifications to gcc-base.conf
QMAKE_CFLAGS           += $${BR_COMPILER_CFLAGS}
QMAKE_CXXFLAGS         += $${BR_COMPILER_CXXFLAGS}
# Remove all optimisation flags, we really only want our own.
QMAKE_CFLAGS_OPTIMIZE       =
QMAKE_CFLAGS_OPTIMIZE_DEBUG =
QMAKE_CFLAGS_OPTIMIZE_FULL  =
QMAKE_CFLAGS_OPTIMIZE_SIZE  =
QMAKE_CFLAGS_DEBUG =
QMAKE_CXXFLAGS_DEBUG =
QMAKE_CFLAGS_RELEASE =
QMAKE_CXXFLAGS_RELEASE =
CONFIG                 += nostrip
QMAKE_LIBS             += -lrt -lpthread -ldl
QMAKE_CFLAGS_ISYSTEM   =
# Architecture specific configuration
include(arch.conf)
EGLFS_DEVICE_INTEGRATION = eglfs_mali
include(../common/linux_device_post.conf)
load(qt_config)

这里不需要修改,保持默认配置就行。

(3)覆盖原本的 aarch64-none-linux-gnu 

删除 toolchain 目录下的 aarch64-none-linux-gnu,将官方提供的 aarch64-none-linux-gnu.tar.gz 压缩包拷贝解压到该目录下。命令如下:

接着输入命令:

$ cd NVR_SDK/rk3588_linux/toolchain
$ rm -rf aarch64-none-linux-gnu
$ cp -rfd xxx/aarch64-none-linux-gnu.tar.gz ./
$ tar -xvf aarch64-none-linux-gnu.tar.gz

toolchain/aarch64-none-linux-gnu/libc这个目录下存放了所有配置需要的动态库,例如 eglfs、mali、kms、drm 等等动态库。

(4)创建交叉编译的配置脚本

接着输入以下命令,新建一个自动配置脚本文件,仍在qtbase-everywhere-src-5.12.2目录下:

$ vi auto.sh

新建的auto.sh为交叉编译自动配置脚本,根据自己实际需求配置 Qt,在其中添加以下内容:

./configure \
-extprefix /home/share/NVR_SDK/rk3588_linux/qt_install/qt5122-arm-kms \
-device nvr \
-device-option CROSS_COMPILE=/home/share/NVR_SDK/rk3588_linux/toolchain/bin/aarch64-none-linux-gnu- \
-device-option 'BR_COMPILER_CFLAGS=-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Os -g0 -D_FORTIFY_SOURCE=1' \
-device-option 'BR_COMPILER_CXXFLAGS=-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Os -g0 -D_FORTIFY_SOURCE=1' \
-hostprefix /home/share/NVR_SDK/rk3588_linux/qt_install/host \
-sysroot /home/share/NVR_SDK/rk3588_linux/toolchain/aarch64-none-linux-gnu/libc \
-no-rpath \
-nomake tests \
-optimized-qmake \
-no-iconv \
-system-zlib \
-system-pcre \
-no-pch \
-shared \
-no-optimize-debug \
-no-sse2 \
-kms \
-gbm \
-release \
-opensource \
-confirm-license \
-no-cups \
-no-sql-mysql \
-no-sql-psql \
-no-sql-sqlite \
-gui \
-system-freetype \
-no-harfbuzz \
-widgets \
--enable-linuxfb \
-no-directfb \
-no-xkbcommon \
-no-xcb \
-eglfs \
-opengl es2 \
-no-gif \
-fontconfig \
-no-dbus \
-no-tslib \
-no-icu \
-no-libinput \
-nomake examples \
-no-gtk \
-no-journald \
-no-syslog \
QMAKE_CXXFLAGS+=-DQT_FB_DRM_RGB565
  • -extprefix <dir>:安装目录, 主机上默认值 [SYSROOT/PREFIX]
  • -hostprefix <dir>:运行在主机上的构建工具的安装目录. 如果没有给出 [dir] ,则使用当前构建目录 [EXTPREFIX]
  • -sysroot <dir>:设置目标 sysroot 为 [dir]
  • -device <name>:指定交叉编译的目标设备
  • -device-option <key=value> 为目标设备 mkspec 添加选项
  • -device-option 用于向 qmake.conf 文件中添加可以引用的变量
  • 注意:这里特意没有配置 libinput 和 -xkbcommon,因为后面运行的时候会报错,暂时没搜到解决办法,故只能后面单独编译了
  • 接着修改该文件权限并执行:

    $ chmod 777 auto.sh 
    $ ./auto.sh
    

    这步会报好几个错误,查看 config.log 搜索 "错误" 可以看到具体报错位置,下面会介绍如何解决这些错误。

    二、解决配置报错

    > main.cpp:2:10: 致命错误: EGL/fbdev_window.h:没有那个文件或目录
    >     2 | #include <EGL/fbdev_window.h>
    >       |          ^~~~~~~~~~~~~~~~~~~~
    > 编译中断。
    > make: *** [Makefile:183:main.o] 错误 1
    

    解决方案:

    cd rk3588_linux/toolchain/aarch64-none-linux-gnu/libc/usr/include/include/EGL
    vi fbdev_window.h
    #添加下面网页的fbdev_window.h的代码内容,保存并退出
    

    (8条消息) rock[(8条消息) rockchip qt5.12.8编译为eglfs时相关问题_fbdev_window.h_lixiaojun216的博客-CSDN博客]

    executing config test egl-viv
    > main.cpp:3:10: 致命错误: EGL/eglvivante.h:没有那个文件或目录
    >     3 | #include <EGL/eglvivante.h>
    >       |          ^~~~~~~~~~~~~~~~~~
    > 编译中断。
    > make: *** [Makefile:183:main.o] 错误 1
    test config.qtbase_gui.tests.egl-viv FAILED
    

    添加 eglvivante.h 到 EGL 目录下。其内容如下:

    /****************************************************************************
    *    The material in this file is confidential and contains trade secrets
    *    of Vivante Corporation. This is proprietary information owned by
    *    Vivante Corporation. No part of this work may be disclosed,
    *    reproduced, copied, transmitted, or used in any way for any purpose,
    *    without the express written permission of Vivante Corporation.
    *****************************************************************************/
    EGLNativeDisplayType fbGetDisplayByIndex(int DisplayIndex)
    	EGLNativeDisplayType diplayType;
    	return diplayType;
    void fbGetDisplayGeometry(EGLNativeDisplayType Display,int * Width,int * Height)
    EGLNativeWindowType
    fbCreateWindow(
        EGLNativeDisplayType Display,
        int X,
        int Y,
        int Width,
        int Height
    	EGLNativeWindowType windowType;
    	return windowType;
    void fbDestroyWindow(EGLNativeWindowType Window)
    #define EGLAPIENTRY
    #ifdef __cplusplus
    #endif
    #endif /* __eglvivante_h_ */
    
    > main.cpp:6:12: 致命错误: GLES3/gl3.h:没有那个文件或目录
    >     6 | #  include <GLES3/gl3.h>
    >       |            ^~~~~~~~~~~~~
    > 编译中断。
    

    发现在 rk3588_linux/toolchain/aarch64-none-linux-gnu/libc/usr/include/include 没有 GLES3 目录,查找有 GLES3 的路径,将其包括 gl31.h gl32.h gl3.h gl3platform.h 这4个文件都拷贝到该目录下。命令如下:

    $ find /home/share/ -name GLES3
    xxx/firefly_arm64_qt5.12.2_18.04/host/opt/sysroot/firefly-arm64-sysroot-18.04/usr/include/GLES3
    $ cd toolchain/aarch64-none-linux-gnu/libc/usr/include/include
    $ cp -rfd xxx/firefly_arm64_qt5.12.2_18.04/host/opt/sysroot/firefly-arm64-sysroot-18.04/usr/include/GLES3 ./ 
    

    三、正式开始交叉编译

    解决完交叉编译的严重报错后,就正式开始交叉编译。先将原本的 qtbase-everywhere-src-5.12.2 删除。然后重新配置:

    $ rm qtbase-everywhere-src-5.12.2
    $ cp -rfd qt-everywhere-src-5.12.2/qtbase/ qtbase-everywhere-src-5.12.2
    $ cd qtbase-everywhere-src-5.12.2qtbase-everywhere-src-5.12.2
    $ rm -rf mkspecs/
    #copy mkspecs to qtbase...
    $ cp ../auto.sh ./
    $ ./auto.sh
    

    输出如下:

    Note: Also available for Linux: linux-clang linux-icc
    Note: PKG_CONFIG_LIBDIR automatically set to /home/share/NVR_SDK/rk3588_linux/toolchain/aarch64-none-linux-gnu/libc/usr/lib/pkgconfig:/home/share/NVR_SDK/rk3588_linux/toolchain/aarch64-none-linux-gnu/libc/usr/share/pkgconfig:/home/share/NVR_SDK/rk3588_linux/toolchain/aarch64-none-linux-gnu/libc/usr/lib/aarch64-none-linux-gnu/pkgconfig
    Note: PKG_CONFIG_SYSROOT_DIR automatically set to /home/share/NVR_SDK/rk3588_linux/toolchain/aarch64-none-linux-gnu/libc
    Note: -optimized-tools is not useful in -release mode.
    Qt is now configured for building. Just run 'make'.
    Once everything is built, you must run 'make install'.
    Qt will be installed into '/home/share/NVR_SDK/rk3588_linux/qt_install/qt5122-arm-kms'.
    Prior to reconfiguration, make sure you remove any leftovers from
    the previous build.
    

    配置阶段无误的话下面这几项会被选择:

    QPA backends:
      DirectFB ............................... no
      EGLFS .................................. yes
      EGLFS details:
        EGLFS OpenWFD ........................ no
        EGLFS i.Mx6 .......................... yes
        EGLFS i.Mx6 Wayland .................. no
        EGLFS RCAR ........................... no
        EGLFS EGLDevice ...................... yes
        EGLFS GBM ............................ yes
        EGLFS VSP2 ........................... no
        EGLFS Mali ........................... yes
        EGLFS Raspberry Pi ................... no
        EGLFS X11 ............................ no
      LinuxFB ................................ yes
      VNC .................................... yes
      Mir client ............................. no
    

    然后 make:

    $ make
    make[2]: 离开目录“/home/share/NVR_SDK/rk3588_linux/qtbase-everywhere-src-5.12.2/qmake”
    make[1]: 离开目录“/home/share/NVR_SDK/rk3588_linux/qtbase-everywhere-src-5.12.2/qmake”
    cd doc/ && ( test -e Makefile || /home/share/NVR_SDK/rk3588_linux/qtbase-everywhere-src-5.12.2/bin/qmake -o Makefile /home/share/NVR_SDK/rk3588_linux/qtbase-everywhere-src-5.12.2/doc/doc.pro ) && make -f Makefile
    make[1]: 进入目录“/home/share/NVR_SDK/rk3588_linux/qtbase-everywhere-src-5.12.2/doc”
    make[1]: 对“first”无需做任何事。
    make[1]: 离开目录“/home/share/NVR_SDK/rk3588_linux/qtbase-everywhere-src-5.12.2/doc”
    

    最后安装:

    $ make install
    

    大约一分钟后安装完毕,如果输出最后有这么一句话:make[2]: Nothing to be done for 'install'.,表示 ARM Qt 库安装成功,可以看见 /opt 目录下出现了我们指定的安装目录rk3588_linux/qt_install/qt5122-arm-kms

    查看安装好的库、插件和 qmake:

    $ ls qt_install/qt5122-arm-kms/plugins/platforms/
    libqeglfs.so  libqlinuxfb.so  libqminimalegl.so  libqminimal.so  libqoffscreen.so  libqvnc.so
    $ ls qt_install/qt5122-arm-kms/plugins/egldeviceintegrations/
    libqeglfs-emu-integration.so  libqeglfs-kms-egldevice-integration.so  libqeglfs-kms-integration.so  libqeglfs-mali-integration.so  libqeglfs-viv-integration.so
    $ ls qt_install/host/
    bin  lib  mkspecs
    $ ls qt_install/host/bin/
    fixqt4headers.pl  moc  qlalr  qmake  qvkgen  rcc  syncqt.pl  uic
    

    四、将交叉编译的Qt库复制到板子上运行

    将生成的 qt5122-arm-kms 压缩拷贝到板子的文件系统上:

    $ tar -cvf qt5122-arm-kms.tar.gz qt5122-arm-kms
    // 复制操作...
    $ tar -xvf qt5122-arm-kms.tar.gz
    

    使用 qmake 编译可执行程序,然后使用 scp 命令将生成的 calendarwidget 拷贝到 /opt/demo/ 目录下:

    $ cd demo/calendarwidget/
    $ /home/share/NVR_SDK/rk3588_linux/qt_install/host/bin/qmake
    Info: creating stash file /home/share/NVR_SDK/rk3588_linux/demo/calendarwidget/.qmake.stash
    $ make
    calendarwidget  calendarwidget.pro  calendarwidget.pro.user  main.cpp  main.o  Makefile  moc_predefs.h  moc_window.cpp  moc_window.o  window.cpp  window.h  window.o
    $ scp /home/share/NVR_SDK/rk3588_linux/demo/calendarwidget/calendarwidget root@192.168.13.89:/opt/demo/
    ./calendarwidget
    

    接着将 qt 程序运行所依赖的相关文件、配置等添加到环境变量中,操作如下:

    $ vi /etc/profile
    

    在其中添加如下内容:

    export QTEDIR=/opt/install/ export LD_LIBRARY_PATH=$QTEDIR/lib:$LD_LIBRARY_PATH export QT_QPA_PLATFORM_PLUGIN_PATH=$QTEDIR/plugins # eglfs export QT_QPA_PLATFORM=eglfs export QT_QPA_FB_DRM=1 export QT_QPA_EGLFS_FB=/dev/dri/card0 export QT_QPA_EGLFS_INTEGRATION=eglfs_kms #in minimal ubuntu, use eglfs_kms. export QT_QPA_EGLFS_KMS_ATOMIC=1 #use drm atomic api or legacy api(two different) export QT_DEBUG_PLUGINS=1

    运行报错,缺少一系列库。解决办法:

    application install libRk3588AllNeed libRk3588AllNeed.tar.gz mingGeInstallRk3588.tar.gz $ cp -df libRk3588AllNeed/libpng16.so libpng16.so libpng16.so.16 libpng16.so.16.34.0 libpng16.so.16.37.0 $ cp -df libRk3588AllNeed/libpng16.so* /usr/lib $ cp -df libRk3588AllNeed/libpcre2-16.so* /usr/lib $ cp -df libRk3588AllNeed/libfontconfig.so* /usr/lib $ cp -df libRk3588AllNeed/libfreetype.so* /usr/lib $ cp -df libRk3588AllNeed/libexpat.so* /usr/lib

    然后运行成功,成功显示界面。

    (8条消息) QT笔记--嵌入式QT交叉编译与移植(含OpenGL ES2)_交叉编译qt pkgconfig_中华田园巨龙的博客-CSDN博客

    RK3399 ARM QT开发环境搭建

    RK3399交叉编译带opengl的qt5.12.0(eglfs-mali 、eglfs-x11)gpu使用及测试

    QT笔记--嵌入式QT交叉编译与移植(含OpenGL ES2)

    QT5+OpenGL es2 + eglfs交叉编译安装(RK3399)