Qtopia的编译系统.docx
《Qtopia的编译系统.docx》由会员分享,可在线阅读,更多相关《Qtopia的编译系统.docx(43页珍藏版)》请在冰豆网上搜索。
Qtopia的编译系统
Qtopia的编译系统
目录
1.qmake2
1.1pro文件2
1.2实例4
2.Qtopia编译系统9
2.1内部的编译系统项目文件说明11
2.2项目文件生成Makefile说明18
2.3src-components.pro和src.pro分析20
2.4configure脚本生成Makefile27
2.5Qtopia的编译过程39
2.5.1库的编译40
2.5.2相互独立的应用程序及插件的编译43
2.5.3文件的安装44
2.5.4打包分发48
1.qmake
由于直接给不同的平台和编译器写个Makefile较难且容易出错,Trolltech公司创建了qmake工具来自动生成Makefile。
qmake处理对编译器和平台的依赖性以及moc和uic的连编规则,开发者创建一个纯文本的"*.pro"项目文件来指明他们的源代码文件,然后运行qmake生成适当的Makefile。
在不同的平台上编译应用程序,你需要设置QMAKESPEC环境变量,在Windows下使用MicrosoftVisualStudio,要把QMAKESPEC环境变量设置为win32-msvc。
在Solaris上使用gcc,把QMAKESPEC环境变量设置为solaris-g++。
在mkspecs中的每一个目录里面,都有一个包含了平台和编译器特定信息的qmake.conf文件。
这些设置适用于你要使用qmake的任何项目。
1.1pro文件
工程(pro)文件包含了qmake编译应用(泛指应用程序、库、插件)所需要的全部信息,对于每个应用而言,都有一个pro文件。
简单的工程文件仅定义了标准变量来包含源文件和头文件信息,复杂的工程文件会采用控制流来调节编译过程。
Qmake在创建Makefile.target的时候会读取pro文件。
下面介绍下重要的语法信息并以实例说明:
1.语法要点
(1)变量
Qmake在写Makefile文件时会在工程文件中查找变量信息,然后根据信息的内容来写Makefile文件。
HEADERS---工程中的头文件信息,qmake一般会自动提取头文件信息,不需要研发人员手工添加。
SOURCES--工程中的源文件信息,qmake一般会自动提取头文件信息,不需要研发人员手工添加。
CONFIG--工程配置信息,工程文件中最重要的一个变量,
DESTDIR--可执行文件或二进制文件的安装信息
INTERFACES--ui文件信息,如果ui文件存在,则会调用uic来进行编译该文件。
RESOURCES--资源文件信息
TEMPLATE--说明编译过程输出的文件类型是应用程序、库、插件,qmake会根据该变量生成适当的Makefile文件。
它允许的值说明如下:
app–缺省值,为编译应用程序创建一个makefile。
lib–为编译库创建一个makefile。
subdirs–为在子目录中编译目录创建一个makefile。
vcapp-win32仅创建一个应用程序项目文件。
vclib–win32仅创建一个库项目文件。
TARGET-可执行应用程序的名称。
默认值为项目文件的名称。
(如果需要扩展名,会被自动加上。
)
DEFINES-应用程序所需的额外的预处理程序定义的列表。
INCLUDEPATH-应用程序所需的额外的包含路径的列表。
DEPENDPATH-应用程序所依赖的搜索路径
(2)常用函数
CONFIG(config)--通过设置范围条件,可以检查某些模块是否可用,
如判断OpenGL模块是否可用:
CONFIG(opengl)
{
message(BuildingwithOpenGLsuport);
}
else
{
message(OpenGLsupportisnotavailable);
}
contains(variablename,value)
检查variablename中是否包含value,如果包含,则返回true,否则返回false。
如检查驱动中是否包含了网络驱动:
contains(drivers,network)
{
message("Configuringfornetworkbuild...")
HEADERS+=network.h
SOURCES+=network.cpp
}
exists(filename)
测试文件filename是否存在。
include(filename)
测试文件filename是否包含在当前工程中。
如果没有包含,将该文件包含。
for(iterate,list)
一个提供循环测试能力的函数。
system(command)
在Shell中执行command命令。
1.2实例
下面用一个实际使用的.pro文件为例来说明.pro文件中的语法,这个test.pro文件将各个.cpp及.h文件连接成一个应用程序,test.pro分析如下:
#qt表示连接qt相关库,warn_on表示打印警告信息,thread表示这是一个多线程应用程序。
CONFIG+=qtwarn_onthread
TEMPLATE=app#创建应用程序的Makefile
#函数include把文件default.cfg的内容插到这里,函数返回值表示是否执行成功。
include(./$$PRODUCT/default.cfg)
merge_app{
DEFINES+=TEST_MERGE_APPLICATIONS
}
#放置可执行程序目标的目录。
DESTDIR=$(TEST_APP_BASE)/am/data
#可执行应用程序的名称。
默认值为项目文件的名称。
TARGET=am
#JavaSession:
#应用程序中用到的预处理定义列表。
DEFINES+=JAVA_SESSION
DEFINES+=AMRAD_DEBUG_MODE
#应用程序所需的头文件列表
HEADERS=\
$(TEST_APP_BASE)/am/mainscreen/engine/AM_StartupInit.h\
$(TEST_APP_BASE)/testsync/ui/usb_control.h
#应用程序所需的源文件列表
SOURCES=\
$(TEST_APP_BASE)/testsync/ui/usb_control.c
#如果MAKE_FTR_LED存在于DEFINES变量的值的列表中
contains(DEFINES,MAKE_FTR_LED){
HEADERS+=\
$(TEST_APP_BASE)/am/mainscreen/engine/AM_LED_EventManager.h
SOURCES+=\
$(TEST_APP_BASE)/am/mainscreen/engine/AM_LED_EventManager.cpp
}
#应用程序的include路径的列表
INCLUDEPATH+=\
$(TEST_APP_BASE)/include\
$(TEST_APP_BASE)/utility/inc\
/vobs/test_api/code/utility/inc
}
#unix表示qmake将在unix模式运行,这种模式下将使用unix文件命名和路径转换,
#在unix下这是缺省模式。
#LIBS变量包括连接进项目的库的链表,如果你使用了-L/-l的unix转换,
#那么,你可以在交叉编译方式下任意使用它们,
#qmake将会在Windows上正确使用这些库(即传递库的全路径给连接器),
#qmake在-L所指路径下找到-l所指的库。
unix:
LIBS+=-L$(TEST_APP_BASE)/lib
unix:
LIBS+=-ltestdb
#如果CONFIG变量链表中含有debug,即是调试版本
contains(CONFIG,debug){
contains(QMAKE_LINK,g++){#含有g++,即x86下的调试版本
DEFINES+=AM_X86
unix:
LIBS+=-ltest-x86-d
unix:
LIBS+=-ltestasprofile-x86-d
}
contains(QMAKE_LINK,arm-linux-g++){#含有arm-linux-g++,即armcpu下的调试版本
unix:
LIBS+=-ltest-xscale-d
unix:
LIBS+=-ltestringtone-play-xscale-d
unix:
LIBS+=-ltestasprofile-xscale-d
}
#CONFIG变量中含有relese,表示是发布版本
contains(CONFIG,release){
contains(QMAKE_LINK,g++){#含有g++,即x86下的发布版本
DEFINES+=AM_X86
unix:
LIBS+=-ltestopenwindow-x86-r
unix:
LIBS+=-lteststaticidle-x86-r
}
#含有arm-linux-g++,即armcpu下的发布版本
contains(QMAKE_LINK,arm-linux-g++){
unix:
LIBS+=-ltestam-xscale-r
unix:
LIBS+=-ltestopenwindow-xscale-r
}
}
#这是国际化语言文件
TRANSLATIONS=\
$(TEST_APP_BASE)/am/am_zh-cn.ts
注:
pro文件完成后,使用qmake-oMakefile.target*.pro命令生成Makefile.target文件
2.Qtopia编译系统
Qtopia通过.pri和.pro文件对编译系统进行分层管理,.pri和.pro文件都是被qmake使用的项目文件,它们的格式一样,.pri文件被.pri或.pro文件包括(使用include语句),.pro文件直接被用来产生Makefile文件。
Qtopia项目文件的层次及configure脚本生成的Makefile层次如图1所示。
configure脚本通过用户选择的编译选项生成config.pri项目文件,在编译的过程中会用这些编译选项。
.qmake.cache用来重定向到config.pri文件。
configure脚本使用qmake命令将各个目录下的.pro文件生成Makefile.target。
顶层的Makefile.src-component包括的是相互无依赖关系的应用程序或插件的项目,顶层的Makefile.target是应用程序所依赖的库的项目。
顶层的Makefile是用户在configure脚本中手动配置的编译入口选项。
在使用make命令进行编译时,编译器先从Makefile找到编译入口,再使用Makefile.target编译被依赖的库,同时Makefile.target文件中使用make来调用Makefile.src-component来编译无依赖关系的应用程序及插件。
图1 Qtopia项目文件的层次及configure脚本生成的Makefile层次
2.1内部的编译系统项目文件说明
Qtopia的顶层项目文件为src.pro文件,它包括了下面几个.pri项目文件,这些.pri文件用来定义了哪些源代码文件需要编译,它们提供了分层管理,方便编译时的文件选择。
与生成Qtopia的顶层Makefile相关的项目文件说明如下:
$QPEDIR/src/config.pri被configure脚本产生,configure脚本将用户选定的选项转换成参数变量。
config.pri在其它每个项目文件处理之前被处理,它的值可被重写。
src/global.pri在其他每个项目文件处理之后被处理,它存有使用可用的设置,如:
如何编译ipkg,如何连接通用库等。
src/ipk_groups.pri在大多情况下,一个项目为一个ipkg。
有时候,多于一个项目在一个ipkg中。
这个文件定义了如何编译这样的一个包。
projects.pri统率来自general.pri、commercial.pri、custom.pri和local.pri的一个项目链表。
src.pro和src-components.pro指定编译的项目。
src.pro文件统率需要以特定次序编译的项目,而src-components.pro文件统率能以任何次序被编译的项目。
来自src.pro的项目在来自src-components.pro项目之前被编译。
src.pro是用来产生顶层的Makefile。
它还知道如何编译在控件文件中的ipkg,因为它们没有.pro文件。
其中,projects.pri文件中包括的几个.pri文件说明如下:
general.pri链接了在所有Qtopia源代码包里的构件,包括所有的GPL和商业版下发布的Qtopia核心源代码。
commercial.pri链接了商业版特有的Qtopia源代码包。
custom.pri链接了用户配置部分的源代码包。
在上面几个.pri项目文件中,通过定义几个项目链表变量,将各种源代码分类链接在一起。
项目链表按次序处理,这样所有的库在应用程序之前编译。
项目链表说明如下:
LIBRARY_PROJECTS--应用程序和插件用的库文件源代码链表。
APP_PROJECTS--应用程序源代码链表。
PLUGIN_PROJECTS--插件和java程序的源代码链表。
THEME_PROJECTS--主题相关的链表。
(1)projects.pri文件
projects.pri文件它将不同类型的源代码分别使用不同的.pri文件来描述,projects.pri文件统管这几个.pri文件。
projects.pri文件列出如下:
!
contains(processed_pri,projects.pri){
processed_pri+=projects.pri
include($${QTOPIA_DEPOT_PATH}/src/general.pri)
include($${QTOPIA_DEPOT_PATH}/src/commercial.pri)
include($${QTOPIA_DEPOT_PATH}/src/custom.pri)
include($$(QPEDIR)/src/local.pri)
LIBRARY_PROJECTS=$$CORE_LIBRARY_PROJECTS$$LIBRARY_PROJECTS
#如果LIBRARY_PROJECTS中包括了libraries/handwriting,则因为重复必须删除一个
!
contains(LIBRARY_PROJECTS,libraries/handwriting){
PLUGIN_PROJECTS-=plugins/inputmethods/handwriting\
plugins/inputmethods/fshandwriting
APP_PROJECTS-=settings/handwriting
}
……
}
(2)config.pri文件
config.pri文件是在运行configure脚本的过程中产生的,它用变量说明了用户给出的选项,config.pri文件部分说明如下:
!
contains(PROCESSED_PRI,config.pri){#确保include进一次
PROCESSED_PRI+=config.pri
QTOPIA_DEPOT_PATH=/home/test/qt_soft/qtopia-free-2.1.1 #源代码所在目录
QTOPIA_ICON_SIZES=141622
QTOPIA_DISP_SIZES=P
QTOPIA_DISP_WIDTH=
QTOPIA_DISP_HEIGHT=
QTOPIA_DISP_ROTS=090180270
CONFIG+=warn_on#打印警告信息
CONFIG+=debug#编译成调试版本
...
QMAKE_POST_INCLUDE_FILES=$${QTOPIA_DEPOT_PATH}/src/global.pri
LANGUAGES=en_US
...
QPE_VERSION=2.1.1
CONFIG+=buildQtopia#编译成Qtopia版本
CONFIG+=defaultbuttons
QTOPIA_ARCHITECTURE=x86 #是能x86下运行的版本
QTOPIA_ARCH=x86
QCONFIGDEFINE=QCONFIG=\"qconfig-qpe.h\"
......
CONFIG+=qt3
include($${QTOPIA_DEPOT_PATH}/src/projects.pri)
}
(3)ipk_groups.pri文件
ipk_groups.pri文件定义了安装插件相关的变量名,其中的一个calc包的定义列出如下:
#calc包
QTOPIA_CALC_PACKAGE=libraries/qtopiacalc\
applications/calculator\
plugins/calculator/simple
contains(QTOPIA_CALC_PACKAGE,$${QTOPIA_ID}){
PACKAGE_NAME=qpe-calculator#插件名
IPK_GROUP_PROJECTS=$${QTOPIA_CALC_PACKAGE}
#插件的描述
PACKAGE_DESCRIPTION=ApluggablecalculatorfortheQtopiaenvironmentthatincludesasimpleinterface.
}
......
(4)general.pri文件
general.pri文件定义了需要加入的普通项目,即需要加入的核心应用程序以及它们所需要的库和插件,general.pri文件部分列出如下:
SERVER=server
#最基本的库,必须加入
CORE_LIBRARY_PROJECTS+=qtlibraries/qtopia
CORE_LIBRARY_PROJECTS+=libraries/qtopia1
...
!
QTOPIA_CORE{#核心库
LIBRARY_PROJECTS+=\
libraries/qtopiapim\
libraries/mediaplayer\
libraries/qtopiacalc
!
QTOPIA_PHONE:
THEME_PROJECTS+=mediaplayer/techno
LIBRARY_PROJECTS+=libraries/qtopiapim1
}
...
!
QTOPIA_CORE{#核心应用程序
APP_PROJECTS+=\
applications/addressbook\
applications/calculator\
applications/camera\
applications/clock\
...
}
...
PLUGIN_PROJECTS+=\
plugins/decorations/flat\
plugins/fontfactories/freetype\
plugins/imagecodecs/notepad\
...
QTOPIA_PDA{#PDA需要加入的应用程序及插件
APP_PROJECTS+=\
applications/today\
games/mindbreaker\
settings/appservices\
settings/buttoneditor\
...
PLUGIN_PROJECTS+=\
plugins/applets/batteryapplet\
plugins/applets/brightness\
plugins/applets/clipboardapplet\
plugins/applets/clockapplet\
...
}
......
(5)global.pri文件
global.pri项目文件在其他每个项目文件后执行,它存有各种全局的设置,如:
如何编译ipkg,如何连接通用库及库之间的依赖关系等。
global.pri项目文件部分列出如下:
!
contains(PROCESSED_PRI,global.pri){#确保include进一次
PROCESSED_PRI+=global.pri
include($${QTOPIA_DEPOT_PATH}/src/projects.pri)
#将所有的项目放在一个链表中
ALL_PROJECTS=$${LIBRARY_PROJECTS}$${APP_PROJECTS}$${PLUGIN_PROJECTS}$${SERVER}$${THEME_PROJECTS}
#各种通用库的连接方法,这里的依赖关系转换成Makefile.target中库的依赖关系。
!
contains(TEMPLATE,subdirs){
qtopiaapp:
CONFIG+=qtopia
qtopia:
CONFIG+=qtopialibqtopiainc
#加入基本库的连接到LIBS中
qtopiadesktop{
CONFIG+=desktop
!
contains(TARGET,qdbase){
LIBS=-lqd-qdbase$$LIBS
win32:
DEFINES+=QDBASE_DLL
}
qtopialib:
LIBS+=-lqd-qpe
...
}
......
#设置路径
CONFIG+=link_prlcreate_prldepend_prl
qtest:
INCLUDEPATH+=$$(QTESTDIR)/qtestlib
......
#Ipkgroups
include($${QTOPIA_DEPOT_PATH}/src/ipk_groups.pri)
......
desktop{
requires(!
isEmpty(DQTDIR))
CONFIG+=thread
INCLUDEPATH=$${DQTDIR}/include$${INCLUDEPATH}
DEPENDPATH=$${DQTDIR}/include$${INCLUDEPATH}
win32:
QMAKE_MOC=$${DQTDIR}\bin\moc.exe
else:
QMAKE_MOC=$${DQTDIR}/bin/moc
win32:
QMAKE