新项目中需要做界面,决定使用Qt框架开发,刚好我在前一个项目中是做这个的,就接手了。由于上一个项目我选用的是Qt-4.7的版本,包括PC版本和嵌入式版本,而这次项目打算用半现成的Qtopia2.2.0版本,考虑到库的存储空间大小和性能需求,不得不说Qt4.7的嵌入式版本编出来的库很占用空间。因为Qtopia2.2.0是别的公司 弄好的,不过还是需要自己理清整个编译、移植的步骤过程,不然以后开发会很麻烦,还好有点经验,只是Qtopia2.2.0确实有点旧了,2005的版本,我现在都找不到官方的版本了。整了两天,基本是搞定了它的编译和移植过程,顺便写了个自动化脚本,自我感觉良好。
开发环境
PC机:Ubuntn 12.10 Server(Linux 3.5.0),gcc-4.7.2(g++) 目标机:ARM9, Linux 2.6.24
编译前环境准备
- X11库
Qtopia编译过程中需要使用X11 里面的一些头文件来生成一些工具,主要是qt2的编译,当然里面的dqt编译肯定是需要用到X11的头文件和库的。使用以下命令即可安装需要X11的环境:
<!-- lang: shell -->
sudo apt-get install libx11-dev libxext-dev libxtst-dev
- uuid库和xmu库
编译过程中会使用到这些库,安装命令:
<!-- lang: shell -->
sudo apt-get install uuid-dev
sudo apt-get install libxmu-dev libxmu6
- 交叉编译工具链
既然是Qtopia的移植,就肯定需要有ARM的交叉编译工具链,这个可以从网上下载,如EABI的工具链,也可以使用开发板厂家提供的。安装好整套工具链,并设置好相应的环境变量,测试通过再继续Qtopia的编译。
- 第三方链接库的下载和编译
这里是指Qtopia应用时使用到的一些功能库,主要是jpeg库、png库、zlib压缩库、uuid库。其实有些库Qtopia包里是有的,如jpeg库、png库、zlib库,可以使用其自带的,当然Qtopia也提供了选项让我们使用外部的第三方库。我拿到的包是使用第三方的,所以也就“继承”下来了。
如果要打算使用第三方库,则要下载到这些库的源码,然后交叉编译好它们,再把编译好的动态库文件和头文件安装好,以便Qtopia编译、链接时能找到它们。当然最后还要在Qtopia的编译选项中指定路径、以及添加这些库。
我使用的第三方库的文件名:libpng-1.2.14.tar.gz, zlib-1.2.3.tar.gz, jpegsrc.v6b.tar.gz, e2fsprogs-1.39.tar.gz(uuid)。
Qtopia编译
在编译这一步,因为用到的编译器狠心,遇到了不少源码的错误,需要一步步地修改。还有在这一步其实qt库的编译选项也是很重要的,需要好好确定。
目标平台的配置文件创建:tmake.conf 和 qmake.conf
在tmake和qtopia的qws目录下,通过拷贝linux-arm-g++配置文件,然后修改来创建对应目标平台的配置文件,主要是修改tmake.conf 和 qmake.conf两个文件里的交叉工具链。
configure中编译配置选项的确定
这个需要根据项目的需求进行选择、确定,也相当与qte库的裁剪、qtopia环境的裁剪,是整个移植过程中最不确定,最复杂的部分。至于有哪些选项可用,使用 ./configure -help 查看帮助。下面是我的一个简单示例,可以用来做编译测试:
<!-- lang: shell -->
echo 'yes' | ./configure \
-qte '-embedded -no-xft -qvfb -xplatform arm-hismall-linux-g++ -qconfig qpe -depths 16,32 -no-qvfb -system-jpeg -gif -system-libpng -I$HOME/qt/Qt-hisi-2.2.0/build/include -lpng -lz -ljpeg -L$HOME/qt/Qt-hisi-2.2.0/build/lib' \
-qpe '-xplatform arm-hismall-linux-g++ -edition pda -displaysize 240x320' \
-libpath $HOME/qt/Qt-hisi-2.2.0/build/lib \
-prefix $HOME/qt/install
编译与安装:make; make install
make的编译过程是时间最长的,也是小问题最多的,我整理了一下我遇到的问题和修改,以上面的选项配置,主要是源码方面的问题,也有链接的。
-
error: `pthread_yield' undeclared (first use this function)。可能跟我使用的uclibc库有关。
qtopia-free-2.2.0/qtopia/src/3rdparty/plugins/codecs/libffmpeg
mediapacketbuffer.h:231: //pthread_yield(); --> sched_yield(); mediapacketbuffer.h:234: //pthread_yield();
-
error: ‘ptrdiff_t’ does not name a type。这个错误应该是libc的版本造成的,修改:
qtopia-free-2.2.0/dqt/src/tools/qvaluelist.h 52 ,添加下面两行:
<!-- lang: cpp --> #include <cstddef> #include "stddef.h"
-
从'QValueListIterator<QString>'转换到'const char*',为实参'1'(属于'int remove(const char*)') ,以及“append()”函数未声明,修改:
qt2/src/tools/qvaluestack.h 52 append ,57 remove ,添加this->;如下:
<!-- lang: cpp --> void push( const T& d ) { this->append(d); } <!-- lang: cpp --> this->remove( this->fromLast() );
-
fatal error: asm/page.h: No such file or directory
2.6内核中不再含有asm-i386的page.h,
qt2/src/kernel/qpixmapcache.cpp,qt2/tools/qvfb/qvfbview.cpp,修改为:
<!-- lang: cpp -->
#define PAGE_SHIFT 12 //new add 2010-12-10
#define PAGE_SIZE (1UL << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
//# include <asm/page.h> // PAGE_SIZE,PAGE_MASK,PAGE_ALIGN
-
error: extra qualification ‘QDawgPrivate::’ on member ‘QDawgPrivate’
qtopia/src/libraries/qtopia/qdawg.cpp +294 去掉析构函数的类名修饰
-
error: `program_invocation_short_name' undeclared (first use in this function)
qtopia/src/3rdparty/libraries/rsync/config_linux.h,修改,取消这个宏的声明:
<!-- lang: cpp --> #undef HAVE_PROGRAM_INVOCATION_NAME
-
open函数缺少第三个参数:添加权限参数 0666
qt2/src/tools/qmemoryfile_unix.cpp:143:
<!-- lang: cpp --> f = ::open(tmpFile.latin1(), O_CREAT | O_WRONLY,0666);
qtopia/src/libraries/qtopia/qmemoryfile_unix.cpp:141:
<!-- lang: cpp --> f = ::open(tmpFile.latin1(), O_CREAT | O_WRONLY, 0666);
-
fatal error: zlib.h: No such file or directory,找不到zlib.h,不知道为什么:
qt2/src/3rdparty/libpng/png.h文件中 295行,改成相对路径就OK了:
#include "zlib.h" --> #include "../zlib/zlib.h"
-
cannont find -lpng,找不到第三方的png动态库
这是因为使用的第三方库,编译生成的png动态库为:libpng12.so.0,包括了版本号,解决方法就是,手动改名:
<!-- lang: shell --> cp libpng12.so.0 libpng.so
移植
make install成功安装qtopia到指定的路径后,接下来就是移植了,很简单:将整个安装路径放到目标机上就可以了,可以通过NFS挂载的方式来运行,也可以把安装路径内容烧写到flash上来跑,甚至还可以通过tftp把内容下载到内存来运行(基于根文件系统是cramfs且没有nfs服务,我只能使用这种方式测试。。。)。
-
设置运行环境变量
<!-- lang: shell --> export QTDIR=/tmp/install export QPEDIR=/tmp/install export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH export QWS_KEYBOARD_PROTO="USB:/dev/input/event1" export QWS_MOUSE_PROTO="USB:/dev/input/mouse0"
可以写成一个脚本,在每次启动时自动加载完成环境变量的设置。
-
运行
<!-- lang: shell --> cd bin; ./qpe &
出现下面的错误: could not open for writing `/root/Settings/locale_new.conf' QCopChannel::send: Must construct a QApplication before using QCopChannel
是因为$HOME环境变量没有设置或者设置的位置不可写(cramfs文件系统),重新设置一个可写的$HOME环境变量:
<!-- lang: shell --> export HOME=/tmp
-
触摸屏相关
如果正常启动了qpe,而且加载了触摸屏支持功能,则第一次运行时需要进行触摸屏校准。因为我的设备不支持触摸屏,因此之后我把触摸屏功能去掉了。为了避开这个校准,可以手动创建校准文件pointercal,其内容是1 0 1 0 1 1 65536,然后拷贝到相应的位置。
<!-- lang: shell --> cp pointercal /etc cp pointercal $HOME
来源:oschina
链接:https://my.oschina.net/u/195885/blog/115841