1. 环境准备与工具链配置

在开始搭建树莓派Qt交叉编译环境之前,我们需要先准备好必要的工具和依赖项。这个过程其实就像准备一顿大餐前的食材采购,缺了哪样都会影响最终的效果。我建议使用Ubuntu 20.04或更高版本,因为这个版本的兼容性更好,社区支持也更完善。

首先安装基础编译工具和依赖库:

sudo apt update
sudo apt install build-essential cmake git python3-dev

接下来安装Qt开发所需的依赖项:

sudo apt install libgl1-mesa-dev libglu1-mesa-dev \
libxcb-xinerama0-dev libxkbcommon-dev \
libxcb-icccm4-dev libxcb-image0-dev \
libxcb-keysyms1-dev libxcb-render-util0-dev

交叉编译工具链的选择很重要,我推荐使用树莓派官方提供的工具链,兼容性最好。下载和配置工具链的步骤如下:

mkdir -p ~/rpi/tools
cd ~/rpi
git clone https://github.com/raspberrypi/tools.git

将工具链添加到系统路径中,方便后续使用:

echo 'export PATH=$PATH:~/rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin' >> ~/.bashrc
source ~/.bashrc

验证工具链是否安装成功:

arm-linux-gnueabihf-gcc --version

如果看到正确的版本信息输出,说明工具链已经准备就绪。

2. 创建sysroot系统根目录

sysroot是交叉编译环境中非常重要的概念,它相当于目标设备(树莓派)的文件系统在开发机上的一个镜像。这样编译器就能找到所有需要的头文件和库文件,就像在真实的树莓派上编译一样。

首先在开发机上创建sysroot目录结构:

mkdir -p ~/rpi/sysroot
mkdir -p ~/rpi/sysroot/usr
mkdir -p ~/rpi/sysroot/opt

接下来需要从树莓派上同步必要的文件。确保你的树莓派已经联网,并且知道它的IP地址。首先在树莓派上安装一些基础开发包:

sudo apt update
sudo apt install libudev-dev libinput-dev libts-dev \
libxcb-xinerama0-dev libxcb-xinerama0

然后在开发机上使用rsync同步文件:

rsync -avz pi@树莓派IP地址:/lib ~/rpi/sysroot
rsync -avz pi@树莓派IP地址:/usr/include ~/rpi/sysroot/usr
rsync -avz pi@树莓派IP地址:/usr/lib ~/rpi/sysroot/usr
rsync -avz pi@树莓派IP地址:/opt/vc ~/rpi/sysroot/opt

同步完成后,需要修复符号链接。因为从树莓派复制过来的符号链接还是指向树莓派上的绝对路径,我们需要将其改为指向sysroot内的相对路径:

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

这个过程可能会花费一些时间,取决于你的网络速度和树莓派上安装的软件数量。我建议在网络状况好的时候进行这个操作,避免中途断线需要重头再来。

3. 编译Qt源码

现在来到最关键的步骤——编译Qt源码。这个过程比较耗时,但每一步都很重要。我选择Qt 5.15.2版本,因为这个版本在树莓派上的稳定性经过验证,而且有很好的社区支持。

首先下载Qt源码:

cd ~/rpi
wget http://download.qt.io/official_releases/qt/5.15/5.15.2/single/qt-everywhere-src-5.15.2.tar.xz
tar xvf qt-everywhere-src-5.15.2.tar.xz
cd qt-everywhere-src-5.15.2

配置编译选项是关键步骤,这里的参数直接影响最终生成的Qt库的功能和性能:

./configure -release -opengl es2 -device linux-rasp-pi3-g++ \
-device-option CROSS_COMPILE=arm-linux-gnueabihf- \
-sysroot ~/rpi/sysroot \
-prefix /usr/local/qt5pi \
-extprefix ~/rpi/qt5pi \
-hostprefix ~/rpi/qt5 \
-opensource -confirm-license \
-skip qtwayland -skip qtlocation -skip qtscript \
-make libs -no-use-gold-linker -v -no-gbm

这里解释几个重要参数:

  • -opengl es2:启用OpenGL ES 2.0支持,树莓派的GPU需要这个
  • -device linux-rasp-pi3-g++:指定设备为树莓派3,但同样适用于树莓派4
  • -sysroot:指定系统根目录路径
  • -prefix:指定在树莓派上的安装路径
  • -extprefix:指定交叉编译生成的库文件的存放路径

配置完成后开始编译:

make -j$(nproc)

使用-j$(nproc)参数可以并行编译,充分利用多核CPU加快编译速度。这个过程可能需要2-4小时,取决于你的电脑性能。

编译完成后安装到本地目录:

make install

将编译好的Qt库部署到树莓派:

rsync -avz ~/rpi/qt5pi pi@树莓派IP地址:/usr/local

4. 配置Qt Creator开发环境

现在我们已经准备好了所有基础组件,接下来配置Qt Creator使其能够进行交叉编译。Qt Creator是一个强大的IDE,正确配置后可以大大提升开发效率。

首先打开Qt Creator,进入Tools > Options > Devices。点击Add按钮添加新设备,选择Generic Linux Device类型。填写设备名称(如RaspberryPi4)、树莓派的IP地址、用户名(通常是pi)和密码。点击Test按钮测试连接是否成功。

接下来配置编译器。进入Kits选项卡,选择Compilers页面。点击Add > GCC > C添加C编译器,路径指向交叉编译工具链中的gcc:

~/rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-gcc

同样添加C++编译器,选择GCC > C++,路径指向:

~/rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-g++

然后配置Qt版本。进入Qt Versions页面,点击Add按钮,选择我们刚编译生成的qmake程序:

~/rpi/qt5/bin/qmake

最后创建编译套件。进入Kits页面,点击Add添加新套件,配置以下参数:

  • Name:给套件起个有意义的名字,如RaspberryPi-Qt5.15
  • Device type:选择Generic Linux Device
  • Device:选择刚才创建的设备
  • Sysroot:选择~/rpi/sysroot目录
  • Compiler:分别选择刚才配置的C和C++编译器
  • Qt version:选择刚才配置的Qt版本
  • Debugger:如果需要调试,可以配置gdb-multiarch

5. 创建和测试示例项目

环境配置完成后,我们来创建一个简单的测试项目验证一切是否正常工作。打开Qt Creator,选择File > New File or Project > Application > Qt Widgets Application。

在项目配置中,特别注意要选择我们刚创建的RaspberryPi编译套件。创建完成后,打开main.cpp文件,添加一些简单的测试代码:

#include "mainwindow.h"
#include <QApplication>
#include <QDebug>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    
    qDebug() << "Hello from Raspberry Pi!";
    qDebug() << "Qt version:" << qVersion();
    
    return a.exec();
}

在项目文件(.pro)中,我们需要添加一些树莓派特定的配置。特别是如果需要使用树莓派的GPIO或其他硬件特性,需要链接相应的库:

target.path = /home/pi/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

# 如果需要使用wiringPi库
unix:!macx {
    LIBS += -L/usr/lib -lwiringPi
}

# 树莓派特定的OpenGL配置
QMAKE_CXXFLAGS += -mfpu=neon-vfpv4

编译项目时,Qt Creator会自动将生成的可执行文件部署到树莓派上。你可以在Qt Creator的编译输出窗口中看到部署过程。如果一切正常,输出窗口会显示"Starting remote process...",然后程序就在树莓派上运行了。

为了验证程序确实在树莓派上运行,你可以在树莓派上直接运行编译好的程序:

cd /home/pi/你的项目名/bin
./你的项目名

6. 常见问题排查与优化

在交叉编译过程中可能会遇到各种问题,这里我分享一些常见问题的解决方法。

如果编译时出现找不到头文件或库文件的错误,首先检查sysroot目录是否完整,符号链接是否正确。可以使用以下命令检查:

find ~/rpi/sysroot -name "*.so" | head -10
ls -la ~/rpi/sysroot/usr/lib/arm-linux-gnueabihf/

如果程序在树莓派上运行时报错说找不到共享库,可能是因为库路径问题。可以在树莓派上设置LD_LIBRARY_PATH:

export LD_LIBRARY_PATH=/usr/local/qt5pi/lib:$LD_LIBRARY_PATH

为了提升编译速度,可以尝试以下优化措施:

  1. 使用ccache缓存编译结果:sudo apt install ccache
  2. 增加make的并行编译线程数:make -j8
  3. 关闭调试信息:在configure时添加-release参数

如果遇到OpenGL相关的问题,检查树莓派上的GPU内存分配是否足够。在树莓派上运行raspi-config,选择Performance Options > GPU Memory,建议分配至少128MB。

对于部署问题,确保Qt Creator能够通过SSH连接到树莓派。测试连接时如果出现问题,检查树莓派的SSH服务是否开启,防火墙设置是否正确。

7. 高级配置与性能调优

当基础环境搭建完成后,你可能还需要进行一些高级配置来优化开发体验和程序性能。

首先考虑使用预编译头文件来加速编译过程。在项目文件(.pro)中添加:

PRECOMPILED_HEADER = stable.h

创建stable.h文件,包含那些不经常变动但被广泛引用的头文件:

#ifndef STABLE_H
#define STABLE_H

#include <QtCore>
#include <QtGui>
#include <QtWidgets>

#endif // STABLE_H

对于树莓派的硬件特性优化,可以添加特定的编译选项:

QMAKE_CXXFLAGS += -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8
QMAKE_CFLAGS += -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8

这些选项针对树莓派4的Cortex-A72处理器进行了优化,能够充分发挥硬件性能。

如果项目需要使用树莓派的特殊硬件接口,如GPIO、I2C、SPI等,需要在项目文件中链接相应的库:

LIBS += -lwiringPi
LIBS += -lbcm2835

对于内存优化,可以在树莓派上设置Qt的图形后端。创建/etc/environment文件并添加:

QT_QPA_PLATFORM=eglfs
QT_QPA_EGLFS_INTEGRATION=eglfs_kms

这样可以减少内存占用并提升图形性能。

最后,建议设置自动化部署脚本,简化开发流程。创建deploy.sh脚本:

#!/bin/bash
rsync -avz ./bin/ pi@树莓派IP地址:/home/pi/project/bin/
ssh pi@树莓派IP地址 "chmod +x /home/pi/project/bin/你的程序名"

这样每次编译完成后,运行这个脚本就可以自动部署到树莓派上。

更多推荐