登录

在这个站点登录

保存我的登录记录

<<忘记密码?

还没有账号?点此注册>>

Jerry

QT树莓派交叉编译开发环境搭建

分享到:

本文已被浏览30770

前两天入手了一块2.8’的tft液晶显示屏,于是和树莓派连了一发,成功将命令行显示在了这块小的可怜的屏幕上之后,觉得这屏幕就显示个黑白内容太浪费了,于是考虑开发一个”脸”(图形用户界面,GUI)。首先考虑用C语言或者Python来堆图形界面,但是发现不管是C语言的图形库SDL亦或者OpenGL来堆这货都有点麻烦,毕竟我也不是想显示个太过于复杂的图形界面在那块屏幕上,只是显示一个最基本的文字数字就满足了。于是考虑到QT库。之前曾经学过一段时间的QT For Win32,那个环境很好搭建,从http://www.qt.io上面下载一个安装包安装就行了。那时候记得QT好像支持嵌入式的开发,同时在度娘那咨询到有人曾经在树莓派上开发了一发QT,但是那个很不幸的是在Startx桌面上跑的,但是我不想跑那个货,而且他是直接在树莓派上安装Qt、编译、执行的,需要一个绝对足够分辨率的屏幕,然而我那块240×320的屏幕显示个Qt Creator显然太挤了。。。。。。于是发现网上有人在做Qt的交叉编译,至于什么是交叉编译:

交叉编译
简单地说,就是在一个平台上生成另一个平台上的可执行代码。一个经常会被问到的问题就是,“既然我们已经有了主机编译器,那为什么还要交叉编译呢?”其实答案很简单。有时是因为目的平台上不允许或不能够安装我们所需要的编译器,而我们又需要这个编译器的某些特征;有时是因为目的平台上的资源贫乏,无法运行我们所需要编译器;有时又是因为目的平台还没有建立,连操作系统都没有,根本谈不上运行什么编译器。
另一个经常会被问到的问题就是:“既然可以交叉编译,那还要主机编译干吗?”其实答案也很简单,交叉编译是不得已而为之!与主机编译相比,交叉编译受的限制更多,虽然在理论上我们可以做任何形式的交叉编译,但事实上,由于受到专利、版权、技术的限制,并不总是能够进行交叉编译,尤其是在业余条件下!

交叉编译有点像开发单片机的过程,编写-编译-部署-运行。这下便解决了我树莓派屏幕太小的Bug。于是考虑走交叉编译的这条路子。

1.工具准备

这里考虑在Win32环境下编译针对ARM核的Linux程序开发环境。所以需要两个东西:Cross-ToolChain和MinGW。

  • Raspberry Pi Cross-ToolChain

ToolChain是个什么东西呢?ToolChain字面意思就是开发工具链(集),有了这货,我们才能做一些和那边操作系统相关的事情。这个ToolChain的下载地址是https://downloads.raspberrypi.org/raspbian_latest
首先,需要看一下树莓派(2)跑的操作系统是个什么版本的。目前支持的版本有两种,一个是较新的的Raspbian Jessie,一个是较旧的Raspbian Wheezy。针对较新的系统版本,需要下载的ToolChain是raspberry-gcc-4.9.2-r2;对于较旧的操作系统,需要下载的ToolChain是raspberry-gcc4.6.3。这里呢我放出来两个链接,是可以直接针对系统下载的ToolChain地址:

GCC For Rasbian Jessie(raspberry-gcc4.9.2-r2.exe)

大小:432MB


GCC For Rasbian Wheezy(raspberry-gcc4.6.3.exe)

大小:111MB


当我们下载完成后,执行安装:
Raspberry ToolChain

  • MinGW For Win32

MinGW如果有开发过开源软件的网友应该是很熟悉的,这就是Win32环境下的编译器。在这里用作去编译一些Win32下的Qt工具(譬如qmake之类的东西)。

MinGW32 GCC

大小:106MB


下载完成后,和ToolChain相同安装。
MinGW安装

  • Qt 5.5.0 Source Code

Qt官方并没有提供已经编译好的Qt Embeded For Raspbian的安装包,我们需要自己去编译这些内容,这里下载Qt的源码包。

  • Python For Win32

Python呢,是用来编译联机调试器用的。

2.配置Raspbian

这里就不对树莓派操作系统怎么装做解释了,网上都大同小异,自行百度即可。
Qt运行依赖于一些库:

sudo apt-get install 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

如果上面的操作执行失败,可以执行一下:

apt-get-update

在上面安装的库里面有两个叫libxcb-sync1 libxcb-sync-dev的包,并不能直接通过apt-get安装,但是我通过度娘搜了很久也没见到有可用的包,所以我直接放弃安装,目前也没见有什么不正常的地方。

3.同步Linux for ARM

既然最后编译出来的东西是要在树莓派上运行的,所以会依赖于一些树莓派上的库,所以在编译以及后续开发的过程中都会用的到。
在C:\Qt\QtEmbeded5.5.0\Raspberry\TOOLS中打开 UpdateSysroot.bat
同步目录
根据自己的同步经历,建议先把树莓派上一些无关紧要,可能到树莓派报废都用不到的捆绑软件在同步前卸载一下,这样在同步的时候会让进城耗时短一些。推荐卸载的内容有Wolfram-engine(一款数学建模软件,这货能跑我就觉得很神奇)、Sonic-pi(声音编程,小孩子用来拼个小节奏的软件)、Minecraft-Pi(我的世界树莓派严重阉割版,能玩,不过不用HDMI输出很吃力)、python-game(一些Python游戏,不好玩),然后同步上图中的一些目录。上图中的那个复选框的意思是在传输过程中是否打包,我同步的时候第一次是用的打包(不勾选),但是传了一会之后就出现了卡死的状态,我一断电,系统坏了,还得重新做。我推荐给他勾上,这样虽然传的稍稍慢了那么点,但是很稳定。

4.编译QMake

之前我曾经装过一遍Qt,有一个QMake,但是试了很多遍也没能用那个,最后还是选择重新编译一次Qmake。
首先要将Qt源码包解压到一个合适的地方(我是直接放在了C:\Qt\QtEmbeded5.5.0目录里),然后打开C:\Qt\QtEmbeded5.5.0\MinGW32\msys\1.0\msys.bat,这个时候应该会出来一个特别像是cmd的东西,但是里面的语法用的是linux的语法,用来执行一些linux格式的shell文件。
mSys
然后确认代码全部解压缩到当前目录下,确认gcc和arm-linux-gnueabihf-gcc工具的路径:
确认gcc与arm-linux-gnueabihf-gcc路径
如果没有找到gcc和arm-linux-gnueabihf-gcc,你可以设置你的Windows系统PATH环境变量,加入 c:\Qt\QtEmbeded5.5.0\Raspberry\bin和c:\Qt\QtEmbeded5.5.0\MinGW32\bin
环境变量
这个时候重点来了。在Qt的源码包中,针对树莓派的Linux类型arm-linux-gnueabihf的配置文件并不存在,但是可以从一个现有的文件修改得到:打开 qt-everywhere-opensource-src-5.5.0\qtbase\mkspecs\linux-arm-gnueabi-g++下的qmake.conf文件,将所有的arm-linux-gnueabi-替换成arm-linux-gnueabihf。
替换qmake.conf文件内容
现在就可以开始准备编译Qt了。Qt的配置文件有个Bug,就是不能直接的交叉编译我们的树莓派上用的Qt,而必须分为两步,先编译针对Win32环境的QMake,然后再编译针对RaspberryPi的Qt。
打开 qt-everywhere-opensource-src-5.5.0\qtbase\mkspecs\win32-g++ 下的qmake.conf文件,在 CXXFLAGS 后面添加 -U__STRICT_ANSI__ 标记。
添加-U__STRICT_ANSI__标记
然后再之前打开的msys中执行:

cd /c/Qt/QtEmbeded5.5.0/
mkdir Build
cd Build
../qt-everywhere-opensource-src-5.5.0/configure -platform win32-g++ -xplatform linux-arm-gnueabi-g++ -release -opengl es2 -device linux-rasp-pi-g++ -sysroot C:/Qt/QtEmbeded5.5.0/Raspberry/arm-linux-gnueabihf/sysroot -prefix /usr/local/qt5

然后得到这样的提示:
编译QMake
在选择了Opensource和yes同意所有协议条款后,开始编译QMake,编译完成后提示:
完成QMake编译

5.交叉编译树莓派Qt

在开始为树莓派进行交叉编译前,需要修改一下configure文件。
在qt-everywhere-opensource-src-5.5.0\qtbase\configure文件的3900行有个if true then;,这句导致每次编译的时候都会默认去编译一下qmake,但是编译Qmake后由不能继续编译,所以我们分为了两步来做,我们已经有了已经编译好的qmake,所以这里需要改成:

setBootstrapVariable()
{
    getQMakeConf "$1" | echo ${2-$1} = `if [ -n "$3" ]; then sed "$3"; else cat; fi` >> "$mkfile"
}

# build qmake
if [ '!' -f "$outpath/bin/qmake.exe" ]; then
    echo "Creating qmake..."

    mkdir -p "$outpath/qmake" || exit
    # fix makefiles

如下图所示:
修改Configure文件
Ok,之后就是为Qt编译创建MakeFile配置文件。在刚刚的msys窗口中执行:

../qt-everywhere-opensource-src-5.5.0/configure -platform win32-g++ -xplatform linux-arm-gnueabi-g++ -release -opengl es2 -device linux-rasp-pi-g++ -sysroot C:/Qt/QtEmbeded5.5.0/Raspberry/arm-linux-gnueabihf/sysroot -prefix /usr/local/qt5 -device-option CROSS_COMPILE=C:/Qt/QtEmbeded5.5.0/Raspberry/bin/arm-linux-gnueabihf- -qt-xcb

执行后和刚刚相同,选择Opensource并同意所有协议条款:
执行Configure
在选中Opensource并同意所有条款后,Configure开始检查并创建MakeFile文件。如果当前编译环境缺少一些必要的库和文件,这时也会提示出来。如果出现了找不到类库和文件,可以去检查下C:\Qt\QtEmbeded5.5.0\Raspberry\arm-linux-gnueabihf\sysroot\etc\ld.so.conf中是否全部包含了以下记录:

/opt/vc/lib
/lib/arm-linux-gnueabihf
/usr/lib/arm-linux-gnueabihf
/usr/lib/arm-linux-gnueabihf/libfakeroot
/usr/local/lib

当创建完成后,会看到Configure为我们列出了所有的可以编译的模块:
Configure结果
到这里,最痛苦的阶段就要开始了。我们要开始真真正正的qt编译阶段。在确认了所有需要的模块都处于可编译状态,执行make&&make install。
根据国外的一篇文章,大概会需要几个小时,我大概花了7个小时左右完成了编译和安装。
编译开始
在开始编译之后就不要再动电脑了,让他静静的去跑。根据我第一次编译的结果,如果想看一下编译的进度,可以去看下我们的构建目录Build中的文件数目。我第一次的编译结果中共计12817个文件,通过对Build文件夹中文件数量的统计,大致能判断出来编译进度。
编译过程中的Build目录属性
在经历了N个小时的编译,终于,msys回到了命令行,也就意味着编译完成。
编译完成
到这里,我们的编译工作完成。下面开始配置开发环境。

6.同步Qt5到树莓派并测试

在之前安装的RaspberryPi ToolChain的Tools目录中有个SmarTTY,打开后连接上树莓派的SSH。
SmarTTY连接树莓派
在这里不建议使用SFTP上传,因为SFTP不能完整的将文件属性上传到树莓派(根据一位网友),所以使用SmarTTY的上传功能。在上传前先在树莓派的/usr/local/中建立一个名为qt5的目录,并将其所有者改为你用来登录SSH的用户(默认是pi,我没有改,所以这里的所有权给pi)

cd /usr/local
sudo mkdir qt5
sudo chown pi qt5

完成上述操作后,点击SCP菜单中的Upload a Directory
点击SCP菜单
打开上传窗口。配置本地目录为C:\Qt\QtEmbeded5.5.0\Raspberry\arm-linux-gnueabihf\sysroot\usr\local\qt5,远程目录为/usr/local/qt5,这里需要注意一件事情,就是底下这个复选框。如果在之前的同步系统目录过程中使用On-the-fly Tar模式同步出现卡死的现象,这里也必须要将传输模式改为单文件模式,否则还会卡死。。。
上传Qt库
当上传完成后我们就可以在SSH命令行中执行一个Demo来判断Qt是否正确的配置了。打开/usr/local/qt5/examples/widgets/richtext/textedit运行./textedit实例,如果正常配置了,那么在HDMI所连接的显示器上将会正常显示出一个文本编辑器。如果手头没有HDMI显示设备,但是树莓派上曾经安装有一块SPI的tftLCD屏幕并已经正确的配置并可以显示控制台,那么也可以在命令前面添加一段对QT_QPA_PLATFORM环境变量配置的代码:

QT_QPA_PLATFORM=linuxfb:fb=/dev/fb* ./textedit

其中fb*是希望输出显示的tft屏幕所对应的framebuffer文件。如果能够正常显示,说明树莓派上的Qt5配置已经成功完成。

7.Qt Creator配置开发环境

当Qt成功的运行在了树莓派上,那么就可以开始准备自己开发Qt软件在树莓派上运行了。
Qt程序的生成规则是:Qt Creator 开发程序生成.pro和.ui文件->QMake将.pro和.ui文件生成CPP文件->QMake将所有需要编译的cpp文件和header文件统一汇总制成Makefile文件->使用Makefile开始编译构建。
所以必须要将QMake,编译器,连接器的信息告知Qt Creator,才能让Qt Creator在构建操作时能够正确的找到必要的工具。同时,树莓派的一些信息也需要告知Qt Creator。

  • 准备Qt Creator

Qt Creator可以使用Qt 5.5.0 For Win32 那个包里的QtCreator,也可以使用下面的连接下载Qt Creator

Qt Creator 3.6.0 For Windows

大小:80.4 MB

  • 添加设备(树莓派)到部署列表

使用Qt Creator直接在树莓派上部署运行Qt 程序必须将树莓派添加到部署列表。这里打开Qt Creator 工具菜单中的选项,选择左侧的设备:
设备列表图
选择添加后弹出选择设备类型的窗口,树莓派属于通用Linux设备,选中通用Linux设备,点击开始向导
创建设备
随后弹出创建通用Linux设备的向导,这里输入树莓派的SSH地址、用户名、密码:
创建设备向导
当填写完成密码等信息后,点击下一步后会要求测试连接,随后弹出连接成功的提示:
测试连接图
这时,便成功向Qt Creator添加了一个设备。

  • 添加QMake到Qt Creator

之后所有的Qt 程序编译都需要用到我们刚刚编译的QMake,所以需要将其添加到QtCreator中。打开Qt Creator选项中的构建和运行,右侧点击Qt Versions:
Qt Versions
上图中已经有的一个是Qt For Win32 的QMake,我们需要天机QMake For Qt Embeded,点击右侧的添加,选择C:\Qt\QtEmbeded5.5.0\Raspberry\arm-linux-gnueabihf\sysroot\usr\local\qt5\bin\qmake.exe 。选中后再Qt Version选项卡中将会多出来一项:
Qt Versions

  • 添加编译器

当前系统中的编译器编译结果是在x86机器上运行的程序,并不能在树莓派ARM芯片上运行,所以需要手动添加一个编译器。这里的编译器还是使用之前下载的Raspberry ToolChain中的编译器。打开Qt Creator的编译与构建选项中编译器选项卡:
编译器选项卡
点击右侧添加一个MinGW编译器,填入下面的信息,点击应用(Apply):
编译器设定完成

  • 创建编译套件(Kits)

当我们把所有相关的信息都录入后,需要创建一个编译套件,来做到QMake,编译器,连接器能够匹配的使用。进入Qt Creator的选项中的构建套件选项卡:
构建套件
点击右侧新建,按照下图中的信息填写:
填写构建套件
上图中填写的一些信息:

  • 设备类型:通用Linux设备
  • 设备:刚刚创建的那个设备
  • Sysroot:C:\Qt\QtEmbeded5.5.0\Raspberry\arm-linux-gnueabihf\sysroot
  • 编译器:刚刚创建的编译器
  • 调试器:None(因为没有创建)
  • Qt版本:刚刚创建的Qt5
  • Qt mkspec: C:\Qt\QtEmbeded5.5.0\Raspberry\arm-linux-gnueabihf\sysroot\usr\local\qt5\mkspecs\devices\linux-rasp-pi-g++

其中的调试器我没有编译,所以也没有添加,而且单步调试感觉没有什么用处,就没有弄,需要的网友可以去参考资料中寻找方法。
至此,我们的Qt Embeded For Raspberry Pi开发环境就已经完成了。

8.常见问题(FAQ)

  1. 中文字体
    树莓派中的Qt 默认是没有中文字体的,所以所有在Qt Creator中设置的中文到了树莓派上都是空白。解决方案很简单,就是把你需要显示的字体从电脑的C:\Windows\Fonts文件夹中拷出来,上传到树莓派的/usr/local/qt5/lib/fonts目录中,然后重启Qt 程序即可。常用的字体有SimSum、微软雅黑、宋体这些,全部考进去就行了
  2. 编写好Qt程序点击运行后提示Command Not Found
    这是因为对于Qt 来说并不知道应该把程序部署到树莓派上的哪个目录中来运行,所以会提示找不到命令来执行。解决方案就是在工程的.pro文件中添加以下内容:

            target.path=部署目录,譬如/home/pi/inject
            INSTALLS+=target
            
  3. 编写好的Qt程序在测试的时候不能显示在FrameBuffer上
    这是因为Qt Creator在部署完成后执行程序时并不会添加上QT_QPA_PLATFORM变量,所以我们需要将这个变量添加至系统变量,在/etc/profile中添加此变量:

            export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb*
            

9.参考文献

  1. Cross-compiling Qt Embedded 5.5 for Raspberry Pi 2
  2. Qt for Embedded Linux
  3. 适用于树莓派Raspberry Pi的嵌入式QT平台(一) — 交叉编译安装Qt Embedded 5.5
  4. 适用于树莓派Raspberry Pi的嵌入式QT平台(二) — 在Windows下用Qt Creator开发编译Raspberry Qt 5应用程序
  5. 适用于树莓派Raspberry Pi的嵌入式QT平台(三) — 交叉编译 Raspberry Pi 版GDB with Python

2017年2月19日补充:

感谢ETRD博客提供了一种通过在树莓派上预先安装好QT的编译环境,然后通过SFTP工具同步至X86平台的方法.
传送门:《搭建树莓派3上的QT环境并使用VS交叉编译开发的方法》

 手机扫描左边的二维码,立刻将文章收入手机!
 微信扫描左边二维码,点击右上角即可分享到朋友圈!
严禁任何非授权的采集与转载,转载须经站长同意并在文章显著位置标注本文连接,站长保留追究法律责任的权利.

评论

 您需要 先登录 才可以回复.