交叉编译并部署Qt5.14.1到树莓派4最新官方镜像-buster版本

写在最前面 呵呵。。

编译成功,完美支持:EGLFS、 EGLFS GBM,EGL on X11暂时不支持,不过我不打算在X11上实现EGL。效果上图:

后面几天我会更新这篇文章,详细说明整个编译过程遇到的坑。

完美支持QML控件的程序

交叉编译并部署Qt5.14.1到树莓派4最新官方镜像-buster版本_第1张图片

运行的程序是Qt自带的automotive.pro例子程序。 

交叉编译并部署Qt5.14.1到树莓派4最新官方镜像-buster版本_第2张图片

 

  EGL .................................... yes
  OpenVG ................................. no
  OpenGL:
    Desktop OpenGL ....................... no
    OpenGL ES 2.0 ........................ yes
    OpenGL ES 3.0 ........................ yes
    OpenGL ES 3.1 ........................ yes
    OpenGL ES 3.2 ........................ yes
  Vulkan ................................. yes
  Session Management ..................... yes
Features used by QPA backends:
  evdev .................................. yes
  libinput ............................... yes
  INTEGRITY HID .......................... no
  mtdev .................................. yes
  tslib .................................. yes
  xkbcommon .............................. yes
  X11 specific:
    XLib ................................. yes
    XCB Xlib ............................. yes
    EGL on X11 ........................... no
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 ...................... no
    EGLFS GBM ............................ yes
    EGLFS VSP2 ........................... no
    EGLFS Mali ........................... no
    EGLFS Raspberry Pi ................... no
    EGLFS X11 ............................ no
  LinuxFB ................................ yes
  VNC .................................... yes
  XCB:
    Using system-provided XCB libraries .. yes
    XCB XKB .............................. yes
    XCB XInput ........................... no
    Native painting (experimental) ....... no
    GL integrations:
      GLX Plugin ......................... no
      EGL-X11 Plugin ..................... no

 

写在前面

这个教程将指导你如何在电脑的虚拟机上交叉编译Qt 5.14.1并安装到树莓派4B上面。这样你就可以在电脑上用Qt Creator设计和编译树莓派的应用,然后直接在树莓派上运行和调试。采用此方式开发出来的Qt窗口应用程序是为了在真正的嵌入式设备上运行的应用。应用程序可以不在X-server或桌面运行、应用程序使用eglfs接口直接调用OpenGL直接驱动GPU绘制窗口。eglfs是Qt的一个平台插件,使Qt程序可以利用OpenGL ES 画图而无需窗口系统。这种方式是在支持gpu的嵌入式设备主要采用的方式。一般需要gpu厂商提供egl和gles驱动模块。Qt可以利用eglfs插件实现直接画图(全屏),或者在有窗口管理系统(如wayland合成器weston或Qtwayland合成器)时通过窗口画图。前者只能全屏显示一个程序,后者可以实现多进程应用。

OpenGL ES(OpenGL for Embeded System)是OpenGL(Open Graphics Library)的精简子集,是以手持和嵌入式设备为目标的高级3D图形API

开发环境

1.[树莓派端]

树莓派型号:Raspberry Pi 4 Model B

CPU: ARM Cortex-A72 1.5GHz 64为四核

内存:2GB

TF卡:16GB

操作系统:2020-02-13-raspbian-buster-full (32位操作系统,因为树莓派官方只有32位操作系统)

raspbian常用的有两个版本Stretch和Buster,Stretch版一般安装在在树莓派3B和3B+上,Buster版安装在最新的树莓派4B上。查询当前操作系统版本的命令是 uname -a

uname -a

在 Raspberry Pi 官方网站的下载有 desktop和 Lite 两种版本,主要分别在于Lite 没有预设安装 X-server 与相关的套件,因此无法用 startx 启动视窗管理员。因为也没有安装 Qt 和 GTK+ 的函式库,因此也无法执行相关的视窗程式。采用本文方式编译出来的窗口程序原理上是不序号X-server即可运行,实际上能不能运行在Lite版本上待我后续试验后告诉大家。
2. [PC端]

操作系统:Win7

虚拟机版本:VMware® Workstation 15 Pro

Linux版版本:Ubuntu 18.04.3 LTS   64位版


准备工作

1. 在命令行界面使用以下命令更新固件,更新完成后重启系统。

sudo rpi-update
reboot

2. 确保树莓派上的SSH协议已经打开。后续Qt Creator需要通过SSH和树莓派通信。可以执行以下命令打开设置界面,选择Interfacing Options,选择ssh,选择yes然后finish。

sudo raspi-config

以下清单总结了交叉编译Qt 5.14.1的主要步骤,我们将在这篇文章中逐一介绍。[PI]表示在树莓派上操作,[PC]表示在电脑上操作。

    1. [PI] 安装开发包

    2. [PI] 准备目标文件夹

    3. [PI] 配置调试及运行环境

    4. [PC] 创建工作文件夹并设置工具链

    5. [PC] 创建和配置sysroot

    6. [PC] 下载Qt

    7. [PC] 配置Qt

    8. [PC] 编译、安装和部署Qt

    9. [PC]  配置Qt Creator实现交叉编译树莓派的应用

    10. [PI] 复制字体


 

1. [PI] 安装开发包
首先修改/etc/apt/sources.list(软件源配置文件)和 /etc/apt/sources.list.d/raspi.list(系统源配置文件)这两个文件,取消掉deb-src前面的注释。

先备份文件原始文件
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
sudo cp /etc/apt/sources.list.d/raspi.list /etc/apt/sources.list.d/raspi.list.bak

编辑文件
sudo nano /etc/apt/sources.list
sudo nano /etc/apt/sources.list.d/raspi.list

编辑好的文件如下,注意版本号是buster (source.list文件格式说明)。

# 编辑 `/etc/apt/sources.list` 文件,删除deb-src前的#号
deb http://mirrors.tuna.tsinghua.edu.cn/raspbian/ buster main non-free contrib
deb-src http://mirrors.tuna.tsinghua.edu.cn/raspbian/ buster main non-free contrib
 
# 编辑 `/etc/apt/sources.list.d/raspi.list` 文件,,删除deb-src前的#号。
deb http://mirrors.tuna.tsinghua.edu.cn/raspberrypi/ buster main ui

下一步是使用apt-get命令更新和下载开发包。由于移动宽带的不给力和我是有钱人的原因,更新过程中我使用的是手机5G热点接入联网方式,整个更新过程大概消耗了约1.3G的流量,不过升级速度真的很快!真的很快!真的很快!重要的事情说三遍。有的教程说使用国内源的方式下载,我尝试了一下,更新和下载过程中有错误发生,不知道原因。国内源修改好的sources.list文件和raspi.list文件内容如下:

#国内源更新sources.list文件和raspi.list文件修改内容
# `/etc/apt/sources.list` 文件
deb http://mirrors.tuna.tsinghua.edu.cn/raspbian/ buster main non-free contrib
deb-src http://mirrors.tuna.tsinghua.edu.cn/raspbian/ buster main non-free contrib
 
# `/etc/apt/sources.list.d/raspi.list` 文件
deb http://mirrors.tuna.tsinghua.edu.cn/raspbian/raspbian/ buster main ui
sudo apt-get update
sudo apt-get upgrade
sudo apt-get build-dep qt4-x11
sudo apt-get build-dep libqt5gui5
sudo apt-get install libudev-dev libinput-dev libts-dev libxcb-xinerama0-dev libxcb-xinerama0

有些教程说需要安装以下软件
sudo apt-get install libfontconfig1-dev libdbus-1-dev libfreetype6-dev libicu-dev libinput-dev libxkbcommon-dev libsqlite3-dev libssl-dev libpng-dev libjpeg-dev libglib2.0-dev libraspberrypi-dev libpq-dev libmariadbclient-dev bluez libbluetooth-dev build-essential

2. [PI] 准备目标文件夹
这步是在树莓派的pi用户下创建/usr/local/qt5pi文件夹,后面编译好的Qt库会从电脑部署到这个文件夹。

sudo mkdir /usr/local/qt5pi
sudo chown pi:pi /usr/local/qt5pi

3. [PI] 配置调试及运行环境
编译好的可执行文件会放在树莓派的/opt目录下,但默认的pi用户没有创建文件夹或文件的权限,需要在根目录执行:

sudo chmod -R 777 /opt

远程调试时需要安装gdbserver:

sudo apt-get install gdbserver

增加分辨率设置:

sudo leafpad ~/.profile

在其中增加:

# physical display properties
export QT_QPA_EGLFS_PHYSICAL_WIDTH=1920
export QT_QPA_EGLFS_PHYSICAL_HEIGHT=1080

然后执行:

source .profile

 

4. [PC] 创建工作文件夹并设置工具链
在电脑上创建交叉编译工具链工作文件夹。

mkdir ~/raspi
mkdir ~/raspi/cross-compile-tool/
cd ~/raspi

在linaro网站下载交叉编译工具链到~raspi目录下,包括gcc、runtime、sysroot三项。提示:用迅雷下,迅雷下的快!

交叉编译并部署Qt5.14.1到树莓派4最新官方镜像-buster版本_第3张图片

下载后解压,合并放在~/raspi/cross-compile-tool/目录下,tar命令详解

sudo tar jxvf gcc-linaro-7.5.01-2019.12-x86_64_gnueabif.tar.xz
sudo tar jxvf runtime-gcc-linaro-7.5.0-2019.12-arm-linux-gnueabihf.tar.xz
sudo tar jxvf sysroot-glibc-linaro-2.25-2019.12-arm-linux-gnueabihf.tar.xz

将交叉编译器路径写入PATH中(设置环境变量的方法和测试方法)

修改方式和内容如下:

sudo nano /etc/profile

#profile文件最后一行增加下面这行代码:
export PATH=$PATH:~/raspi/cross-compile-tool/bin


sudo nano /etc/sudoers
#sudoers文件修改好的样子:

刷新环境变量

#刷新变量文件
source /etc/profile

#测试变量是否写入成功
echo $PATH

检查配置是否正常

arm-linux-gnueabihf-g++  -v
sudo arm-linux-gnueabihf-g++ -v

编译一个小程序试试效果

1、nano编辑一段代码:

#include 
int main(int argc, char **argv)
{
    printf("Hello, you do it succeed!!!\n");
    return 0;
}

2、编译代码

arm-linux-gnueabihf-g++ main.c

3、 将编译输出文件a.out复制到目标机用户主目录下,增加运行权限,执行代码。

sudo chmod ugo+x ./a.out
./a.out

#运行输出:
Hello, you do it succeed!!!

为什么一定要sudo aarch64-linux-gnu-g++ -v 也有正常输出?因为在下面的编译过程中make中没有用到sudo,但是安装的时候要sudo make install,这一步的操作也需要交叉编译器,如果不正确配置,会出现make成功,而sudo make install失败的情况。

如果输入sudo aarch64-linux-gnu-g++ -v,提示没有找到命令,而直接输入aarch64-linux-gnu-g++ -v可正常显示。解决方法是在sudos配置文件下把交叉编译器的bin路径也加在secure_path变量里面。

 

5. [PC] 创建和配置sysroot 
sysroot是树莓派上的文件在PC上的拷贝,编译过程中需要的头文件、库等会在这里查找,此文件夹创建在~/rasp目录下。

cd ~/raspi/cross-compile-tool
mkdir ./sysroot/opt

我们可以使用rsync将树莓派rootfs目录下的/lib、/usr/include、usr/lib、/opt的目录同步到PC端的sysroot目录下。如果电脑上的sysroot文件夹发生任何变化,都会被自动同步到树莓派上。raspberrypi_ip代表树莓派的网络名或IP地址。

rsync -avz pi@raspberrypi_ip:/lib sysroot
rsync -avz pi@raspberrypi_ip:/usr/include sysroot/usr
rsync -avz pi@raspberrypi_ip:/usr/lib sysroot/usr
rsync -avz pi@raspberrypi_ip:/opt/vc sysroot/opt

简述一下sysroot目录的作用:

将sysroot-glibc-linaro-2.25-2019.12-arm-linux-gnueabihf.tar解压出来的目录与树莓派合成一个文件系统,用来提供给交叉编译时编译器寻找头文件.h和库文件.so。这样才能提供一个基本与目标开发板一致的环境,有了这个环境之后,编译时找头文件就不在笔记本(ubuntu)的环境找了,只在sysroot这个目录里面找。

下一步,我们需要将sysroot中的符号链接调整为相对的,因为这个文件夹在电脑和树莓派上都会有。用wget工具将sysroot-relativelinks.py文件下载到 ~/raspi/cross-compile-tool目录下,增加可执行权限,并运行。

wget https://raw.githubusercontent.com/riscv/riscv-poky/master/scripts/sysroot-relativelinks.py
chmod +x sysroot-relativelinks.py
./sysroot-relativelinks.py sysroot

到这里,这个交叉编译环境就基本OK了!

 6. [PC] 下载Qt
下载Qt 源代码文件,我下载的是5.14.1,当然其他版本也可以。进入QT官网下载网站,进入对应QT版本的目录(例如:5.14),子版本目录(5.14.1),single目录下载对应的Qt源代码文件:qt-everywhere-src-5.14.1.tar.xz。另外下载对应版本的PC端安装包。

安装包是用来给PC端装一个Qt,源码是用来编译一个 对应平台的Qt,即编译一个arm平台可用的Qt。

#源代码下载路径:
http://download.qt.io/archive/qt/5.14/5.14.1/single/qt-everywhere-src-5.14.1.tar.xz
#安装包下载路径:
http://download.qt.io/official_releases/qt/5.14/5.14.1/qt-opensource-linux-x64-5.14.1.run

 7. [PC] 配置Qt

~/rasp目录下解压缩Qt源代码文件,Qt源代码目录的qtbase/mkspecs文件夹下面放置着各种平台下的编译配置信息,本次需要编译的平台的文件夹是:~/rasp/qt-everywhere-src-5.14.1/qtbase/mkspecs/devices/linux-rasp-pi4-v3d-g++。编辑pi4平台下的qmake.conf文件。

#Qt源码包下载到~/rasp目录下,并在这个目录下解压缩,修改qmake.conf配置文件
tar xvf  qt-everywhere-src-5.14.1.tar.xz
sudo nano ./qt-everywhere-src-5.14.1/qtbase/mkspecs/devices/linux-rasp-pi4-v3d-g++/qmake.conf

qmake.conf的原始内容:

# qmake configuration for the Raspberry Pi 4 (32-bit) using the Mesa V3D
# graphics stack. (not the Broadcom stack)
#
# This supports accelerated OpenGL both for X11 and DRM/KMS.  Perhaps
# Wayland too.
#
# Tested with a sysroot created from Raspbian Buster and a gcc 7.4
# toolchain from Linaro.
#
# Example configure command line, assuming installation to
# /usr/local/qt5pi on device and ~/rpi/qt5 on the host:
#
# ./configure -release -opengl es2 -device linux-rasp-pi4-v3d-g++ -device-option CROSS_COMPILE=~/rpi/gcc-linaro-7.4.1-2019.02-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- \
#   -sysroot ~/rpi/sysroot -opensource -confirm-license -make libs -prefix /usr/local/qt5pi -extprefix ~/rpi/qt5 -v
#
# Check the configure output carefully. EGLFS, EGLFS GBM, and EGL on X11
# should all be 'yes'. Otherwise something is wrong.
#
# If getting linker errors like "undefined reference to `_dl_stack_flags'" check the
# symlinks in the sysroot, they were probably not adjusted
# correctly. F.ex. sysroot/usr/lib/arm-linux-gnueabihf/libpthread.so must point to
# sysroot/lib/arm-linux-gnueabihf/libpthread.so.0. If it is a broken link instead, bad
# things will happen.

include(../common/linux_device_pre.conf)

QMAKE_LIBS_EGL         += -lEGL
QMAKE_LIBS_OPENGL_ES2  += -lGLESv2 -lEGL

QMAKE_CFLAGS            = -march=armv8-a -mtune=cortex-a72 -mfpu=crypto-neon-fp-armv8
QMAKE_CXXFLAGS          = $$QMAKE_CFLAGS

DISTRO_OPTS            += hard-float
DISTRO_OPTS            += deb-multi-arch

EGLFS_DEVICE_INTEGRATION = eglfs_kms

include(../common/linux_arm_device_post.conf)

load(qt_config)

就qmake.conf文件的注释有些需要重点说明一下

qmake configuration for the Raspberry Pi 4 (32-bit) using the Mesa V3D graphics stack. (not the Broadcom stack)

This supports accelerated OpenGL both for X11 and DRM/KMS.  Perhaps Wayland too.

qmake成支持V3D graphics stack 栈而不是之前的Broadcom 栈。这样Qt程序可以同时在窗口管理系统X11和DRM/KMS上支持OpenGL加速。没准Wayland窗口管理系统也可以。

Tested with a sysroot created from Raspbian Buster and a gcc 7.4  toolchain from Linaro.

编译Qt源码用到的sysroot目录和gcc编译器的最低版本是7.4,我下载的是高版本的7.5.0。 树莓派官方指定的git下载目录https://github.com/raspberrypi/tools里面的版本太低,我记得应该是4.7.1吧。

Check the configure output carefully. EGLFS, EGLFS GBM, and EGL on X11 should all be 'yes'. Otherwise something is wrong.

完成配置后注意查看配置状态表上EGLFS, EGLFS GBM, 和 EGL on X11这几项是不是yes,否则编译会不成功。

If getting linker errors like "undefined reference to `_dl_stack_flags'" check the  symlinks in the sysroot, they were probably not adjusted  correctly. F.ex. sysroot/usr/lib/arm-linux-gnueabihf/libpthread.so must point to sysroot/lib/arm-linux-gnueabihf/libpthread.so.0. If it is a broken link instead, bad things will happen.

如果在make过程中出现 "undefined reference to `_dl_stack_flags'"错误,应该是sysroot目录下的libpthread.so库文件的软连接不对,用进入到文件目录下用 ls -l 命令查询一下,如果不是链接到“sysroot/lib/arm-linux-gnueabihf/libpthread.so.0.”需要用ln命令修复软链接: sudo ln -sf libpthread.so sysroot/lib/arm-linux-gnueabihf/libpthread.so.0.

配置Qt库:

进入Qt源代码文件夹的qtbase目录下运行./configure命令进行编译前配置。 因为./configure的配置参数很多,建议先阅读文章Qt源码编译configure配置参数。

简单来说./configure作用是根据不同的设置参数和选项明确目标平台信息、要编译的库、不编译的库等一些列选项,来编译出一个我们需要的arm目标平台版本的Qt。一些关键选项看下面这张表:

-release 

加上此选项编译程序Qt不会做出优化,往往在开发过程使用此选项,是默认选项

-opengl es2 

表示编译带opengl es2的Qt

-device linux-rasp-pi4-v3d-g++

选择的目标设备,目标设备的配置文件可在/qtbase/mkspec/device找到

-device-option CROSS_COMPILE=
~/raspi/home/用户名/raspi/cross-compile-tool/bin/arm-linux-gnueabihf- 

交叉编译器的路径,注意最后那里的arm-linux-gnueabihf- ,确实有一杠,不要以为打错了

-sysroot ~/raspi//cross-compile-tool/sysroot 

刚刚构建的树莓派文件系统的路径

-opensource 

以开源版本发布程序

-confirm-license 

自动确认许可证(使用开源或是商业)

-make libs 

在make时添加要构建的组件. (默认为:libs tools examples)

-prefix /usr/local/qt5pi

目标板的Qt程序安装目录,默认路径是/usr/local/Qt-版本号 (make完成后看看PC端对应目录下是否有qt5pi目录)

-extprefix ~/raspi/qt5pi 

指定Qt 交叉编译库存放位置。默认路径是SYSROOT/PREFIX。此目录最后需要同步rsysc到目标板的/usr/local/目录下。

-hostprefix ~/raspi/qt5-host

指定Qt 编译的可执行工具存放的位置,比如 qmake,默认路径与-extprefix参数一致。

-no-use-gold-linker 

不要使用GNU gold linker进行链接。对于 5.9.1 或更高版本的 Qt必须添加此选项,不然编译会报错

-v 

显示每个步骤的详细信息

-no-gbm

不要编译 GBM 的后端

进入到源码的根目录下的qtbase目录输入如下命令,并运行./configure的完整指令,开始运行配置过程。

cd  ~/rasp/qt-everywhere-src-5.14.1/qtbase
./configure -release -opengl es2 -device linux-rasp-pi4-v3d-g++ -device-option CROSS_COMPILE=~/raspi/cross-compile-tool/bin/arm-linux-gnueabihf- -sysroot ~/raspi/cross-compile-tool/sysroot -opensource -confirm-license -make libs -prefix /usr/local/qt5pi -extprefix ~/raspi/qt5pi -hostprefix ~/raspi/qt5pi-host -v 


#qmake.conf注释中说这两项参数不需要
-no-use-gold-linker -no-gbm

8. [PC] 编译、安装和部署Qt
这一步大概需要2小时。

make -j4
make install

编译完成后使用rsync命令将Qt部署到树莓派上。我们只需同步~/raspi/qt5pi目录到到树莓派的/usr/local/qt5pi目录下。

cd ~/rasp
rsync -avz qt5pi pi@raspberrypi_ip:/usr/local

 

你可能感兴趣的:(交叉编译并部署Qt5.14.1到树莓派4最新官方镜像-buster版本)