测试函数

测试函数返回一个布尔值,您可以在作用域的条件部分对其进行测试。测试函数可分为内置函数和函数库。

另请参阅替换函数

内置测试函数

基本测试函数以内置函数的形式实现。

cache(variablename, [set|add|sub] [transient] [super|stash], [source variablename])

这是一个内部函数,您通常用不着它。

该函数在 Qt 5.0 中引入。

CONFIG(config)

该函数可用于测试放在CONFIG变量中的变量。这与 scopes 相同,但它的另一个优点是可以传递第二个参数来测试活动配置。在CONFIG 变量中,值的顺序非常重要(也就是说,对于互斥值,最后一组将被视为活动配置),因此可以使用第二个参数来指定要考虑的一组值。例如

CONFIG = debug
CONFIG += release
CONFIG(release, debug|release):message(Release build!) #will print
CONFIG(debug, debug|release):message(Debug build!) #no print

由于 release 被视为活动设置(用于特征解析),因此它将是用于生成构建文件的 CONFIG。在一般情况下不需要第二个参数,但对于特定的互斥测试,第二个参数就显得非常重要了。

contains(variablename, value)

如果变量variablename 包含值value ,则成功;否则失败。可以为参数值指定正则表达式。

可以使用作用域检查此函数的返回值。

例如

contains( drivers, network ) {
    # drivers contains 'network'
    message( "Configuring for network build..." )
    HEADERS += network.h
    SOURCES += network.cpp
}

只有当drivers 变量包含值network 时,才会处理作用域的内容。如果是这种情况,就会在SOURCESHEADERS变量中添加相应的文件。

count(variablename, number)

如果variablename 变量包含一个具有指定number 值的列表,则执行成功;否则执行失败。

此函数用于确保只有在变量包含正确数量的值时,才会处理作用域内的声明。例如

options = $$find(CONFIG, "debug") $$find(CONFIG, "release")
count(options, 2) {
    message(Both release and debug specified.)
}

debug(level, message)

检查 qmake 是否在指定的调试级别下运行。如果是,则返回 true 并打印调试信息。

defined(name[, type])

测试函数或变量name 是否已定义。如果省略type ,则检查所有函数。要只检查变量或特定类型的函数,请指定type 。它可以有以下值:

  • test 只检查测试函数
  • replace 只检查替换函数
  • var 只检查变量

等于(变量名,值)

测试variablename 是否等于字符串value

例如

TARGET = helloworld
equals(TARGET, "helloworld") {
    message("The target assignment was successful.")
}

error(string)

qmake 会向用户显示string 作为错误信息并退出。此函数只能用于不可恢复的错误。

例如:eval(string)

error(An error has occurred in the configuration process.)

eval(string)

使用 qmake 语法规则评估字符串的内容并返回 true。可以在字符串中使用定义和赋值来修改现有变量的值或创建新的定义。

例如

eval(TARGET = myapp) {
    message($$TARGET)
}

注意: 可以使用引号来限定字符串,如果不需要返回值,可以将其丢弃。

exists(filename)

测试给定filename 的文件是否存在。如果文件存在,函数执行成功;否则执行失败。

filename 参数可能包含通配符。在这种情况下,如果有文件匹配,则函数成功执行。

例如

exists( $(QTDIR)/lib/libqt-mt* ) {
      message( "Configuring for multi-threaded Qt..." )
      CONFIG += thread
}

注意: 无论使用何种平台,都应使用"/"作为目录分隔符。

export(variablename)

variablename 的当前值从函数的本地上下文导出到全局上下文。

for(iterate, list)

启动一个循环,遍历list 中的所有值,依次将iterate 设置为每个值。为了方便起见,如果list 的值为 1..10,那么 iterate 将遍历 1 到 10 的值。

例如

LIST = 1 2 3
for(a, LIST):exists(file.$${a}):message(I see a file.$${a}!)

可以使用break() 中断循环。next() 语句跳过循环体的剩余部分,继续执行下一次迭代。

greaterThan(variablename, value)

测试variablename 的值是否大于value 。首先,该函数尝试进行数值比较。如果至少有一个操作数转换失败,该函数将进行字符串比较。

例如

ANSWER = 42
greaterThan(ANSWER, 1) {
    message("The answer might be correct.")
}

不可能直接将两个数字作为字符串进行比较。作为一种变通方法,可以使用非数字前缀构建临时值并进行比较。

例如

VALUE = 123
TMP_VALUE = x$$VALUE
greaterThan(TMP_VALUE, x456): message("Condition may be true.")

另请参阅lessThan()

if(condition)

计算condition 。它用于分组布尔表达式。

例如

if(linux-g++*|macx-g++*):CONFIG(debug, debug|release) {
    message("We are on Linux or Mac OS, and we are in debug mode.")
}

include(filename)

在当前项目中包含filename 指定的文件内容。如果filename 已被包含,则此函数执行成功;否则执行失败。包含的文件将立即被处理。

您可以使用此函数作为作用域的条件来检查文件是否被包含。例如

include( shared.pri )
OPTIONS = standard custom
!include( options.pri ) {
    message( "No custom build options specified" )
OPTIONS -= custom
}

infile(filename, var, val)

如果文件filename (由 qmake 本身解析时)包含值为val 的变量var ,则成功;否则失败。如果不指定val ,函数将测试文件中是否已分配var

isActiveConfig

这是CONFIG 函数的别名。

isEmpty(variablename)

如果variablename 变量为空,则成功;否则失败。它与count( variablename, 0 ) 的功能等同。

例如

isEmpty( CONFIG ) {
CONFIG += warn_on debug
}

isEqual

equals 函数的别名。

lessThan(变量名,值)

测试variablename 的值是否小于value 。与greaterThan() 类似。

例如

ANSWER = 42
lessThan(ANSWER, 1) {
    message("The answer might be wrong.")
}

load(feature)

加载feature 指定的特征文件 (.prf) ,除非该特征文件已被加载。

log(message)

在控制台上打印一条信息。与message 函数不同,它既不预置文本,也不追加换行符。

此函数在 Qt 5.0 中引入。

另请参阅message()

message(string)

总是成功,并向用户显示string 作为一般消息。与error() 函数不同,该函数允许继续处理。

message( "This is a message" )

上面一行会将 "这是一条消息 "写入控制台。可以不使用引号,但建议使用。

注意: 默认情况下,qmake 为给定项目生成的每个 Makefile 都会写入消息。如果您想确保每个项目只出现一次消息,可以在联编过程中使用build_pass 变量和作用域来过滤消息。例如

!build_pass:message( "This is a message" )

mkpath(dirPath)

创建目录路径dirPath 。该函数是QDir::mkpath 函数的封装。

该函数在 Qt 5.0 中引入。

requires(condition)

评估condition 。如果条件为 false,则 qmake 在联编时跳过该项目(及其子目录)。

注意: 您也可以使用REQUIRES变量来实现这一目的。不过,我们建议使用此函数。

system(command)

在辅助 shell 中执行给定的command 命令。如果命令返回的退出状态为零,则执行成功;否则执行失败。您可以使用作用域检查此函数的返回值。

例如

system("ls /bin"): HAS_BIN = TRUE

另请参阅system() 的 replace 变体。

touch(filename, reference_filename)

更新filename 的时间戳,使其与reference_filename 的时间戳一致。

此函数在 Qt 5.0 中引入。

unset(variablename)

从当前上下文中删除variablename

例如

NARF = zort
unset(NARF)
!defined(NARF, var) {
    message("NARF is not defined.")
}

versionAtLeast(variablename, versionNumber)

测试variablename 中的版本号是否大于或等于versionNumber 。版本号被视为以". "分隔的非负数十进制数字序列;字符串尾部的任何非数字将被忽略。比较从左到右分段进行;如果一个版本是另一个版本的前缀,则认为该版本较小。

此函数在 Qt 5.10 中引入。

versionAtMost(variablename, 版本号)

测试variablename 中的版本号是否小于或等于versionNumber 。与versionAtLeast() 类似。

此函数在 Qt 5.10 中引入。

warning(string)

总是成功,并向用户显示string 作为警告信息。

write_file(filename, [variablename, [mode]])

variablename 的值写入名称为filename 的文件,每个值单独一行。如果未指定variablename ,则创建一个空文件。如果modeappend ,且文件已经存在,则会追加而不是替换文件。

此函数在 Qt 5.0 中引入。

测试函数库

复杂的测试函数在 .prf 文件库中实现。

packagesExist(packages)

使用 PKGCONFIG 机制确定在项目解析时给定的软件包是否存在。

这对于有选择地启用或禁用功能非常有用。例如

packagesExist(sqlite3 QtNetwork QtDeclarative) {
    DEFINES += USE_FANCY_UI
}

然后,在代码中

#ifdef USE_FANCY_UI
    // Use the fancy UI, as we have extra packages available
#endif

prepareRecursiveTarget(target)

通过准备一个遍历所有子目录的目标,便于创建类似install 目标的全项目目标。例如:prepareRecursiveTarget(target)

TEMPLATE = subdirs
SUBDIRS = one two three
prepareRecursiveTarget(check)

在其 .CONFIG 中指定了have_no_defaultno_<target>_target 的子目录将被排除在此目标之外:

two.CONFIG += no_check_target

您必须将准备好的目标手动添加到QMAKE_EXTRA_TARGETS

QMAKE_EXTRA_TARGETS += check

要使目标成为全局目标,需要在每个子目录子项目中加入上述代码。此外,要让这些目标执行任何操作,非子目录子项目也需要包含相应的代码。最简单的方法是创建一个自定义功能文件。例如

# <project root>/features/mycheck.prf
equals(TEMPLATE, subdirs) {
    prepareRecursiveTarget(check)
} else {
    check.commands = echo hello user
}
QMAKE_EXTRA_TARGETS += check

例如,需要通过 .qmake.conf 将特性文件注入每个子项目:

# <project root>/.qmake.conf
CONFIG += mycheck

该函数在 Qt 5.0 中引入。

qtCompileTest(test)

编译测试项目。如果测试通过,则返回 true 并将config_<test> 添加到CONFIG变量。否则,返回 false。

要使用此函数,需要加载相应的特性文件:

# <project root>/project.pro
load(configure)

这也会将 QMAKE_CONFIG_TESTS_DIR 变量设置为项目父目录下的config.tests 子目录。加载特性文件后,可以覆盖该值。

在测试目录下,每个测试都必须有一个子目录,其中包含一个简单的 qmake 项目。下面的代码片段展示了该项目的 .pro 文件:

# <project root>/config.tests/test/test.pro
SOURCES = main.cpp
LIBS += -ltheFeature
# Note that the test project is built without Qt by default.

下面的代码片段展示了项目的主 .cpp 文件:

// <project root>/config.tests/test/main.cpp
#include <TheFeature/MainHeader.h>
int main() { return featureFunction(); }

下面的代码片段显示了测试的调用:

# <project root>/project.pro
qtCompileTest(test)

如果测试项目构建成功,则测试通过。

测试结果会自动缓存,所有子项目都可以使用这些结果。因此,建议在顶层项目文件中运行所有配置测试。

要禁止重新使用缓存结果,可向 qmake 传递CONFIG+=recheck

另请参阅load()

此函数在 Qt 5.0 中引入。

qtHaveModule(name)

检查name 指定的 Qt 模块是否存在。有关可能的值列表,请参阅QT

此函数在 Qt 5.0.1 中引入。

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.