文章主要内容有:先介绍下QtE,再说说我的QtE4.8.5移植。
Qtopia和QtE:
Qtopia和QtE是不同的!惭愧,刚开始着手移植工作的时候,没有搞清楚Qtopia和QtE的区别,再加上我用的是从一个离职很久的同事机器上翻出来的source code。弄得是各种混乱。
网友彬ye介绍:
值得特别注意的是在版本4之前,Qt/E和Qtopia是不同的两套程序,Qt/E是基础类库,Qtopia是构建于Qt/E之上的一系列应用程序。但从版本4开始,Trolltech将Qt/E并入到了Qtopia产品线中去了,并推出了新的Qtopia4。但实际上原来的Qt/E仍然作为基础类库,只是改名为Qtopia Core了,也许又感觉Qtopia Core跟Qtopia容易让人搞混,所以又改名为qt-embedded-linux-opensource-linux/wince(QT也支持Wince )。它作为嵌入式版本的核心,既可以与Qtopia配合,也可以独立使用。而原来的Qtopia则被分成几层,核心的应用框架和插件系统被称为 Qtopia Platform,上层的应用程序则按照不同的目标用户分为不同的包,如Qtopai PDA,Qtopia Phone。这下清楚了,我的需求是就只要移植QtE好了。Qte的改名过程,Qte-->Qtopia Core-->Qt-embedded-linux-xxxx --> qt-everywhere-opensource-src-xxxxx(目前是这样的,博主注)
这几个其实差不多是一个东西,名称很容易搞混。
记住在QT4版本前要安装Qtopia需要先装Qt/E,但之后的就不需要了。4之后的Qtopia 已经带有QT/E库了。
所以总的来说,QT也就三种:面向桌面的x11、面向嵌入式的Qt/E、以及面向嵌入式带各种应用程序的Qtopia桌面系统!!!
QtE4.8.5
下载源代码:(很多介绍移植的blog都不给个下载链接的。。。)wget
再根据网友Vincent_Song的介绍(很清楚的了,可以参照他的操作执行)。
我的configure配置如下:
我把它写成了脚本autoconf_QtE_4_8_5.sh,方便后续执行了。
-
#!/bin/sh
-
./configure -prefix /usr/local/QtE_Zhangsh_4_8_5 \
-
-opensource -confirm-license \
-
-xplatform qws/linux-arm-g++ \
-
-embedded arm \
-
-little-endian \
-
-depths 4,8,16,24,32 \
-
-shared \
-
-nomake docs \
-
-no-largefile \
-
-no-3dnow \
-
-no-sse \
-
-no-sse2 \
-
-no-mmx \
-
-no-cups \
-
-no-iconv \
-
-no-gfx-vnc \
-
-no-svg \
-
-qt-gfx-linuxfb \
-
-qt-gfx-qvfb \
-
-qt-kbd-linuxinput \
-
-qt-mouse-tslib \
-
-qt-zlib \
-
-qt-freetype \
-
-qt-libtiff \
-
-qt-libpng \
-
-qt-libmng \
-
-qt-sql-sqlite \
-
-qt-libjpeg \
-
-qt3support \
- -I/usr/local/tslib/include -L/usr/local/tslib/lib
1,QtE4.8.5的configure与4.5.3的不同,多看下configure文件就会明白,或者报错的时候再见招拆招;
2,须要先编译tslib,因为我们要用tslib来做输入,需要使用到tslib的头文件和库,在configure时指定:-I/usr/local/tslib/include -L/usr/local/tslib/lib,(我的tslib编好后,放在/usr/local/下)。
配置完以后
make
make install
以上,网上有比较详细的介绍了。
我主要记录下我遇到的一个错误:
在编译3rdparty和examples时,提示找不到tslib的库:
- make[3]: 进入目录“/usr/local/src/qt-everywhere-opensource-src-4.8.5/examples/network/broadcastreceiver”
- arm-linux-g++ -c -pipe -I/usr/local/tslib/include -fno-exceptions -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_SHARED -I../../../mkspecs/qws/linux-arm-g++ -I. -I../../../include/QtCore -I../../../include/QtNetwork -I../../../include/QtGui -I../../../include -I.moc/release-shared-emb-arm -o .obj/release-shared-emb-arm/receiver.o receiver.cpp
- arm-linux-g++ -c -pipe -I/usr/local/tslib/include -fno-exceptions -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_SHARED -I../../../mkspecs/qws/linux-arm-g++ -I. -I../../../include/QtCore -I../../../include/QtNetwork -I../../../include/QtGui -I../../../include -I.moc/release-shared-emb-arm -o .obj/release-shared-emb-arm/main.o main.cpp
- /usr/local/src/qt-everywhere-opensource-src-4.8.5/bin/moc -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_SHARED -I../../../mkspecs/qws/linux-arm-g++ -I. -I../../../include/QtCore -I../../../include/QtNetwork -I../../../include/QtGui -I../../../include -I.moc/release-shared-emb-arm receiver.h -o .moc/release-shared-emb-arm/moc_receiver.cpp
- arm-linux-g++ -c -pipe -I/usr/local/tslib/include -fno-exceptions -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_SHARED -I../../../mkspecs/qws/linux-arm-g++ -I. -I../../../include/QtCore -I../../../include/QtNetwork -I../../../include/QtGui -I../../../include -I.moc/release-shared-emb-arm -o .obj/release-shared-emb-arm/moc_receiver.o .moc/release-shared-emb-arm/moc_receiver.cpp
- arm-linux-g++ -Wl,-rpath-link,/usr/local/src/qt-everywhere-opensource-src-4.8.5/lib -fno-exceptions -Wl,-O1 -Wl,-rpath,/usr/local/QtE_Zhangsh_4_8_5/lib -Wl,-rpath,/usr/local/QtE_Zhangsh_4_8_5/lib -o broadcastreceiver .obj/release-shared-emb-arm/receiver.o .obj/release-shared-emb-arm/main.o .obj/release-shared-emb-arm/moc_receiver.o -L/usr/local/tslib/lib -L/usr/local/src/qt-everywhere-opensource-src-4.8.5/lib -lQtGui -L/usr/local/tslib/lib -L/usr/local/src/qt-everywhere-opensource-src-4.8.5/lib -lQtNetwork -lQtCore -lpthread
- /opt/FriendlyARM/toolschain/4.4.3/lib/gcc/arm-none-linux-gnueabi/4.4.3/../../../../arm-none-linux-gnueabi/bin/ld: warning: libts-1.0.so.0, needed by /usr/local/src/qt-everywhere-opensource-src-4.8.5/lib/libQtGui.so, not found (try using -rpath or -rpath-link)
- /usr/local/src/qt-everywhere-opensource-src-4.8.5/lib/libQtGui.so: undefined reference to `ts_read_raw'
- /usr/local/src/qt-everywhere-opensource-src-4.8.5/lib/libQtGui.so: undefined reference to `ts_open'
- /usr/local/src/qt-everywhere-opensource-src-4.8.5/lib/libQtGui.so: undefined reference to `ts_fd'
- /usr/local/src/qt-everywhere-opensource-src-4.8.5/lib/libQtGui.so: undefined reference to `ts_config'
- /usr/local/src/qt-everywhere-opensource-src-4.8.5/lib/libQtGui.so: undefined reference to `ts_close'
- /usr/local/src/qt-everywhere-opensource-src-4.8.5/lib/libQtGui.so: undefined reference to `ts_read'
- collect2: ld returned 1 exit status
- make[3]: *** [broadcastreceiver] 错误 1
- make[3]: 离开目录“/usr/local/src/qt-everywhere-opensource-src-4.8.5/examples/network/broadcastreceiver”
- make[2]: *** [sub-broadcastreceiver-make_default] 错误 2
- make[2]: 离开目录“/usr/local/src/qt-everywhere-opensource-src-4.8.5/examples/network”
- make[1]: *** [sub-network-make_default] 错误 2
- make[1]: 离开目录“/usr/local/src/qt-everywhere-opensource-src-4.8.5/examples”
- make: *** [sub-examples-make_default-ordered] 错误 2
我们可以:
1,进入到编译报错的目录,在这里是“examples/network/broadcastreceiver“
2,修改这个目录中的Makefile文件,找到LFLAGS一行,在最后面加上”-Wl,-rpath,/usr/local/tslib/lib“,也就是手动指定tslib的目录。(这里还没清楚为何configure时的参数没起作用)
3,就地make
4,退回到主目录
5,继续make
对应下面的粗体字的操作。
- [root@localhost qt-everywhere-opensource-src-4.8.5]# cd examples/network/broadcastreceiver
- [root@localhost broadcastreceiver]# vim Makefile
- [root@localhost broadcastreceiver]# make
- arm-linux-g++ -Wl,-rpath-link,/usr/local/src/qt-everywhere-opensource-src-4.8.5/lib -fno-exceptions -Wl,-O1 -Wl,-rpath,/usr/local/QtE_Zhangsh_4_8_5/lib -Wl,-rpath,/usr/local/QtE_Zhangsh_4_8_5/lib -Wl,-rpath,/usr/local/tslib/lib -o broadcastreceiver .obj/release-shared-emb-arm/receiver.o .obj/release-shared-emb-arm/main.o .obj/release-shared-emb-arm/moc_receiver.o -L/usr/local/tslib/lib -L/usr/local/src/qt-everywhere-opensource-src-4.8.5/lib -lQtGui -L/usr/local/tslib/lib -L/usr/local/src/qt-everywhere-opensource-src-4.8.5/lib -lQtNetwork -lQtCore -lpthread
- [root@localhost broadcastreceiver]# cd -
- /usr/local/src/qt-everywhere-opensource-src-4.8.5
-
[root@localhost qt-everywhere-opensource-src-4.8.5]# make
上面的操作,如果每个Makefile都要编辑一遍的话,那就太麻烦了,我们偷偷懒。
针对Makefile的LFLAGS一行的特点,我们使用find、grep、awk、sed、xargs来完成这个操作,如下:
进入到出错目录的顶层,如上示例,我们进入到examples。
- cd examples
-
- find . -name Makefile | xargs grep rpath-link | grep -v tslib | awk -F: '{fname[NR]=$1} END {for (i=1;i<=NR;i++){print fname[i]}}' | xargs sed -i 's/LFLAGS.*/& -Wl,-rpath,\/usr\/local\/tslib\/lib/'
解释一下以上命令:
1,我们找到各个Makefile。
- find . -name Makefile
- find . -name Makefile | xargs grep rpath-link | grep -v tslib
- find . -name Makefile | xargs grep rpath-link | grep -v tslib | awk -F: '{fname[NR]=$1} END {for (i=1;i<=NR;i++){print fname[i]}
- find . -name Makefile | xargs grep rpath-link | grep -v tslib | awk -F: '{fname[NR]=$1} END {for (i=1;i<=NR;i++){print fname[i]}}' | xargs sed -i 's/LFLAGS.*/& -Wl,-rpath,\/usr\/local\/tslib\/lib/'
注:在Makefile的最后添加"-Wl,-rpath,/usr/local\tslib/lib"的操作,参照sed的手册。
- sed -i 's/LFLAGS.*/& -Wl,-rpath,\/usr\/local\/tslib\/lib/' Makefile
这个命令,下班前急忙花了半个小时写成的,应可以再优化一下。
有时退到主目录的话,还是不能编译。同时为了避免每个底层目录都操做一遍,也可以在主目录的次一级进行操作,如上例子中应是examples,在examples中执行make,完成后,回到主目录接着执行make。
后面就没什么错误了,编译完成(4.8.5时间太长了,我的破机器前前后后用了至少8小时,可以在配置的时候-no-make-examples -no-make-demos等等)。
后续操作:
我们把编译出的bin、lib、examples、test目录拷贝到nfs系统中。
我是将这四个目录拷贝到里nfs系统的“/qte”之下(自己新建),这里拷贝到什么地方无所谓,因为需要在ENV中说明的,在后续export ENV的时候指过去就行。
我的export,写在/etc/profile中(包括了tslib):
-
# Ash profile
# vim: syntax= sh
# No core file by defaults
# ulimit - S - c 0> / dev/ null 2> & 1
USER="id -un"
LOGNAME=$USER
PS1="[\u@\h \w]#"
PATH=$PATH
HOSTNAME= '/bin/hostname'
alias cls="clear"
export USER LOGNAME PS1 PATH
- # tslib path
- export TSLIB_TSDEVICE=/dev/event0
- export TSLIB_CALIBFILE=/etc/pointercal
- export TSLIB_CONFFILE=/etc/ts.conf
- export TSLIB_PLUGINDIR=/lib/ts
- export TSLIB_CONSOLEDEVICE=none
- export TSLIB_FBDEVICE=/dev/fb0
-
- # qt path
- export QTDIR=/qte
- export QTDIRLIB=/qte/lib
- export LD_LIBRARY_PATH=$QTDIRLIB:$LD_LIBRARY_PATH
- export PATH=$PATH:$QTDIR/bin
- export QWS_KEYBOARD=USB:/dev/event1
- export QWS_MOUSE_PROTO=tslib:/dev/event0
- export QWS_SIZE=480x272
- export QT_QWS_FONTDIR=/qte/lib/fonts
在执行的时候出现几个问题,以下两个错误跟内核的配置有关,感谢网友Channels_net的经验分享。
错误1:
QWSServerSocket::init: Function not implemented
QWSServerSocket: unable to create socket.
QWSServerPrivate::initServer: server socket not listening: Illegal seek
Failed to bind to /tmp/qtembedded-0/QtEmbedded-0
解决方法:
重新配置内核:# make menuconfig
选中:Networking——>Networlding options——>Unix domain sockets
重新编译,再次烧入内核。
错误2:
Cannot create semaphore /tmp/qtembedded-root/QtEmbedded-0
这是说明系统禁止了锁,可以在内核配置的第一个 generated配置里面找到:
[*] System V IPC
选上它,重新编译,再次烧入内核。
后记;
由于后面还有其他工作,这次移植工作告一段落了,其实搞清楚了交叉编译,多在网上检索,参照代码,移植工作还是会比较顺利的。在这次移植工作中,也学习到了不少东西。