Qt移植學習之路 QT4.5.3至mini2440
本文介紹的是Qt移植學習之路 QT4.5.3至mini2440,終于成功移植QT 4.5.3至mini2440,并能運行QT自帶的應用程序,總得來說還算很順利,下面是我移植的全部過程。
首先,我交待一下我的開發(fā)環(huán)境:
宿主機:Fedora9
主機Gcc:gcc 版本 4.3.0 20080428 (Red Hat 4.3.0-8) (GCC)
交叉編譯器:arm-linux-gcc-4.3.2 (友善光盤自帶)
開發(fā)板:mini2440(NAND 128M SDRAM 64M)
移植步驟:
1.準備源碼包
從ftp://ftp.qt.nokia.com/qt/source/ 下載:qt-embedded-linux-opensource-src-4.5.3.tar.gz和
qt-x11-opensource-src-4.5.3.tar.gz
前者是移植到開發(fā)板上運行的,后者是方便在X86機上開發(fā)應用程序,待一切調試成功再經(jīng)交叉編譯后下載到開發(fā)板上運行。
從網(wǎng)上下載tslib-1.4.tar.gz包,這包用于管理觸摸屏,例如可用于它來校正觸摸屏,并保存校正數(shù)據(jù)。
2.編譯安裝tslib-1.4
把tslib-1.4 COPY到Fedora9的 /opt下,在Fedora9的終端下執(zhí)行:
- #cd /tmp
- # tar zxvf tslib-1.4.tar.gz ――――――――(最后在/tmp下解壓生成tslib)
- #cd tslib
- #./autogen.sh
- #./configure --prefix=/home/mytslib/ --host=arm-linux ac_cv_func_malloc_0_nonnull=yes
- #make
- #make install
成功后可在/home下生成mytslib,進入mytslib可以看到有bin include lib etc四個文件夾。我們暫時先不理它,在接下來的移植過程中才用到這些文件夾。
3. 編譯安裝QT-X11-4.5.3
QT-X11-4.5.3是運行于linux平臺下用于仿真QT應用程序的軟件,這樣你便可以在linux平臺下把你應用程序都調試好,然后再利用QT4.5.3把應用程序編譯成ARM版本下載至開發(fā)板,這樣你就可以在開發(fā)板上運行你的QT應用程序了。
下面是安裝步驟:
首先把qt-x11-opensource-src-4.5.3.tar.gz 拷貝到Fedora9下的/tmp目錄下,接著執(zhí)行:
- #tar zxvf qt-x11-opensource-src-4.5.3.tar.gz
- #cd qt-x11-opensource-src-4.5.3
- #./configure
- #gmake //一般用時2-3小時,如果你的機子配置不太低的情況下
- #gmake install
安裝OK后,在/usr/local/目錄下生成Trolltech目錄,這就是我們要用于在x86平臺(Fedora9)下開發(fā)應用程序時所依賴的一些目錄。現(xiàn)在你可以進入/usr/local/Trolltech/Qt-4.5.3/examples下,進入一個例子,比如進入/usr/local/Trolltech/Qt-4.5.3/examples/widgets/analogclock下,你會發(fā)現(xiàn),這個例子都已經(jīng)編譯好了,在Fedora9的終端下直接運行:
- #./analogclock –qvfb
則在Fedora9的屏幕上出現(xiàn)下圖:
也許你會想,我是否能重新編譯一遍analogclock呢?因為analogclock目錄下有一個Makefile,于是執(zhí)行:
- #make clean
- #qmake –project
唉,你會發(fā)現(xiàn),提示說找不到命令“qmake”,怎么辦呢?很簡單,因為我們還沒有設置環(huán)境變量,當然會找不到命令啦。
讓我們來設置一下QT-X11-4.5.3的環(huán)境變量,首先進入你的安裝QT-x11-4.5.3目錄:
- #cd /opt/qt-x11-opensource-src-4.5.3
在此目錄下建立一個名為:qt_x11_setenv.sh的shell文件,內容如下:
- #!bin/bash
- PATH=/usr/local/Trolltech/Qt-4.5.3/bin:$PATH
- QTDIR=/usr/local/Trolltech/QT-4.5.3
- MAINPATH=$QTDIR/man:$MAINPATH
- LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
- export PATH QTDIR MAINPATH LD_LIBRARY_PATH
- echo " set qt-x11 env. successful "
保存退出,在終端執(zhí)行:
- #source qt_x11_setenv.sh
終端回顯:set qt-x11 env. successful
- #echo $QTDIR
終端回顯:/usr/local/Trolltech/QT-4.5.3 ――――――說明:環(huán)境變量設置成功。
在這之后,我們再執(zhí)行一下:
- #qmake –project (建立*.pro文件)
- #qmake (產生Makefile文件)
- #make (編譯產生可執(zhí)行程序)
如果沒有錯誤將生成analogclock可執(zhí)行程序,終端執(zhí)行:
- #./analogclock –qvfb
看看是否出現(xiàn)畫面了~~~~~~~~~~
注意一點:
在每次進入qt-x11-linux-opensource-src-4.5.3目錄中要 #source setenv-x11.sh
把環(huán)境變量設置好,否則又會出現(xiàn)無法編譯。
成功后,是不是有點迫不及待地想自己試驗一個QT程序呢,讓我們來編寫一個hello程序吧!
- #cd qt-x11-linux-opensource-src-4.5.3/ /opt/qt-x11-opensource-src-4.5.3/examples/
- #mkdir hello
- #vi hello.cpp
然后把下列源程序COPY到hello.cpp中。
- #include <QApplication>
- nclude <QPushButton>
- int main(int argc, char *argv[])
- {
- QApplication app(argc,argv);
- QPushButton b("Hello World !");
- b.show();
- QObject::connect(&b,SIGNAL(clicked()),&app,SLOT(quit()));
- return app.exec();
- }
進入前記得執(zhí)行source setenv-x11.sh
- # qmake –project (產生hello.pro文件)
- #qmake (產生Makefile文件)
- #make (執(zhí)行Makefile以生成可執(zhí)行程序)
如果不出錯在當前目錄下生成hello可執(zhí)行程序,既然生成了,那還等什么,執(zhí)行吧。
- #./hello –qvfb
我執(zhí)行后就出圖了,你的呢?
其實圖是可以拉大的,你試試!
4.編譯安裝QT4.5.3
首先我們建立兩個目錄用來存放接下來編譯出來的一些目標文件,在Fedora9的根目錄下建立mini2440 和 tslib兩個目錄,終端執(zhí)行:
- #cd /
- #mkdir mini2440
- #mkdir tslib
接下來我們把qt-embedded-linux-opensource-src-4.5.3.tar.gz COPY到/tmp下, 終端執(zhí)行:
- #cd /tmp
- #tar zxvf qt-embedded-linux-opensource-src-4.5.3.tar.gz
- #cd qt-embedded-linux-opensource-src-4.5.3
- #./configure -prefix /mini2440 -release -shared -fast -pch -no-qt3support -qt-sql-sqlite -no-libtiff -no-libmng -qt-libjpeg
- -qt-zlib -qt-libpng -qt-freetype -no-openssl -nomake examples -nomake demos -nomake tools -optimized-qmake -no-phonon -no-nis
- -no-opengl -no-cups -no-xcursor -no-xfixes -no-xrandr -no-xrender -no-xkb -no-sm -no-xinerama -no-xshape -no-separate-debug-info
- -xplatform qws/linux-arm-g++ -embedded arm -depths 16 -no-qvfb -qt-gfx-linuxfb -no-gfx-qvfb -no-kbd-qvfb -no-mouse-qvfb -qt-kbd-usb
- -confirm-license -qt-mouse-tslib -I/home/mytslib/include -L/home/mytslib/lib
上面最后一句“-I/home/mytslib/include -L/home/ mytslib/lib ”指明我們剛才編譯出來觸摸屏的庫文件及頭文件存放路徑。它前面的“-qt-mouse-tslib”表示將使用觸摸屏。
然后執(zhí)行:
- #gmake
- #gmake install
上面編譯時間較長,一般要2到3個小時。
這樣,嵌入式版本的qt4裝成功了,若想進行交叉編譯,首先也得改變環(huán)境變量,所以也可以在當前目錄下建一個環(huán)境變量的文件setenv-embedded.sh 如下:
- #gedit setenv-embedded.sh
這時跳出一個編輯文本輸入:
- PATH=/mini2440/bin:$PATH
- QTDIR=/mini2440
- MAINPATH=$QTDIR/man:$MAINPATH
- LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
- export PATH QTDIR MAINPATH LD_LIBRARY_PATH
保存退出。每次進行qt4-embedded的交叉編譯前先# source setenv-embedded.sh,注意我們在編譯QT應用程序時要用到上述變量。下文會提到。
#p#
4. 移植相關庫文件至開發(fā)板
首我們得準備一個文件系統(tǒng),我是根據(jù)友善提供的文檔制作了一個文件系統(tǒng),路徑為/opt/studyarm/rootfs, 其中rootfs就是我的根文件系統(tǒng)。
首先在rootfs 的根目錄下建立兩個目錄:
在開發(fā)板的終端下執(zhí)行:
- #cd /
- #mkdir mini2440
- #mkdir tslib
接下來我們要COPY我們剛才編譯生成的一些庫文件及配置文件至開發(fā)板上的mini2440, tslib。我是用NFS方式掛載文件系統(tǒng)的,當然你可以用其它下載方式把目標庫文件等下載到你的開發(fā)板就行。
因為是用NFS掛載方式,所以我在Fedora9終端上執(zhí)行:
- #cp –rf /home/mytslib/lib /opt/studyarm/rootfs/tslib/
- #cp –rf /home/mytslib/etc /opt/studyarm/rootfs/tslib/
- #cp –rf /mini2440/lib /opt/studyarm/rootfs/mini2440/
- #cp –rf /home/mytslib/etc /opt/studyarm/rootfs/tslib
- #cp /home/mytslib/bin/ts_calibrate /opt/studyarm/rootfs/bin
- #cp /home/mytslib/bin/ts_test /opt/studyarm/rootfs/bin
- 編輯開發(fā)板/etc/profile,用來在在開發(fā)板上設置環(huán)境變量,開發(fā)板終端輸入內容如下:
- Cat >> /etc/profile/ << EOF
- (當然也可以一個一個變量敲入,但是這種方法設置的變量在斷電重新上電后又得設置一遍很麻煩,所以把變量直接寫入/etc/profile后,系統(tǒng)啟動時會自動更新變量,很簡便)
- export QTDIR=/mini2440
- export T_ROOT=/tslib
- export PATH=$QTDIR/bin:$PATH
- export TSLIB_CONSOLEDEVICE=none
- export TSLIB_FBDEVICE=/dev/fb0
- export TSLIB_TSDEVICE=/dev/ event0
- export TSLIB_PLUGINDIR=$T_ROOT/lib/ts
- export TSLIB_CONFFILE=$T_ROOT/etc/ts.conf
- export TSLIB_CALIBFILE=/etc/pointercal
- export QWS_MOUSE_PROTO=tslib:/dev/event0
- export LD_LIBRARY_PATH=$T_ROOT/lib:$QTDIR/lib
- EOF
終端輸入上述變量設置后,再執(zhí)行一下:source /etc/profile使系統(tǒng)更新一遍剛設置的系統(tǒng)環(huán)境變量。
驗證變量設置是否成功:
在開發(fā)板終端下執(zhí)行:
#echo $QTDIR 如果顯示 #/mini2440,則說明設置成功了,在QT的移植過程中環(huán)境變量的設置是非常重要的,如果設置的不正確會出現(xiàn)很多問題。
比如說:在參考別人QT移植的文章時,有人環(huán)境變量設置與我的不同,主要有如下幾個:
- export TSLIB_FBDEVICE=/dev/input/fb0
- export TSLIB_TSDEVICE=/dev/input/event0
- export QWS_MOUSE_PROTO=tslib:/dev/input/event0
注意到?jīng)]有:他們的環(huán)境變量中,fb0,event0設備都在/dev/input下,而我查看了我的/dev下沒有input目錄,所以這點要根據(jù)自已所做文件系統(tǒng)的實際情況來設置這些變量。
接下來我們還得設置一下觸摸屏的配置文件ts.conf. 它在哪里呢?前面我們把mytslib下的etc目錄COPY到了開發(fā)板的/tslib/下,那么tslib一共就有bin及etc兩個目錄,而ts.conf就在etc目錄下,開發(fā)板下用vi /tslib/etc/ts.conf
把# module_raw collie 前面的“#”號去掉,然后把該行移至行首,最后我的配置文件如下:
- module_raw collie
- module pthres pmin=1
- module variance delta=30
- module dejitter delta=100
- module linear
自執(zhí)行source /etc/profile后,開發(fā)板的環(huán)境變量就完全設置好了,并且QT4.5.3的移植也基本完成了,這所以說基本,是因為現(xiàn)在可以運行QT程序了,但是還需要進一步的做一些移植,比如說字庫,中文顯示等等。接下來將驗證tslib及QT4.5.3是否移植成功。
5. 測試觸摸屏校正
在開發(fā)板終端下執(zhí)行:
- #ts_calibrate ---------觸摸較正程序
運行該程序后,屏幕將出現(xiàn)五點校正畫面,依次點擊五點后,將生成觸摸屏校正數(shù)據(jù)文件/etc/pointercal.
- #ts_test ----------觸摸屏拖曳測試程序
運行后屏幕出現(xiàn)drag,draw 依次選擇后進行測試,同時終端下出現(xiàn)拖曳后的取點數(shù)據(jù)。
6.運行QT應用程序以驗證QT4.5.3是否移植成功
我們要編譯一些例子程序,同時將它們下載至開發(fā)板運行。
在終端下首先檢測一下環(huán)境變量,因為在qt-embedded-linux-opensource-src-4.5.3下編譯應用程序要依賴于它所生成的一些庫,我們在前面第3步,不是在主機/mini2440下生成了一些庫和其它文件么?其中/mini2440/lib我們移植到了開發(fā)板,這些庫和其它目錄中的文件我們編譯QT應用程序時也是要依賴它們的,所以環(huán)境變量路徑是否設置正確直接影響應用程序編譯是否成功。
主機終端執(zhí)行:
#echo $QTDIR ――――回顯為“/mini2440”則說明環(huán)境變量設置OK,如果回顯為空,或者為其它路徑,則要source setenv-embedded.sh一下,不明白的請回到第3步再看一遍。
環(huán)境變量測試沒問題,那么就可以編譯QT程序了。
- #cd ……/ qt-embedded-linux-opensource-src-4.5.3/ examples/mainwindows/application/
- #qmake –project (如果提示無“qmake”命令,則肯定是你的環(huán)境變量的路徑設置不正確,或者source setenv-embedded.sh一下即可)
- #qmake (成生Makefile)
- #make (生成可執(zhí)行程序)
至此,如果你沒發(fā)生什么錯誤應該可以在application下看到“application”的可執(zhí)行程序了,把它下載到你的開發(fā)板下并執(zhí)行:
- #./application –qws
現(xiàn)在可以看到屏幕上的對話框了吧?可能顯示的不是很“正”,(但可以用觸摸筆把它拖到屏中央),并且字也不是看得很清。
你可以編譯其它自帶的例子運行試試看。
接下來的工作就是如何把修正字體等其它工作。但初步移植算是成功了。
7. QT自帶例子運行出現(xiàn)錯誤
編譯home/qt-4.5.3/qt-embedded-linux-opensource-src-4.5.3/examples/widgets/imageviewer
成功后,下載板子后運行,出現(xiàn):Segmentation fault,但多運行幾次發(fā)現(xiàn)可以運行,也就是說偶爾會出現(xiàn)不能運行的錯誤,這是一個經(jīng)典問題。很多文章介紹說是編譯器的問題。
有的網(wǎng)友說:EABI的編譯器編譯出來的Qt-4.5的程序都會出現(xiàn)段錯誤。原因不明。這個我不敢茍同,因為我試了很多自帶的例子,用帶EABI的編譯器arm-linux-gcc-4.3.2-EABI是可以運行的。
百度了一下,發(fā)現(xiàn)有價值的文章不多,下引自一網(wǎng)友的BLOG:http://zhubangbing.blog.163.com/blog/static/52609270200993015132315/
c/c++/qt中的段錯誤(segment fault)
關于內存的那些話就不說了,被一幫會裝會轉載的人說爛了,這里只說我在寫程序時遇到段錯誤的原因,如何解決的,總之一句話,涉及到指針的,你不能在未定義,未初始化,未 “new” 之前使用,否則等待你的肯定是 segment fault,然后程序直接退出
1. 類A在執(zhí)行中可能會幾次用到用到類B,也可能只有一次用到,也可能一次都不用,這種情況下我的習慣就是在類A的構造函數(shù)中初始化B類對象為NULL,然后在用的地方先判斷B是否實例化,未實例化,實例化,然后使用,delete B類對象時也要先判斷下B是否實例化
因為這里已經(jīng)初始化了類B的對象,使用時容易出的錯誤是在判斷是否實例化時,如果在判斷類本身是否實例化之前,判斷了(或者說使用了)類B的成員函數(shù)/成員變量,出現(xiàn)段錯誤,因為這個類不存在,其成員函數(shù)/變量也不存在
例子:
A 的構造函數(shù)中有這樣一句this->m_b = NULL;//將B類對象 m_b初始化為NULL ,此處B類為QThread的子類使用中
- void new_b()
- {
- if(!this->m_b)
- {
- this->m_b = new B;
- this->m_b->start();
- .....
- }
- }
- void delete_b()
- {
- if(this->m_b||this->m_b->isRunning())//delete B 類對象時判斷條件
- {
- while(!this->m_b->isFinished())
- {
- this->m_b->quit();
- this->m_b->wait(500);
- }
- delete this->m_b;
- this->m_b = NULL;
- }
- }
這樣使用時,在只調用一次delete_b()時,可能不會出問題,因為這個時候m_b可能已經(jīng)實例化了,所以程序只要判斷到 this->m_b 為真,就會認為if條件為真,然后往下執(zhí)行,但是問題是,如果調用了兩次 delete_b()或者在調用之前m_b沒有 new_b(),那么判斷時this->m_b為假,程序就會繼續(xù)判斷this->m_b->isRunning()是否為真,這就出現(xiàn)段錯誤了,因為m_b未 “new”
2.兩個線程共用緩存
我們的項目中音頻的發(fā)送和接收是用兩個線程實現(xiàn)的,線程的結束時間是不可控的,線程達到結束條件時肯定需要做清理工作,比如緩存的釋放,設備關閉,如果一個線程結束時沒有判斷另外一個是否結束,清理了共用的緩存,而另外一個線程又去訪問了這個緩存,就出現(xiàn)了段錯誤
在友善ARM9論壇上發(fā)現(xiàn)一篇可能可以解決段錯誤的文章:
http://www.arm9home.net/read.php?tid-2993-fpage-0-toread--page-2.html
程序 qt-embedded-linux-opensource-src-4.5.0/src/gui/embedded/qscreenlinuxfb_qws.cpp
作如下修改:
- 410行:
- /* //EmbedSky_del start 20091208
- canaccel = useOffscreen();
- if(canaccel)
- setupOffScreen();
- */ //EmbedSky_del end 20091208
- canaccel = false;
- 706行:
- /* //EmbedSky_del start 20091208
- if (canaccel) {
- *entryp=0;
- *lowest = mapsize;
- insert_entry(*entryp, *lowest, *lowest); // dummy entry to mark start
- }
- */ //EmbedSky_del end 20091208
- canaccel = false;
可能解決segmentation fault問題,請大家測試
[ 此帖被lpc2292在2010-03-24 14:37重新編輯 ]
有網(wǎng)友試驗過上面修改embedded/qscreenlinuxfb_qws.cpp的方法,并成功解決此錯誤,我暫時沒有去試,因為要重新編譯一遍QT,幾個小時下來,夠讓人等的。
下面引自一網(wǎng)友的文章,簡單的說明了一下段錯誤的產生原因,及調試方法。
qt 段錯誤,簡單調試方法
如果Qt程序不大也不小,有些地方難免會出現(xiàn)聲明指針后沒有具體實現(xiàn)的情況。這種情況下Qt在編譯階段是不會出現(xiàn)錯誤的,但是運行的時候會出現(xiàn)“段錯誤”,其他什么都不會顯示。
而段錯誤就是你的指針訪問了沒有分配地址的空間,或者是指針為NULL。
在這種情況下想快速確定是哪個地方出現(xiàn)的錯誤應該用gdb調試debug信息,但是我對那東西還不熟悉,還沒具體研究過(等我程序寫的大體像個樣子再說)。不過懶人我找到了一個簡單的方法......
在主程序中加入qDebug("Msg");一步一步跟蹤進實現(xiàn)函數(shù),就會知道到底是哪個地方出現(xiàn)問題了。這個東西還挺管用的,對于我這樣的初學者就足夠了。
小結:關于Qt移植學習之路 QT4.5.3至mini2440的內容介紹完了,希望本文對你有所幫助。