Rockchip RK3588 - linux下Qt和opencv交叉编译环境搭建
----------------------------------------------------------------------------------------------------------------------------
开发板 :NanoPC-T6
开发板
eMMC
:256GB
LPDDR4
:16GB
显示屏 :15.6
英寸HDMI
接口显示屏
u-boot
:2017.09
linux
:6.1
----------------------------------------------------------------------------------------------------------------------------
本节的目的很简单,介绍两种编译Qt
程序的方法;
- 在
ubuntu20.04
上交叉编译Qt
程序并在NanoPC-T6
开发板 上部署运行;这种方式需要我们在ubuntu
宿主机搭建好Qt
交叉编译环境,然后在ubuntu
宿主机编译Qt
程序,并拷贝到开发板运行;(推荐这种方式) - 在
NanoPC-T6
开发板直接直接编译并运行Qt
程序;这种方式需要在开发板系统搭建好Qt
开发环境,然后在开发板编译运行;
在实际项目中,我们一般只选择一种开发方式,推荐第一种。
一、搭建Qt6
交叉编译环境
我们在《移植QT5.6
到mini2440
》中介绍了交叉编译安装Qt
,当时使用的版本是qt-everywhere-opensource-src-5.6.0.tar.xz
,其支持ARMv4t
架构。
这一节我们打算在ubuntu20.04
系统交叉编译Qt6
安装,编译Qt6
需要占用很大的物理磁盘,我们预留30GB
以上的物理磁盘。
在《野火Qt
开发环境》中详细描述了交叉编译Qt5
、Qt6
的流程,在ubuntu
宿主机编译不同版本的Qt
,对aarch64-linux-gnu
的版本有一定的要求,具体如下(务必按照下表要求,否则编译可能出现各种问题);
开发板系统 | 虚拟机系统 | 虚拟机交叉编译工具链 | 开发板编译工具链 | Qt库版本 |
---|---|---|---|---|
Ubuntu20.04 | Ubuntu20.04 | aarch64-linux-gnu 9.4.0 | —— | Qt 5.15.8 |
Debian10 | Ubuntu20.04 | aarch64-linux-gnu 8.3.0 | —— | Qt 5.15.8/Qt6.2.4 |
Debian11 | Ubuntu20.04 | aarch64-none-linux-gnu 10.2.0 | —— | Qt 5.15.8 |
Debian11 | Ubuntu20.04 | aarch64-linux-gnu-gcc 10.5.0 | aarch64-linux-gnu 10.2.1 | Qt 6.5.0 |
注意:开发板编译工具链版本要低于或等于虚拟机交叉编译工具链。
1.1 ubuntu
宿主机准备工作
1.1.1 安装Qt
依赖
ubunut20.04
环境配置,首先,让我们将我们的ubuntu
宿主机更新到最新版本;
root@zhengyang:/opt# sudo apt update
接下来,我们将安装一些额外的软件包依赖项。其中一些软件包是编译Qt6
所需的构建工具,你可能已经安装了它们,也可能没有;
root@zhengyang:/opt# apt install -y libssl-dev gperf pkg-config git bison ninja-build
root@zhengyang:/opt# apt install -y build-essential libclang-dev \
libfontconfig1-dev libfreetype6-dev libx11-dev libx11-xcb-dev \
libxext-dev libxfixes-dev libxi-dev libxrender-dev libxcb1-dev libxcb-glx0-dev \
libxcb-keysyms1-dev libxcb-image0-dev libxcb-shm0-dev libxcb-icccm4-dev libxcb-sync-dev \
libxcb-xfixes0-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-render-util0-dev \
libxcb-util-dev libxcb-xinerama0-dev libxcb-xkb-dev libxkbcommon-dev libxkbcommon-x11-dev \
libatspi2.0-dev libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev
root@zhengyang:/opt# sudo apt install xcb libxcb-cursor-dev "^libxcb.*"
1.1.2 安装交叉编译器
参考《Rockchip RK3588
- 移植uboot 2017.09 & linux 6.1
(友善之家脚本方式)》小节《安装交叉编译工具》,务必选择第一种方式。
在测试的时候发现,如果采用第二种方式在后续交叉编译Qt
中的编译配置环节中出现各种错误,最终不得不放弃该方式;
ld: error: cannot open crti.o: No such file or directory
cannot find crt1.o
1.1.3 CMake
安装
CMake
是一个跨平台的构建工具,其支持程度要好于qmake
。CMake
的配置更加灵活、强大,也更容易维护。CMak
是一个比make
更高级的编译配置工具,它可以根据不同平台、不同的编译器,生成相应的Makefile
或者vcproj
项目。
Qt6
主要推荐使用CMake
来构建工程,qmake
也是支持,但不是主要支持工具。交叉编译需要3.16版本以上的cmake
.
接着回到安装目录,拉取源码并解压:
root@zhengyang:/opt# wget https://github.com/Kitware/CMake/releases/download/v3.21.2/cmake-3.21.2.tar.gz
root@zhengyang:/opt# tar -xvf cmake-3.21.2.tar.gz
root@zhengyang:/opt# cd cmake-3.21.2
如果下载慢,可以更换为国内镜像:https://521github.com/Kitware/CMake/releases/download/v3.21.2/cmake-3.21.2.tar.gz
。
构建安装CMake
:
root@zhengyang:/opt/cmake-3.21.2# apt install openssl libssl-dev # 安装依赖
root@zhengyang:/opt/cmake-3.21.2# ./configure --prefix=/opt/cmake
root@zhengyang:/opt/opt/cmake-3.21.2# make -j4 && make install
root@zhengyang:/opt/cmake-3.21.2# cd ..
root@zhengyang:/opt# rm -rf cmake-3.21.2*
这里我们指定了安装路径为/opt/cmake
:
root@zhengyang:/opt# cd cmake
root@zhengyang:/opt/cmake# ls -l
drwxr-xr-x 2 root root 4096 Dec 15 23:26 bin
drwxr-xr-x 3 root root 4096 Dec 15 23:26 doc
drwxr-xr-x 7 root root 4096 Dec 15 23:26 share
root@zhengyang:/opt/cmake# ls -l bin/
-rwxr-xr-x 1 root root 12363720 Dec 15 23:26 ccmake
-rwxr-xr-x 1 root root 12691032 Dec 15 23:26 cmake
-rwxr-xr-x 1 root root 13090144 Dec 15 23:26 cpack
-rwxr-xr-x 1 root root 14331184 Dec 15 23:26 ctest
配置环境变量:
root@zhengyang:/opt/cmake# sudo vim /etc/profile
export PATH=$PATH:/opt/cmake/bin
root@zhengyang:/opt/cmake# source /etc/profile
查看版本信息:
root@zhengyang:/opt/cmake# cmake --version
cmake version 3.21.2
CMake suite maintained and supported by Kitware (kitware.com/cmake).
1.2 debian
开发板准备工作
debain
环境配置,首先,让我们将我们的开发板debain
系统更新到最新版本;
pi@NanoPC-T6:/# sudo aptitude update
1.2.1 安装依赖包
接下来,从debian
软件仓库安装一系列Qt
部署到开发板上所需的依赖包:
# x11相关
pi@NanoPC-T6:/# sudo aptitude install -y libx11-dev freetds-dev libsqlite3-dev libpq-dev libiodbc2-dev firebird-dev libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-sync1 libxcb-sync-dev libxcb-render-util0 libxcb-render-util0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-glx0-dev libxi-dev libdrm-dev libxcb-xinerama0 libxcb-xinerama0-dev libatspi2.0-dev libxcursor-dev libxcomposite-dev libxdamage-dev libxss-dev libxtst-dev libpci-dev libcap-dev libxrandr-dev libdirectfb-dev libaudio-dev libxkbcommon-x11-dev
pi@NanoPC-T6:/# sudo aptitude install -y "~n^libxcb" xcb libxcb-cursor-dev
# gst 1.0相关
pi@NanoPC-T6:/# sudo aptitude install -y libgstreamer1.0-0 gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav qtgstreamer-doc gstreamer1.0-tools libunwind-dev
# 其他等等
pi@NanoPC-T6:/# sudo aptitude install -y libfreetype6-dev libicu-dev libsqlite3-dev libasound2-dev libnss3-dev libxss-dev libxtst-dev libpci-dev libcap-dev libsrtp2-dev libxrandr-dev libdirectfb-dev libaudio-dev libavcodec-dev libavformat-dev libswscale-dev libts-dev libfontconfig1-dev libboost-all-dev libudev-dev libmtdev-dev libxkbcommon-dev mesa-common-dev libpulse-dev libvpx-dev libsnappy-dev flex bison libxslt-dev ruby gperf libbz2-dev libcups2-dev libatkmm-1.6-dev libxi6 libxcomposite1
pi@NanoPC-T6:/# sudo aptitude install -y libgst-dev libxext-dev libinput-dev libinput-pad-dev
# Opengl相关
pi@NanoPC-T6:/# sudo aptitude install -y libssl-dev libdbus-1-dev libglib2.0-dev libegl1-mesa-dev libgbm-dev libgles2-mesa-dev libgles2-mesa rsyslog libjpeg-dev
# 检查系统是否有必要的库和依赖项
pi@NanoPC-T6:/# sudo aptitude install -f
需要注意的是:上面安装过程中如果找不到包(可以使用sudo aptitude search xxxx
查找仓库)或者安装终止,请查找替代包或执行多次尝试。
我们还将创建一个目录,用于存放针对开发板的Qt
安装。实际上,这可以在从宿主机发送Qt6
构建到开发板之前的任何时候进行,但在本指南中,我们将在此时创建它:
pi@NanoPC-T6:/# sudo mkdir /opt/qt6.5
1.2.2 处理Chromium
无法打开问题
安装了上面这些库之后,可能存在debian
桌面Chromium
浏览器打开失败的问题,具体解决方案如下:
pi@NanoPC-T6:~$ sudo aptitude install chromium chromium-driver chromium-sandbox fonts-liberation libu2f-udev system-config-printer
# 安装语言包,中文
pi@NanoPC-T6:~$ sudo aptitude install chromium-l10n
# 查看版本
pi@NanoPC-T6:~$ chromium --version
Chromium 120.0.6099.109 built on Debian 11.8, running on Debian 11.7
1.3 编译前准备
这里我们使用的版本为qt-everywhere-src-6.5.0.tar.xz
,至于为啥不选较低的版本,考虑到我们使用的RK3588
采用的Armv8-A
架构,低版本的Qt
可能并不支持。
官方安装文档:
https://doc.qt.io/archives/qt-6.0/linux-requirements.html#platform-plugin-dependencies
;https://doc.qt.io/archives/qt-6.0/linux-building.html
;- 官方编译
Qt
教程;
1.3.1 qt-everywhere
下载
在ubuntu
系统下载程序包:
root@zhengyang:/opt# mkdir qt6.5
root@zhengyang:/opt# cd qt6.5
root@zhengyang:/opt/qt6.5# wget http://mirrors.ustc.edu.cn/qtproject/official_releases/qt/6.5/6.5.0/single/qt-everywhere-src-6.5.0.tar.xz
1.3.2 建立sysroot
目录
在ubuntu20.04
上建立sysroot
目录,并通过rsync
命令将一些目录从开发板复制到宿主机上,以构建sysroot
目录。
sysroot
是包含目标系统核心文件和库的目录,它是开发交叉编译环境时不可缺少的一部分。
(1) 首先,确保宿主机和开发板都安装了rsync
。如果尚未安装,可以使用以下命令进行安装:
root@zhengyang:/opt# apt install rsync # 宿主机
pi@NanoPC-T6:/opt# sudo aptitude install rsync # 开发板
(2) 我们在开发板debina
系统创建sysroot
目录;
pi@NanoPC-T6:/opt# sudo mkdir -p /opt/qt6.5/sysroot
pi@NanoPC-T6:/opt/qt6.5# cd /opt/qt6.5/sysroot
pi@NanoPC-T6:/opt/qt6.5/sysroot# sudo mkdir usr
pi@NanoPC-T6:/opt/qt6.5/sysroot# sudo mkdir lib
pi@NanoPC-T6:/opt/qt6.5/sysroot# sudo mkdir opt
pi@NanoPC-T6:/opt/qt6.5/sysroot# sudo cp -arvx /lib/* ./lib
pi@NanoPC-T6:/opt/qt6.5/sysroot# sudo cp -arvx /usr/include ./usr
pi@NanoPC-T6:/opt/qt6.5/sysroot# sudo cp -arvx /usr/lib ./usr
pi@NanoPC-T6:/opt/qt6.5/sysroot# sudo rm -rf /opt/qt6.5/sysroot/usr/lib/modules/6.1.25/
在构建完自己的sysroot
之后,可能会发现其中的一些符号链接变成了绝对路径,这可能会导致一些问题。为了解决这个问题,使用如下命令将链接路径中的绝对路径/
转换为/opt/qt6.5/sysroot
:
pi@NanoPC-T6:/opt/qt6.5/sysroot# sudo find -type l -lname '/*' -exec sh -c 'ln -sf "/opt/qt6.5/sysroot$(readlink "$0")" "$0"' {} \;
效果如下:
lrwxrwxrwx 1 root root 50 12月 16 21:52 /opt/qt6.5/sysroot/lib/aarch64-linux-gnu/libm.so -> /opt/qt6.5/sysroot/lib/aarch64-linux-gnu/libm.so.6 # 转换前为/lib/aarch64-linux-gnu/libm.so.6
为此,我们可以创建一个脚本build_sysroot.sh
用于构建sysroot
:
sudo mkdir -p /opt/qt6.5/sysroot
cd /opt/qt6.5/sysroot
sudo mkdir usr
sudo mkdir lib
sudo mkdir opt
sudo cp -arvx /lib/* ./lib
sudo cp -arvx /usr/include ./usr
sudo cp -arvx /usr/lib ./usr
sudo rm -rf /opt/qt6.5/sysroot/usr/lib/modules/6.1.25/
sudo find -type l -lname '/*' -exec sh -c 'ln -sf "/opt/qt6.5/sysroot$(readlink "$0")" "$0"' {} \;
ls /opt/qt6.5/sysroot/lib/aarch64-linux-gnu/libm.so -l
(3) 在ubuntu
宿主机使用rsync
命令将开发板上的/opt/qt6.5/sysroot
目录同步到宿主机的/opt/qt6.5/sysroot
目录中:
root@zhengyang:/opt/qt6.5# rsync -avzS --rsync-path="sudo rsync" --delete pi@192.168.0.101:/opt/qt6.5/sysroot ./
root@zhengyang:/opt/qt6.5# cd sysroot
root@zhengyang:/opt/qt6.5/sysroot# ll
drwxr-xr-x 83 root root 4096 Dec 16 16:08 lib/
drwx------ 2 root root 4096 Dec 16 16:11 opt/
drwx------ 2 root root 4096 Dec 16 16:11 usr/
其中:
-
rsync
命令用于从远程机器同步文件到本地机器; -
-avz
表示以归档模式(包括递归、保留权限、保留时间戳和保留链接)、压缩和显示进度等选项同步文件; -
--rsync-path="sudo rsync"
表示在远程机器上使用sudo
权限运行rsync
命令,以便拥有必要的读取权限来同步某些文件; -
-delete
表示将删除本地机器上不存在于远程机器上的文件; -
192.168.0.101
为开发板的IP
地址。
(4) 最终的效果是:将开发板上的/lib
、/usr/include
、/usr/lib
目录同步到宿主机上的/opt/qt6.5/sysroot
目录中。
在完成所有设置过程之后,我们终于可以开始构建Qt6
。这将分为两个部分:
- 构建宿主机上的
Qt6
; - 构建目标设备(例如
Nano-PC T6
开发板)上的Qt6
;
1.4 编译宿主机Qt6
1.4.1 编译配置
在opt/qt6.5
目录下创建一个安装目录qt-host
、以及构建目录qt-hostbuild
;
root@zhengyang:/opt# cd qt6.5
root@zhengyang:/opt/qt6.5# mkdir qt-host
root@zhengyang:/opt/qt6.5# mkdir qt-hostbuild
编译配置:
root@zhengyang:/opt/qt6.5# tar -xvf qt-everywhere-src-6.5.0.tar.xz
root@zhengyang:/opt/qt6.5# cd qt-hostbuild
root@zhengyang:/opt/qt6.5/qt-hostbuild# cmake ../qt-everywhere-src-6.5.0/ -GNinja -DCMAKE_BUILD_TYPE=Release -DINPUT_opengl=es2 -DQT_BUILD_EXAMPLES=OFF -DQT_BUILD_TESTS=OFF -DCMAKE_INSTALL_PREFIX=/opt/qt6.5/qt-host -DQT_FEATURE_xcb=ON -DFEATURE_xcb_xlib=ON -DQT_FEATURE_xlib=ON
.......
--
Qt is now configured for building. Just run 'cmake --build . --parallel'
Once everything is built, you must run 'cmake --install .'
Qt will be installed into '/opt/qt6.5/qt-host'
To configure and build other Qt modules, you can use the following convenience script:
/opt/qt6.5/qt-host/bin/qt-configure-module
If reconfiguration fails for some reason, try removing 'CMakeCache.txt' from the build directory
-- Configuring done
-- Generating done
-- Build files have been written to: /opt/qt6.5/qt-hostbuild
1.4.2 编译安装
配置完成之后,就可以进行编译和安装了,大约需要十几到几十分钟:
root@zhengyang:/opt/qt6.5/qt-hostbuild# cmake --build . --parallel -j4
root@zhengyang:/opt/qt6.5/qt-hostbuild# cmake --install .
编译完成后,会下载文件到/opt/qt6.5/qt-host
目录中,具体根据前面配置的-DCMAKE_INSTALL_PREFIX
目录;
root@zhengyang:/opt/qt6.5/qt-hostbuild# ll /opt/qt6.5/qt-host
drwxr-xr-x 2 root root 4096 Dec 16 01:04 bin/
drwxr-xr-x 4 root root 4096 Dec 16 01:04 doc/
drwxr-xr-x 130 root root 4096 Dec 16 01:04 include/
drwxr-xr-x 4 root root 28672 Dec 16 01:04 lib/
drwxr-xr-x 2 root root 4096 Dec 16 01:04 libexec/
drwxr-xr-x 2 root root 12288 Dec 16 01:04 metatypes/
drwxr-xr-x 65 root root 4096 Dec 16 01:04 mkspecs/
drwxr-xr-x 2 root root 4096 Dec 16 01:04 modules/
drwxr-xr-x 2 root root 4096 Dec 16 01:04 phrasebooks/
drwxr-xr-x 27 root root 4096 Dec 16 01:04 plugins/
drwxr-xr-x 25 root root 4096 Dec 16 01:04 qml/
drwxr-xr-x 2 root root 12288 Dec 16 01:04 translations/
1.5 交叉编译Qt6
接下来,我们将在宿主机上编译Qt6
,并将其安装到开发板上。配置和构建的指令与为宿主机构建Qt6
类似,但是我们需要做一些额外的工作以获得预期的结果。
1.5.1 创建cmake toolcain
文件
首先,我们要创建自己的CMake
工具链文件。这个文件是重要的,它可以链接正确的编译器和库,以便CMake
可以生成适用于开发板的合适的Qt
构建。
在/opt/qt6.5
目录下创建一个配置文件toolchain.cmake
,文件中指定编译器路径、sysroot
路径,编译链接参数等;
cmake_minimum_required(VERSION 3.18)
include_guard(GLOBAL)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
# 配置sysroot
set(TARGET_SYSROOT /opt/qt6.5/sysroot)
set(CMAKE_SYSROOT ${TARGET_SYSROOT})
set(ENV{PKG_CONFIG_PATH} $PKG_CONFIG_PATH:/usr/lib/aarch64-linux-gnu/pkgconfig)
set(ENV{PKG_CONFIG_LIBDIR} /usr/lib/pkgconfig:/usr/share/pkgconfig/:${TARGET_SYSROOT}/usr/lib/aarch64-linux-gnu/pkgconfig:${TARGET_SYSROOT}/usr/lib/pkgconfig)
set(ENV{PKG_CONFIG_SYSROOT_DIR} ${CMAKE_SYSROOT})
# if you use other version of gcc and g++ than gcc/g++ 9, you must change the following variables
set(CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc-10)
set(CMAKE_CXX_COMPILER /usr/bin/aarch64-linux-gnu-g++-10)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${TARGET_SYSROOT}/usr/include")
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}")
set(QT_COMPILER_FLAGS "-march=armv8-a")
set(QT_COMPILER_FLAGS_RELEASE "-O2 -pipe")
set(QT_LINKER_FLAGS "-Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
set(CMAKE_BUILD_RPATH ${TARGET_SYSROOT})
include(CMakeInitializeConfigs)
include(CMakeInitializeConfigs)
function(cmake_initialize_per_config_variable _PREFIX _DOCSTRING)
if (_PREFIX MATCHES "CMAKE_(C|CXX|ASM)_FLAGS")
set(CMAKE_${CMAKE_MATCH_1}_FLAGS_INIT "${QT_COMPILER_FLAGS}")
foreach (config DEBUG RELEASE MINSIZEREL RELWITHDEBINFO)
if (DEFINED QT_COMPILER_FLAGS_${config})
set(CMAKE_${CMAKE_MATCH_1}_FLAGS_${config}_INIT "${QT_COMPILER_FLAGS_${config}}")
endif()
endforeach()
endif()
if (_PREFIX MATCHES "CMAKE_(SHARED|MODULE|EXE)_LINKER_FLAGS")
foreach (config SHARED MODULE EXE)
set(CMAKE_${config}_LINKER_FLAGS_INIT "${QT_LINKER_FLAGS}")
endforeach()
endif()
_cmake_initialize_per_config_variable(${ARGV})
endfunction()
set(XCB_PATH_VARIABLE ${TARGET_SYSROOT})
set(GL_INC_DIR ${TARGET_SYSROOT}/usr/include)
set(GL_LIB_DIR ${TARGET_SYSROOT}:${TARGET_SYSROOT}/usr/lib/aarch64-linux-gnu/:${TARGET_SYSROOT}/usr:${TARGET_SYSROOT}/usr/lib)
set(EGL_INCLUDE_DIR ${GL_INC_DIR})
set(EGL_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libEGL.so)
set(OPENGL_INCLUDE_DIR ${GL_INC_DIR})
set(OPENGL_opengl_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libOpenGL.so)
set(GLESv2_INCLUDE_DIR ${GL_INC_DIR})
set(GLESv2_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libGLESv2.so)
set(gbm_INCLUDE_DIR ${GL_INC_DIR})
set(gbm_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libgbm.so)
set(Libdrm_INCLUDE_DIR ${GL_INC_DIR})
set(Libdrm_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libdrm.so)
set(XCB_XCB_INCLUDE_DIR ${GL_INC_DIR})
set(XCB_XCB_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libxcb.so)
设定了sysroot
其会对编译和链接过程中,查找头文件和链接库造成影响,cmake
设置--sysroot
通过CMAKE_SYSROOT
配置;
例如原本默认会从/usr/include
目录中搜索头文件、从/usr/lib
中搜索依赖库,当设置了--sysroot=/opt/qt6.5/sysroot
后则会从/opt/qt6.5/sysroot/usr/include
搜索头文件、从/opt/qt6.5/sysroot/usr/lib
中搜索依赖库。
未设置--sysroot | 设置了--sysroot=dir后 | |
---|---|---|
头文件搜索路径 | /usr/include | /opt/qt6.5/sysroot/usr/include |
依赖库搜索路径 | /usr/lib | /opt/qt6.5/sysroot/usr/lib |
1.5.2 创建qmake.conf
既然我们已经有了工具链,交叉编译器和sysroot
,我们可以继续配置和构建适用于开发板的Qt
。
在/opt/qt6.5# cd qt-everywhere-src-6.5.0
目录下创建qtbase/mkspecs/devices/linux-nanopc-t6-g++/qmake.conf
;
root@zhengyang:/opt/qt6.5# cd qt-everywhere-src-6.5.0
root@zhengyang:/opt/qt6.5/qt-everywhere-src-6.5.0# mkdir qtbase/mkspecs/devices/linux-nanopc-t6-g++
root@zhengyang:/opt/qt6.5/qt-everywhere-src-6.5.0# vim qtbase/mkspecs/devices/linux-nanopc-t6-g++/qmake.conf
#
# Generic qmake configuration for building with g++ on Raspberry Pi 4 (64-bit).
#
# Tested with Raspberry Pi OS 64-bit and aarch64 gcc compiler from Debian package repository
#
# A minimal configure line could look something like this:
DISTRO_OPTS += deb-multi-arch
include(../common/linux_device_pre.conf)
QMAKE_LIBS_EGL += -lEGL -lGLESv2 -lmali
QMAKE_LIBS_OPENGL_ES2 += -lGLESv2 -lEGL -lmali
QMAKE_CFLAGS += -march=armv8-a
QMAKE_CXXFLAGS += $$QMAKE_CFLAGS
QMAKE_INCDIR_POST += \
$$[QT_SYSROOT]/usr/include \
$$[QT_SYSROOT]/usr/include/aarch64-linux-gnu
QMAKE_LIBDIR_POST += \
$$[QT_SYSROOT]/usr/lib \
$$[QT_SYSROOT]/lib/aarch64-linux-gnu \
$$[QT_SYSROOT]/usr/lib/aarch64-linux-gnu
QMAKE_RPATHLINKDIR_POST += \
$$[QT_SYSROOT]/usr/lib \
$$[QT_SYSROOT]/usr/lib/aarch64-linux-gnu \
$$[QT_SYSROOT]/lib/aarch64-linux-gnu
# Added line as requested in the comments above
QMAKE_LIBDIR_EGL = $$[QT_SYSROOT]/usr/lib/aarch64-linux-gnu
QMAKE_INCDIR_EGL = $$[QT_SYSROOT]/usr/include
#Not sure if this line really does something or not
# This is, as far as I understand, where the libraries for GLES2 reside
QMAKE_LIBDIR_OPENGL_ES2 = $$[QT_SYSROOT]/usr/lib/aarch64-linux-gnu
QMAKE_INCDIR_OPENGL_ES2 = $$[QT_SYSROOT]/usr/include
EGLFS_DEVICE_INTEGRATION = eglfs_kms
LINKER_FLAGS += -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed
include(../common/linux_device_post.conf)
load(qt_config)
同时在qtbase/mkspecs/devices/linux-nanopc-t6-g++
路径下创建qplatformdefs.h
文件;
#include "../../linux-g++/qplatformdefs.h"
1.5.3 编译配置
在opt/qt
目录下创建一个安装目录qt-nanopi
、以及构建目录qt-nanopibuild
;
root@zhengyang:/opt/qt6.5# mkdir qt-nanopi
root@zhengyang:/opt/qt6.5# mkdir qt-nanopibuild
编译配置(可以使用cmake
,也可以使用configure
编译,教程使用cmake
方式编译):
root@zhengyang:/opt/qt6.5/qt-nanopibuild# cmake ../qt-everywhere-src-6.5.0/ -GNinja -DCMAKE_BUILD_TYPE=Release -DFEATURE_opengles2=ON -DQT_FEATURE_opengl_desktop=OFF -DQT_FEATURE_opengles3=ON -DTEST_opengles31=TRUE -DFEATURE_opengles31=ON -DTEST_opengles32=TRUE -DFEATURE_opengles32=ON -DQT_BUILD_EXAMPLES=OFF -DQT_BUILD_TESTS=OFF -DQT_HOST_PATH=/opt/qt6.5/qt-host -DCMAKE_STAGING_PREFIX=/opt/qt6.5/sysroot/opt/prefix -DCMAKE_INSTALL_PREFIX=/opt/qt6.5/qt-nanopi -DCMAKE_TOOLCHAIN_FILE=/opt/qt6.5/toolchain.cmake -DQT_QMAKE_TARGET_MKSPEC=devices/linux-nanopc-t6-g++ -DQT_FEATURE_xcb=ON -DFEATURE_xcb_xlib=ON -DQT_FEATURE_xlib=ON -DFEATURE_egl=ON -DFEATURE_egl_x11=ON -DFEATURE_eglfs=ON -DFEATURE_eglfs_mali=ON -DFEATURE_eglfs_x11=ON -DFEATURE_libinput=ON -DFEATURE_qtwebengine_build=OFF
其中:
-DQT_HOST_PATH=/opt/qt6.5/qt-host
该目录是前面编译宿主机Qt6
的安装目录,;-DQT_FEATURE_opengles3=ON
开启了opengl es3
;-DCMAKE_STAGING_PREFIX=/opt/qt6.5/sysroot/opt/prefix
用于指定将构建结果安装到临时安装目录的路径;- -
DCMAKE_INSTALL_PREFIX=/opt/qt6.5/qt-nanopi
指定构建过程中最终安装的目标路径; -DCMAKE_TOOLCHAIN_FILE
是目标的cmake toolcain
文件,需要根据自己实际目录修改;-DQT_QMAKE_TARGET_MKSPEC=devices/linux-nanopc-t6-g++
指定Qt
项目构建时使用的qmake
规范;
更多配置选项可以通过cmake ../qt-everywhere-src-6.5.0/ -LH
命令查看。
(1) 如果出现错误,比如eglfs_mali
未生效;
CMake Error at qtbase/cmake/QtBuildInformation.cmake:508 (message):
Feature "eglfs_mali": Forcing to "ON" breaks its condition:
QT_FEATURE_eglfs AND ( TEST_egl_mali OR TEST_egl_mali_2 )
Condition values dump:
QT_FEATURE_eglfs = "ON"
TEST_egl_mali = ""
TEST_egl_mali_2 = ""
Call Stack (most recent call first):
qtbase/cmake/QtFeature.cmake:288 (qt_configure_add_report_error)
qtbase/cmake/QtFeature.cmake:410 (qt_feature_check_and_save_internal_value)
qtbase/cmake/QtFeature.cmake:625 (qt_evaluate_feature)
qtbase/cmake/QtFeature.cmake:594 (qt_feature_module_end)
qtbase/src/CMakeLists.txt:13 (qt_feature_evaluate_features)
可以看到eglfs_mali
如果要生效,除了依赖于QT_FEATURE_eglfs
,还依赖于TEST_egl_mali
或TEST_egl_mali_2
;
TEST_egl_mali
生效取决于(qtbase/src/gui/configure.cmake
文件):
# egl-mali
qt_config_compile_test(egl_mali
LABEL "Mali EGL"
LIBRARIES
EGL::EGL
CODE
"#include <EGL/fbdev_window.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
int main(void)
{
/* BEGIN TEST: */
fbdev_window *w = 0;
/* END TEST: */
return 0;
}
")
需要在/opt/qt6.5/sysroot/usr/include/EGL
目录下创建fbdev_window.h
文件:
/*
* This confidential and proprietary software may be used only as
* authorised by a licensing agreement from ARM Limited
* (C) COPYRIGHT 2008-2011 ARM Limited
* ALL RIGHTS RESERVED
* The entire notice above must be reproduced on all authorised
* copies and copies may only be made to the extent permitted
* by a licensing agreement from ARM Limited.
*/
/**
* @file fbdev_window.h
* @brief A window type for the framebuffer device (used by egl and tests)
*/
#ifndef _FBDEV_WINDOW_H_
#define _FBDEV_WINDOW_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
FBDEV_PIXMAP_DEFAULT = 0,
FBDEV_PIXMAP_SUPPORTS_UMP = (1<<0),
FBDEV_PIXMAP_ALPHA_FORMAT_PRE = (1<<1),
FBDEV_PIXMAP_COLORSPACE_sRGB = (1<<2),
FBDEV_PIXMAP_EGL_MEMORY = (1<<3) /* EGL allocates/frees this memory */
} fbdev_pixmap_flags;
typedef struct fbdev_window
{
unsigned short width;
unsigned short height;
} fbdev_window;
typedef struct fbdev_pixmap
{
unsigned int height;
unsigned int width;
unsigned int bytes_per_pixel;
unsigned char buffer_size;
unsigned char red_size;
unsigned char green_size;
unsigned char blue_size;
unsigned char alpha_size;
unsigned char luminance_size;
fbdev_pixmap_flags flags;
unsigned short *data;
unsigned int format; /* extra format information in case rgbal is not enough, especially for YUV formats */
} fbdev_pixmap;
#ifdef __cplusplus
}
#endif
#endif
参考文章:《RK3588 Qt
交叉编译之三:编译eglfs_kms
版本 》。
(2) 我们可以通过config.summary
查看我们的配置:
点击查看代码
root@zhengyang:/opt/qt6.5/qt-nanopibuild# cat config.summary
Building for: devices/linux-nanopc-t6-g++ (arm64, CPU features: cx16 neon)
Compiler: gcc 10.5.0
Build options:
Mode ................................... release
Optimize release build for size ........ no
Fully optimize release builds (-O3) .... no
Building shared libraries .............. yes
Using C standard ....................... C11
Using C++ standard ..................... C++17
Using ccache ........................... no
Using new DTAGS ........................ yes
Relocatable ............................ yes
Using precompiled headers .............. yes
Using Link Time Optimization (LTCG) .... no
Using Intel CET ........................ no
Target compiler supports:
ARM Extensions ....................... NEON
Sanitizers:
Addresses ............................ no
Threads .............................. no
Memory ............................... no
Fuzzer (instrumentation only) ........ no
Undefined ............................ no
Build parts ............................ libs
Qt modules and options:
Qt Concurrent .......................... yes
Qt D-Bus ............................... yes
Qt D-Bus directly linked to libdbus .... yes
Qt Gui ................................. yes
Qt Network ............................. yes
Qt PrintSupport ........................ yes
Qt Sql ................................. yes
Qt Testlib ............................. yes
Qt Widgets ............................. yes
Qt Xml ................................. yes
Support enabled for:
Using pkg-config ....................... yes
udev ................................... yes
OpenSSL ................................ yes
Qt directly linked to OpenSSL ........ no
OpenSSL 1.1 ............................ yes
OpenSSL 3.0 ............................ no
Using system zlib ...................... yes
Zstandard support ...................... no
Thread support ......................... yes
Common build options:
Linker can resolve circular dependencies yes
Qt Core:
backtrace .............................. yes
DoubleConversion ....................... yes
Using system DoubleConversion ........ no
GLib ................................... yes
ICU .................................... yes
Using system libb2 ..................... no
Built-in copy of the MIME database ..... yes
cpp/winrt base ......................... no
Tracing backend ........................ <none>
Logging backends:
journald ............................. no
syslog ............................... no
slog2 ................................ no
PCRE2 .................................. yes
Using system PCRE2 ................... yes
CLONE_PIDFD support in forkfd .......... yes
Application permissions ................ no
Qt Sql:
SQL item models ........................ yes
Qt Network:
getifaddrs() ........................... yes
IPv6 ifname ............................ yes
libproxy ............................... no
Linux AF_NETLINK ....................... yes
DTLS ................................... yes
OCSP-stapling .......................... yes
SCTP ................................... no
Use system proxies ..................... yes
GSSAPI ................................. no
Brotli Decompression Support ........... yes
qIsEffectiveTLD() ...................... yes
Built-in publicsuffix database ....... yes
System publicsuffix database ......... yes
Core tools:
Android deployment tool ................ no
macOS deployment tool .................. no
Windows deployment tool ................ no
qmake .................................. yes
Qt Gui:
Accessibility .......................... yes
FreeType ............................... yes
Using system FreeType ................ yes
HarfBuzz ............................... yes
Using system HarfBuzz ................ yes
Fontconfig ............................. yes
Image formats:
GIF .................................. yes
ICO .................................. yes
JPEG ................................. yes
Using system libjpeg ............... yes
PNG .................................. yes
Using system libpng ................ yes
Text formats:
HtmlParser ........................... yes
CssParser ............................ yes
OdfWriter ............................ yes
MarkdownReader ....................... yes
Using system libmd4c ............... no
MarkdownWriter ....................... yes
EGL .................................... yes
OpenVG ................................. no
OpenGL:
opengl_desktop ....................... no
OpenGL ES 2.0 ........................ yes
opengles3 ............................ yes
OpenGL ES 3.1 ........................ yes
OpenGL ES 3.2 ........................ yes
Vulkan ................................. no
Session Management ..................... yes
Features used by QPA backends:
evdev .................................. yes
libinput ............................... yes
HiRes wheel support in libinput ........ no
integrityhid ........................... yes
mtdev .................................. yes
tslib .................................. yes
xkbcommon .............................. yes
X11 specific:
xlib ................................. yes
XCB Xlib ............................. yes
EGL on X11 ........................... yes
xkbcommon-x11 ........................ yes
xcb-sm ............................... yes
QPA backends:
DirectFB ............................... no
EGLFS .................................. yes
EGLFS details:
EGLFS OpenWFD ........................ no
EGLFS i.Mx6 .......................... no
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 ............................ yes
LinuxFB ................................ yes
VNC .................................... yes
VK_KHR_display ......................... no
QNX:
lgmon ................................ no
IMF .................................. no
XCB:
Using system-provided xcb-xinput ..... no
GL integrations:
GLX Plugin ......................... no
XCB GLX .......................... no
EGL-X11 Plugin ..................... yes
Windows:
Direct 2D ............................ no
Direct 2D 1.1 ........................ no
DirectWrite .......................... no
DirectWrite 3 ........................ no
Qt Widgets:
GTK+ ................................... no
Styles ................................. Fusion Windows
Qt Testlib:
Tester for item models ................. yes
Batch tests ............................ no
Qt PrintSupport:
CUPS ................................... yes
Qt Sql Drivers:
DB2 (IBM) .............................. no
InterBase .............................. yes
MySql .................................. no
OCI (Oracle) ........................... no
ODBC ................................... yes
PostgreSQL ............................. yes
SQLite ................................. yes
Using system provided SQLite ......... no
Further Image Formats:
JasPer ................................. no
MNG .................................... no
TIFF ................................... yes
Using system libtiff ................. yes
WEBP ................................... yes
Using system libwebp ................. no
Qt QML:
QML network support .................... yes
QML debugging and profiling support .... yes
QML just-in-time compiler .............. yes
QML XML http request ................... yes
QML Locale ............................. yes
Qt QML Models:
QML list model ......................... yes
QML delegate model ..................... yes
Qt Quick:
AnimatedImage item ..................... yes
Canvas item ............................ yes
Support for Qt Quick Designer .......... yes
Flipable item .......................... yes
GridView item .......................... yes
ListView item .......................... yes
TableView item ......................... yes
TreeView item .......................... yes
Path support ........................... yes
PathView item .......................... yes
Positioner items ....................... yes
Repeater item .......................... yes
ShaderEffect item ...................... yes
Sprite item ............................ yes
Qt Quick Templates 2:
Hover support .......................... yes
Multi-touch support .................... yes
Calendar support ....................... yes
Qt Quick Controls 2:
Styles ................................. Basic Fusion Imagine iOS Material Universal macOS Windows
QtQuick3D:
Assimp ................................. yes
System Assimp .......................... no
Qt Multimedia:
Spatial Audio .......................... yes
Spatial Audio (Quick3D) ................ yes
Low level Audio Backend:
ALSA (experimental) .................. no
PulseAudio ........................... yes
MMRenderer ........................... no
CoreAudio ............................ no
Windows Media SDK .................... no
Open SLES (Android) .................. no
Web Assembly ......................... no
Plugin:
GStreamer 1.0 ........................ yes
FFmpeg ............................... yes
MMRenderer ........................... no
AVFoundation ......................... no
Windows Media Foundation ............. no
Hardware acceleration and features:
Video for Linux ...................... yes
VAAPI support ........................ no
Linux DMA buffer support ............. yes
VideoToolbox ......................... no
Qt 3D:
Assimp ................................. yes
System Assimp .......................... no
Use SSE2 instructions .................. no
Use AVX2 instructions .................. no
Aspects:
Render aspect ........................ yes
Input aspect ......................... yes
Logic aspect ......................... yes
Animation aspect ..................... yes
Extras aspect ........................ yes
Qt 3D APIs:
Vulkan ................................. no
Qt 3D Renderers:
OpenGL Renderer ........................ yes
RHI Renderer ........................... yes
Qt3D Geometry Loaders:
Autodesk FBX ........................... no
Qt 5 Compatibility Libraries:
iconv .................................. no
Qt Charts Types:
Area Chart ............................. yes
Line Chart ............................. yes
Spline Chart ........................... yes
Scatter Chart .......................... yes
Bar Chart .............................. yes
Pie Chart .............................. yes
Boxplot Chart .......................... yes
Candlestick Chart ...................... yes
Qt Axis Types:
DateTime Axis .......................... yes
Qt Bluetooth:
BlueZ .................................. no
BlueZ Low Energy ....................... no
Linux Crypto API ....................... no
WinRT Bluetooth API .................... no
Qt Tools:
Qt Assistant ........................... yes
QDoc ................................... no
Clang-based lupdate parser ............. no
Qt Designer ............................ yes
Qt Distance Field Generator ............ yes
Qt Linguist ............................ yes
pixeltool .............................. yes
qdbus .................................. yes
Qt Attributions Scanner ................ yes
qtdiag ................................. yes
qtplugininfo ........................... yes
Serial Port:
ntddmodm ............................... no
WebEngine Repository Build Options:
Build Ninja ............................ no
Build Gn ............................... yes
Jumbo Build ............................ yes
Developer build ........................ no
Build QtWebEngine Modules:
Build QtWebEngineCore ................ no
Build QtWebEngineWidgets ............. no
Build QtWebEngineQuick ............... no
Build QtPdf Modules:
Build QtPdfWidgets ................... no
Build QtPdfQuick ..................... no
Optional system libraries:
re2 .................................. no
icu .................................. no
libwebp, libwebpmux and libwebpdemux . no
opus ................................. no
ffmpeg ............................... no
libvpx ............................... no
snappy ............................... yes
glib ................................. yes
zlib ................................. yes
minizip .............................. no
libevent ............................. yes
libxml2 and libxslt .................. yes
lcms2 ................................ no
png .................................. yes
jpeg ................................. yes
libopenjpeg2 ......................... no
harfbuzz ............................. no
freetype ............................. yes
libpci ............................... yes
Qt Protobuf tools:
Qt Protobuf generator .................. no
Qt GRPC:
gRPC support ........................... yes
Native gRPC support .................... no
Qt GRPC tools:
Qt GRPC generator ...................... no
Qt Opcua:
Open62541 .............................. yes
Unified Automation C++ SDK ............. no
Support for namespace 0 NodeId names ... yes
Namespace 0 NodeIds generator .......... no
Open62541 security support ............. yes
Support for global discovery server .... yes
Qt Remote Objects:
High Availability Manager (ham) ........ no
Qt Scxml:
ECMAScript data model for QtScxml ...... yes
Qt Sensors:
sensorfw ............................... no
sensorfw_enabled_with_cmake ............ no
Qt SerialBus:
Socket CAN ............................. yes
Socket CAN FD .......................... yes
SerialPort Support ..................... yes
Qt TextToSpeech:
Flite .................................. no
Flite with ALSA ........................ no
Speech Dispatcher ...................... no
Qt Virtualkeyboard:
Desktop integration .................... yes
Built-in layouts ....................... yes
Key navigation ......................... no
Retro style as default ................. no
Sensitive Debug ........................ no
Cerence ................................ no
Static Linking ....................... no
Handwriting .......................... no
Alphabetic ......................... no
CJK ................................ no
XT9 .................................. no
XT9 Debug .......................... no
XT9 9-key layouts .................. no
Bundle resources ..................... no
Handwriting ........................ no
XT9 ................................ no
Hunspell ............................... no
Using Hunspell copy from 3rdparty/ ... no
OpenWnn ................................ yes
MyScript ............................... no
Language support enabled for:
Arabic ............................... yes
Bulgarian ............................ yes
Czech ................................ yes
Danish ............................... yes
German ............................... yes
Greek ................................ yes
English GB ........................... yes
English US ........................... yes
Spanish .............................. yes
Spanish Mexico ....................... yes
Estonian ............................. yes
Farsi ................................ yes
Finnish .............................. yes
French Canada ........................ yes
French France ........................ yes
Hebrew ............................... yes
Hindi ................................ yes
Croatian ............................. yes
Hungarian ............................ yes
Indonesian ........................... yes
Italian .............................. yes
Japanese ............................. yes
Korean ............................... yes
Malay ................................ yes
Norwegian ............................ yes
Dutch ................................ yes
Polish ............................... yes
Portuguese Brazil .................... yes
Portuguese Portugal .................. yes
Romanian ............................. yes
Russian .............................. yes
Slovak ............................... yes
Slovenian ............................ yes
Albanian ............................. yes
Serbian .............................. yes
Swedish .............................. yes
Thai ................................. yes
Turkish .............................. yes
Ukrainian ............................ yes
Vietnamese ........................... yes
Simplified Chinese ................... yes
Traditional Chinese .................. yes
HongKong Chinese ..................... no
Traditional chinese input methods:
Zhuyin ............................... yes
Cangjie .............................. yes
Note: Hunspell in Qt Virtual Keyboard is not enabled. Spelling correction will not be available.
Note: Due to CMAKE_STAGING_PREFIX usage and an unfixed CMake bug,
to ensure correct build time rpaths, directory-level install
rules like ninja src/gui/install will not work.
Check QTBUG-102592 for further details.
WARNING: QDoc will not be compiled, probably because libclang could not be located. This means that you cannot build the Qt documentation.
Either set CMAKE_PREFIX_PATH or LLVM_INSTALL_DIR to the location of your llvm installation.
On Linux systems, you may be able to install libclang by installing the libclang-dev or libclang-devel package, depending on your distribution.
On macOS, you can use Homebrew's llvm package.
You will also need to set the FEATURE_clang CMake variable to ON to re-evaluate this check.
WARNING: Clang-based lupdate parser will not be available. LLVM and Clang C++ libraries have not been found.
You will need to set the FEATURE_clangcpp CMake variable to ON to re-evaluate this check.
WARNING: QtWebEngine won't be built. node.js version 12 or later is required.
WARNING: QtPdf won't be built. node.js version 12 or later is required.
root@zhengyang:/opt/qt6.5/qt-nanopibuild#
1.5.4 编译安装
配置完成之后,就可以进行编译和安装了,大约需要十几到几十分钟:
root@zhengyang:/opt/qt6.5/qt-nanopibuild# cmake --build . --parallel -j4
root@zhengyang:/opt/qt6.5/qt-nanopibuild# cmake --install .
安装完成后,应该会在安装目录/opt/qt6.5/qt-nanopi
下生成文件,然后实际测试发现被安装到了/opt/qt6.5/sysroot/opt/prefix/
,因此我们拷贝一份过去;
root@zhengyang:/opt/qt6.5/qt-nanopibuild# ls /opt/qt6.5/qt-nanopi
root@zhengyang:/opt/qt6.5/qt-hostbuild# ls /opt/qt6.5/sysroot/opt/prefix/ -l
drwxr-xr-x 2 root root 4096 Dec 17 16:00 bin
drwxr-xr-x 4 root root 4096 Dec 17 16:00 doc
drwxr-xr-x 130 root root 4096 Dec 17 16:00 include
drwxr-xr-x 4 root root 28672 Dec 17 16:00 lib # 比较重要 库文件
drwxr-xr-x 2 root root 4096 Dec 17 16:00 libexec
drwxr-xr-x 2 root root 12288 Dec 17 16:00 metatypes
drwxr-xr-x 64 root root 4096 Dec 17 16:00 mkspecs
drwxr-xr-x 2 root root 4096 Dec 17 16:00 modules
drwxr-xr-x 2 root root 4096 Dec 17 16:00 phrasebooks
drwxr-xr-x 27 root root 4096 Dec 17 16:00 plugins # 比较重要 插件
drwxr-xr-x 25 root root 4096 Dec 17 16:00 qml
drwxr-xr-x 2 root root 12288 Dec 17 16:00 translations
root@zhengyang:/opt/qt6.5/qt-hostbuild# cp -ar /opt/qt6.5/sysroot/opt/prefix/* /opt/qt6.5/qt-nanopi
(1) 如果使用了libxkbcommon 1.6.0
及更高版本,编译过程可能出现如下错误:
/opt/qt6.5/qt-everywhere-src-6.5.0/qtbase/src/gui/platform/unix/qxkbcommon.cpp:242:16: error: ‘XKB_KEY_dead_lowline’ was not declared in this scope; did you mean ‘XKB_KEY_dead_belowring’?
242 | Xkb2Qt<XKB_KEY_dead_lowline, Qt::Key_Dead_Lowline>,
| ^~~~~~~~~~~~~~~~~~~~
| XKB_KEY_dead_belowring
/opt/qt6.5/qt-everywhere-src-6.5.0/qtbase/src/gui/platform/unix/qxkbcommon.cpp:242:69: error: template argument 1 is invalid
242 | Xkb2Qt<XKB_KEY_dead_lowline, Qt::Key_Dead_Lowline>,
| ^
修改src/gui/platform/unix/qxkbcommon.cpp
文件:
修改后的代码如下:
/* The following four XKB_KEY_dead keys got removed in libxkbcommon 1.6.0
The define check is kind of version check here. */
#ifdef XKB_KEY_dead_lowline
Xkb2Qt<XKB_KEY_dead_lowline, Qt::Key_Dead_Lowline>,
Xkb2Qt<XKB_KEY_dead_aboveverticalline, Qt::Key_Dead_Aboveverticalline>,
Xkb2Qt<XKB_KEY_dead_belowverticalline, Qt::Key_Dead_Belowverticalline>,
Xkb2Qt<XKB_KEY_dead_longsolidusoverlay, Qt::Key_Dead_Longsolidusoverlay>,
#endif
(2) 如果编译过程出现GLIBC
相关错误,比如:
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /opt/qt6.5/sysroot/lib/aarch64-linux-gnu/libglib-2.0.so.0: undefined reference to `pthread_rwlock_destroy@GLIBC_2.34'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: /opt/qt6.5/sysroot/lib/aarch64-linux-gnu/libglib-2.0.so.0: undefined reference to `pthread_key_create@GLIBC_2.34'
/usr/lib/gcc-cross/aarch64-linux-gnu/10/../../../../aarch64-linux-gnu/bin/ld: qtbase/lib/libQt6Core.so.6.5.0: undefined reference to `dlopen@GLIBC_2.17'
collect2: error: ld returned 1 exit status
[3237/8385] Building CXX object qtdeclarative/tools/qmlls/CMakeFiles/qmlls.dir/qmlcompletionsupport.cpp.o
ninja: build stopped: subcommand failed.
出现这种问题就是因为“编译库的编译器” 和 “编译当前程序的编译器” 版本是不一样的,具体一点就是因为,当前程序的编译器的版本是比较低的,只要升级一下就可以了。
查看/opt/qt6.5/sysroot/lib/aarch64-linux-gnu/libglib-2.0.so.0
依赖的glibc
版本:
pi@NanoPC-T6:/opt/qt6.5$ ldd /opt/qt6.5/sysroot/lib/aarch64-linux-gnu/libglib-2.0.so.0.7800.3 # libglib-2.0.so指向这个文件
linux-vdso.so.1 (0x0000007f9fc99000)
libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x0000007f9fa30000)
libpcre2-8.so.0 => /lib/aarch64-linux-gnu/libpcre2-8.so.0 (0x0000007f9f990000)
libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000007f9f7e0000)
/lib/ld-linux-aarch64.so.1 (0x0000007f9fc5c000)
libpthread.so.0 => /lib/aarch64-linux-gnu/libpthread.so.0 (0x0000007f9f7b0000)
pi@NanoPC-T6:/opt/qt6.5$ objdump -p /opt/qt6.5/sysroot/lib/aarch64-linux-gnu/libglib-2.0.so.0.7800.3 | grep GLIBC_
0x06969197 0x00 05 GLIBC_2.17
0x06969188 0x00 07 GLIBC_2.28
0x069691b3 0x00 06 GLIBC_2.33 # 依赖2.33版本
0x069691b2 0x00 04 GLIBC_2.32
0x069691b4 0x00 03 GLIBC_2.34 # 依赖2.34版本
0x06969197 0x00 02 GLIBC_2.17
因此需要为交叉编译工具aarch64-linux-gnu
升级glibc
版本;首先查看glibc
支持的版本,可以看到其的确不支持2.34
版本;
root@zhengyang:/opt# strings /usr/aarch64-linux-gnu/lib/libc.so.6 | grep GLIBC_
GLIBC_2.17
GLIBC_2.18
GLIBC_2.22
GLIBC_2.23
GLIBC_2.24
GLIBC_2.25
GLIBC_2.26
GLIBC_2.27
GLIBC_2.28
GLIBC_2.29
GLIBC_2.30
GLIBC_PRIVATE
这里我们通过对glibc
源码进行交叉编译得到高版本的glibc
,这里选择一个大于2.34
的版本;
# 下载软件包
root@zhengyang:/opt# wget https://mirrors.aliyun.com/gnu/glibc/glibc-2.36.tar.gz
# 解压
root@zhengyang:/opt# tar -zxvf glibc-2.36.tar.gz
root@zhengyang:/opt# cd glibc-2.36
# 预编译
root@zhengyang:/opt/glibc-2.36# mkdir build
root@zhengyang:/opt/glibc-2.36# cd build
root@zhengyang:/opt/glibc-2.36/build# apt install gawk
root@zhengyang:/opt/glibc-2.36/build# apt install bison
root@zhengyang:/opt/glibc-2.36/build# export LD_LIBRARY_PATH=
root@zhengyang:/opt/glibc-2.36/build# CC=/usr/bin/aarch64-linux-gnu-gcc ../configure --prefix=/usr/aarch64-linux-gnu --build=x86_64-linux-gnu --host=aarch64-linux-gnu --target=aarch64-linux-gnu --with-headers=/usr/aarch64-linux-gnu/include --disable-multilib libc_cv_forced_unwind=yes LDFLAGS="-L/usr/aarch64-linux-gnu/lib" --disable-werror
# 编译
root@zhengyang:/opt/glibc-2.36/build# make -j4
root@zhengyang:/opt/glibc-2.36/build# make install
root@zhengyang:/opt/glibc-2.36/build# ll /usr/aarch64-linux-gnu
drwxr-xr-x 2 root root 4096 Dec 17 23:20 bin/
drwxr-xr-x 2 root root 4096 Dec 17 23:20 etc/
drwxr-xr-x 34 root root 4096 Dec 17 23:20 include/
drwxr-xr-x 4 root root 4096 Dec 17 23:20 lib/
drwxr-xr-x 3 root root 4096 Dec 17 23:19 libexec/
drwxr-xr-x 2 root root 4096 Dec 17 23:20 sbin/
drwxr-xr-x 5 root root 4096 Dec 17 23:20 share/
drwxr-xr-x 3 root root 4096 Dec 17 23:20 var/
再次查看glibc
支持的版本:
root@zhengyang:/opt/glibc-2.36/build# strings /usr/aarch64-linux-gnu/lib/libc.so.6 | grep GLIBC_2.
GLIBC_2.17
GLIBC_2.18
GLIBC_2.22
GLIBC_2.23
GLIBC_2.24
GLIBC_2.25
GLIBC_2.26
GLIBC_2.27
GLIBC_2.28
GLIBC_2.29
GLIBC_2.30
GLIBC_2.31
GLIBC_2.32
GLIBC_2.33 # 新增
GLIBC_2.34 # 新增
GLIBC_2.35 # 新增
GLIBC_2.36 # 新增
参考文章:
1.5.5 同步文件到开发板
同步文件到开发板(这是使用rsync
):
root@zhengyang:/opt# rsync -avz --rsync-path="sudo rsync" /opt/qt6.5/sysroot/opt/prefix/* pi@192.168.0.101:/opt/qt6.5 # 宿主机运行
pi@NanoPC-T6:~$ ls /opt/qt6.5/ -l # 开发板运行
drwxr-xr-x 2 root root 4096 12月 17 16:00 bin
-rwxr-xr-x 1 root root 343 12月 17 14:40 build_sysroot.sh
drwxr-xr-x 4 root root 4096 12月 17 16:00 doc
drwxr-xr-x 130 root root 4096 12月 17 16:00 include
drwxr-xr-x 4 root root 24576 12月 17 16:00 lib
drwxr-xr-x 2 root root 4096 12月 17 16:00 libexec
drwxr-xr-x 2 root root 12288 12月 17 16:00 metatypes
drwxr-xr-x 64 root root 4096 12月 17 16:00 mkspecs
drwxr-xr-x 2 root root 4096 12月 17 16:00 modules
drwxr-xr-x 2 root root 4096 12月 17 16:00 phrasebooks
drwxr-xr-x 27 root root 4096 12月 17 16:00 plugins
drwxr-xr-x 25 root root 4096 12月 17 16:00 qml
drwxr-xr-x 5 root root 4096 12月 17 14:40 sysroot
drwxr-xr-x 2 root root 12288 12月 17 16:00 translations
当然也可以使用scp
命令:
root@zhengyang:/opt# scp -r /opt/qt6.5/sysroot/opt/prefix/* pi@192.168.0.101:/opt/qt6.5
1.5.6 配置环境变量
设置 LD_LIBRARY_PATH
环境变量,将 /opt/qt6.5/lib
目录添加到了动态链接库搜索路径中;
设置QT_QPA_PLATFORM_PLUGIN_PATH
环境变量,将将 /opt/qt6.5/plugins
目录添加到了插件搜索路径中;
pi@NanoPC-T6:/opt# sudo vim /etc/profile
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/qt6.5/lib
export QT_QPA_PLATFORM_PLUGIN_PATH=$QT_QPA_PLATFORM_PLUGIN_PATH:/opt/qt6.5/plugins
pi@NanoPC-T6:/opt$ source /etc/profile
pi@NanoPC-T6:/opt# echo "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/qt6.5/lib" >> ~/.bashrc
pi@NanoPC-T6:/opt# echo "export QT_QPA_PLATFORM_PLUGIN_PATH=$QT_QPA_PLATFORM_PLUGIN_PATH:/opt/qt6.5/plugins" >> ~/.bashrc
pi@NanoPC-T6:/opt# source ~/.bashrc
pi@NanoPC-T6:/opt# su root
root@NanoPC-T6:/opt# echo "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/qt6.5/lib" >> ~/.bashrc
root@NanoPC-T6:/opt# echo "export QT_QPA_PLATFORM_PLUGIN_PATH=$QT_QPA_PLATFORM_PLUGIN_PATH:/opt/qt6.5/plugins" >> ~/.bashrc
root@NanoPC-T6:/opt# source ~/.bashrc
这里有必要说一下/etc/profile
和~/.bashrc
区别,/etc/profile
和~/.bashrc
都是用于定义环境变量和执行初始化命令的文件,不同之处在于它们的作用范围和执行时机;
/etc/profile
是系统级别的配置文件,适用于所有用户。当用户登录时,系统会自动读取该文件中定义的环境变量和初始化命令,并将其应用于整个系统。因此,如果您希望在所有用户之间共享环境变量或执行初始化命令,可以将它们添加到/etc/profile
中;~/.bashrc
是用户级别的配置文件,只适用于当前用户。当用户登录后,系统会自动读取该文件并将其中定义的环境变量和初始化命令应用于该用户的bash shell
。因此,如果您只需要在当前用户的bash shell中定义环境变量或执行初始化命令,可以将它们添加到~/.bashrc
中;
这里为啥配置了/etc/profile
还配置了~/.bashrc
,主要是因为我在测试的时候发现,如果只配置/etc/profile
,在debian
桌面终端(非SSH
连接终端)运行Qt
程序的时候,LD_LIBRARY_PATH
环境变量并没有生效,而配置了用户级的~/.bashrc
会生效。
1.6 安装Qt Creator
1.6.1 下载安装包
下载Qt Creator 11.0
到ubuntu
中:
root@zhengyang:/opt# wget https://download.qt.io/official_releases/qtcreator/11.0/11.0.0/qt-creator-opensource-linux-x86_64-11.0.0.run
# 安装依赖库
root@zhengyang:/opt# sudo apt install --assume-yes xfce4 xorg-dev libopencc2 libopencc2-data unzip zip # 选择gdm3
root@zhengyang:/opt# sudo apt install --reinstall libxcb-xinerama0
1.6.2 修改权限并安装
需要在ubuntu
桌面环境,打开终端运行:
zhengyang@zhengyang:~/桌面$ cd /opt
zhengyang@zhengyang:/opt# sudo chmod 777 qt-creator-opensource-linux-x86_64-11.0.0.run
zhengyang@zhengyang:/opt# sudo ./qt-creator-opensource-linux-x86_64-11.0.0.run
之后就会弹窗,需要我们登录下,没有账号就去Qt
官网注册一个:
安装过程基本上一路 Next
下去,其中:
- 选择安装目录,配置为
/opt/qtcreator-11.0.0
; - 选择组件:全部勾选;
一直下一步,直到安装完成。安装完成后,打开Qt Creator
的开发界面:
1.6.3 查看安装路径
root@zhengyang:/opt# cd qtcreator-11.0.0/
root@zhengyang:/opt/qtcreator-11.0.0# ll
drwxr-xr-x 2 root root 4096 Nov 22 16:09 bin/
-rw-r--r-- 1 root root 3540 Dec 17 17:11 components.xml
-rw-r--r-- 1 root root 6685 Dec 17 17:11 InstallationLog.txt
-rw-r--r-- 1 root root 48 Dec 17 17:11 installer.dat
drwxr-xr-x 5 root root 4096 Dec 17 17:11 installerResources/
drwxr-xr-x 6 root root 4096 Nov 22 16:09 lib/
drwxr-xr-x 3 root root 4096 Nov 22 16:09 libexec/
-rw-r--r-- 1 root root 725 Dec 17 17:11 licenseInfo.txt
drwxr-xr-x 2 root root 4096 Dec 17 17:11 Licenses/
-rw-r--r-- 1 root root 472 Dec 17 17:11 network.xml
-rwxr-xr-x 1 root root 43893816 Dec 17 17:11 QtCreatorUninstaller*
-rw-r--r-- 1 root root 360709 Dec 17 17:11 QtCreatorUninstaller.dat
-rw-r--r-- 1 root root 6123 Dec 17 17:11 QtCreatorUninstaller.ini
drwxr-xr-x 6 root root 4096 Dec 17 17:11 share/
drwxr-xr-x 3 root root 4096 Nov 22 21:40 Tools/
root@zhengyang:/opt/qtcreator-11.0.0# ls bin
qbs qbs-config qbs-config-ui qbs-create-project qbs-setup-android qbs-setup-qt qbs-setup-toolchains qt.conf qtcreator qtcreator.sh
1.7 简单示例
在宿主机打开Qt Creator
,点击【工具】-【外部】- 【配置】,进入配置页面。
zhengyang@zhengyang:/$ sudo /opt/qtcreator-11.0.0/bin/qtcreator
1.7.1 编译器
点击左侧【构建套件】,选择【编译器】,这里已经检测到我们的交叉编译器(aarch64-linux-gnu-gcc
和aarch64-linux-gnu-g++
);如果没有,请添加一个GCC
编译器并定位编译器的位置。然后点击“应用”。
1.7.2 Qt
版本
点击左侧【Qt
版本】,手动添加:
qt-hot
用于为宿主机编译Qt
应用程序;
qt-nanopi
用于为开发板编译Qt
应用程序。
1.7.3 添加设备
我们还需要设置Qt Creator
中的设备。在【选项】菜单中,选择侧边栏中的【设备】;
(1)在【设备】选项卡下,选择【添加】。在设备配置向导中,选择Remote Linux Device
,然后点击开始向导;
指定一个可识别的名称、您用于SSH
的开发板IP
地址和用户名;
系统会提示您将公钥部署到目标设备上。这将加快部署过程,因为每次Qt Creator
尝试向目标发送文件时,您不需要输入密码。
点击下一步,然后点击完成。Qt Creator
将在完成后测试连接,并告诉您是否可以建立与目标设备的连接。
(2)上面配置完成后,就可以正常部署运行,每次ssh
连接都需要输入密码,接下来讲下使用密钥登录, 打开Qt Creator
,依次点击 【工具】- 【外部】 - 【配置】 -【设备】,就可以看到前面配置的ssh
登录设备:
步骤如下:
- 如果没有密钥对,先点击生成密钥:
-
保存的密钥对默认在用户目录
~/.ssh
下,然后点击部署密钥,选择前面生成的公钥,输入开发板debain
的用户密码即可完成部署。 或者自己复制公钥到开发板上,然后命令:cat qtc_id.pub >> ~/.ssh/authorized_keys # 如果没有authorized_keys,使用命令创建一个: touch authorized_keys
-
部署密钥之后,验证类型点击使用
Specific key
,之后就可以使用密钥直接远程连接;
1.7.4 安装调试器
在宿主机ubuntu
系统,先使用命令安装gdb
工具:
root@zhengyang:/opt/# sudo apt install -y gdb-multiarch
root@zhengyang:/opt# which gdb-multiarch
/usr/bin/gdb-multiarch
开发板一般默认已经安装gdb
工具,如果没有可以使用命令安装下:
pi@NanoPC-T6:/opt/qt-project$ sudo aptitude install -y gdbserver
pi@NanoPC-T6:/opt/qt-project$ which gdbserver
/usr/bin/gdbserver
在Qt Creator
配置页面,点击左侧【构建套件】,选择【Debuggers
】,单击新增:
添加路径/usr/bin/gdb-multiarch
,保存应用。
1.7.5 定义构建套件
(1) ubuntu_rk3588_debian11_qt6
编译套件
设置完所有必要的组件后,接下来我们添加一个编译套件( ubuntu_rk3588_debian11_qt6
),用来搭建一个交叉编译环境,为开发板编译Qt
程序;
然后配置使用我们之前安装的cmake
(注意使用3.16
版本以上),配置cmake generator
使用makefile
(也可以使用ninja
等)。
并且要修改下cmake
的配置,这里添加配置文件qt.toolchain.cmake
路径:
-DCMAKE_TOOLCHAIN_FILE:FILEPATH=/opt/qt6.5/qt-nanopi/lib/cmake/Qt6/qt.toolchain.cmake
(2) 桌面套件,用于为宿主机ubuntu
系统开发Qt
程序;
1.7.6 创建项目
在Qt Creator
首页点击【创建项目】 ;
选中【Application(Qt)
】- 【Qt Widgets Application
】;
(1) Location
:指定项目名称以及保存路径,然后点击【下一步】;
(2) 构建系统选择cmake
,然后点击【下一步】;
(3) Details
点击【下一步】;
(4) Tranlation
语言选择Chinese(China)
,然后点击【下一步】;
(5) 构建套件,全选;
(6) 汇总:点击【完成】;
1.8 本地运行测试
1.8.1 运行效果
点击左侧【项目】,选中【桌面】下【构建】按钮,单后点击左下角的【运行】按钮:
可以看到该Qt
程序可以在宿主机ubuntu
系统正常运行。
1.8.2 XCB
错误处理
如果运行时出现找不到插件XCB
错误:
19:06:11: Starting /opt/qt-project/build-demo1-unknown-Debug/demo1...
qt.qpa.plugin: Could not find the Qt platform plugin "xcb" in ""
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
Available platform plugins are: vkkhrdisplay, minimal, minimalegl, eglfs, linuxfb, vnc, offscreen.
开启Debug
模式,在项目中添加环境变量;左侧【项目】 – 【桌面】 – 【构建】 – 【构建设置】– 【Build Environment
】;
export QT_DEBUG_PLUGINS=1
可以看到,搜索的是Qt
源码编译的安装路径,该路径下没有libqxcb.so
;
root@zhengyang:/opt# ll /opt/qt6.5/qt-host/plugins/platforms
-rw-r--r-- 1 root root 35280 Dec 17 18:24 libqeglfs.so
-rw-r--r-- 1 root root 360192 Dec 17 18:25 libqlinuxfb.so
-rw-r--r-- 1 root root 79176 Dec 17 18:24 libqminimalegl.so
-rw-r--r-- 1 root root 68408 Dec 17 18:24 libqminimal.so
-rw-r--r-- 1 root root 159304 Dec 17 18:24 libqoffscreen.so
-rw-r--r-- 1 root root 314464 Dec 17 18:25 libqvkkhrdisplay.so
-rw-r--r-- 1 root root 192232 Dec 17 18:25 libqvnc.so
在编译宿主机Qt6
编译配置时指定,然后重新编译配置以及源码;
-DQT_FEATURE_xcb=ON -DFEATURE_xcb_xlib=ON -DQT_FEATURE_xlib=ON
1.9 远程机器运行测试
1.9.1 远程部署错误
点击左侧【项目】,选中【ubuntu_rk3588_debian11_qt6
】下【构建】按钮,接着点击左下角的【运行】图标按钮,错误信息如下:
20:27:24: 为项目demo1执行步骤 ...
20:27:24: 正在启动 "/opt/cmake/bin/cmake" --build /opt/qt-project/build-demo1-ubuntu_rk3588_debian11_qt6-Debug --target all install
[ 20%] Automatic MOC and UIC for target demo1
[ 20%] Built target demo1_autogen
[100%] Built target demo1
Install the project...
-- Install configuration: "Debug"
-- Up-to-date: /tmp/QtCreator-dLvOjN/staging-ccdd2a4bbb6f2446/usr/local/bin/demo1
20:27:24: 进程"/opt/cmake/bin/cmake"正常退出。
20:27:24: Trying to kill "/usr/local/bin/demo1" on remote device...
20:27:24: Remote application killed.
20:27:24: 部署步骤完成。
sending incremental file list
demo1
sent 1,146,921 bytes received 35 bytes 2,293,912.00 bytes/sec
total size is 1,146,568 speedup is 1.00
20:27:25: rsync failed with exit code 23.
rsync: [receiver] mkstemp "/usr/local/bin/.demo1.cOVHCN" failed: Permission denied (13)
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1205) [sender=3.1.3]
20:27:25: 部署步骤失败。
Error while building/deploying project demo1 (kit: ubuntu_rk3588_debian11_qt6)
When executing step "Deploy files via rsync"
20:27:25: Elapsed time: 00:01.
可以看到在使用rsync
进行文件同步的时候失败了,主要是因为配置的开发板debain
系统的pi
用户没有创建文件的权限。
因此配置开发板可以通过root
用户登录,利用vim
打开并修改/etc/ssh/sshd_config
文件:
pi@NanoPC-T6:/$ sudo vim /etc/ssh/sshd_config
PermitRootLogin yes
#重新启动SSH服务器
pi@NanoPC-T6:/$ sudo /etc/init.d/ssh restart
然后通过Qt Creator
打开【工具】—【外部】—【配置】—【设备】,删除设备重新创建,用户设置为root
。
注意:这里我们也可以点击【ubuntu_rk3588_debian11_qt6
】下【运行】按钮,通过右侧【运行配置】中的部署来调整文件同步策略。
1.9.2 测试环境变量
首先确保开发板配置的环境变量LD_LIBRARY_PATH
、QT_QPA_PLATFORM_PLUGIN_PATH
没有问题;在桌面终端和SSH
终端均运行如下命令测试:
pi@NanoPC-T6:/$ echo $LD_LIBRARY_PATH
:/opt/qt6.5/lib:/opt/qt6.5/lib
pi@NanoPC-T6:/$ echo $QT_QPA_PLATFORM_PLUGIN_PATH
:/opt/qt6.5/plugins:/opt/qt6.5/plugins:/opt/qt6.5/plugins
1.9.3 QPA
插件
这块内容涉及到linux
图像显示的内容,推荐先去阅读这篇文章:《Linux
图形显示》。
在开发板上运行Qt
程序,通过QPA(Qt Platform Abstraction)
平台抽象显示,不同平台显示可以使用不同QPA
插件, 一般Qt
将根据平台选择一个默认的QPA
插件, 也可以设置QT_QPA_PLATFORM
环境变量或者-platform
命令行参数选择不同的平台插件。
在嵌入式Linux
系统上,可以使用多个平台插件:EGLFS
,LinuxFB
,DirectFB
或Wayland
、XCB
。但是,这些插件的可用性取决于 Qt
的配置方式。
我们在交叉编译Qt
时已经配置了:
Qt Gui:
Accessibility .......................... yes
FreeType ............................... yes
Using system FreeType ................ yes
HarfBuzz ............................... yes
Using system HarfBuzz ................ yes
Fontconfig ............................. yes
Image formats:
GIF .................................. yes
ICO .................................. yes
JPEG ................................. yes
Using system libjpeg ............... yes
PNG .................................. yes
Using system libpng ................ yes
Text formats:
HtmlParser ........................... yes
CssParser ............................ yes
OdfWriter ............................ yes
MarkdownReader ....................... yes
Using system libmd4c ............... no
MarkdownWriter ....................... yes
EGL .................................... yes # 需要配置为yes
OpenVG ................................. no
OpenGL:
opengl_desktop ....................... no
OpenGL ES 2.0 ........................ yes # 需要配置为yes
opengles3 ............................ yes # 需要配置为yes
OpenGL ES 3.1 ........................ yes # 需要配置为yes
OpenGL ES 3.2 ........................ yes # 需要配置为yes
Vulkan ................................. no
Session Management ..................... yes
Features used by QPA backends:
evdev .................................. yes # 需要配置为yes
libinput ............................... yes # 需要配置为yes
HiRes wheel support in libinput ........ no
INTEGRITY HID .......................... no
mtdev .................................. yes # 需要配置为yes
tslib .................................. yes # 需要配置为yes
xkbcommon .............................. yes # 需要配置为yes
X11 specific: # 下面的要必须都是yes
xlib ................................. yes
XCB Xlib ............................. yes
EGL on X11 ........................... yes
xkbcommon-x11 ........................ yes
xcb-sm ............................... yes
QPA backends:
DirectFB ............................... no
EGLFS .................................. yes # 需要配置为yes
EGLFS details:
EGLFS OpenWFD ........................ no
EGLFS i.Mx6 .......................... no
EGLFS i.Mx6 Wayland .................. no
EGLFS RCAR ........................... no
EGLFS EGLDevice ...................... yes # 需要配置为yes
EGLFS GBM ............................ yes # 需要配置为yes
EGLFS VSP2 ........................... no
EGLFS Mali ........................... yes # 需要配置为yes
EGLFS Raspberry Pi ................... no
EGLFS X11 ............................ yes # 需要配置为yes
LinuxFB ................................ yes # 需要配置为yes
VNC .................................... yes
VK_KHR_display ......................... no
QNX:
lgmon ................................ no
IMF .................................. no
XCB:
Using system-provided xcb-xinput ..... no
GL integrations: # 下面的要必须都是yes
GLX Plugin ......................... yes
XCB GLX .......................... yes
EGL-X11 Plugin ..................... yes
Windows:
Direct 2D ............................ no
Direct 2D 1.1 ........................ no
DirectWrite .......................... no
DirectWrite 3 ........................ no
QPA
可以通过使用以下环境变量进行配置:
环境变量 | 描述 |
---|---|
QT_QPA_PLATFORM | 指定平台插件,比如eglfs、xcb、linuxfb(如果指定fb设备,可以设置为linuxfb:fb=/dev/fb0) |
QT_QPA_FONTDIR | 字体库路径 |
QT_QPA_PLATFORM_PLUGIN_PATH | 设置插件路径,比如/opt/qt6.5/plugins |
QWS_MOUSE_PROTO | 触摸屏输入设备,比如/dev/input/event0 |
QT_QPA_GENERIC_PLUGINS | 插件,比如 触摸库tslib 鼠标插件,evdevmouse:/dev/input/event 键盘插件,evdevkeyboard:/dev/input/event |
QT_QPA_EVDEV_KEYBOARD_PARAMETERS | 键盘设备 |
QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS | 触摸配置 |
1.9.4 LinuxFB
该插件通过Linux
的fbdev
子系统直接写入帧缓冲区。仅支持软件渲染的内容。请注意,在某些设置下,显示性能可能会受到限制。
由于fbdev
在Linux
内核中已被弃用,因此从Qt 5.9
开始,还提供了DRM
支持。要使用它,请将QT_QPA_FB_DRM
环境变量设置为非零值。设置后,只要系统支持DRM
,/dev/fb0
就不会访问旧式帧缓存设备。取而代之的是,通过DRM API
来设置呈现,类似于eglfs_kms
EGLFS
中的后端。输出经过双缓冲和页面翻转,也为软件渲染的内容提供了适当的垂直同步。
该插件显示会全屏输出,设置QT_QPA_FB_FORCE_FULLSCREEN
环境变量设置为0,将非全屏显示。
(1) LinuxFB
可以通过使用以下环境变量进行配置:
环境变量 | 描述 |
---|---|
QT_QPA_FB_DRM | 使用DRM,设置为1 |
QT_QPA_FB_FORCE_FULLSCREEN | 是否全屏显示,设置为0,将非全屏显示 |
QT_QPA_FB_HIDECURSOR | 显示或者隐藏鼠标 |
QT_QPA_FB_DISABLE_INPUT | LinuxFB禁用输入,即不使用libinput |
更多配置参考:https://doc.qt.io/qt-5/embedded-linux.html#linuxfb
。
(2) 首先进行环境变量配置:
pi@NanoPC-T6:/opt# sudo vim /etc/profile
export QT_QPA_FB_DRM=1
export QT_QPA_FB_FORCE_FULLSCREEN=0
pi@NanoPC-T6:/opt$ source /etc/profile
接着Qt Creator
具体配置如下:
- 点击左侧【项目】 — 【
ubuntu_rk3588_debian11_qt6
】 — 【构建】; - 右侧【运行配置】 — 【运行】 — 【
Command line arguments
】输入:-platform linuxfb
;指定Qt
以linuxfb
的方式显示,输出设备默认为/dev/fb0
;
点击左侧【运行】图标,运行程序,测试发现这个在开发板连接的显示屏上全屏显示,但是我设置的是非全屏显示啊,说明我们在/etc/profile
中配置的环境变量并没有生效。
从控制台的启动日志看到,实际上就是在开发板上执行了如下命令:
/usr/local/bin/demo1 -platform linuxfb
因此,我尝试在开发板终端执行了这个命令,发现Qt
程序可以正常运行,并且非全屏显示。
1.9.5 EGLFS
EGLFS
是一个为了Qt5
应用运行的平台插件,EGLFS
是Qt
自己实现的一个GUI
显示插件,可以在EGL
和OpenGL ES
之上运行Qt
应用程序,而不需要真实的视窗系统(比如X11
、Wayland
)。 EGLFS
还支持软件渲染窗口,如QWidget
的内容使用CPU
渲染成图像,然后上传到纹理中,并由插件进行合成;
对于包含GPU
的现代嵌入式Linux
设备,推荐使用EGLFS
插件。 EGLFS
强制第一个顶级窗口(QWidget
或者QQucikView
)为全屏。这个窗口也是根Widget
窗口,其它的顶级窗口(例如对话框)都是这个根窗口的子窗口。
(1) Rk3588
系列使用Mali-G610
,支持OpenGL ES1.1, 2.0 and 3.2, OpenGL 2.2, Vulkan 1.2 etc
以及OpenCL 1.1, 1.2, 2.0
。
Mali GPU
驱动一般分为两部分:
- 一小部分在
linux
内核中; - 另外一大部分在
Userspace
,在Userspace
的部分向下操作内核中的驱动,向上对应用层提供标准的API
接口,例如:OpenGL ES 1.1、2.0、3.0、3.1、3.2
;OpenCL 1.1、1.2、2.0
;Vulkan 1.0
;RenderScript
(受支持的API
列表因二进制和GPU
类型而异)。
在Linux
系统上使用OpenGL ES
或者OpenCL
接口,需要添加libmali
库以及头文件, libmali
有不同的版本(X11
,fbdev
,Wayland
等),提供了opengles
,egl
,opencl
接口。
除了GPU
,RK
系列板卡上还有一个独立的2D
硬件加速器–RGA
(Raster Graphic Acceleration Unit
),可以不占用CPU
资源下, 加速点/线绘制,执行图像缩放、旋转、bitBlt
、alpha
混合等常见的2D
图形操作,用户空间使用通过librga
库。
(2) EGLFS
可以通过使用以下环境变量进行配置:
环境变量 | 描述 |
---|---|
QT_QPA_EGLFS_FB | 覆盖帧缓冲设备。默认值为/dev/fb0 。在大多数嵌入式平台上,此变量不太重要,因为帧缓冲区仅用于查询显示尺寸等设置。但是,在某些设备上,此变量提供了指定在多个显示设置中使用哪个显示器的功能,类似于LinuxFB 中的fb 参数。 |
QT_QPA_EGLFS_WIDTH和 QT_QPA_EGLFS_HEIGHT |
包含屏幕的宽度和高度(以像素为单位)。虽然EGLFS尝试从帧缓冲设备/dev/fb0 确定尺寸,但这并不总是有效。可能需要手动指定尺寸。 |
QT_QPA_EGLFS_PHYSICAL_WIDTH和 QT_QPA_EGLFS_PHYSICAL_HEIGHT |
指定物理屏幕的宽度和高度(以毫米为单位)。有些平台没有/dev/fb0或者查询失败的情况,这些值使用默认的DPI=100计算宽和高。 |
QT_QPA_EGLFS_DEPTH | 覆盖屏幕的颜色深度。在帧缓冲设备/dev/fb0不可用或查询不成功的平台上,使用默认值32。注意:此变量仅影响QScreen的色深值。它与EGL配置和OpenGL 渲染所使用的颜色深度无关。 |
QT_QPA_EGLFS_SWAPINTERVAL | 默认的交换值为1。这将会同步垂直刷新。例如,设置间隔为0,将会尽最快的方式运行不带任何同步。 |
QT_QPA_EGLFS_DEBUG | 设置后,一些调试信息会打印在调试输出上。 |
QT_QPA_EGLFS_INTEGRATION | 除了编译进的hooks,能够提供设备或者厂商修改的可动态加载的插件。该环境变量指定一个特定的插件。 设置为eglfs_kms将使用KMS/DRM后端。 |
QT_QPA_EGLFS_KMS_ATOMIC | 默认情况下,KMS后端将使用旧版API,可以启用DRM atomic API,通过将QT_QPA_EGLFS_KMS_ATOMIC环境变量设置为1 |
QT_QPA_EGLFS_KMS_CONFIG | KMS/DRM后端还通过JSON文件支持自定义配置 |
QT_QPA_EGLFS_ALWAYS_SET_MODE | 指定将current选择一种分辨率与当前模式匹配的模式,QT_QPA_EGLFS_ALWAYS_SET_MODE |
QT_QPA_EGLFS_TSLIB | 启用tslib支持 |
QT_QPA_EGLFS_HIDECURSOR | 显示或者隐藏鼠标 |
QT_QPA_EGLFS_ROTATION | 界面旋转角度 0,90,180,270,(使用触摸屏幕,触摸也要旋转) |
QT_QPA_EGLFS_DISABLE_INPUT | EGLFS禁用输入,即不使用libinput |
更多配置参考:https://doc.qt.io/qt-5/embedded-linux.html#display-outpu
。
(3) 首先进行环境变量配置:
pi@NanoPC-T6:/opt# sudo vim /etc/profile
export QT_QPA_EGLFS_INTEGRATION=eglfs_kms
pi@NanoPC-T6:/opt$ source /etc/profile
接着Qt Creator
具体配置如下:
- 点击左侧【项目】 — 【
ubuntu_rk3588_debian11_qt6
】 — 【构建】; - 右侧【运行配置】 — 【运行】 — 【
Command line arguments
】输入:-platform eglfs
;
点击左侧【运行】图标,运行程序,运行完之后发现Qt
应用程序在开发板连接的显示屏全屏显示了。
我们可以尝试在开发板终端运行如下命令,发现Qt
应用程序也是全屏显示。
/usr/local/bin/demo1 -platform eglfs
1.9.6 XCB
Qt
程序也可以通过桌面窗口系统运行显示。 XCB
是桌面Linux
平台上使用的X11
插件,使用窗口系统显示Qt
程序。
(1) XCB
是Xlib
的替代方案,提供了更简单、更灵活的API
,可以帮助开发人员更轻松地创建X
应用程序;
Xlib
或者X
库是X
协议的的一个简单的封装,Gtk+
、Qt
等使用该库来创建软件应用程序的图形前端;- 更多内容请参考《
X Window System
》。
注意:在某些设备上,X11
下没有EGL
和OpenGL
支持,因为EGL
实现与Xlib
不兼容。在这种情况下,XCB
插件是在没有EGL
支持的情况下构建的,这意味着Qt Quick 2
或其他基于OpenGL
的应用程序无法与此平台插件一起使用。但是,它仍然可以用于运行软件渲染的应用程序(例如,基于QWidget
)。
通常,不建议在嵌入式设备上使用XCB
。像 EGLFS
这样的插件可能会提供更好的性能和硬件加速。
(2) Qt Creator
具体配置如下:
- 点击左侧【项目】 — 【
ubuntu_rk3588_debian11_qt6
】 — 【构建】; - 右侧【运行配置】 — 【运行】 — 【
Command line arguments
】输入:-platform xcb
; - 选中右侧【运行配置】 — 【运行】 — 【
X11 Forwarding
】中的Forward to local display
,从而实现远程开发板应用程序GUI
在宿主机上展示,具体原理参考《快速理解X server, DISPLAY
与X11 Forwarding
》;如果未配置,控制台会出现如下错误;
点击左侧【运行】图标,运行程序;
尝试在开发板debain
桌面终端运行Qt
程序,开发板连接的显示屏可以正常显示;
1.9.7 运行脚本
我们编写run_xcb.sh
脚本指定Qt
程序以xcb
方式方式;
pi@NanoPC-T6:/opt$ sudo vim run_xcb.sh
#! /bin/bash
# 指定应用程序图形界面显示在第0号X server.该X server管理的第0号screen
export DISPLAY=:0.0
# 导出qtdemo的安装目录
export APP_DIR=/usr/local/bin
# 指定qt库路径
export LD_LIBRARY_PATH=/opt/qt6.5/lib
# 指定qt插件路径
export QT_QPA_PLATFORM_PLUGIN_PATH=/opt/6.5/plugins
# 指定平台,通过QT_QPA_PLATFORM 或者-platform命令行选项指定其他设置
export QT_QPA_PLATFORM=xcb
echo "start demo1 APP..."
#运行FireApp
$APP_DIR/demo1
pi@NanoPC-T6:/opt$ sudo chmod +x run_xcb.sh
pi@NanoPC-T6:/opt$ ./run_xcb.sh
二、开发板安装Qt5
和Qt Creator
2.1 安装Qt5
和Qt Creator
本节我们直接使用aptitude
将Qt5
安装到NanoPC-T6
开发板的debain
系统中。
2.1 命令安装
首先将debian
的软件更新:
pi@NanoPC-T6:/$ sudo aptitude update
接着查看一下有没有安装Qt
:
pi@NanoPC-T6:/$ sudo apt list --installed | grep qtcreator
如果未安装,那么安装Qt
,这里安装的版本为Qt5.x
,默认安装的是该大版本下的最新版本:
pi@NanoPC-T6:/$ sudo aptitude install qtbase5-dev qtdeclarative5-dev qtchooser qt5-qmake qtbase5-dev-tools fcitx-frontend-qt5
pi@NanoPC-T6:/$ sudo aptitude install qtcreator
pi@NanoPC-T6:/$ sudo aptitude install "~n^qt5"
pi@NanoPC-T6:/$ sudo apt install libqt5multimedia* qtmultimedia5-*
其中:
qtcreator
是一套可视化的集成开发环境,使用Qt Creator
可以高效的进行Qt
开发;qtbase5-dev
: 这个包包含了Qt5
的基本开发文件,包括头文件和静态库。它是进行Qt5
应用程序开发的基础;qtchooser
: 这个包是一个工具,用于选择不同版本的Qt
工具链,例如qmake
和moc
;qt5-qmake
: 这个包提供了Qt5
的构建工具qmake
。qmake
是一个跨平台的项目管理工具,可以帮助您构建和管理Qt5
项目;qtbase5-dev-tools
: 这个包包含了一些辅助开发工具,例如Qt5
的文档生成工具、Qt5 Assistant
帮助查看器等;fcitx-frontend-qt5
:是一个用于在Qt5
应用程序中支持Fcitx
输入法框架的前端库。Fcitx
是一个流行的开源输入法框架,而fcitx-frontend-qt5
则允许Qt5
应用程序与Fcitx
输入法进行集成。
2.1.2 安装目录
Qt
默认是安装到/usr/lib/aarch64-linux-gnu/qt5
目录,这里安装的版本为Qt 5.15.2
;
root@NanoPC-T6:~# ls -l /usr/lib/aarch64-linux-gnu | grep qt
lrwxrwxrwx 1 root root 24 9月 7 2020 libgsettings-qt.so.1 -> libgsettings-qt.so.1.0.0
lrwxrwxrwx 1 root root 24 9月 7 2020 libgsettings-qt.so.1.0 -> libgsettings-qt.so.1.0.0
-rw-r--r-- 1 root root 38848 9月 7 2020 libgsettings-qt.so.1.0.0
lrwxrwxrwx 1 root root 24 9月 4 2022 libpoppler-qt5.so.1 -> libpoppler-qt5.so.1.25.0
-rw-r--r-- 1 root root 513904 9月 4 2022 libpoppler-qt5.so.1.25.0
lrwxrwxrwx 1 root root 19 1月 12 2020 libqt5keychain.so -> libqt5keychain.so.1
-rw-r--r-- 1 root root 145344 1月 12 2020 libqt5keychain.so.0.10.0
lrwxrwxrwx 1 root root 24 1月 12 2020 libqt5keychain.so.1 -> libqt5keychain.so.0.10.0
lrwxrwxrwx 1 root root 21 4月 12 2020 libqt5qevercloud.so -> libqt5qevercloud.so.3
lrwxrwxrwx 1 root root 25 4月 12 2020 libqt5qevercloud.so.3 -> libqt5qevercloud.so.3.0.3
-rw-r--r-- 1 root root 993240 4月 12 2020 libqt5qevercloud.so.3.0.3
lrwxrwxrwx 1 root root 26 1月 8 2021 libqt5-ukui-style.so.1 -> libqt5-ukui-style.so.1.0.0
lrwxrwxrwx 1 root root 26 1月 8 2021 libqt5-ukui-style.so.1.0 -> libqt5-ukui-style.so.1.0.0
-rw-r--r-- 1 root root 145352 1月 8 2021 libqt5-ukui-style.so.1.0.0
drwxr-xr-x 1 root root 4096 12月 20 19:20 qt5
drwxr-xr-x 2 root root 4096 12月 20 19:18 qtchooser
drwxr-xr-x 3 root root 4096 12月 20 19:19 qtcreator
drwxr-xr-x 3 root root 4096 6月 29 17:50 qt-default
root@NanoPC-T6:~# ls -l /usr/lib/aarch64-linux-gnu/qt5
drwxr-xr-x 2 root root 4096 12月 20 19:20 bin
drwxr-xr-x 1 root root 4096 12月 20 19:20 examples
drwxr-xr-x 2 root root 4096 12月 20 19:20 libexec
drwxr-xr-x 77 root root 4096 12月 20 19:18 mkspecs
drwxr-xr-x 1 root root 4096 12月 20 19:20 plugins # 插 件比较重要
drwxr-xr-x 1 root root 4096 12月 20 19:19 qml
-rw-r--r-- 1 root root 562 7月 2 2021 qt.conf
root@NanoPC-T6:~# ls -l /usr/lib/aarch64-linux-gnu/qt5/bin/
lrwxrwxrwx 1 root root 26 2月 26 2021 assistant -> ../../../qt5/bin/assistant
lrwxrwxrwx 1 root root 33 7月 2 2021 fixqt4headers.pl -> ../../../qt5/bin/fixqt4headers.pl
lrwxrwxrwx 1 root root 20 7月 2 2021 moc -> ../../../qt5/bin/moc
lrwxrwxrwx 1 root root 29 7月 2 2021 qdbuscpp2xml -> ../../../qt5/bin/qdbuscpp2xml
lrwxrwxrwx 1 root root 29 7月 2 2021 qdbusxml2cpp -> ../../../qt5/bin/qdbusxml2cpp
lrwxrwxrwx 1 root root 22 7月 2 2021 qlalr -> ../../../qt5/bin/qlalr
lrwxrwxrwx 1 root root 39 7月 2 2021 qmake -> ../../../../bin/aarch64-linux-gnu-qmake
lrwxrwxrwx 1 root root 20 7月 2 2021 rcc -> ../../../qt5/bin/rcc
lrwxrwxrwx 1 root root 26 7月 2 2021 syncqt.pl -> ../../../qt5/bin/syncqt.pl
lrwxrwxrwx 1 root root 20 7月 2 2021 uic -> ../../../qt5/bin/uic
root@NanoPC-T6:~# qmake -v
QMake version 3.1
Using Qt version 5.15.2 in /usr/lib/aarch64-linux-gnu
同时在路径/usr/lib/aarch64-linux-gnu/
下有qt5
的安装库;
root@NanoPC-T6:~# ls -l /usr/lib/aarch64-linux-gnu | grep Qt5
-rw-r--r-- 1 root root 963 7月 2 2021 libQt5Concurrent.prl
lrwxrwxrwx 1 root root 26 7月 2 2021 libQt5Concurrent.so -> libQt5Concurrent.so.5.15.2
lrwxrwxrwx 1 root root 26 7月 2 2021 libQt5Concurrent.so.5 -> libQt5Concurrent.so.5.15.2
lrwxrwxrwx 1 root root 26 7月 2 2021 libQt5Concurrent.so.5.15 -> libQt5Concurrent.so.5.15.2
-rw-r--r-- 1 root root 27080 7月 2 2021 libQt5Concurrent.so.5.15.2
-rw-r--r-- 1 root root 967 7月 2 2021 libQt5Core.prl
lrwxrwxrwx 1 root root 20 7月 2 2021 libQt5Core.so -> libQt5Core.so.5.15.2
lrwxrwxrwx 1 root root 20 7月 2 2021 libQt5Core.so.5 -> libQt5Core.so.5.15.2
lrwxrwxrwx 1 root root 20 7月 2 2021 libQt5Core.so.5.15 -> libQt5Core.so.5.15.2
-rw-r--r-- 1 root root 5588424 7月 2 2021 libQt5Core.so.5.15.2
-rw-r--r-- 1 root root 944 7月 2 2021 libQt5DBus.prl
lrwxrwxrwx 1 root root 20 7月 2 2021 libQt5DBus.so -> libQt5DBus.so.5.15.2
lrwxrwxrwx 1 root root 20 7月 2 2021 libQt5DBus.so.5 -> libQt5DBus.so.5.15.2
lrwxrwxrwx 1 root root 20 7月 2 2021 libQt5DBus.so.5.15 -> libQt5DBus.so.5.15.2
-rw-r--r-- 1 root root 568448 7月 2 2021 libQt5DBus.so.5.15.2
.....
2.2 Qt
配置
安装完成后,我们进入debian
桌面系统,可以看到Qt Creater
;如果是以root
用户登录的话,可以直接双击图标,启动程序;
否则开启一个终端,使用如下命令启动Qt Creater
;
pi@NanoPC-T6:/$ sudo qtcreator
点击【工具】-【外部】- 【Configure
】,进入配置页面。
2.2.1 编译器
点击左侧【Kits
】,选择【编译器】,这里已经检测到系统安装的C、C++
编译器;当然如果有需求的话,也可以自己添加编译器,指定名称和编译器路径即可:
这里我们只关注C
、C++
中的第一个,即/usr/bin/gcc
、/usr/bin/g++
;
root@NanoPC-T6:~# gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/aarch64-linux-gnu/10/lto-wrapper
Target: aarch64-linux-gnu
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 10.2.1 20210110 (Debian 10.2.1-6)
root@NanoPC-T6:~# g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/aarch64-linux-gnu/10/lto-wrapper
Target: aarch64-linux-gnu
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 10.2.1 20210110 (Debian 10.2.1-6)
可以看到系统中安装了gcc 10.2.1
版本和gcc 10.2.1
版本。
2.2.2 Qt Vsersions
点击左侧【Kits
】,选择【Qt Vsersions
】,可以手动设置qmake
路径,这里默认值为/usr/lib/qt5/bin/qmake
;
这里我们查看一下/usr/lib/qt5
目录:
root@NanoPC-T6:~# ls -l /usr/lib/qt5/
drwxr-xr-x 2 root root 4096 12月 20 19:20 bin
root@NanoPC-T6:~# ls -l /usr/lib/qt5/bin/
-rwxr-xr-x 1 root root 881184 2月 26 2021 assistant
-rwxr-xr-x 1 root root 6340 7月 2 2021 fixqt4headers.pl
-rwxr-xr-x 1 root root 953472 7月 2 2021 moc
-rwxr-xr-x 1 root root 270096 7月 2 2021 qdbuscpp2xml
-rwxr-xr-x 1 root root 64608 7月 2 2021 qdbusxml2cpp
-rwxr-xr-x 1 root root 125880 7月 2 2021 qlalr
-rwxr-xr-x 1 root root 2764360 7月 2 2021 qmake
-rwxr-xr-x 1 root root 35440 7月 2 2021 qvkgen
-rwxr-xr-x 1 root root 855136 7月 2 2021 rcc
-rwxr-xr-x 1 root root 48360 7月 2 2021 syncqt.pl
-rwxr-xr-x 1 root root 605208 7月 2 2021 tracegen
-rwxr-xr-x 1 root root 540592 7月 2 2021 uic
2.2.3 定义构建套件
点击左侧【Kits
】,选择【Kits
】,添加套件:
2.3 示例教程
2.3.1 运行
我们直接选择一个示例教程,如图所示:
选中项目Qt Quick Demo - Clocks
。
打开项目后,选中左侧【项目】- 【桌面】-【Build
& Run
】- 【Run
】,然后点击左下角【Run
】图标按钮;
测试如果返现在编译输出窗口出现如下错误;
Project ERROR: Unknown module(s) in QT: qml quick
需要安装如下依赖包:
pi@NanoPC-T6:/$ sudo aptitude install qtdeclarative5-dev
安装完成后,重新运行程序,运行结果如下:
2.3.2 目录结构
项目代码位于/usr/lib/aarch64-linux-gnu/qt5/examples/demos/clocks/
:
root@NanoPC-T6:~# ls /usr/lib/aarch64-linux-gnu/qt5/examples/demos/clocks/ -l
-rwxr-xr-x 1 root root 674816 12月 20 20:13 clocks
-rw-r--r-- 1 root root 285 11月 6 2020 clocks.pro
-rw-r--r-- 1 root root 21833 12月 20 20:02 clocks.pro.user
-rw-r--r-- 1 root root 3932 11月 6 2020 clocks.qml
-rw-r--r-- 1 root root 167 11月 6 2020 clocks.qmlproject
-rw-r--r-- 1 root root 503 11月 6 2020 clocks.qrc
drwxr-xr-x 2 root root 4096 12月 20 19:20 content
-rw-r--r-- 1 root root 3076 11月 6 2020 main.cpp
-rw-r--r-- 1 root root 918736 12月 20 20:13 main.o
-rw-r--r-- 1 root root 18187 12月 20 20:13 Makefile
-rw-r--r-- 1 root root 536820 12月 20 20:13 qrc_clocks.cpp
-rw-r--r-- 1 root root 112056 12月 20 20:13 qrc_clocks.o
一些工程文件的解释:
.h .cpp
文件为头文件和源文件,我们的代码通常都是写在这两种文件中的;.ui
文件就是我们前面提到界面文件,其实质是xml
格式的文本文件;.pro
文件就是工程管理文件,以qmake
特有的语法记录了工程的文件和配置;.pri
文件通常也用于工程管理,将代码整理成一个模块,通过引入pri
文件来引入代码模块;.pro.user
为用户描述文件,记录了我们工程的开发环境构建环境等等,也是xml
格式的文本文件;.qrc
除上面的文件,工程中一般还会有qrc
资源文件,用于记录图片,音视频等文件。
三、opencv
安装及配置
这里我们简单介绍一下opencv
,opencv
是一个基于Apache2.0
许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux
、Windows
、Android
和Mac OS
操作系统上。
3.1 安装opencv
3.1.1 安装依赖
首先安装依赖项:
pi@NanoPC-T6:/$ sudo aptitude install cmake
pi@NanoPC-T6:/$ sudo aptitude install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libxvidcore-dev libx264-dev libatlas-base-dev gfortran libgtk2.0-dev libjpeg-dev libpng-dev ffmpeg
其中:
libavcodec-dev
: 提供了音频和视频编解码器的开发库,用于处理音视频数据的编解码;libavformat-dev
: 包含了音视频封装格式处理的开发库,用于读取和写入不同的音视频封装格式;libswscale-dev
: 提供了用于图像缩放和颜色空间转换的开发库;libv4l-dev
: 提供了v4l2
的开发库,用于访问视频设备;libxvidcore-dev
: 提供了Xvid
视频编解码器的开发库;libx264-dev
: 提供了x264
视频编码器的开发库;libatlas-base-dev
:ATLAS
是一个开源的数学库,提供了BLAS
和LAPACK
等线性代数函数的优化实现,这个包提供了ATLAS
的开发文件;gfortran
:GNU Fortran
编译器,用于编译Fortran
语言的程序;libgtk2.0-dev
:GTK+
图形用户界面工具包的开发文件,用于开发基于GTK+
的图形界面应用程序;libjpeg-dev
: 提供了JPEG
图像格式的处理库的开发文件;libpng-dev
: 提供了PNG
图像格式的处理库的开发文件;
3.1.2 下载opencv
在windows
系统下载opencv-3.4.14.zip
,并拷贝到开发板debian
系统;
解压:
pi@NanoPC-T6:/$ sudo cd /opt
pi@NanoPC-T6:opt/$ sudo unzip opencv-3.4.14.zip
3.2 编译安装
由于opencv
的后端是一般编译是支撑多种插件,详细信息请参考OpenCV: Video I/O with OpenCV Overview
,这里引用里面的图:
一些后端(backend
),例如Direct Show
(DSHOW
)、Video For Windows
(VFW
)、Microsoft Media Foundation
(MSMF
)、Video 4 Linux
(V4L
)等,是操作系统提供的视频输入/输出库的接口。
而另一些后端,例如OpenNI2 for Kinect
、Intel Perceptual Computing SDK
、GStreamer
、XIMEA Camera API
等,则是对专有驱动程序或外部库的接口。请在此处查看支持的后端列表:cv::VideoCaptureAPIs
。
3.2.1 编译配置
进opencv-3.4.14
文件夹,在该目录下新建一个build
文件夹,执行如下命令:
pi@NanoPC-T6:opt/$ cd opencv-3.4.14
pi@NanoPC-T6:/opt/opencv-3.4.14$ sudo mkdir build
pi@NanoPC-T6:/opt/opencv-3.4.14$ cd build
pi@NanoPC-T6:/opt/opencv-3.4.14/build$ sudo cmake .. -DWITH_CAMV4L2=ON
要启用/禁用某个后端,可以通过配置OpenCV
实现,比如:
-DWITH_GSTREAMER=ON
;-DWITH_MSMF=ON
;-DWITH_VFW=ON;
更多配置可以参考:《OpenCV
配置选项参考文档》。
需要注意的VideoCapture
在linux
下缺省用的是GStreamer
做后端,,cmake ..
之后会输出:
......
-- Video I/O:
-- DC1394: YES (ver 2.2.6)
-- FFMPEG: YES
-- avcodec: YES (ver 58.91.100)
-- avformat: YES (ver 58.45.100)
-- avutil: YES (ver 56.51.100)
-- swscale: YES (ver 5.7.100)
-- avresample: YES (ver 4.0.0)
-- GStreamer: YES
-- base: YES (ver 1.18.5)
-- video: YES (ver 1.18.5)
-- app: YES (ver 1.18.5)
-- riff: YES (ver 1.18.5)
-- pbutils: YES (ver 1.18.5)
-- libv4l/libv4l2: NO
-- v4l/v4l2: linux/videodev2.h
......
-- OpenCL: YES (no extra features) # 默认启用
-- Include path: /opt/opencv-3.4.14/3rdparty/include/opencl/1.2
-- Link libraries: Dynamic load
......
如果我们没有指定-DWIDTH_XXXX=ON
,那么CMakeLists.txt
中会自动进行判定,以WITH_OPENCL
为例:
OCV_OPTION(WITH_OPENCL "Include OpenCL Runtime support" (NOT ANDROID AND NOT CV_DISABLE_OPTIMIZATION)
这个代码片段的意思是:设置一个名为WITH_OPENCL
的CMake option
,其默认值取决于是否为Android
平台和是否禁用了优化。如果既不是Android
平台也没有禁用优化,则该option
的默认值为ON
,表示包含OpenCL
运行时支持。
3.2.2 编译安装
pi@NanoPC-T6:/opt/opencv-3.4.14/build$ sudo make -j7 # 执行make开始编译,这个时间比较长,耐心等待。
pi@NanoPC-T6:/opt/opencv-3.4.14/build$ sudo make install # 安装
默认安装到/usr/local
路径下;比如:
/usr/local/include/opencv
、/usr/local/include/opencv2
:头文件安装目录;/usr/local/lib
:库文件安装目录;
pi@NanoPC-T6:/opt/opencv-3.4.14/build$ ls /usr/local/lib/
libopencv_calib3d.so libopencv_flann.so.3.4.14 libopencv_objdetect.so.3.4 libopencv_videoio.so
libopencv_calib3d.so.3.4 libopencv_highgui.so libopencv_objdetect.so.3.4.14 libopencv_videoio.so.3.4
libopencv_calib3d.so.3.4.14 libopencv_highgui.so.3.4 libopencv_photo.so libopencv_videoio.so.3.4.14
libopencv_core.so libopencv_highgui.so.3.4.14 libopencv_photo.so.3.4 libopencv_video.so
libopencv_core.so.3.4 libopencv_imgcodecs.so libopencv_photo.so.3.4.14 libopencv_video.so.3.4
libopencv_core.so.3.4.14 libopencv_imgcodecs.so.3.4 libopencv_shape.so libopencv_video.so.3.4.14
libopencv_dnn.so libopencv_imgcodecs.so.3.4.14 libopencv_shape.so.3.4 libopencv_videostab.so
libopencv_dnn.so.3.4 libopencv_imgproc.so libopencv_shape.so.3.4.14 libopencv_videostab.so.3.4
libopencv_dnn.so.3.4.14 libopencv_imgproc.so.3.4 libopencv_stitching.so libopencv_videostab.so.3.4.14
libopencv_features2d.so libopencv_imgproc.so.3.4.14 libopencv_stitching.so.3.4 pkgconfig
libopencv_features2d.so.3.4 libopencv_ml.so libopencv_stitching.so.3.4.14 python3.9
libopencv_features2d.so.3.4.14 libopencv_ml.so.3.4 libopencv_superres.so
libopencv_flann.so libopencv_ml.so.3.4.14 libopencv_superres.so.3.4
libopencv_flann.so.3.4 libopencv_objdetect.so libopencv_superres.so.3.4.14
pi@NanoPC-T6:/opt/opencv-3.4.14/build$ ls /usr/local/include/opencv
cvaux.h cvaux.hpp cv.h cv.hpp cvwimage.h cxcore.h cxcore.hpp cxeigen.hpp cxmisc.h highgui.h ml.h
pi@NanoPC-T6:/opt/opencv-3.4.14/build$ ls /usr/local/include/opencv2/
calib3d dnn flann.hpp imgproc objdetect.hpp shape superres.hpp videostab
calib3d.hpp dnn.hpp highgui imgproc.hpp opencv.hpp shape.hpp video videostab.hpp
core features2d highgui.hpp ml opencv_modules.hpp stitching video.hpp
core.hpp features2d.hpp imgcodecs ml.hpp photo stitching.hpp videoio
cvconfig.h flann imgcodecs.hpp objdetect photo.hpp superres videoio.hpp
我们可以在/usr/local/include/opencv2/cvconfig.h
查看当前可以的后端(例如HAVE_MSMF
、HAVE_VFW
、HAVE_LIBV4L
等)。
2.2.3 错误处理
编译过程中可能出现若干错误,如果出现如下错误,可以按照如下方法进行处理;
(1) -Werror=address
错误,具体如下:
[ 32%] Building CXX object modules/core/CMakeFiles/opencv_core.dir/src/persistence_json.cpp.o
/opt/opencv-3.4.14/modules/core/src/persistence_base64.cpp: In function ‘bool base64::base64_valid(const uint8_t*, size_t, size_t)’:
/opt/opencv-3.4.14/modules/core/src/persistence_base64.cpp:167:31: error: comparing the result of pointer addition ‘(src + ((sizetype)off))’ and NULL [-Werror=address]
167 | if (src == 0 || src + off == 0)
| ~~~~~~~~~~^~~~
[ 32%] Building CXX object modules/core/CMakeFiles/opencv_core.dir/src/persistence_types.cpp.o
cc1plus: some warnings being treated as errors
make[2]: *** [modules/core/CMakeFiles/opencv_core.dir/build.make:971:modules/core/CMakeFiles/opencv_core.dir/src/persistence_base64.cpp.o] 错误 1
make[2]: *** 正在等待未完成的任务....
make[1]: *** [CMakeFiles/Makefile2:1997:modules/core/CMakeFiles/opencv_core.dir/all] 错误 2
make: *** [Makefile:166:all] 错误 2
定位到opencv-3.4.14/cmake/OpenCVCompilerOptions.cmake
文件,移除或者注释掉124
行如下内容:
add_extra_compiler_option(-Werror=address)
(2) CODEC_ID_H264
错误,具体如下:
[ 52%] Building CXX object modules/dnn/CMakeFiles/opencv_dnn.dir/src/layers/convolution_layer.cpp.o
/opt/opencv-3.4.14/modules/videoio/src/ffmpeg_codecs.hpp:81:26: error: ‘CODEC_ID_H264’ was not declared in this scope; did you mean ‘AV_CODEC_ID_H264’?
81 | #define AV_CODEC_ID_H264 CODEC_ID_H264
| ^~~~~~~~~~~~~
/opt/opencv-3.4.14/modules/videoio/src/ffmpeg_codecs.hpp:146:7: note: in expansion of macro ‘AV_CODEC_ID_H264’
146 | { AV_CODEC_ID_H264, MKTAG('H', '2', '6', '4') },
| ^~~~~~~~~~~~~~~~
/opt/opencv-3.4.14/modules/videoio/src/ffmpeg_codecs.hpp:81:26: error: ‘CODEC_ID_H264’ was not declared in this scope; did you mean ‘AV_CODEC_ID_H264’?
81 | #define AV_CODEC_ID_H264 CODEC_ID_H264
......
解决方案:在make
之前,cmake
直接关闭ffmpeg
,在后面加上:
pi@NanoPC-T6:/opt/opencv-3.4.14/build$ cd ..
pi@NanoPC-T6:/opt/opencv-3.4.14$ sudo rm -rf CMakeCache.txt
pi@NanoPC-T6:/opt/opencv-3.4.14/build$ sudo cmake ../ -D WITH_FFMPEG=OFF
3.3 配置
配置动态链接库,编辑/etc/ld.so.conf
,文末加入/usr/local/lib
,执行sudo /sbin/ldconfig -v
生效;
pi@NanoPC-T6:/opt/opencv-3.4.14$ sudo vim /etc/ld.so.conf
include /etc/ld.so.conf.d/*.conf
/usr/local/lib
pi@NanoPC-T6:/opt/opencv-3.4.14$ sudo /sbin/ldconfig -v
如果是交叉编译,同时记得重新更新宿主机的sysroot
目录;
sudo mkdir -p /opt/qt6.5/sysroot
cd /opt/qt6.5/sysroot
sudo mkdir usr
sudo mkdir lib
sudo mkdir opt
sudo mkdir local
sudo cp -arvx /lib/* ./lib
sudo cp -arvx /usr/include ./usr
sudo cp -arvx /usr/lib ./usr
sudo cp -arvx /usr/local ./usr
sudo rm -rf /opt/qt6.5/sysroot/usr/lib/modules/6.1.25/
sudo find -type l -lname '/*' -exec sh -c 'ln -sf "/opt/qt6.5/sysroot$(readlink "$0")" "$0"' {} \;
ls /opt/qt6.5/sysroot/lib/aarch64-linux-gnu/libm.so -l
四、打包根文件系统
4.1 备份debain
根文件系统
开发板上执行以下命令,备份整个文件系统(包括OS
与数据):
pi@NanoPC-T6:/# sudo passwd root
pi@NanoPC-T6:/# su root
root@NanoPC-T6:/# cd /
root@NanoPC-T6:/# tar --warning=no-file-changed -cvpzf /rootfs.tar.gz \
--exclude=/rootfs.tar.gz --exclude=/var/lib/docker/runtimes \
--exclude=/etc/firstuser --exclude=/etc/friendlyelec-release \
--exclude=/usr/local/first_boot_flag --one-file-system /
注:备份时,如果系统中有挂载目录,最后会出现一个错误提示信息,可以无视它,我们本来就是要忽略这些目录。
最终会在/
路径下生成rootfs.tar.gz
文件,这里我将其下载到PC
并重命名为rootfs-debian-bullseye-desktop-arm64-qt.tgz
:
链接 https://pan.baidu.com/s/1lZheRdToDCDEFY8OBPCUBQ
提取码:gvzy
4.2 备份ubuntu qt6.5
root@zhengyang:/opt# cd /opt
root@zhengyang:/opt# ll
-rwxr-xr-x 1 root root 1479 12月 16 13:30 build-gcc.sh*
drwxr-xr-x 5 root root 4096 12月 15 23:26 cmake/
drwxr-xr-x 10 root root 4096 12月 17 02:35 glibc/
drwxrwxr-x 69 root root 4096 12月 17 23:15 glibc-2.36/
-rw-r--r-- 1 root root 36962019 8月 2 2022 glibc-2.36.tar.gz
drwxr-xr-x 8 root root 4096 12月 20 01:03 qt6.5/
drwxr-xr-x 10 root root 4096 12月 17 17:28 qtcreator-11.0.0/
-rwxrwxrwx 1 root root 200509321 7月 19 18:29 qt-creator-opensource-linux-x86_64-11.0.0.run*
drwxr-xr-x 8 root root 4096 12月 24 13:19 qt-project/
root@zhengyang:/opt/qt6.5# ll
drwxrwxr-x 45 1002 1002 4096 12月 17 21:09 qt-everywhere-src-6.5.0/
-rw-r--r-- 1 root root 792011632 4月 2 2023 qt-everywhere-src-6.5.0.tar.xz
drwxr-xr-x 14 root root 4096 12月 18 01:26 qt-host/
drwxr-xr-x 46 root root 4096 12月 18 01:26 qt-hostbuild/
drwxr-xr-x 14 root root 4096 12月 20 01:03 qt-nanopi/
drwxr-xr-x 46 root root 4096 12月 20 01:03 qt-nanopibuild/
drwxr-xr-x 6 root root 4096 12月 20 23:40 sysroot/
-rw-r--r-- 1 root root 2884 12月 17 21:50 toolchain.cmake
root@zhengyang:/opt/qt6.5# tar -zcvf qt-host.tar.gz qt-host
root@zhengyang:/opt/qt6.5# tar -zcvf qt-nanopi.tar.gz qt-nanopi
root@zhengyang:/opt/qt6.5# ls -l *.tar.gz
-rw-r--r-- 1 root root 104178582 12月 25 19:55 qt-host.tar.gz
-rw-r--r-- 1 root root 83504826 12月 25 19:56 qt-nanopi.tar.gz
将qt-host.tar.gz
、 qt-nanopi.tar.gz
拷贝到PC
,至于sysroot
自己从debain
根文件系统/opt/qt6.5
目录scp
过来即可;
链接:https://pan.baidu.com/s/1HtX-PFiEYIIavdpVUHJ1Vw
提取码:ylam
参考文章
[2] Linux Ubuntu
搭建Qt RK3399
编译 运行 调试环境
[4] linux GUI
-移植QT5.6
到mini2440
[5] 在Ubuntu Linux
上从源代码构建Qt 6.2.2
的简短教程
[6] RK3588
安装Qt+opencv+
采集USB
摄像头画面
[8] Linux
下Qt
配置opencv
环境(ippicv,ffmpeg
手动配置)
[9] https://www.debian.org/mirror/list
[11] 官方编译Qt
教程