Qt QML 杂记

qmake 手册 014 测试函数

2020-07-17  本文已影响0人  赵者也

测试函数返回一个布尔值,我们可以在范围的条件部分测试该值。测试函数可以分为内置函数和函数库。

也可参阅 Replace Functions

1. 内置的测试函数

基本测试函数被实现为内置函数。

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

这是一个我们通常不需要的内部功能。

这个函数是在 Qt 5.0 中引入的。

1.1. 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 被认为是活动设置(用于特性解析),所以它将是用来生成构建文件的配置。在常见情况下,不需要第二个参数,但对于特定的互斥测试来说,它是很重要的。

1.2. contains(variablename, value)

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

我们可以使用范围检查此函数的返回值。

例如:

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

只有当 drivers 变量包含值 network 时,范围的内容才会被处理。如果是这种情况,将向 HEADERS 和 SOURCES 变量添加适当的文件。

1.3. count(variablename, number)

如果变量 variablename 包含指定 number 值的列表,则成功;否则失败。

此函数用于确保只有在变量包含正确数量的值时才处理范围内的声明。例如:

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

1.4. debug(level, message)

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

1.5. defined(name[, type])

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

1.6. equals(variablename, value)

测试 variablename 是否等于字符串 value。

例如:

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

1.7. error(string)

这个函数从不返回值。qmake 将 string 作为错误消息显示给用户并退出。此函数仅用于不可恢复的错误。

例如:

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

1.8. eval(string)

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

例如:

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

注意:可以使用引号来分隔字符串,如果不需要返回值,可以丢弃它。

1.9. exists(filename)

测试具有给定 filename 的文件是否存在。如果该文件存在,则函数成功;否则失败。如果为 filename 指定了正则表达式,如果有任何文件与指定的正则表达式匹配,则此函数成功。

例如:

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

注意:“/”应该用作目录分隔符,不管使用的是什么平台。

1.10. export(variablename)

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

1.11. 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}!)

1.12. 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()

1.13. 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.")
}

1.14. include(filename)

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

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

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

1.15. infile(filename, var, val)

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

1.16. isActiveConfig

这是 CONFIG 函数的别名。

1.17. isEmpty(variablename)

如果变量 variablename 为空,则成功;否则失败。这相当于 count(variablename,0)

例如:

isEmpty( CONFIG ) {
CONFIG += warn_on debug
}

1.18. isEqual

这是 equals 函数的别名。

1.19. lessThan(variablename, value)

测试 variablename 的值小于 value。工作机制类似于 greaterThan()

例如:

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

1.20. load(feature)

加载 feature 指定的特性文件(.prf),除非特性已经加载。

1.21. log(message)

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

这个函数是在 Qt 5.0 中引入的。

也可参阅 message().

1.22. message(string)

总是成功,并将 string 作为一条通用消息显示给用户。与 error() 函数不同,此函数允许继续处理。

message( "This is a message" )

上面的行会将“This is a message”写入控制台。使用引号是可选的,但建议使用。

注意:默认情况下,将为 qmake 为给定项目生成的每个 Makefile 写入消息。如果我们想确保每个项目的消息只出现一次,那么测试 build_pass 变量与一个范围,以便在构建期间过滤掉消息。例如:

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

1.23. mkpath(dirPath)

创建目录路径 dirPath。此函数是 QDir::mkpath
函数的包装器。

这个函数是在 Qt 5.0 中引入的。

1.24. requires(condition)

评估 condition。如果条件为假,qmake 在构建时跳过这个项目(及其子目录)。

注意: 也可以为此使用 REQUIRES 变量。但是,我们建议使用此函数。

1.25. system(command)

在二级shell中执行给定的 command。如果命令以零退出状态返回,则成功;否则失败。我们可以使用范围检查此函数的返回值。

例如:

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

也可参见 system() 的替换变量。

1.26. touch(filename, reference_filename)

更新 filename 的时间戳以匹配 reference_filename 的时间戳。

这个函数是在 Qt 5.0 中引入的。

1.27. unset(variablename)

从当前上下文中删除 variablename 。

例如:

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

1.28. versionAtLeast(variablename, versionNumber)

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

这个函数是在 Qt 5.10 中引入的。

1.29. versionAtMost(variablename, versionNumber)

测试来自 variablename 的版本号是否小于或等于 versionNumber。工作机制类似 versionAtLeast().

这个函数是在 Qt 5.10 中引入的。

1.30. warning(string)

总是成功,并将 string 作为警告消息显示给用户。

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

将 variablename 的值写入名为 filename 的文件,每个值在单独的行上。如果没有指定 variablename,则创建一个空文件。如果 mode 是 append 并且该文件已经存在,则追加而不是替换它。

这个函数是在 Qt 5.0 中引入的。

2. 测试函数库

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

2.1. 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

2.2. prepareRecursiveTarget(target)

通过准备一个遍历所有子目录的目标,促进类似于 install 目标的项目范围目标的创建。例如:

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

为了使目标全局化,上面的代码需要包含到每个 subdirs 子项目中。另外,为了让这些目标做任何事情,非 subdirs 子项目需要包含各自的代码。实现这一点最简单的方法是创建一个自定义特性文件。例如:

# <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 中引入的。

2.3. qtCompileTest(test)

构建测试项目。如果测试通过,则返回 true 并将 config_<test> 添加到配置变量中。否则,返回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.

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

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

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

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

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

测试结果被自动缓存,这也使得它们对所有子项目可用。因此,建议在顶级项目文件中运行所有配置测试。

要避免缓存结果的重用,请将 CONFIG+=recheck传递给 qmake。

也可参阅 load()

这个函数是在 Qt 5.0 中引入的。

2.4. qtHaveModule(name)

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

这个函数是在 Qt 5.0.1 中引入的。

.

上一篇下一篇

猜你喜欢

热点阅读