Qt5.3.0的安装与测试(交叉编译,用于arm,支持tslib触摸屏)
本次移植可以使用触摸屏。
首先下载源码包:
http://download.qt.io/official_releases/qt/
由于我之前pc机安装的是5.3.0,因此这里也下载linux的5.3.0
我选择的是:
qt-everywhere-opensource-src-5.3.0.tar.xz
下载地址(http://download.qt.io/official_releases/qt/5.3/5.3.0/single/)
接下来解压文件:
xz –d qt-everywhere-opensource-src-5.3.0.tar.xz
得到qt-everywhere-opensource-src-5.3.0.tar 继续解压:
tar –xvf qt-everywhere-opensource-src-5.3.0
进入qt目录,修改配置文件。本人是s3c2440arm9指令集是armv4t。
修改源码包目录下的/qtbase/mkspecs/linux-arm-gnueabi-g++/qmake.conf文件:
MAKEFILE_GENERATOR = UNIX
CONFIG += incremental
QMAKE_INCREMENTAL_STYLE = sublib
/********************************新加入***************************/
QT_QPA_DEFAULT_PLATFORM = linuxfb
QMAKE_CFLAGS_RELEASE +=-O2 -march=armv4t
#这里指出指令局。跟芯片有关系,根据芯片改正-march=? -O2是编译器的优化等级
QMAKE_CXXFLAGS_RELEASE +=-O2 -march=armv4t
include(../common/linux.conf)
include(../common/gcc-base-unix.conf)
include(../common/g++-unix.conf)
# modifications to g++.conf
QMAKE_CC = arm-linux-gcc //修改编译工具因人而异,后面的几个也要改
QMAKE_CXX = arm-linux-g++
QMAKE_LINK = arm-linux-g++
QMAKE_LINK_SHLIB = arm-linux-g++
# modifications to linux.conf
QMAKE_AR = arm-linux-ar cqs
QMAKE_OBJCOPY =arm-linux-objcopy
QMAKE_NM = arm-linux-nm -P
QMAKE_STRIP = arm-linux-strip
load(qt_config)
修改完毕后保存退出,并在qt-everywhere-opensource-src-5.3.0/目录下为方便配置建立一个autoconfig.sh文件,内容为:
[email protected]:~/work/qt-everywhere-opensource-src-5.3.0$vi autoconfig.sh
#!/bin/sh
./configure \
-v \
-prefix/work/tools/qt5 \
-release \
-make libs \
-xplatform linux-arm-gnueabi-g++\
-optimized-qmake\
-pch \
-qt-sql-sqlite \
-qt-libjpeg \
-qt-zlib \
-no-opengl \
-no-sse2 \
-no-openssl \
-no-nis \
-no-cups \
-no-glib \
-no-iconv \ #应该要加上,不然提示iconv_openfailed
-no-xcursor-no-xfixes -no-xrandr -no-xrender \
-no-separate-debug-info\
-nomake examples-nomake tools \
-I/work/tools/tslib/include \ #这是是tslib的安装目录。因人而异
-L/work/tools/tslib/lib #注意连接符与文字之间必须有空格
exit
上面的这些内容就是告诉qt需要哪些模块,不需要那么模块,及其安装路径等等具体的可以输入./configure --help查看。
设置完成后,运行:
./autoconfig.sh
这里将会提示是否使用开源版本。及其是否接受条约。(第一个选择 o 第二个选择 yes)
完成后就可以:
make
出现了错误:
Project ERROR:Unknown module(s) in QT: quick-private
make[2]: ***[sub-quickwidgets-make_first-ordered] 错误 3
make[2]:正在离开目录 `/home/jason/work/qt-everywhere-opensource-src-5.3.0/qtdeclarative/src‘
make[1]: ***[sub-src-make_first] 错误 2
make[1]:正在离开目录`/home/jason/work/qt-everywhere-opensource-src-5.3.0/qtdeclarative‘
make: ***[module-qtdeclarative-make_first] 错误 2
根据:https://qt.gitorious.org/qt/qtdeclarative/commit/f0ecb4c1fa432175a16570216e517efdeaaf1f42
按照上面的解释说:quickwidgets模块依赖quick模块,quick模块有依赖openGL
有两种解决办法(本人使用方法一):
(1)
/ qtdeclarative/examples/quick/quick.pro的文件里的29行30行的
SUBDIRS +=embeddedinwidgets \
quickwidgets
改成:
SUBDIRS+= embeddedinwidgets
qtHaveModule(quickwidgets): SUBDIRS +=quickwidgets
在/ qtdeclarative/src/src.pro文件的第18行
qtHaveModule(widgets):SUBDIRS+= quickwidgets
改成:
qtHaveModule(quick):qtHaveModule(widgets): SUBDIRS += quickwidgets
(2)将autoconfig.sh中的:
-no -opengl去掉(也就是说在./configure不要添加参数-no -opengl)
(本人并未测试方法2的可行性,只是猜测)
然后继续:make
make成功后:
make install
安装完后会在安装目录生成(我的是/work/tools/qt5):
在linux上添加环境变量sudo vi /etc/environment
就是在原来的后面加上:/work/tools/qt5/bin (注意有冒号)
我在板子的根文件系统里建立一个tools/qt5的文件目录
在qt的安装目录(我的是/work/tools/qt5)下的/bin/目录下有编译个执行程序qmake,但是由于
ubuntu本身已经安装好了qt,所以用编译ubuntu本身的qmake,这就导致不一样的额命令有一样的名字,这里可以给交叉编译的qmake改一
个名字,取名qmake-arm
mv qmake qmake-2440
接下来我们为了使用tslab较正的触摸屏,需要做一个支持tslab较正的触摸屏的工作,为了使用tslib,官方的说明是这样的:
对于一些支持单触点的电阻屏,一般不再依赖linux的多触点的事件设备的协议。而使用tslib返回的较正触摸屏的值
进行触控。相比那么没有使用tslib的设备,在运行的时候可以指定-plugin tslib而不是 -plugin
evdevtouch来设置使用触摸屏。
此时我们要做的就是目录:
cd qt-everywhere-opensource-src-5.3.0/qtbase/src/plugins/generic/tslib
执行qmake-2440
然后执行make
接下来会提示一个错误:
/work/tools/cr-ng-2440/lib/gcc/arm-class-linux-gnueabi/4.9.1/../../../../arm-class-linux-gnueabi/bin/ld.bfd:cannot find -lts
collect2: error: ld returned 1 exit statu
这个错误比较显然。就是缺少libts.so这个库文件
其实,在编译的时候只要是提示:
cannot find –lxxxx就说明是找不到libxxxx.so
实际上libts.so是在编译tslab的时候生成的,在tslib的安装目录下的lib目录下有:
[email protected]:/work/tools/tslib/lib$ ll
total 32
drwxrwxr-x 4 hello hello 4096 5月 30 21:36 ./
drwxrwxr-x 6 hello hello 4096 5月 30 21:36 ../
lrwxrwxrwx 1 hello hello 18 5月 30 21:36 libts-0.0.so.0 ->libts-0.0.so.0.1.1*
-rwxr-xr-x 1 hello hello 10286 5月 30 21:36libts-0.0.so.0.1.1*
-rwxr-xr-x 1 hello hello 942 5月 30 21:36 libts.la*
lrwxrwxrwx 1 hello hello 18 5月 30 21:36 libts.so ->libts-0.0.so.0.1.1*
drwxrwxr-x 2 hello hello 4096 5月 30 21:36 pkgconfig/
drwxrwxr-x 2 hello hello 4096 5月 30 21:36 ts/
可以看到实际上已经有libts.so这个库文件了,该文件指向的是libts-0.0.so.0.1.1,因此我们把libts.so拷贝到交叉编译工具链的库目录就可以,执行:
在tslib/lib目录下执行:
sudo cp libts-0.0.so.0.1.1 /work/tools/cr-ng-2440/arm-class-linux-gnueabi/sysroot/lib/libts.so
其中/work/tools/cr-ng-2440/是我的交叉编译工具链的安装目录
(注意将libts-0.0.so.0.1.1拷贝的时候重命名为libts.so,也可以建立软连接)
make完毕后,就可以执行make install
执行完毕后就可以在qt的安装目录看到生成的支持tslib的库了,比如我的qt的安装目录为:
/work/tools/qt5/。那么可以看到libqtslibplugin.so:
[email protected]:/work/tools/qt5/plugins/generic$ls
libqevdevkeyboardplugin.so libqevdevtabletplugin.so libqtslibplugin.so
libqevdevmouseplugin.so libqevdevtouchplugin.so
将安装好的qt5.3.0里面的lib和 plugins拷贝到根文件系统目录中的tools/qt5目录下
进入qt的安装目录我的拷贝命令是:
cp /lib /work/root/tools/ -r
cp /plugins /work/root/tools/ -r
然后在板子的文件系统添加环境变量修改 /etv/profile文件,加入:
exportTSLIB_TSDEVICE=/dev/input/event0
export TSLIB_CONFFILE=/etc/ts.conf
export TSLIB_PLUGINDIR=/lib/ts
export TSLIB_CALIBFILE=/etc/pointercal
export TSLIB_CONSOLEDEVICE=none
export TSLIB_FBDEVICE=/dev/fb0
export QTDIR=/tools
exportLD_LIBRARY_PATH=/tools/lib:$LD_LIBRARY_PATH:/lib
export POINTERCAL_FILE=/etc/pointercal
exportQT_QPA_GENERIC_PLUGINS=tslib,evdevmouse:/dev/input/mice
#exportQT_QPA_FONTDIR=/tools/lib/fonts
exportQT_QPA_PLATFORM_PLUGIN_PATH=/tools/plugins
export QT_QPA_EGLFS_FB=/dev/fb0
exportQT_QPA_PLATFORM=linuxfb:fb=/dev/fb0,size=480x272,tty=/dev/tty0
export LD_PRELOAD=/lib/libts.so
(需要支持触摸屏需要之前生成libqtslibplugin.so)
qt5之前的版本都是使用的QWS ,现在使用的是platformplugins,官网的说明是这样的:
With the releaseof Qt 5.0, Qt no longer contains its own window
system implementation: QWS isno longer a supported platform. For
single-process use cases, the Qt
Platform Abstraction is a superiorsolution. Multiple graphical processes will be supported through Wayland.
There are multiple platform plugins that are potentially usable onEmbedded Linux systems: EGLFS,LinuxFB,
KMS, DirectFB,
Wayland. Theavailability of these depend on the configuration of Qt.
The default platformplugin is also device specific. For instance, on
many boards eglfs will bechosen as the default one. If the default is
not suitable, the QT_QPA_PLATFORM environment
variable parameter can be used to request anotherplugin. Alternatively, for quick tests, the -platform command-linecan be used with the same syntax.
上面一大堆就是说,qt程序在可用环境变量QT_QPA_PLATFORM制定使用的平台,当然也可以在命令行使用-platform来指定。
下面大概介绍一个这些变量的含义,详细的请看官方的说明:
http://doc.qt.io/qt-5/embedded-linux.html
下面来大概说一下各个变量的含义:
LD_LIBRARY_PATH=指向库文件的路径
POINTERCAL_FILE指向库tslib生成的校正文件。
QTDIR这是qt在板子的安装目录,加不加无所谓,加上只是为了后面设置方便而已
QT_QPA_FONTDIR字库文件所在地
QT_QPA_PLATFORM_PLUGIN_PATH //插件路径,必须写,不然报错
QT_QPA_EGLFS_FB 显示器 默认的就是/dev/fb0
QT_QPA_PLATFORM 指示的是Linux的系统类型,这里我们选的的是linuxfb
LD_PRELOAD 指向的程序连接库
接下俩就可以编写测试代码了,在linux编写代码:
////文件qtText.cpp
#include <QtWidgets/QApplication>
#include <QtWidgets/QLabel>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QLabel *label = new QLabel("Hello QT!");
label->show(); //显示一个label
return app.exec();
}
然后就可以编译代码了。在代码所在目录执行:
qmake-2440 -project //生成project文件
qmake-2440 //使用默认参数-makefile 生成Makefile文件
make
至于后面参数的含义可以使用qmake-2440 –help来查看
假如make的时候有提示找不到一些库文件:
qt_test1.cpp:(.text.startup+0x20):undefined reference to `QApplication::QApplication(int&, char**, int)‘
qt_test1.cpp:(.text.startup+0x64):undefined reference to `QPushButton::QPushButton(QString const&, QWidget*)‘
qt_test1.cpp:(.text.startup+0x74):undefined reference to `QWidget::show()‘
qt_test1.cpp:(.text.startup+0x78):undefined reference to `QApplication::exec()‘
qt_test1.cpp:(.text.startup+0x84):undefined reference to `QPushButton::~QPushButton()‘
qt_test1.cpp:(.text.startup+0x8c):undefined reference to `QApplication::~QApplication()‘
qt_test1.cpp:(.text.startup+0xa4):undefined reference to `QApplication::~QApplication()‘
qt_test1.cpp:(.text.startup+0xb0):undefined reference to `QPushButton::~QPushButton()‘
qt_test1.cpp:(.text.startup+0xbc):undefined reference to `QPushButton::~QPushButton()‘
qt_test1.cpp:(.text.startup+0xd8):undefined reference to `QPushButton::staticMetaObject‘
collect2: error: ld returned 1 exit status
make: *** [qt_test1] 错误 1
这里可以在生成的Makefile里添加需要连接的库,本次用到的label或者pushbutton等都是继承的Widget类一次需要添加该类的库:
在makefile的
LIBS = $(SUBLIBS) -L/work/tools/qt5/lib -lQt5Gui -lQt5Widgets-L/work/tools/tslib/lib-lQt5Core -lpthread
(红色的为添加部分。添加上-lQt5Widgets)
或者也可以设置环境变量的值SUBLIBS):
export SUBLIBS=-lQt5Widgets (对应上面那个黄色背景文字)
为了不再麻烦,可以在ubuntu下的/etc/profiles里面加上:
export SUBLIBS=-lQt5Widgets
接下俩就是将生成的qtTest拷贝到开发板中运行
./qtTest -platform linuxfb -plugin tslib
假如运行有提示:
Illegal instruction (非法指令)
这里很可能是因为对芯片的指令集没有选择好,本人用的是s3c2440那么 /qtbase/mkspecs/linux-arm-gnueabi-g++/qmake.conf文件加入的是:
-march=armv4t
这里假如有提示:
QFontDatabase: Cannot findfont directory /work/tools/qt5/lib/fonts – is Qt installed correctly?
这里是提示找不到字库文件。一般情况下只要设置好环境变量:
export QT_QPA_FONTDIR =/tools/qt5/lib/fonts
就不应该出现这种问题,主要是我安装的时候指定了安装目录为/work/tools/qt5,但是我拷贝到板子的时候是/tools/qt5,这个问题暂时没有找到更好的解决办法,我只好在开发板的文件系统里建立这个文件目录:
mdkir /work/ tools/qt5/lib/fonts
然后将库文件拷贝进去
但是看到有人说可以在代码中指定文件目录:
QGuiApplication app(argc, argv);
QQuickViewview; // Load the embedded font.
QString fontPath = ":/fonts/MyFont.ttf";
int fontId =QFontDatabase::addApplicationFont(fontPath);
if (fontId != -1)
{
QFont font("MyFont");
app.setFont(font);
}
(参考http://w3facility.org/question/static-qt5-build-on-linux-how-to-handle-fonts-when-deploying/)
这里假如有提示:
QIconvCodec::convertFromUnicode: usingLatin-1 for conversion, iconv_open failed
QIconvCodec::convertToUnicode: using Latin-1for conversion, iconv_open failed?
这是因为在./configure的时候没有添加-no-iconv 也就是在autuconfig.sh添加上-no-iconv
\ 就可以,假如没加上,qt会使用QIconvCodec类进行编码的转换,而qt本身不再使用该类,所以不要使用该库。当然也可以下载去这个网址http://ftp.gnu.org/gnu/libiconv/下载libiconv来安装该库
后来看帮组文档,有QWidget::setFont函数结合QFont::setPointSize函数,或者QApplication::setFont函数设子字体,其中的参数不同具体的可看参阅帮组文档。
之所以不显示中文,主要是字库问题。这里可以随便从window系统里面拷贝一个字库文件(需要支持中文)放到把板子的字库目录下就可以,然后用setFont设置所要使用的字库。
(比如我在windows的C:\Windows\Fonts\STKAITI.TTF字库文件拷贝到我的开发板的work/tools/qt5/lib/fonts/目录下,win下没有的话下载一个就可以)
我的测试程序为:
#include<QtWidgets/QApplication>
#include<QtWidgets/QPushButton>
#include<QtWidgets/QVBoxLayout>
//#include<QtCore/QIODevicea>
#include<QtCore/QTextCodec>
int main(int argc,char **argv)
{
QApplication app(argc, argv);
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
// QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
// QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
app.setFont(QFont("STKAITI",80));
// QFont font;
// font.setPointSize(60);
//QMessageBox::information(this, QString::fromLocal8Bit("提示"),QStringLiteral("中文显示"));
// app.font(font);
QWidget *window = new QWidget;
// window->setFont(font);
QPushButton *button1 = newQPushButton("可以显示数字1");
QPushButton *button2 = newQPushButton("可以显示英语hello");
QPushButton *button3 = newQPushButton(QStringLiteral("这样也可以"));
QPushButton *button4 = newQPushButton(QString::fromStdWString(L"这样也可以"));
QPushButton *button5 = newQPushButton(QString::fromLocal8Bit("这样也可以的哦"));
button1->setMinimumSize(200,45);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(button3);
layout->addWidget(button4);
layout->addWidget(button5);
window->setLayout(layout);
window->setMinimumSize(450,250);
window->show();
return app.exec();
}下面进一步解释:
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));这句设置编码格式。linux下文件的编码格式是UTF-8,windows下为其他。Qt可以设置的编码格式有:
Apple Roman Big5 Big5-HKSCS CP949 EUC-JP EUC-KR
GB18030-0 IBM 850 IBM 866 IBM 874 ISO 2022-JP ISO 8859-1 to 10
ISO 8859-13 to16 Iscii-Bng, Dev, Gjr, Knd, Mlm, Ori,Pnj, Tlg, and Tml
JIS X 0201 JIS X 0208 KOI8-R KOI8-U Shift-JIS
TIS-620 TSCII UTF-8 UTF-16
UTF-16BE UTF-16LE UTF-32 UTF-32BE
UTF-32LE Windows-1250 to 1258
这里只需要知道linux下的问UTF-8,其他的查阅相关资料就可以。
app.setFont(QFont("STKAITI", 80));这句话是设置所需的字库及其显示字体的大小,数值越大显示的字体也就越大。这里设置的字库是"STKAITI",那么程序就会想字库目录找本字库文件。
这里使用QStringLiteral和 QString::fromStdWString函数,在linux均不需要设置文件的编码格式就可以直接显示中文,也就是说使用这两个函数不需要使用:
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));来设置linux下的文件编码格式。
但是众所周知,在windows下直接使用QString::fromLocal8Bit得到的string就可以直接显示出汉字,但是在linux下,假如想使用(QString::fromLocal8Bit得到的string显示出来就必须使用:
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));来设置linux下的文件编码格式。
总结一句话,汉字出问题大概是字库选的不对。
参考:
http://lists.busybox.net/pipermail/buildroot/2013-March/068037.html
https://bbs.archlinux.org/viewtopic.php?id=156189
http://blog.csdn.net/u013000434/article/details/17047773
http://www.embedu.org/column/Column415.htm
http://www.friendlyarm.net/forum/topic/439
http://qt-project.org/forums/viewthread/10466
http://blog.csdn.net/zhaocj/article/details/38065857
http://www.qtcn.org/bbs/read-htm-tid-55852.html
http://blog.csdn.net/wisape/article/details/38494005
http://blog.csdn.net/zhx6044/article/details/38373687#comments