QMake和CMake
区别和相同点
qmake和cmake两者都用来构建系统,都生成一个Makefile,该文件由make读取以构建项目,告诉编译器和链接器该做什么,以创建可执行文件(或动态或静态库)。qmake专注于使用Qt的项目,QtCreator可以轻松生成项目文件(适合初学者),并由QtCreator支持;CMake用于广泛的项目,支持多种平台和语言,受多个IDE支持:例如QtCreator,Visual Studio,生成多个IDE的项目描述,包含简化Qt使用的命令(最重要:automoc)。如果项目使用Qt,则最好使用qmake。 CMake更通用,几乎适合任何类型的项目。
如果项目使用Qt,但又不想使用qmake,则必须自己做一些事情:运行元对象编译器(MOC),包含路径(告诉编译器在哪里寻找Qt标头),链接(告诉链接器在哪里寻找Qt库)。
QMake语法
变量
工程文件中,变量用于保存字符串列表。简单工程中,变量会告诉qmake使用的配置选项,提供在构建过程中使用的文件名和路径。
qmake会在工程文件中查找某些变量,变量的内容将决定哪些内容会生成到MakeFile。例如,HEADERS和SOURCES变量的列表值会告诉qmake相关的头文件和源文件(工程文件所在目录)。
变量可以用于存储临时的列表值,覆写存在的列表值或是扩展新的值。下列代码显示了如何赋值列表值给变量:
1 HEADERS = mainwindow.h paintwidget.h
注意:第一种赋值方法只包括同一行指定的值。第二种赋值方法会使用“\”字符分隔列表值的项。
变量的列表值可以使用如下方式扩展:
1 SOURCES = main.cpp mainwindow.cpp \ 2 paintwidget.cpp 3 4 CONFIG += qt
- CONFIG是一个qmake生成MakeFile文件时的特殊变量。
- qmake会识别下列变量的值,并描述变量的内容。
- CONFIG:通用工程配置选项
- DESTDIR:可执行文件或库文件的输出目录
- FORMS:由uic处理的UI文件列表
- HEADERS:构建工程使用的头文件列表
- QT:Qt相关配置选
- RESOURCES:包含到最终工程的资源文件列表
- SOURCES:用于构建工程的源文件列表
- TEMPLATE:构建工程的模板,决定构建过程输出一个应用,一个库或是一个插件
变量的内容可以通过在变量名称前加“$$”符号来访问,用于将一个变量的内容赋值给另一个变量。、
1 TEMP_SOURCES = $$SOURCES
$$操作符可以被扩展用于操作字符串和值列表的内置函数中。
通常,变量用于包含空格分隔符的值列表,但有时需要指定包含空格的值,必须使用双引号包含。
1 DEST = "Program Files"
引号内的文本在值列表内作为单个值对待。类似的方法可以用于处理包含空格的路径,尤其是在Windows平台定义INCLUDEPATH和LIBS变量。
1 win32:INCLUDEPATH += "C:/mylibs/extra headers" 2 3 unix:INCLUDEPATH += "/home/user/extra headers"
注释
可以在工程文件中增加注释。注释需要#符号开头,直到#所在行结束。
1 # Comments usually start at the beginning of a line, but they 2 3 # can also follow other content on the same line.
为了在变量赋值中包括#,必须使用内置变量LITERAL_HASH。
内置函数和控制流
qmake提供了多个内置函数用于处理变量内容。在简单工程中,最常使用的函数是使用一个文件名作为参数的include函数。在工程文件中,给定文件的内容会被包含在include函数调用的位置。 include函数最常用于包含其它工程文件.pro。
1 include(other.pro)
通过代码块作用域可以实现类似编程语言中IF语句的行为,支持条件控制结构。
1 win32 { 2 3 SOURCES += paintwidget_win.cpp 4 }
只有条件为true时,括号内的赋值才会有效。在这个例子中,特殊变量win32必须被设置。在 Windows平台上,win32会自动设置。当在其它平台上,通过运行带-win32参数选项的qmake可以指定win32。左括号必须与条件在同一行。
使用for函数通过遍历列表值可以构建一个简单的循环。下列代码会在目录存在的情况下增加目录到SUBDIRS变量。
1 EXTRAS = handlers tests docsfor(dir, EXTRAS) { 2 exists($$dir) { 3 SUBDIRS += $$dir 4 }}
对变量进行更复杂的操作可以通过内置函数find、unique、count。内置函数可以提供对字符串、路径的操作,支持用户输入,并调用其它外部工具。
工程模板
TEMPLATE变量用于定义构建的工程的类型。如果工程文件中没有声明TEMPLATE变量,qmake会默认构建一个应用程序,并生成一个MakeFile文件。
下列时可用工程类型:
- app:创建一个构建应用程序的MakeFile
- lib:创建一个构建库的MakeFile
- subdirs:创建一个包含使用SUBDIRS变量指定子目录的规则的MakeFile,每个子目录必须包含自己的工程文件。
- vcapp:创建一个构建应用程序的Visual Studio平台的工程文件
- vclib:创建一个构建库的Visual Studio平台的工程文件
- vcsubdirs:创建一个在子目录构建工程的Visual Studio平台的解决方案文件
当使用subdirs模板时,qmake会生成一个MakeFile检查每个子目录,处理查找到的任何工程文件。并且在新生成的MakeFile上运行平台的make工具。SUBDIRS变量用于包含要处理的子目录列表。
通用配置
CONFIG变量用于指定编译器使用的选项和属性以及链接库。CONFIG变量可以增加任何选项,但是本节所述选项会被qmake内部识别。
下列选项控制用于构建工程的编译器选项:
- release:工程使用release模式构建,如果debug也被指定会被忽略。
- debug:工程使用debug模式构建
- debug_and_release:工程使用debug和release两种模式构建
- debug_and_release_target:工程使用debug和release两种模式构建,目标会被构建到debug和release两个目录下
- build_all:如果指定debug_and_release,工程默认使用debug和release两种模式构建
- autogen_precompile_source:自动生成.cpp文件,包含在.pro文件中指定的预编译头文件
- ordered:当使用subdirs模板时,本选项会指定按照列出的目录给定的顺序处理
- warn_on:编译器会尽可能多输出警告信息,如果指定warn_off,警告信息会被忽略
- warn_off:编译器尽可能少的输出警告信息
- copy_dir_files:打开要复制目录安装规则,而不只复制文件
- debug_and_release选项是一个特殊选项,会开启工程的debug和release两种版本构建。qmake生成的MakeFile文件会包含两种版本的构建规则,使用下列方式进行调用:
make all
增加build_all选项到CONFIG变量会生成构建工程的默认规则,并且创建debug和release版本的安装目标。
注意:CONFIG变量指定每个选项可以用于条件作用域。可以使用CONFIG内置函数测试某个配置选项的表现。下列代码将展示CONFIG函数作为作用域的条件,测试opengl选项是否在用。
1 CONFIG(opengl) { 2 message(Building with OpenGL support.) 3 } 4 else { 5 message(OpenGL support is not available.) 6 }
下列选项会定义构建工程的类型,注意,某些选项只有在特定平台才会生效。
- qt:工程是一个Qt应用程序,会链接Qt库。可以使用QT变量控制应用程序需要的任何附加Qt模块
- thread:工程是一个多线程应用程序
- x11:工程是一个X11应用程序或库
当使用应用程序或库的工程模板时,很多配置选项用于微调构建过程。例如,如果应用程序使用Qt库,并且在debug模式构建多线程应用时,工程文件如下:
1 CONFIG += qt thread debug
注意:必须使用“+=”而不是“=”,否则qmake不会使用Qt配置决定工程需要的设置。
声明Qt库
如果CONFIG变量包含qt,qmake对Qt应用程序的支持会开启,这会使微调应用程序的Qt模块变得可能。用于声明需要扩展模块的QT变量可以实现微调。例如,可以使用下列代码开启XML和network模块:
1 CONFIG += qt 2 3 QT += network xml
注意QT默认包含core和gui模块,上述代码会增加network和xml模块到默认值列表。下列代码将会忽略默认模块,这会导致应用程序源码编译时错误。
1 QT = network xml # This will omit the core and gui modules
如果要不使用gui模块构建工程,可以使用“-=”排除gui模块。默认情况下,QT包含core和gui两个模块,所以下列代码会构建一个最小化工程。
1 QT -= gui # Only the core module is used.
下列选项可以用于QT变量:
- Core:QtCore模块,默认包含
- Gui:QtGui模块,默认包含
- Network:QtNetwork模块
- Opengl:QtOpenGL模块
- Sql:QtSql模块
- Svg:QtSvg模块
- Xml:QtXml模块
- Xmlpatterns:QtXmlPatterns
- qt3support:Qt3Support模块
注意,增加opengl选项到QT变量会自动促使相应选项到增加到CONFIG变量。因此,对于Qt应用程序,增加opengl选项到QT和CONFIG变量不是必须的。
配置特性
qmake可以使用特性文件.prf文件设置额外的配置特性。这些额外特性常常提供了对构建过程中自定义工具的支持。为了增加特性到构建过程,可以增加特性名称到CONFIG变量。
例如,qmake可以利用pkg-config支持的外部库对构建过程进行配置,例如D-Bus或ogg外部库,代码如下:
1 CONFIG += link_pkgconfig 2 3 PKGCONFIG += ogg dbus-1
声明第三方库
如果在工程中使用除Qt支持的库以外的第三方库,需要在工程文件中指定。
qmake搜索库的路径和要链接的特定库要加入到LIBS变量的列表值中。给出库本身的路径,或是指定库的类unix风格标记和路径可以优先使用。
例如,下列代码展示如何指定库:
1 LIBS += -L/usr/local/lib -lmath
包含头文件的路径可以使用INCLUDEPATH变量指定。
QMake命令行使用
当qmake有多个选项在命令行运行,qmake的行为可以被自定义。qmake选项可以微调构建过程,提供有用的诊断信息,并指定工程的目标平台。
语法
qmake的使用采用下列简单形式:
1 qmake [mode] [options] files
Qmake支持两种不同的操作模式:默认模式下,qmake会使用工程文件的信息生成MakeFile文件,但qmake也可以生成工程文件。如果要显示设置模式,必须在其它所有选项前指定模式。模式有下列两个选项值:
- -makefile:qmake生成MakeFile
- -project:qmake生成工程文件,生成的过程文件可能需要编辑。
通用选项参数
为了自定义构建过程和覆写平台的默认设置,qmake可以在命令行指定一系列参数选项。下列基本选项提供有用的信息,指定qmake输出的文件的位置,控制输出到控制台调试信息的水平。
- -help:qmake会回顾特性,给出有用帮助信息
- -o file:qmake的输出会被重定向到file 文件。如果本选项不指定,qmake会根据运行的模式为输出选择一个合适的文件名。如果指定了“-”,输出定向到stdout。
- -d:qmake会输出调试信息
对于每个目标平台都需要不同构建的有多个子目录的工程,qmake可以使用下列选项在每个工程文件中设置相应特定平台的变量。
- -unix:qmake运行在unix模式,会使用unix的文件和路径命名规范,增加对unix的测试会成功,是所有的类unix平台的默认模式。
- -macx:qmake运行在Mac OS X模式,会使用unix的文件和路径命名规范,增加对macx的测试会成功,是Mac OS X平台的默认模式。
- -win32:qmake运行在win32模式,会使用Windows的文件和路径命名规范,增加对win32的测试会成功,是Windows平台的默认模式。
工程使用的模板通常在工程文件中使用TEMPLATE变量设置,可以使用下列选项覆写或修改:
- -t tmpl:qamke会使用tmpl设置TEMPLATE变量,但仅在.pro文件被处理后。
- -t prefix:增加前缀prefix到TEMPLATE变量
调整警告信息的水平可以帮助找到工程文件中的问题。
- -Wall:qmake会报告已知的所有警告信息
- -Wnone:不生成任何警告信息
- -Wparser:qmake只会生成解析警告信息,解析警告信息会在解析工程文件过程中提醒开发者常见的陷阱和潜在问题。
- -Wlogic:qmake会警告工程文件中的常见陷阱和潜在问题。例如,如果一个文件是否被多次放到文件列表中,或是如果文件没有找到,qmake会警告。
MakeFile模式选项
qmake -makefile [options] files
在makefile模式,qmake会生成用于构建工程的makefile文件。此外,下列选项可以被用于makefile模式中:
- -after:qmake会在指定文件后的命令行上处理给定赋值
- -nocache:qmake会忽略.qmake.cache文件
- -nodepend:qmake不会生成任何依赖信息
- -cache file:qmake会使用file作为缓存文件,其它的.qmake.cache文件会被忽略。
- -spec spec:qmake会使用spec作为平台和编译器信息的路径,QMAKESPEC变量的值会被忽略。
可以在命令行上进行qmake赋值,赋值会在指定的所有文件处理。例如:
1 qmake -makefile -unix -o Makefile “CONFIG+=test” test.pro
如果确定变量在指定文件后被处理,可以使用-after选项。当-after选项指定,在-after后的所有命令行的赋值会被延迟到指定文件被解析后进行。
工程模式选项
1 qmake -project [options] files
在project模式下,qmake会生成一个工程文件。可以在project模式下使用下列选项:
- -r:qmake会递归处理给定的目录
- -nopwd:qmake不会查找当前源码的工作路径,只使用指定文件。
在project模式下,files参数是文件或目录列表。如果指定一个目录,会被包含到DEPENDPATH变量,相关代码会包含到生成的工程文件中;如果给定一个文件,会被追加到依赖于扩展的合适变量。例如,UI会被增加到FORMS变量,C++文件会被增加到SOURCES变量。
QMake平台相关事项
很多跨平台工程使用qmake的基本配置和特性进行处理。在一些平台上,利用平台相关特性有时是有用的,甚至是必须的。qmake直到很多特性,这些特性只能通过特定变量访问,特定变量只在独立平台上有效。
1、Mac OS X平台
本平台特有的特性包括支持创建通用二进制文件、框架和捆绑包。
A、源包和二进制包
源包中提供的qmake版本与二进制包中提供的配置略有不同,因为它使用了不同的特性规范。源包通常使用macx-g++规范,二进制包通常被配置为使用macx-xcode代码规范。
每个包的用户需要使用-spec参数选项调用qmake覆写配置。例如,在一个工程目录使用下列命令可以从一个二进制包生成Makefile文件:
1 qmake -spec macx-g++
B、框架使用
qmake会自动生成链接框架的构建规则,这些框架的标准框架路径在Mac OS X平台下是/Library/Frameworks/。
除了标准框架目录之外,需要向构建系统指定目录,通过增加链接器选项到QMAKE_LFLAGS变量可以实现。
1 QMAKE_LFLAGS += -F/path/to/framework/directory/
框架本身会通过附加-framework选项和框架的名称被链接到LIBS变量。
1 LIBS += -framework #TheFramework
C、创建框架
任何给定的库项目都可以被配置,以便生成的库文件放置在准备部署的框架中。通过设置工程使用lib模板,并增加lib_bundle选项到CONFIG变量可以实现。
1 TEMPLATE = lib 2 3 CONFIG += lib_bundle
与库关联的数据使用QMAKE_BUNDLE_DATA变量指定。这将保存将使用库捆绑包进行安装的项,并且通常用于指定头文件集合。例如:
1 FRAMEWORK_HEADERS.version = Versions 2 3 FRAMEWORK_HEADERS.files = path/to/header_one.h path/to/header_two.h 4 5 FRAMEWORK_HEADERS.path = Headers 6 7 QMAKE_BUNDLE_DATA += FRAMEWORK_HEADERS
FRAMEWORK_HEADERS是用户定义的变量,用于定义使用特殊框架所需的头文件。追加FRAMEWORK_HEADERS到QMAKE_BUNDLE_DATA变量,确保头文件信息被增加到所安装的库捆绑包的资源集合中。框架的名称和版本由变量QMAKE_FRAMEWORK_BUNDLE_NAME和QMAKE_FRAMEWORK_VERSION指定,默认情况下,使用TARGET和VERSION变量的值。
D、创建通用二进制包
为了创建应用程序的通用二进制包,需要使用已经配置了-universal选项的Qt版本。
在二进制包中,支持的架构通常在CONFIG变量指定。例如,下列代码会使qmake生成同时支持PowerPC 和X86架构的通用二进制包的构建规则。
1 CONFIG += x86 ppc
此外,开发者使用PowerPC平台需要设置QMAKE_MAC_SK变量。
E、创建和移动XCode项目
MAC OS X平台的开发者可以利用qmake对XCode工程文件的支持,通过运行qmake从已有的qmake工程文件生成一个XCode工程。
1 qmake -spec macx-xcode project.pro
注意:如果工程在磁盘上进行了移动,需要再次运行qmake处理工程文件生成一个XCode工程。
F、同时支持两种构建目标
要实现同时支持两个构建目标目前并不可行,因为在概念上,主动构建配置的XCode概念不同于qmake构建目标的概念。
XCode主动构建配置用于修改xcode配置、编译器选项以及类似的构建选项。不像Visual Studio,XCode不允许基于构建配置是否选择debug或release来选择特定的库文件。Qmake的debug和release设置会控制链接到执行文件的库文件。
目前不可能在qamke生成的XCode工程文件中设置XCode设置中的文件。
此外,所选的主动构建配置存储在.pbxuser文件中,.pbxuser文件是由XCode在第一次加载中生成的,而不是qamke创建的。
2、Windows平台
Windows平台特有的特性包括在部署Visual Studio 2005开发的Qt应用程序时支持创建Visual Studio工程文件和处理清单文件。
A、创建Visual Studio工程文件
使用Visual Studio编写Qt应用程序的开发人员可以使用Qt商业版提供的Visual Studio集成工具,而不必担心如何管理项目依赖关系。
但是,某些开发者可能需要导入已经存在的qmake工程到Visual Studio。qmake能够利用工程文件创建一个包含开发环境所需必须信息的Visual Studio工程。通过设置qmake工程模板为vcapp或vclib可以实现,可以使用命令行进行:
1 qmake -tp vc
在子目录递归生成.vcproj文件和在主目录生成文件如下:
1 qmake -tp vc -r
每次更新工程文件时,需要运行qmake生成一个更新的Visual Studio工程。
注意:如果使用Vi
B、Visual Studio 2005 Manifest文件
当部署使用Visual Studio 2005构建的Qt应用程序时,确保应用程序链接时创建的Manifest文件被正确处理是必须的。对于生成DLL的工程来说是自动处理的。
移除嵌入在应用程序可执行文件的manifest文件可以使用下列赋值给CONFIG变量完成:
1 CONFIG -= embed_manifest_exe
移除嵌入在应用程序DLL文件的manifest文件可以使用下列赋值给CONFIG变量完成:
1 CONFIG -= embed_manifest_dll
3、Symbian平台
Symbian平台特有的特性包括处理静态数据,兼容性,栈和堆大小,编译器特定选项,应用程序或库的唯一标识符。
A、处理静态数据
如果应用程序使用了任何静态数据,构建系统需要了解这些静态数据。这是因为Symbian系统会试图在没有使用静态数据的情况下节省内存。
若要指定静态数据支持,将其添加到项目文件中:
1 TARGET.EPOCALLOWDLLDATA = 1
默认值为0
B、栈和堆大小
Symbian平台使用预定义大小的堆栈和堆。如果应用程序超过任一限制,则可能崩溃或无法完成其任务。毫无理由的崩溃常常可以追溯到堆栈和堆大小不足。
堆栈大小具有最大值,而堆大小具有最小值和最大值,均以字节指定。如果内存不可用,则最小值阻止应用程序启动。最小值和最大值由一个空间分隔。例如:
1 TARGET.EPOCHEAPSIZE = 10000 10000000 2 3 TARGET.EPOCSTACKSIZE = 0x8000
默认值取决于所使用的Symbian SDK的版本,但是,Qt工具链将此设置为最大可能值,并且不应该更改此值。
C、编译器特定选项
通用编译器选项通常使用QMAKE_CFLAGS和QMAKE_CXXFLAGS变量进行设置。为了设置特定的编译器选项,可以使用QMAKE_CFLAGS.<compiler>和QMAKE_CXXFLAGS.<compiler>。<compiler>可以是WINSCW架构(仿真器)的CW,或是ARMV5架构(硬件)的ARMCC,或是ARMV5架构(硬件)的GCCE。例如:
1 QMAKE_CXXFLAGS.CW += -O2 2 3 QMAKE_CXXFLAGS.ARMCC += -O0
D、唯一标识符
Symbian应用程序可能有附加的唯一标识符。下面是如何在工程文件中定义唯一标识符。
支持IDS的可用类型有四种:UID2、UID3、SID和VID。它们可以如下指定的:
1 TARGET.UID2 = 0x00000001 2 3 TARGET.UID3 = 0x00000002 4 5 TARGET.SID = 0x00000003 6 7 TARGET.VID = 0x00000004
如果未指定SID,则默认与UID3值相同。如果未指定UID3,qmake将自动生成适合开发和调试的UID3。应该为要释放的应用程序手动指定UID3值。
这儿也有一个UID1,但不会被任何应用所涉及。
UID2对于不同类型的文件具有特定的值;例如app/exes总是0x10039 CE。工具链将为最常见的文件类型(如EXE/APP和共享库DLL)设置值。
E、Capability
Capability为应用程序定义额外的特权,例如列出文件系统上的所有文件的能力。Capability在项目文件中定义如下:
1 TARGET.CAPABILITY += AllFiles
可以通过首先指定所有的能力,然后在它们前面减去不必要的能力来指定哪些能力不具备,例如:
1 TARGET.CAPABILITY = ALL -TCB -DRM -AllFiles
QMake高级功能
1、qmake高级功能简介
许多qamke工程文件使用varname=values和varname+=values定义的列表来简单描述工程使用的源文件和头文件。qamke还提供用于处理变量声明中提供的信息的其它运算符、函数和作用域。这些高级特性允许从单个工程文件生成多个平台的MakeFile文件。
2、操作符
在许多工程文件中,赋值操作符“=”和追加操作符“+=”可以用于包含有关工程的所有信息。典型的使用模式是将值列表赋值给变量,并根据各种测试的结果追加更多的值。由于qmake使用默认值定义了某些变量,因此有时需要使用移除操作符“-=”过滤出不需要的值。下面的运算符可以用来操作变量的内容。
赋值操作符“=”用于将一个值赋值给一个变量。
1 TARGET = myapp
上述代码会设置TARGET变量的值为myapp,会使用myapp覆写TARGET变量以前设置的任何值。
追加操作符“+=”用于追加一个新的值到变量的值列表中。
1 DEFINES += QT_DLL
上述代码会将QT_DLL从预处理列表的定义中移除,以将其结果放入生成的Makefile文件中。
增加操作符“*=”会增加一个值到变量的值列表中,但仅限这个值不存在的情况。“*=”操作符胡阻止一个值被多次包含到变量中。
1 DEFINES *= QT_DLL
上述代码只有在预处理列表的定义不存在QT_DLL情况下,才会将QT_DLL加入,以将其结果放入生成的Makefile文件中。
注意:unique函数也可以确保变量中每个值只包含一个实例。
“~=”操作符可以代替指定的正则表达式匹配的任何值。
1 DEFINES ~= s/QT_[DT].+/QT
上述代码,值列表中的以QT_D或QT_T开头放入任何值使用QT替换。
“$$”操作符用于提取变量的内容,用于在变量中传递值或是提供给函数使用。
1 EVERYTHING = $$SOURCES $$HEADERS 2 message("The project contains the following files:") 3 message($$EVERYTHING)
3、作用域
作用域与过程化编程语言的IF语句比较类似。如果条件为true,作用域内的声明会被处理。
A、语法
作用域由一个条件和同一行跟随的一个左括号,一系列命令和定义,新一行的右括号组成。
1 <condition> { 2 3 <command or definition> 4 5 ... 6 7 }
左括号必须与条件在同一行。作用域可能会被连接多个条件。
B、作用域和条件
条件后面的作用域是一对括号中包含的一系列声明。例如:
1 win32 { 2 3 SOURCES += paintwidget_win.cpp 4 }
如果qmake运行在Windows平台,上述代码会增加paintwidget_win.cpp源文件到生成的Makefile的源文件列表中。如果qmake运行在其它平台,定义会被忽略。
在给定作用域使用的条件也可以取反,用于提供一组可替代的声明,仅在原始条件为false时才被处理。例如,假设想要在除了Windows平台上的所有平台上处理某些事务,代码如下:
1 !win32 { 2 3 SOURCES -= paintwidget_win.cpp}
作用域可以将嵌套,以组合多个条件。例如,如果想要在某个平台包含某个特定文件,仅且在调试开启时处理。代码如下:
1 macx { 2 debug { 3 HEADERS += debugging.h 4 }}
为了省去写很多作用域,可以通过使用“:”嵌套作用域。上述嵌套作用域可以重写如下:
1 macx:debug { 2 HEADERS += debugging.h 3 }
也可以使用“:”操作符执行单行条件赋值。
1 win32:DEFINES += QT_DLL
上述代码只有在Windows平台才会增加QT_DLL到DEFINES变量。
通常,“:”操作符更像一个逻辑与操作符,用于连接多个条件,并且必须所有条件为true。
“|”操作符的行为像一个逻辑或操作符(OR),连接多个条件,只要求其中一个条件为true。
1 win32|macx { 2 3 HEADERS += debugging.h 4 }
可以通过使用else作用域来向作用域内的内容提供替代声明。如果前一个作用域的条件为false,对else作用域进行处理。例如:
1 win32:xml { 2 message(Building for Windows) 3 SOURCES += xmlhandler_win.cpp} 4 else:xml 5 { 6 SOURCES += xmlhandler.cpp 7 } 8 else 9 { 10 message("Unknown configuration") 11 }
C、配置和作用域
存储在CONFIG变量的值会被qmake特殊处理。每个可能的值都可以作为作用域的条件。例如,CONFIG的值列表可以使用opengl值扩展。
1 CONFIG += opengl
上述代码的结果是测试opengl的任何作用域都会被处理,可以利用这个特性给最终的可执行文件一个合适的名称。
1 opengl { 2 3 TARGET = application-gl 4 } 5 else { 6 7 TARGET = application 8 }
这个特性使得在不必丢失需要特定配置的所有自定义设置的情况下,就可以很容易地更改工程的配置。上述代码中,第一个作用域的声明被处理时,最终的可执行文件是application-gl。但是,如果opengl没有被指定,第二个作用域的声明会被处理,最终的可执行文件是application。
由于可以在CONFIG上设置自己的值,这提供了一种便捷的方法去自定义工程文件并微调生成的MakeFile文件。
D、平台的作用域值
除了在许多作用域条件中使用的win32、macx和unix值之外,还可以使用多种其它内置平台和编译器特定值对作用域进行测试。这些都是基于Qt的mkspecs目录中提供的平台规范。例如,工程文件中的下列代码会显示在用的当前规范和测试linux-g++规范。
1 message($$QMAKESPEC) 2 3 linux-g++ { 4 message(Linux) 5 }
只要在mkspecs目录中存在一个规范,就可以测试任何其他平台编译器组合。
在Symbian平台上,unix作用域为true。
4、变量
在工程文件中使用的很多变量是qmake在生成MakeFile文件时使用的特殊变量,例如,DEFINES,、SOURCES和HEADERS。用户可以创建自定义变量,当遇到对一个名称赋值时,qmake会使用给定的名称创建一个新的变量。例如:
1 MY_VARIABLE = value
对于自定义的变量,没有任何使用限制,因为qmake将忽略它们,除非在处理作用域时需要对它们进行评估。
通过变量名使用“$$”前缀可以将一个变量的值赋值给另一个变量。例如:
1 MY_DEFINES = $$DEFINES
第二种写法允许将变量的内容追加到另一个值,而不必用空格分隔这两个值。例如,下列代码会确保最终的可执行文件有一个包含所使用模板的名称。
TARGET = myproject_$${TEMPLATE}
变量可以用于存储环境变量的内容。
为了获取qamke运行时的环境的值,可以使用$$(…)操作符。
1 DESTDIR = $$(PWD) 2 3 message(The project will be installed in $$DESTDIR)
在上述赋值后,当工程文件被处理时,PWD环境变量的值会被读取。
为了在生成Mafkefile文件时获取环境变量值的内容,可以使用$(…)操作符。
1 DESTDIR = $$(PWD) 2 message(The project will be installed in $$DESTDIR) 3 4 DESTDIR = $(PWD) 5 message(The project will be installed in the value of PWD) 6 message(when the Makefile is processed.)
在上述代码中,当工程文件被处理时,PWD的值会被立即读取,但$(PWD)会在生成的MakeFile文件中被赋值给DESTDIR变量。这使得构建过程更加灵活,只要在处理MakeFile文件时环境变量被正确设置。
特殊的$$[…]操作符被用于访问Qt构建时的多个配置选项。
1 message(Qt version: $$[QT_VERSION]) 2 3 message(Qt is installed in $$[QT_INSTALL_PREFIX]) 4 5 message(Qt resources can be found in the following locations:) 6 7 message(Documentation: $$[QT_INSTALL_DOCS]) 8 9 message(Header files: $$[QT_INSTALL_HEADERS]) 10 11 message(Libraries: $$[QT_INSTALL_LIBS]) 12 13 message(Binary files (executables): $$[QT_INSTALL_BINS]) 14 15 message(Plugins: $$[QT_INSTALL_PLUGINS]) 16 17 message(Data files: $$[QT_INSTALL_DATA]) 18 19 message(Translation files: $$[QT_INSTALL_TRANSLATIONS]) 20 21 message(Settings: $$[QT_INSTALL_SETTINGS]) 22 23 message(Examples: $$[QT_INSTALL_EXAMPLES]) 24 25 message(Demonstrations: $$[QT_INSTALL_DEMOS])
使用这个操作符访问的变量通常用于使第三方插件与组件集成。例如,如果工程文件中有下列声明,Qt Designer插件可以与Qt Designer内置插件一起安装。
1 target.path = $$[QT_INSTALL_PLUGINS]/designer 2 3 INSTALLS += target
5、变量处理函数
qmake提供了一个内置函数的选择,以允许变量的内容被处理。内置函数处理被提供的参数,将值或值列表作为结果返回。为了将内置函数结果赋值给变量,必须对内置函数使用$$操作符,就像将一个变量的内置赋值给另一个变量一样。
1 HEADERS = model.h 2 3 HEADERS += $$OTHER_HEADERS 4 5 HEADERS = $$unique(HEADERS)
内置函数应该用于操作符的右侧。
可以自定义一个函数处理变量内容。自定义函数按如下定义:
1 defineReplace(functionName){ 2 #function code 3 }
下列函数使用一个变量作为唯一参数,使用eval内置函数从变量中提取出了一个值列表,并且编辑了值列表。
1 defineReplace(headersAndSources) { 2 variable = $$1 3 names = $$eval($$variable) 4 headers = 5 sources = 6 7 for(name, names) { 8 header = $${name}.h 9 exists($$header) { 10 headers += $$header 11 } 12 source = $${name}.cpp 13 exists($$source) { 14 sources += $$source 15 } 16 } 17 return($$headers $$sources) 18 }
6、条件判断函数
qmake提供了用于编写作用域时作为条件的内置函数。这些内置函数不会返回一个值,而是指明成功或失败。
1 count(options, 2) { 2 message(Both release and debug specified.) 3 }
这些内置函数只能用于条件表达式。
可以自定义函数提供作用域的条件。下列代码用于测试一个列表中的每个文件是否存在,如果所有的文件都存在,返回true;否则返回false。
defineTest(allFiles) { files = $$ARGS for(file, files) { !exists($$file) { return(false) } } return (true) }
7、增加新的配置特性
Qmake允许用户创建自己的特性,增加到工程文件中,通过增加名称到CONFIG变量的值列表中。