s3c6410 arm移植实验四:qte4.8.5移植,其中AWK和sed的应用!

ARM 285浏览

文章主要内容有:先介绍下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-->Qtopia Core-->Qt-embedded-linux-xxxx --> qt-everywhere-opensource-src-xxxxx(目前是这样的,博主注

这几个其实差不多是一个东西,名称很容易搞混。

记住在QT4版本前要安装Qtopia需要先装Qt/E,但之后的就不需要了。4之后的Qtopia 已经带有QT/E库了。

所以总的来说,QT也就三种:面向桌面的x11、面向嵌入式的Qt/E、以及面向嵌入式带各种应用程序的Qtopia桌面系统!!!

这下清楚了,我的需求是就只要移植QtE好了。


QtE4.8.5

下载源代码:(很多介绍移植的blog都不给个下载链接的。。。)
wget http://mirrors.neusoft.edu.cn/qt/official_releases/qt/4.8/4.8.5/qt-everywhere-opensource-src-4.8.5.tar.gz

再根据网友Vincent_Song的介绍(很清楚的了,可以参照他的操作执行)。

我的configure配置如下:
我把它写成了脚本autoconf_QtE_4_8_5.sh,方便后续执行了。

  1. #!/bin/sh
  2. ./configure -prefix /usr/local/QtE_Zhangsh_4_8_5
  3. -opensource -confirm-license
  4. -xplatform qws/linux-arm-g++
  5. -embedded arm
  6. -little-endian
  7. -depths 4,8,16,24,32
  8. -shared
  9. -nomake docs
  10. -no-largefile
  11. -no-3dnow
  12. -no-sse
  13. -no-sse2
  14. -no-mmx
  15. -no-cups
  16. -no-iconv
  17. -no-gfx-vnc
  18. -no-svg
  19. -qt-gfx-linuxfb
  20. -qt-gfx-qvfb
  21. -qt-kbd-linuxinput
  22. -qt-mouse-tslib
  23. -qt-zlib
  24. -qt-freetype
  25. -qt-libtiff
  26. -qt-libpng
  27. -qt-libmng
  28. -qt-sql-sqlite
  29. -qt-libjpeg
  30. -qt3support
  31. -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的库

  1. make[3]: 进入目录“/usr/local/src/qt-everywhere-opensource-src-4.8.5/examples/network/broadcastreceiver”
  2. 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
  3. 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
  4. /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
  5. 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
  6. 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
  7. /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)
  8. /usr/local/src/qt-everywhere-opensource-src-4.8.5/lib/libQtGui.so: undefined reference to `ts_read_raw'
  9. /usr/local/src/qt-everywhere-opensource-src-4.8.5/lib/libQtGui.so: undefined reference to `ts_open'
  10. /usr/local/src/qt-everywhere-opensource-src-4.8.5/lib/libQtGui.so: undefined reference to `ts_fd'
  11. /usr/local/src/qt-everywhere-opensource-src-4.8.5/lib/libQtGui.so: undefined reference to `ts_config'
  12. /usr/local/src/qt-everywhere-opensource-src-4.8.5/lib/libQtGui.so: undefined reference to `ts_close'
  13. /usr/local/src/qt-everywhere-opensource-src-4.8.5/lib/libQtGui.so: undefined reference to `ts_read'
  14. collect2: ld returned 1 exit status
  15. make[3]: *** [broadcastreceiver] 错误 1
  16. make[3]: 离开目录“/usr/local/src/qt-everywhere-opensource-src-4.8.5/examples/network/broadcastreceiver”
  17. make[2]: *** [sub-broadcastreceiver-make_default] 错误 2
  18. make[2]: 离开目录“/usr/local/src/qt-everywhere-opensource-src-4.8.5/examples/network”
  19. make[1]: *** [sub-network-make_default] 错误 2
  20. make[1]: 离开目录“/usr/local/src/qt-everywhere-opensource-src-4.8.5/examples”
  21. make: *** [sub-examples-make_default-ordered] 错误 2

提示没有tslib的库,当然了,提示中也清楚的说了(try using -rpath or -rpath-link)
我们可以:
1,进入到编译报错的目录,在这里是“examples/network/broadcastreceiver
2,修改这个目录中的Makefile文件,找到LFLAGS一行,在最后面加上”-Wl,-rpath,/usr/local/tslib/lib“,也就是手动指定tslib的目录。(这里还没清楚为何configure时的参数没起作用)
3,就地make
4,退回到主目录
5,继续make
对应下面的粗体字的操作。

  1. [root@localhost qt-everywhere-opensource-src-4.8.5]# cd examples/network/broadcastreceiver
  2. [root@localhost broadcastreceiver]# vim Makefile
  3. [root@localhost broadcastreceiver]# make
  4. 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
  5. [root@localhost broadcastreceiver]# cd -
  6. /usr/local/src/qt-everywhere-opensource-src-4.8.5
  7. [root@localhost qt-everywhere-opensource-src-4.8.5]# make

利用脚本快速完成以上操作!
上面的操作,如果每个Makefile都要编辑一遍的话,那就太麻烦了,我们偷偷懒。

针对Makefile的LFLAGS一行的特点,我们使用find、grep、awk、sed、xargs来完成这个操作,如下:
进入到出错目录的顶层,如上示例,我们进入到examples。

  1. cd examples

  2. 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,请试验成功后再使用。>

解释一下以上命令:

1,我们找到各个Makefile。

  1. find . -name Makefile

2,在以上基础上用grep过滤,找到符合我们需求的Makefile。(需要添加"-Wl,-rpath,/usr/local/tslib/lib"但没有添加的Makefile)

  1. find . -name Makefile | xargs grep rpath-link | grep -v tslib

3,使用awk,实现依次操作find文件的功能。

  1. 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]}

4,开始处理。

  1. 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/localtslib/lib"的操作,参照sed的手册。

  1. 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):

  1. # 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

  2. # tslib path
  3. export TSLIB_TSDEVICE=/dev/event0
  4. export TSLIB_CALIBFILE=/etc/pointercal
  5. export TSLIB_CONFFILE=/etc/ts.conf
  6. export TSLIB_PLUGINDIR=/lib/ts
  7. export TSLIB_CONSOLEDEVICE=none
  8. export TSLIB_FBDEVICE=/dev/fb0
  9. # qt path
  10. export QTDIR=/qte
  11. export QTDIRLIB=/qte/lib
  12. export LD_LIBRARY_PATH=$QTDIRLIB:$LD_LIBRARY_PATH
  13. export PATH=$PATH:$QTDIR/bin
  14. export QWS_KEYBOARD=USB:/dev/event1
  15. export QWS_MOUSE_PROTO=tslib:/dev/event0
  16. export QWS_SIZE=480x272
  17. export QT_QWS_FONTDIR=/qte/lib/fonts

因为我还没些qt程序,所以将examples、test拷过去,打算用来试验。


在执行的时候出现几个问题,以下两个错误跟内核的配置有关,感谢网友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
选上它,重新编译,再次烧入内核。



后记;

由于后面还有其他工作,这次移植工作告一段落了,其实搞清楚了交叉编译,多在网上检索,参照代码,移植工作还是会比较顺利的。在这次移植工作中,也学习到了不少东西。