RK3588 Qt 交叉编译之三:编译 eglfs_kms 版本

由于 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 \
-v \
-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 搜索 "错误" 可以看到具体报错位置,下面会介绍如何解决这些错误。

二、解决配置报错

报错1

> 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博客]


报错2

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 目录下。其内容如下:

/****************************************************************************
*
*    Copyright (c) 2005 - 2012 by Vivante Corp.  All rights reserved.
*
*    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.
*
*****************************************************************************/




/*
 * Vivante specific definitions and declarations for EGL library.
 */

#ifndef __eglvivante_h_
#define __eglvivante_h_

#include "egl.h"

#ifdef __cplusplus
extern "C" {
#endif

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_ */

报错3

> 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
....
$ ls
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

在其中添加如下内容:

# Qt
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

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

$ ls
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)


posted @ 2023-04-23 14:13  fengMisaka  阅读(3072)  评论(2编辑  收藏  举报