嵌入式QT移植的实现

 

一、软件包、环境说明

1.1 软件包

1.1.1 通用交叉编译工具链

gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz

1.1.2 qt源码

qt-everywhere-src-5.12.9.tar.xz
下载地址:https://download.qt.io/archive/qt/5.12/5.12.9/single/

1.1.3 tslib(触摸屏校准插件)

tslib-1.21.tar.bz2
下载git地址:https://github.com/libts/tslib

1.1.4 fonts字体库(qt支持中文)

DroidSansFallback.ttf

1.2 环境说明

1、Ubuntu版本:16.04
2、Qt应用程序版本:Q5.14.2
3、开发板:正点原子阿尔法开发板(I.MX6ULL)
4、触摸屏:正点原子RGB触摸屏4.3寸、800*480

 

二、环境搭建

2.1 ubuntu下安装通用的交叉编译器

1、将交叉编译工具包(gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz)拷贝到ubuntu的/usr/local/arm/目录下。

2、在当前目录解压交叉编译工具包

3、解压完成后,将路径加入到环境变量中/etc/profile文件

sudo vim /etc/profile

在末尾加入:

4、重新使能环境变量

source /etc/profile

5、查看交叉编译工具是否添加成功

arm-linux-gnueabihf-gcc -v (tab键可补全)

出现这个则说明通用的交叉编译工具链安装成功,版本为4.9.4
没有的话,检查/etc/profile里面添加的文件路径是否正确
至此,通用的交叉编译工具链安装完成

2.2 ubuntu下编译Qt源码

2.2.1 编译这个有什么用呢?

windows下面开发qt是不用编译,因为在你qt软件的安装目录下已经有这个lib库文件,直接运行会自动连接到去qt安装目录下找库文件,如qpushbutton.h、qcombox.h等文件,在qt安装目录下E:\qt\Qt5.12.9\5.12.9\Src\qtbase\include\QtWidgets里面。
qt应用程序移植到开发板上面运行,也需要连接到lib库,编译qt源码就是处理lib库,方便qt在开发板上运行不报xx文件找不到的错误。

2.2.2 拷贝qt源码到ubuntu

拷贝源码到你Ubuntu指定的目录下面,解压。(后面这个路径需要用到)

2.2.3 修改qmake.conf文件

主要配置你编译qt源码使用的交叉工具链(上面装的那个工具链)和一些配置信息。
进入到qt源码目录:

编辑 qtbase/mkspecs/qws/linux-arm-gnueabi-g++/qmake.conf文件

添加红色框里面的内容:

/*硬件配置信息、armv7-a、估计不同arm内核这里要改,具体没研究过*/
QT_QPA_DEFAULT_PLATFORM = linuxfb
QMAKE_CFLAGS += -O2 -march=armv7-a -mtune=cortex-a7 -mfpu=neon -mfloat-abi=hard
QMAKE_CXXFLAGS += -O2 -march=armv7-a -mtune=cortex-a7 -mfpu=neon -mfloat-abi=hard
/*编译qt源码使用的交叉编译工具链*/
arm-linux-gnueabihf

修改之后保存。

2.2.4 修改配置编译选项

在qt源码目录下有一个configure的脚本,使用对qt源码进行配置的。可以根据自己的需求裁剪一些不必要的功能,编译之后lib库文件大小当然也会相应的缩小。
终端输入 ./configure -help 可以查看配置选项
这里搞在弄一个shell脚本,进行配置qt源码:
终端输入 vim autoconfigure.sh
输入下面指令:

./configure -prefix /home/wx/linux/qt/source-code/qt-everywhere-src-5.12.9/arm-qt \
-opensource \
-confirm-license \
-release \
-strip \
-shared \
-xplatform linux-arm-gnueabi-g++ \
-optimized-qmake \
-c++std c++11 \
--rpath=no \
-pch \
-skip qt3d \
-skip qtactiveqt \
-skip qtandroidextras \
-skip qtcanvas3d \
-skip qtconnectivity \
-skip qtdatavis3d \
-skip qtdoc \
-skip qtgamepad \
-skip qtlocation \
-skip qtmacextras \
-skip qtnetworkauth \
-skip qtpurchasing \
-skip qtremoteobjects \
-skip qtscript \
-skip qtscxml \
-skip qtsensors \
-skip qtspeech \
-skip qtsvg \
-skip qttools \
-skip qttranslations \
-skip qtwayland \
-skip qtwebengine \
-skip qtwebview \
-skip qtwinextras \
-skip qtx11extras \
-skip qtxmlpatterns \
-make libs \
-make examples \
-nomake tools -nomake tests \
-gui \
-widgets \
-dbus-runtime \
--glib=no \
--iconv=no \
--pcre=qt \
--zlib=qt \
-no-openssl \
--freetype=qt \
--harfbuzz=qt \
-no-opengl \
-linuxfb \
--xcb=no \
-tslib \
--libpng=qt \
--libjpeg=qt \
--sqlite=qt \
-plugin-sql-sqlite \
-I/home/wx/linux/qt/tslib/tslib-1.21/arm-tslib/include \ 
-L/home/wx/linux/qt/tslib/tslib-1.21/arm-tslib/lib \ 
-recheck-all

倒数第三行、第二行是tslib库的头文件路径和库文件路径,根据自己的填入即可,tslib的编译后面会讲到。
这个是我使用的配置文件,测试是没有问题的。直接复制的话注意每一行的那个(换行符)后面不要留空格,留空格的话执行会报找不到命令错误。
修改完成之后,给脚本加上可执行权限

chmod +777 autoconfigure.sh

之后执行脚本

./autoconfigure.sh

出现这种则说明配置完成。

2.2.5 编译qt源码

接上面,配置后面提示、输入make、现在就编译源码。
输入make install,装载编译后源码到执行目录。
这个的指定目录就是autoconfigure.sh这个脚本第一行的路径。

我这里是在qt源码的根目录下新建一个arm-qt目录,大家也指定其他目录。
终端输入make、开始编译qt源码

等待编译完成。

源码编译完成后,在终端输入make install,将生成的lib库文件拷贝到指定的目录里面,我这指定的是qt源码目录下arm-qt文件夹里面。
等待拷贝完成后,进入arm-qt文件夹里面,查看内容:

至此,QT源码编译就完成了,后面会用到arm-qt文件夹里面的东西。

2.3 ubuntu下编译tslib库

2.3.1 拷贝解压tslib到Ubuntu

开始之前,先安装几个工具,编译tslib库时需要用到。

sudo apt-get update
sudo apt-get install autoconf automake libtool

tslib源码包大家自行拷贝解压到自己的目录下:

我这里已经拷贝解压了,大家根据自己的目录拷贝解压即可。

2.3.2 配置tslib

进入tslib文件夹里面,看到有一个configure的文件,和qt源码根目录里面的一样,也是一个配置脚本。我们需要执行这个脚本来指定使用交叉工具链和编译后生成文件的存放路径。
执行下列命令:

./configure --host=arm-linux-gnueabihf ac_cv_func_malloc_0_nonnull=yes --cache-file=arm-linux.cache -prefix=/home/wx/linux/qt/tslib/tslib-1.21/arm-tslib

这里/home/wx/linux/qt/tslib/tslib-1.21/arm-tslib路径是我的存放路径,你也可以在你tslib根目录下创建一个arm-tslib文件夹用于 存放编译后的文件。

mkdir arm-tslib

等待配置完成之后就可以执行make.
终端输入make回车,开始编译tslib。

如果之前你已经编译过,那make之前需要执行make clean命令,把之前make编译的文件删除掉,不执行好像也可以,个人感觉最好清一下。
等待make完成之后,执行sudo make install指令(不加sudo好像不行,没权限)。

make install时报这个错误,我记得我第一次编译没问题的,很奇怪,百度找找了。

配置的时候参数改成上面那样就没有问题,所以有一些告警,可以忽略。

./configure --host=arm-linux --prefix=`pwd`/arm-tslib CC=/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc

gcc交叉编译工具改成了绝对路径,大家根据自己实际情况修改。
好了,再次配置tslib,

make clean
make
sudo make install

ok,这次没有问题。
进入arm-tslib目录下, ls下,该有文件都已经有了。

看一下文件的类型:是不是ARM架构下的文件

file bin/ts_calibrate


是arm架构,没问题,如果你的是x86架构,请检查你的交叉编译工具是否正确。
至此,tslib库编译已经完成。

2.4 配置ARM架构下Qt Creator环境

2.4.1 qt creator环境配置

安装qt creator就不讲了,大家不会的百度很容易找到。
打开qt creator软件
在菜单栏中选择工具->选项->kits->Qt Versions->addr

配置kits:

这里图我就直接贴正点原子的了,感觉挺易懂明了的。

2.4.2 编译测试qt程序

qt creator环境配置好之后,编译qt测试应用测试。
新建工程什么的,大家应该都会了,新建工程的最后一步,大家需要特别注意,一定到勾选ARM平台的开发套件(Kits)。

创建好工程后,编写测试应用程序。

/*mainwindow.h文件*/
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QPushButton>
#include <QTextBrowser>
#include <QFontDatabase>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
  Q_OBJECT

public:
  MainWindow(QWidget *parent = nullptr);
  ~MainWindow();

private:
  Ui::MainWindow *ui;
  QPushButton *pPushButton_Test1;
  QPushButton *pPushButton_Test2;
  QTextBrowser *pTestBrowser;

private slots:
  void pPushButton_Test1_clicked(void);
  void pPushButton_Test2_clicked(void);
};
#endif // MAINWINDOW_H

/*mainwindow.cpp文件*/
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
  : QMainWindow(parent)
  , ui(new Ui::MainWindow)
{
  ui->setupUi(this);

  /*实例化对象*/
  pPushButton_Test1 = new QPushButton(this);
  pPushButton_Test1->setText("测试按钮1");
  pPushButton_Test2 = new QPushButton(this);
  pPushButton_Test2->setText("测试按钮2");
  pTestBrowser = new QTextBrowser(this);

  /*设置位置*/
  pPushButton_Test1->setGeometry(10,10,150,50);
  pPushButton_Test2->setGeometry(10,80,150,50);
  pTestBrowser->setGeometry(200,10,500,250);

/*字体库路径设置、ubuntu里面不用打开,arm里面需要打开,否则会找不到字库的位置
* /etc/fonts/DroidSansFallback.ttf - 是我开发板文件系统里面字库的位置
*/
#if 1
  int id = QFontDatabase::addApplicationFont("/etc/fonts/DroidSansFallback.ttf");
  QString msyh = QFontDatabase::applicationFontFamilies (id).at(0);
  QFont font(msyh,10);
  font.setPointSize(20);
  this->setFont(font);
#endif
  /*关联信号与槽*/
  connect(pPushButton_Test1,SIGNAL(clicked()),this,SLOT(pPushButton_Test1_clicked()));
  connect(pPushButton_Test2,SIGNAL(clicked()),this,SLOT(pPushButton_Test2_clicked()));
}

MainWindow::~MainWindow()
{
  delete ui;
}

void MainWindow::pPushButton_Test1_clicked(void)
{
  pTestBrowser->append("测试按钮1被点击!");
}
void MainWindow::pPushButton_Test2_clicked(void)
{
  pTestBrowser->append("测试按钮2被点击!");
}

编写完成之后,Debug那里选择要使用kits。

选择ARM架构的开发套件编译之后的可执行文件是ARM架构,可以在arm开发板上运行,选择x86架构的开发套件可执行文件是x86架构,直接可以在ubuntu里面或者windows里面运行,这里我们选择ARM架构的套件。

选好之后,在菜单栏构建->build All Projects;

最下面状态栏点击4编译输出,出现下列提示,则说明编译成功。

个人感觉可以先选择x86的开发套件,在windos下直接运行,看看效果,然后在选择arm架构的套件编译。
注意:选择arm架构的开发套件生成的可执行文件是无法直接运行的,因为你的机器(电脑)是x86架构。
进入qt的工程目录下面,查找最后生成的可执行文件:

进入到build-test_demo-ARM_Qt5_12_9-Debug目录里面:

ls
file test_demo

当然,你也可以使用qmake 、make,生成可执行文件。
文件类型是32位ARM结构的可执行文件,那就没错了。

至此,Qt测试应用程序就做好了。

2.5 移植qt到开发板文件系统

2.5.1 拷贝库文件到开发板文件系统

我这里用的是SD卡启动,内核、设备树、根文件系统都在SD卡里面。

1、将qt源码目录下arm-qt文件拷贝到开发板根文件系统/usr/lib/下面。

sudo cp -rvf arm-qt /media/wx/rootfs/usr/lib/

我这里SD卡的分区2(存放的根文件系统)已经挂载到ubuntu的/media/wx/rootfs/下面了,故这里直接拷贝即可,注意要加上sudo权限。

2、将tslib库文件也拷贝到开发板根文件系统/usr/lib/下面

arm-qt、arm-tslib都是前面编译好的文件。

3、将font字体文件拷贝到开发板根文件系统/etc/font文件夹下面
/etc/下没有这个文件夹你就创建一个。

4、将qt测试应用程序拷贝到开发板根文件系统/temp文件夹下面
其他文件夹应该也行,我这里是拷贝到/temp

特别注意:这里是指开发板的根文件目录下面,不要拷贝你ubuntu的根目录下面,不然就尴尬了。

2.5.2 修改开发板/etc/profile,添加环境变量

前面你把这些库文件都添加进去了,不添加环境变量系统是找不到的。

#!/bin/sh
LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH

export TERM=vt100
export TERMINFO=/usr/share/terminfo

export TSLIB_FBDEVICE=/dev/fb0
export TSLIB_ROOT=/usr/lib/arm-tslib
export TSLIB_CONSOLEDEVICE=none
export TSLIB_FBDEVICE=/dev/fb0
export TSLIB_TSDEVICE=/dev/input/event1
export TSLIB_CONFFILE=$TSLIB_ROOT/etc/ts.conf
export TSLIB_PLUGINDIR=/lib/ts
export TSLIB_CALIBFILE=/etc/pointercal

export QT_ROOT=/usr/lib/arm-qt
export QT_QPA_GENERIC_PLUGINS=tslib:/dev/input/event1
export QT_QPA_PLATFORM_PLUGIN_PATH=$QT_ROOT/plugins
export QT_QPA_PLATFORM=linuxfb:tty=/dev/fb0
export QT_PLUGIN_PATH=$QT_ROOT/plugins
export LD_LIBRARY_PATH=$QT_ROOT/lib:$QT_ROOT/plugins/platforms
export QML2_IMPORT_PATH=$QT_ROOT/qml
export QT_QPA_FB_TSLIB=1

export ALSA_CONFIG_PATH=/usr/share/arm-alsa/alsa.conf

export XDG_RUNTIME_DIR=/usr/lib/
export RUNLEVEL=3
export QT_QPA_FONTDIR=/etc/fonts/

上面是我profile里面的内容,简单说一吧,其实我也刚接触不是了解太多,不正确的地址请指正哈。
export TSLIB_ROOT=/usr/lib/arm-tslib //tslib的放的位置
export TSLIB_TSDEVICE=/dev/input/event1 //触摸屏的设备文件
export TSLIB_CONFFILE=$TSLIB_ROOT/etc/ts.conf //tslib库的配置文件
export QT_ROOT=/usr/lib/arm-qt //qt源码库的位置
export QT_QPA_GENERIC_PLUGINS=tslib:/dev/input/event1 //qt程序触摸对应的设备文件,我就是因为没有加这个导致qt程序运行起来后,无法触摸点击,鼠标是可以动
export QT_QPA_FONTDIR=/etc/fonts/ //字体库的位置、其他位置应该也可以
好了,到这里差不多了。

 

三、测试

将SD插入开发板中,设置开发板从SD启动。

进入/temp目录里面,执行test_demo
cd /temp/
./test_demo & /&是后台运行/

可以看到中文显示和触摸点击都ok!大功告成。
还有一点:
你编译qt编码的交叉编译器必须和编译qt测试程序的编译器一致,不然可能会有问题。

关于嵌入式QT移植的实现的文章就介绍至此,更多相关嵌入式QT移植内容请搜索编程宝库以前的文章,希望以后支持编程宝库

 一、类和对象、this指针OOP语言的四大特征是什么?抽象封装、隐藏继承多态类体内实现的方法会自动处理为inline函数。类对象的内存大小之和成员变量有关类在内存上需要对齐,是 ...