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文件,內容為:
jason@jason-virtual-machine:~/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目錄下有:
hello@hello-K42Jc:/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:
hello@hello-K42Jc:/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_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