想起自己当初刚开始学习Qt的那个苦恼,一开始不知道各个软件之间的关系和安装时具体为什么这么做,现在就把它总结一下,希望对大家有所帮助。
1. 硬件环境
A. 主机:x86系列PC机。
B. 开发板:博创2410-s。
C. 通讯连接:串口和网络。
2. 软件环境
A. 主机操作系统:VMware虚拟机下的Redhat linux 9.0(完全安装) 。
B. 开发板操作系统:嵌入式Linux,内核版本为2.6.13。
C. 交叉编译器:armv41-unknown-linux-c++。
D. 通讯方式:虚拟机与主机(Windows XP)使用telnet、nfs、ftp、ssh等方式通讯,主机与开发板使用串口和网络(例如nfs)通讯。
3. 相关说明
A. 命令:所有以#开头的均为在shell中执行的命令。
B. 交叉编译器位置:/opt/host/armv41。
C. 工作目录:默认为/root/linux-qt/s。
D. 脚本注释:均放在命令下一行的圆括号内。
4. 下载源码包
A. 工程管理tmake-1.13.tar.gz,用于生成Makefile。
B. Qt/X11软件包qt-x11-2.3.2.tar.gz,用于生成qvfb等开发工具。
C. Qt/Embedded软件包qt-embedded-2.3.10-free.tar.gz,Qt/Embedded图形库。
[以上文件都可以在网上很方便的获得 ,当然这个版本搭建的环境是很低的了,我们只不过是用此来说明qt开发的环境在linux下的搭建方法和简单使用。同时也了解一下linux系统和我们使用的软件之间的关系]
5. 编译前准备
A. 建立工作目录
#mkdir /root/linux-qt
#cd /root/linux-qt
#cp …
(复制所有源码包到此目录)
B. 解压源码包
#cd /root/qt/
tar -zxvf tmake-1.13.tar.gz (此命令用于解压此文件)
解压完后 在当前目录生成一个 tmake-1.13目录
tar -zxvf qt-x11-2.3.2.tar.gz (此命令用于解压此文件)
(解压源码包到当前目录)
为了以后方便,我们把这三个的名字改成容易记忆的命令名
解压完后 在当前目录生成一个 qt-2.3.2 目录
tar -zxvf qt-embedded-2.3.10-free.tar.gz(此命令用于解压此文件)
解压完后 在当前目录生成一个 qt-2.3.10 目录
#mv tmake-1.13 tmake (把tmake-1.13 目录名改成tmake)
#mv qt-2.3.2 qt-x11 (把 qt-2.3.2目录名改成qt-x11)
#mv qt-2.3.10 qt-embedded(把qt-2.3.10 命令名改成qt-embedded)
二、 搭建Qt/Embedded仿真开发环境
1. 安装tmake
#cd /root/qt-linux/
#export TMAKEDIR=$PWD/tmake
#export TMAKEPATH = $PWD/tmake/ lib/qws/linux-x86-g++
(注册好tmake的环境变量,这个能影响到你用tmake生成 工程文件和Makefile。目录不对可能生成的Makefile文件不对)
将常用到的命令progen tmake 拷贝到bin目录下。
cp progen /bin
cp tmake /bin
2. 安装Qt/X11
#cd qt-x11
#export QTDIR=$PWD
(设置环境变量)
#./configure –static –no-xft –no-opengl –no-sm
(配置,回答yes)
#make (编译)
#cp src/moc/moc bin
(复制moc工具到bin目录,moc是根据你界面化设计的文件生成工程文件的工具)
#cp tools/designer/designer bin
(编译Designer,用于可视化界面设计)
3.建立qvfb使用环境
#export QTDIR=$PWD
#export PATH=$QTDIR/bin:$PATH
#export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
(这一步是为了建立了 Qt/Embedded 2.3.10到 Qt 2.3.2的静态库的链接。要用到tmake这个工具,因此先检测你刚才设置的关于tmake的环境变量还有效吗?如果没有效,应该重新设置。检测方法,echo $TMAKEPATH.若输出的不是刚才安装tmake时的路径。要重新设置。咱一开始设置好了 ,一般没事)
cd qt-x11/tools/qvfb
tmake -o Makefile qvfb.pro
make
cp qvfb /bin(复制qvfb到bin目录去。其中
qvfb 工具用来生成 Virtual framebuffer,这是一个非常有用的工具,它可以模拟在开发板上的显示情况,如果在 Virtual framebuffer中运行没有问题的话,可以直接通过交叉编译在开发板上运行。)
4. 编译Qt/Embedded
#export QTDIR=$PWD/qt-embedded
#export PATH=$QTDIR/bin:$TMAKEDIR/bin: $PATH
#cd qt-embedded
(设置环境变量)
#./configure –system-jpeg –gif –system-libpng –system-zlib –platform linux-generic-g++ -qconfig qpe –depths 16,24,32
(配置Qt/Embedded图形库,然后回答两个yes,在配置./configure 中-qvfb用来支持 Virtual framebuffer,-depths 4,8,16,32 支持4 位,8位,16 位,32 位的显示深度,此外还可以添加如-syestem-jpeg 和-gif 来提供对 jpeg 和 gif
的支持。配置系统同时还支持对特定平台系统选项的添加,但一般来讲,凡是支持framebuffer的 Linux 系统都可以使用“linux-generic-g++”平台。详细的配置信息可以通过运行./configure --help 命令来查看。 )
#make
(编译Qt/Embedded)
5. 编写环境变量脚本
大家在以后使用tmake时可以看一下tmake最后生成的Makefile文件。可以知道它生成的文件全部环境变量都是咱们在安装时指定的那些名字。因此在使用tmake和其他qt开发环境时应该先设置环境变量。
用此脚本更改环境变量的方法:
shell 脚本内容:
#shell
export QTDIR=$PWD/qt-embedded
# export QPEDIR=$PWD/qtopia
export TMAKEDIR=$PWD/tmake
export TMAKEPATH=$TMAKEDIR/lib/qws/linux-x86-g++
export PATH=$QTDIR/bin:$QPEDIR/bin:$TMAKEDIR/bin:$PATH
先把此文件改成可执行文件
1,source qt.sh
2,. qt.sh(用点代替 但点后有一空格)
好了到现在为止,你的qt开发和编辑环境已经搭建好了。
下面我们测试一下:
我们用qt库函数写一个简单的窗口程序:
#cd /root/linux-qt
#mkdir hello
(在咱们的工作目录下建一个hello目录)
我们学一门语言时,一般我们要写一个hello world 的程序,这次也不例外。呵呵
hello.cpp
//hello.cpp
1 #include
2 #include
3 int main(int argc, char *argv[])
4 {
5 QApplication app (argc, argv);
6 QLabel *hello = new QLabel("Hello Qt/Embedded!", 0);
7 app.setMainWidget(hello);
8 hello->show();
9 return app.exec();
10 }
现在开始逐行讲解一下每一句是什么意思,掌握了这些以后可以帮助我们更加了解 Qt
的程序设计。
第 1 行和第 2 行包含了两个头文件,这两个头文件中包含了 QApplication 和 QLabel
类的定义。
第 5 行创建了一个 QApplication 对象,用于管理整个程序的资源,它需要 2 个参数,
因为 Qt 本身需要一些命令行的参数。
第 6 行创建了一个用来显示 Hello Qt/Embedded!的部件。在 Qt 中,部件是一个可视化
用户接口,按钮、菜单、滚动条都是部件的实例。部件可以包含其它部件,例如,一个应
用程序窗口通常是一个包含 QMenuBar、QToolBar、QStatusBar 和其它部件的一个部件。
在 QLabel 函数中的参数 0 表示,这是一个窗口而不是嵌入到其它窗口中的部件。
第 7 行设置hello 部件为程序的主部件,当用户关闭主部件后,应用程序将会被关闭。
如果没有主部件的话,即使用户关闭了窗口程序也会在后台继续运行。
第 8 行使hello 部件可视, 一般来说部件被创建后都是被隐藏的,因此可以在显示前根
据需要来订制部件,这样的好处是可以避免部件创建所造成的闪烁。
第 9 行把程序的控制权交还给 Qt,这时候程序进入就绪模式,可是随时被用户行为
激活,例如点击鼠标、敲击键盘等。
下面我们要让我们的程序跑起来,首先要让它能够在 Virtual framebuffer中显示出来,
然后再通过交叉编译在开发板上运行。
下面,我们就用这个文件来生成工程文件和Makefile文件。
首先,我们执行刚才写的脚本qt.sh
1.生成工程文件(.pro)
每一个 Qt 程序都对应着一个工程文件,因为 tmake 工具要借此工程生成相应的
Makefile 文件。生成工程文件需要使用 progen 工具,它的位置在$TMAKEDIR/bin 下,使
用 progen 生成工程文件的方法如下:
progen –t app.t –o hello.pro
生成的这个 hello.pro 工程文件是可以被修改的,可以编辑里面的头文件、源文件等内
容。
2.生成 Makefile 文件
Qt 提供了生成 Makefile文件的工具 tmake,这极大地方便了应用程序的开发,节
大量的时间,而且还可根据不同平台的需要生成适合于不同平台的 Makefile 文件。
先看源文件:脚本内容如下,在/root/linux-qt /下保存为qt.sh,在编译或者运行Qt程序之前进入该目录执行此脚本。
export QTDIR=$PWD/qt
export TMAKEDIR=$PWD/tmake
export TMAKEPATH=$TMAKEDIR/lib/qws/linux-x86-g++
export PATH=$QTDIR/bin:$QPEDIR/bin:$TMAKEDIR/bin:$PATH
然后,我们让这个程序在Virtual framebuffer显示.
tmake –o Makefile hello.pro
完成上面的步骤以后就可以在当前的目录中生成一个 Makefile 文件,关于 Makefile
文件的功能和结构这里就不再做过多的介绍了,可以参考前面的章节来了解 Makefile。 【这次,我们只是在我们机器上做一个测试,我把我的机器上生成的 Makefile 的文件放在这里:
1 ######################################################################## #####
2 # Makefile for building hello
3 # Generated by tmake at 08:24, 2011/04/27
4 # Project: hello
5 # Template: app
6 ######################################################################## #####
7
8 ####### Compiler, tools and options
9
10 CC = g++
11 CXX = g++
12 CFLAGS = -pipe -Wall -W -O2 -DNO_DEBUG
13 CXXFLAGS= -pipe -DQWS -fno-exceptions -fno-rtti -Wall -W -O2 -DNO_ DEBUG
14 INCPATH = -I$(QTDIR)/include
15 LINK = g++
16 LFLAGS =
17 LIBS = $(SUBLIBS) -L$(QTDIR)/lib -lm -lqte
18 MOC = $(QTDIR)/bin/moc
19 UIC = $(QTDIR)/bin/uic
20
21 TAR = tar -cf
22 GZIP = gzip -9f
23
24 ####### Files
25
26 HEADERS =
27 SOURCES = hello.cpp
28 OBJECTS = hello.o
29 INTERFACES =
30 UICDECLS =
31 UICIMPLS =
32 SRCMOC =
33 OBJMOC =
34 DIST =
35 TARGET = hello
36 INTERFACE_DECL_PATH = .
37
38 ####### Implicit rules
39
40 .SUFFIXES: .cpp .cxx .cc .C .c
41
42 .cpp.o:
43 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
44
45 .cxx.o:
46 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
47
48 .cc.o:
49 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
50
51 .C.o:
52 $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
53
54 .c.o:
55 $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
56
57 ####### Build rules
58
59
60 all: $(TARGET)
61
62 $(TARGET): $(UICDECLS) $(OBJECTS) $(OBJMOC)
63 $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)
64
65 moc: $(SRCMOC)
66
67 tmake: Makefile
68
69 Makefile: hello.pro
70 tmake hello.pro -o Makefile
71
72 dist:
73 $(TAR) hello.tar hello.pro $(SOURCES) $(HEADERS) $(INTERFACES) $ (DIST)
74 $(GZIP) hello.tar
75
76 clean:
77 -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(UICIMPLS) $(UICDECLS) $( TARGET)
78 -rm -f *~ core
79
80 ####### Sub-libraries
81
82
83 ###### Combined headers
84
85
86 ####### Compile
87
88 hello.o: hello.cpp
89
】
最后在命令行中输入 “make”命令就可以对整个程序进行编译链接了,最终生成了一
hello 可执行文件。
#cd hello
#qvfb &
#./hello -qws
就可以看到我们刚才做的一个简单的窗口。
(注意,你的linux主机需支持x-window,在界面模式下用 terminal 输入这些命令)
好了,到目前为止,你已经搭建了一个在x86 机器的qt的整个运行平台。在x86上用frame buffer 运行qt程序了。那么,接下来就应该建立arm板子的qt库文件了。也就是如果你想把你的qt程序移植到arm板子上的话。你还应该用交叉编译器重新编译qt-embedded源文件,也就是编译成arm运行时所需要的库文件。我用的交叉编译器是arm-linux-gcc -3.4.1 。步骤如下:
1. Build Qt/Embedded
cd $QTEDIR
export TMAKEPATH=$TMAKEDIR/lib/qws/linux-arm-g++
export QTDIR=$QTEDIR
export PATH=$QTDIR/bin:$PATH
export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
./configure -xplatform linux-arm-g++ -no-xft -no-qvfb -depths 4,8,16,32
make
如果make过程出现错误,要到网上去搜一搜相关的错误信息。因为出现错误的原因是在是很多,这里就不一一列举。
好了,编译成功后。
进入 当前目录的 lib 你会看到你刚才编译的库文件。
你用 file命令来查看一下文件属性:
file libqte.so.2.3.10
libqte.so.2.3.10: ELF 32-bit LSB shared object, ARM, version 1 (ARM), not stripped
如出现上面的信息,则说明你编译的arm的qt库是可以使用的。呵呵 ,先祝贺一下。
大家,知道我们的qt程序在arm板子上跑起来需要这些库文件。所以我们把文件复制到arm板子上。
我们使用nfs 的mount 命令来做。
先给大家说一下我的开发具体的环境。在windows下的虚拟机上安装了一个red hat 9.0 。red hat 9。0 的ip是 114.214.1.100 netmask 255.255.0.0 然后我的red hat 上开启nfs功能 ,我的共享目录是 /arm2410
所以,我用命令
mount 114.214.1.100:/arm2410 /var/tmp 我把我的共享文件挂载到 我的arm板子的 /var/tmp 上。
首先,我们把刚才编译好的qt的库先复制到共享目录 /arm2410 中去。
然后,我们用arm-linux-gcc 重新编译一下咱们上面用的hello world 程序。
具体,编译方法就是更改一下 原来的Makefile 文件。把 编译器改成arm-linux-gcc 和链接库文件的目录改成你刚编译好的库文件目录。
然后把生成的可执行文件复制到共享目录 /arm2410 中去。
好了,我们直接进入 /var/tmp 去 执行 hello
错误提示:找不到libqte.so.2.3.10文件
错误分析:arm板子运行时有一个关于库的搜索路径的变量,变量代表的路径里没有你的库所在路径。
解决方法:把你qt库所在位置添加到你的环境变量里。export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/var/tmp(因为我的qt库文件在这个目录)。
接下来在运行一下 hello
提示错误:找不到 arm-linux-g++ 的一个库文件(原错误没有记录下来,这只是个大概意思)。
分析原因,你用的arm-linux-gcc 编译器的库文件在你red hat 里 ,所以在arm板子上运行时找不到此库文件。
解决方法:找到你arm-linux-gcc 编译器的库位置,把所有的库文件都拷贝到共享目录下。
然后执行hello
又提示错误:Cannot create Qt/Embedded data directory: /tmp/qtembedded-0
错误分析:qt程序在arm板子上运行时需要建立这个目录,呵呵,这个错误对我们来说是一件好事,起码说明这个程序能运行了,只不过在运行时创建目录失败而已。
解决方法:在板子上建立这个目录,因为我用的板子的文件系统是只读的,不能直接创建目录。而且在文件系统上的根目录下有一个链接文件tmp 它链接的目录是/mny/yaffs/Qtopia 因此,我们的一个解决方案是把/mny/yaffs/Qtopia目录挂载成我们redhat的共享目录,在共享目录里建一个tmp文件夹。这样就解决了不能创建目录的问题。因为arm板子上的程序再运行时,创建目录是在red hat 中创建的。呵呵呵
再接着运行hello 程序。
呵呵呵
久违的hello world 程序终于出现在arm板子上了 。
板子的文件系统是不可写的,解决上面的问题,当然还有一种更彻底的方案:
就是按照上面所需要的文件和目录再重新制作一个根文件系统。(具体的制作方法以后再说)
呵呵
arm板子的简单qt 开发、运行环境终于搭建好了!!!!!!!!!!