
狠多的 qmake 项目文件都只是使用一堆 name = value 和 name += value 定义来列举该项目中使用的源文件和头文件。 qmake 还提供了其它的操作符、函数和作用域, 可用来处理 在各个变量声明中提供的信息。利用 这些高端特性,可以只用一个项目文件就为多个平台生成独特的Makefile 。
在狠多项目文件中, 可使用赋值 ( = ) 和追加 ( += )操作符 来包含一个项目中全部的信息。典型 的使用模式是, 将一组值赋值给某个变量,然后依据 各种各样的测试的结果来追加更多 的值。由于 qmake 会使用默认值来定义特定的变量,所以 ,某些时候有必要使用删除 ( -= )操作符 来 将那些不需要的值滤除掉。 以下操作符可用于对不同变量的内容进行操作。
= 操作符 将一个值赋予给某个变量:
TARGET = myapp
以上这一行代码会将 TARGET 变量的值设置为 myapp 。 这会使用 myapp 来覆盖掉之前为 TARGET 设置过的任何值。
+= 操作符 向某个变量 的值列表中追加一个新的值:
DEFINES += QT_DLL
以上这一行代码, 会将 QT_DLL 追加 到预处理器的定义列表中, 该定义列表最终会被输出到Makefile 中。
-= 操作符 从某个变量的值列表中删除一个值:
DEFINES -= QT_DLL
以上这一行代码, 会从预处理器的定义列表中删除 QT_DLL ,该定义列表最终会输出到Makefile 中。
*= 操作符 会将某个 值添加到一个变量的值列表中,但是前提 中该列表中当前还没有这个值。 这样能够避免在一个变量中多个包含同一个值。例如:
DEFINES *= QT_DLL
在以上这行代码中,只有 在预处理器的定义列表中不包含 QT_DLL 的情况下,才会将它加入。注意 , unique() 函数 也可用于确保某个变量 中 的每个值都只出现一次。
~= 操作符 会使用指定的值来替换掉任何匹配 了某个正则表达式的值:
DEFINES ~= s/QT_[DT].+/QT
在以上这行代码中,列表 中 以 QT_D 或 QT_T 开 头 的任何值 都会被替换为 QT 。
$$ 操作符 可用来提取某个变量的内容, 以便在不同变量之间传递值,或者将值传递给函数:
EVERYTHING = $$SOURCES $$HEADERS
message("The project contains the following files:")
message($$EVERYTHING)
作用 域( Scopes )与过程 式编程语言中的 if 语句类似。如果特定 的条件为真,则 该作用域之中的声明会被处理。
作用域以下元素组成:一个条件及随后在同一行出现的开括号,一组命令及定义序列,以及在新的一行出现的闭括号:
<条件> {
<命令 或定义 >
...
}
开括号 必须 与条件写在同一行 。作用 域可连接起来,以包含多于1个条件;参考 以下的示例。
一个作用域,由一个条件及之后包含在一对括号里的一组声明组成;例如:
win32 {
SOURCES += paintwidget_win.cpp
}
以上代码,如果是在Windows 平台上运行 qmake 的话, 则会将 paintwidget_win.cpp 文件添加到所生成的Makefile 中的源文件列表中。如果 qmake 不是在Windows 平台上运行,则该定义会被无视。
在指定作用域中的条件也可以反转,以提供一组替代声明,当原始条件为假时会执行该组声明。例如,假设我们想在 除 Windows 之外 的其它平台上处理某个东西。那么,我们可以反转该作用域,如下所示:
!win32 {
SOURCES -= paintwidget_win.cpp
}
作用域可以嵌套,以将多个条件组合起来。例如,假设妳想在某个特定平台上只在启用调试模式的情况下才包含某个特定文件,那么,可以这样写:
macx {
debug {
HEADERS += debugging.h
}
}
为了避免写下过多的嵌套作用域, 妳可以使用 : 操作符来对作用域进行嵌套。 上面那个例子中的嵌套作用域可以写成下面这个样子:
macx:debug {
HEADERS += debugging.h
}
妳还可以使用 : 操作符 来进行单行 的条件性赋值;例如:
win32:DEFINES += QT_DLL
以上这一行,只有在处于Windows 平台时,才会将 QT_DLL 添加 到 DEFINES 变量中。普遍 来讲, : 操作符相当 于一个逻辑 与 (AND)操作符, 它将多个条件组合到一起,并且 要求这些条件全部为真。
同样地,还有 | 操作符 , 它相当于一个逻辑 或 (OR)操作符, 它将多个条件组合到一起,并且 只要求其中有一个条件为真。
win32|macx {
HEADERS += debugging.h
}
妳还可以使用 else 作用域来为某个作用域中的那些声明提供替代声明。每个 else 作用 域会在前一个作用域中的条件为假时被处理。 这样, 妳就可以在组合多个作用域( 像之前的示例那样以 : 操作符分隔 )时写出复杂的测试条件。例如:
win32:xml {
message(Building for Windows)
SOURCES += xmlhandler_win.cpp
} else:xml {
SOURCES += xmlhandler.cpp
} else {
message("Unknown configuration")
}
CONFIG 变量 中储存的那些值会被 qmake 特殊对待。 这个变量中每个可能的值都可以用作某个作用域的条件。例如, 在 CONFIG 储存的值当中,可以追加一个 opengl 值:
CONFIG += opengl
作为 这个操作的后果,任何 一个以 opengl 为条件的作用域都会被处理。 我们可以利用这个特性来为最终的可执行程序赋予一个适当 的名字:
opengl {
TARGET = application-gl
} else {
TARGET = application
}
有了这个特性, 就可以在不丢失针对某个特定配置 的那些自定义设置选项 的情况下轻易改变某个项目 的配置。 在上面这段代码中,第一 个作用域中的声明会被处理,最终生成 的可执行程序会被命名为 application-gl 。然而 ,在未指定 opengl 的情况下,第二 个作用域中的声明会被处理,因而最终生成 的可执行程序会被命名为 application 。
由于 妳可以向 CONFIG 中加入自定义的值,因此, 妳可以利用这个特性来方便 地对项目文件进行自定义,并且对生成的Makefile进行微调。
除了在狠多作用域条件中用到的 win32 、 macx 和 unix 值之外, 还有其它内置的平台及编译器相关的值可被用作作用 域的测试条件。 这些值是基于Qt 的 mkspecs 目录中提供的那些与平台相关的规范的。例如,某个项目文件 中包含以下代码的话, 就会显示出当前使用中的规范,并且测试 是否是 在使用 linux-g++ 规范:
message($$QMAKESPEC)
linux-g++ {
message(Linux)
}
对于其它 的平台/编译器组合,只要在 mkspecs 目录中存在着针对它的一个规范,妳就可以 对它进行测试。
对于Symbian 平台 , unix 作用域为真。
项目文件 中使用的狠多变量都是 qmake 在生成Makefile时使用的特殊变量,例如 DEFINES 、 SOURCES 和 HEADERS 。 妳可以为自己的需要而创建新的变量; 当 qmake 发现针对 新变量名的赋值语句时,会创建对应名字的新变量。例如:
MY_VARIABLE = value
妳可以对自己定义的变量做任何事情,因为 ,除非 qmake 需要在处理某个作用域时计算它 们 的值, 不然的话会无视它 们 。
妳还可以在变量名之前加上$$,以将当前变量的值赋予给另一个变量。例如:
MY_DEFINES = $$DEFINES
现在,在该项目文件中的这个执行点,MY_DEFINES 变量中的内容与变量DEFINES 中的内容一致。以上代码也等价于:
MY_DEFINES = $${DEFINES}
第二种写法使得妳可以将某个变量的内容追加到另一个值之后,并且不需要在两个值之间使用空格分隔。例如,以下代码能够确保,最终生成的可执行程序的名字当中会包含所使用的模板名字:
TARGET = myproject_$${TEMPLATE}
变量 还可以用来储存环境变量的内容。 这些值,可以在 qmake 运行时被计算,也可以包含到生成的Makefile 中以便在编译项目时计算。
要想在 qmake 运行时获取某个环境变量的值,则使用 $$(...) 操作符:
DESTDIR = $$(PWD)
message(The project will be installed in $$DESTDIR)
在以上的赋值语句中, 会在处理项目文件时读取 PWD 环境变量 的值。
要想在生成的Makefile 被处理时获取某个环境变量的值,则使用 $(...) 操作符:
DESTDIR = $$(PWD)
message(The project will be installed in $$DESTDIR)
DESTDIR = $(PWD)
message(The project will be installed in the value of PWD)
message(when the Makefile is processed.)
在以上的赋值语句中, 在项目文件被处理时,会立即读取 PWD 的值,但是 ,在生成的Makefile 中, $(PWD) 也会被赋值给 DESTDIR 。 这就使得编译过程更加灵活,只要确保在 Makefile 被处理时设置了正确的环境变量就可以了。
特殊 的 $$[...] 操作符 ,可用来获取到在构建Qt 时设置的各种配置选项:
message(Qt version: $$[QT_VERSION])
message(Qt is installed in $$[QT_INSTALL_PREFIX])
message(Qt resources can be found in the following locations:)
message(Documentation: $$[QT_INSTALL_DOCS])
message(Header files: $$[QT_INSTALL_HEADERS])
message(Libraries: $$[QT_INSTALL_LIBS])
message(Binary files (executables): $$[QT_INSTALL_BINS])
message(Plugins: $$[QT_INSTALL_PLUGINS])
message(Data files: $$[QT_INSTALL_DATA])
message(Translation files: $$[QT_INSTALL_TRANSLATIONS])
message(Settings: $$[QT_INSTALL_SETTINGS])
message(Examples: $$[QT_INSTALL_EXAMPLES])
message(Demonstrations: $$[QT_INSTALL_DEMOS])
通过这个操作符访问的那些变量,通常是用来让第三方插件及组件与Qt 整合的。例如,在项目文件中加入以下声明之后,一个 Qt Designer插件就可以被安装到与 Qt Designer 的内置插件相同的目录:
target.path = $$[QT_INSTALL_PLUGINS]/designer
INSTALLS += target
qmake 提供 了一组内置函数,用于处理变量的内容。 这些函数会对提供给它们的参数进行处理,返回 一个值或者一个由值组成的列表作为结果。 为了将结果赋值给某个变量,需要 对这种类型的函数使用 $$ 操作符, 就像之前说的将一个变量的内容赋予给另一个变量一样:
HEADERS = model.h
HEADERS += $$OTHER_HEADERS
HEADERS = $$unique(HEADERS)
这种类型的函数应当在赋值语句的右侧使用(也就是说,作为一个操作数)。
可以定义妳自己的函数来处理变量的内容。按照以下形式来定义这种函数:
defineReplace(functionName){
#function code
}
以下示例函数, 它的唯一一个参数就是某个变量的名字 ,它会使用内置函数 eval() 从该变量中获取一个值列表,然后组合输出 一个文件名列表:
defineReplace(headersAndSources) {
variable = $$1
names = $$eval($$variable)
headers =
sources =
for(name, names) {
header = $${name}.h
exists($$header) {
headers += $$header
}
source = $${name}.cpp
exists($$source) {
sources += $$source
}
}
return($$headers $$sources)
}
qmake 提供 了一些可在编写作用域代码时用作条件的内置函数。 这些函数不会返回一个值,而是报告“成功”或“失败”:
count(options, 2) {
message(Both release and debug specified.)
}
这种类型的函数只应当在条件性表达式中使用。
妳也可以自己定义一些用作作用域的判断条件的函数。以下示例函数,会测试某个列表中的每个文件是否存在,如果它们全部都存在,则返回真,否则返回假:
defineTest(allFiles) {
files = $$ARGS
for(file, files) {
!exists($$file) {
return(false)
}
}
return(true)
}
qmake 允许 妳创建自己的 特性 ( features ), 将它们的名字加入到 CONFIG 变量所储存的值列表中,就可以 把对应的特性包含到项目文件中了。特性 指的是 .prf 文件 中包含的那些自定义函数和定义的集合, 这种文件可以放置到多个标准目录中去。 这些目录的位置是在多处定义的, qmake 在寻找 .prf 文件时,会按照以下顺序来查找那些位置:
1. 在 QMAKEFEATURES 环境变量列出的目录列表中查找; 这个环境变量中包含一个以冒号分隔的目录列表。
2. 在 QMAKEFEATURES 属性变量列出的目录列表中查找; 这个属性变量中 包含一个以冒号分隔的目录列表。
3. 在某个 mkspecs 目录中包含的features 目录里查找。 mkspecs 目录 可以位于 QMAKEPATH 环境变量 ( 以冒号分隔的目录列表 ) 所列出的任意一个目录之下。 ( $QMAKEPATH/mkspecs/<features> )
4. 在 QMAKESPEC 环境变量指定的 那 个目录之下的features 目录中查找。 ( $QMAKESPEC/<features> )
5. 在 data_install/mkspecs 目录之下的features 目录中查找。 ( data_install/mkspecs/<features> )
6. 在与 QMAKESPEC 环境变量所指定的那个目录处于同级的features 目录中查找。 ( $QMAKESPEC/../<features> )
会在以下特性目录中查找特性文件:
1. features/unix 、 features/win32 或 features/macx , 具体取决 于所用的平台
2. features/
例如,假设在某个项目文件中有以下赋值语句:
CONFIG += myfeatures
在这里向 CONFIG 变量中加入了一个值, qmake 在解析完了妳的项目文件之后, 就会在以上所列出的那些位置中查找 myfeatures.prf 文件。 在 Unix 类系统中,它会寻找以下文件:
1. $QMAKEFEATURES/myfeatures.prf (对于 QMAKEFEATURES 环境变量 中列出的每个目录都要寻找一次 )
2. $$QMAKEFEATURES/myfeatures.prf (对于 QMAKEFEATURES 属性变量 中列出的每个目录都要寻找一次 )
3. myfeatures.prf ( 在项目的根目录中寻找 )
4. $QMAKEPATH/mkspecs/features/unix/myfeatures.prf 和 $QMAKEPATH/mkspecs/features/myfeatures.prf (对于 QMAKEPATH 环境 变量中列出的每个目录都要寻找一次 )
5. $QMAKESPEC/features/unix/myfeatures.prf 和 $QMAKESPEC/features/myfeatures.prf
6. data_install/mkspecs/features/unix/myfeatures.prf 和 data_install/mkspecs/features/myfeatures.prf
7. $QMAKESPEC/../features/unix/myfeatures.prf 和 $QMAKESPEC/../features/myfeatures.prf
注意 : .prf 文件 的文件名必须是小写。
HxLauncher: Launch Android applications by voice commands