Тестирующие функции
Тестирующие функции возвращают булево значение, которое можно проверить в условных частях области видимости. Тестирующие функции могут быть разделены на встроенные функции и функции библиотек.
См. также Функции замены.
Встроенные тестирующие функции
Базовые тестирующие функции реализованы как встроенные функции.
cache(variablename, [set|add|sub] [transient] [super|stash], [source variablename])
Это внутренняя функция, которой обычно не нужно пользоваться.
CONFIG(config)
Эта функция может использоваться для проверки переменных, помещенных в переменную CONFIG. Она аналогична областям видимости, но имеет дополнительное преимущество, заключающееся в возможности передачи второго параметра для проверки активной конфигурации. Поскольку порядок значений важен в CONFIG переменных (то есть, последнее установленное значение будет считаться активной конфигурацией для взаимоисключающих значений), второй параметр может использоваться для указания набора значений для рассмотрения. Например:
CONFIG = debug CONFIG += release CONFIG(release, debug|release):message(Release build!) #will print CONFIG(debug, debug|release):message(Debug build!) #no print
Поскольку выпуск считается активной настройкой (для анализа функций), он будет использоваться для генерации файла сборки. В общем случае второй параметр не нужен, но для специфических проверок взаимоисключающих значений он бесценен.
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. В этом случае соответствующие файлы добавляются в переменные SOURCES и HEADERS.
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только проверяет переменные
equals(variablename, value)
Проверяет, равна ли variablename строке value.
Например:
TARGET = helloworld
equals(TARGET, "helloworld") {
message("The target assignment was successful.")
} error(string)
Эта функция никогда не возвращает значения. qmake отображает string как сообщение об ошибке пользователю и завершает работу. Эту функцию следует использовать только для неисправимых ошибок.
Например:
error(An error has occurred in the configuration process.)
eval(string)
Вычисляет содержимое строки с использованием правил синтаксиса qmake и возвращает true. В строке можно использовать определения и присваивания для изменения значений существующих переменных или создания новых определений.
Например:
eval(TARGET = myapp) {
message($$TARGET)
} Примечание: Кавычки могут использоваться для ограничения строки, а значение возврата можно игнорировать, если оно не нужно.
exists(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}!) 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) содержит переменную var со значением val; в противном случае — неуспешно. Если вы не укажете val, функция проверяет, была ли переменная var назначена в файле.
isActiveConfig
Это псевдоним для функции CONFIG.
isEmpty(variablename)
Успешно выполняется, если переменная variablename пуста; в противном случае — неуспешно. Это эквивалентно count( variablename, 0 ).
Например:
isEmpty( CONFIG ) {
CONFIG += warn_on debug
} isEqual
Это псевдоним для функции equals.
lessThan(variablename, value)
Проверяет, что значение variablename меньше, чем value. Работает как greaterThan().
Например:
ANSWER = 42
lessThan(ANSWER, 1) {
message("The answer might be wrong.")
} load(feature)
Загружает файл функции (.prf) указанный feature, если функция ещё не была загружена.
log(message)
Выводит сообщение в консоль. В отличие от функции message, не добавляет текст в начало или перевод строки в конец.
См. также message().
message(string)
Всегда успешно выполняется и отображает string как общее сообщение пользователю. В отличие от функции error(), эта функция позволяет продолжить обработку.
message( "This is a message" )
Вышеприведенная строка вызывает вывод "Это сообщение" в консоль. Использование кавычек необязательно, но рекомендуется.
Примечание: По умолчанию сообщения выводятся для каждого файла Makefile, генерируемого qmake для заданного проекта. Если вы хотите, чтобы сообщения появлялись только один раз для каждого проекта, проверьте переменную build_pass в сочетании с областью видимости для фильтрации сообщений во время сборки. Например:
!build_pass:message( "This is a message" )
mkpath(dirPath)
Создаёт путь к каталогу dirPath. Эта функция является оболочкой вокруг функции QDir::mkpath.
requires(condition)
Вычисляет condition. Если условие ложно, qmake пропускает этот проект (и его SUBDIRS) при сборке.
Примечание: Вы также можете использовать переменную REQUIRES для этой цели. Однако мы рекомендуем использовать эту функцию вместо нее.
system(command)
Выполняет заданную command команду в дочерней оболочке. Успешно выполняется, если команда возвращает код выхода 0; в противном случае — неуспешно. Вы можете проверить значение возврата этой функции, используя область видимости.
Например:
system("ls /bin"): HAS_BIN = TRUE См. также вариант замены system().
touch(filename, reference_filename)
Обновляет метку времени filename для соответствия метке времени reference_filename.
unset(variablename)
Удаляет variablename из текущего контекста.
Например:
NARF = zort
unset(NARF)
!defined(NARF, var) {
message("NARF is not defined.")
} versionAtLeast(variablename, versionNumber)
Проверяет, что номер версии из variablename больше или равен versionNumber. Номер версии рассматривается как последовательность неотрицательных десятичных чисел, разделённых точкой "; любые нечисловые хвосты строки будут игнорироваться. Сравнение выполняется по сегментам слева направо; если одна версия является префиксом другой, она считается меньше.
versionAtMost(variablename, versionNumber)
Проверяет, что номер версии из variablename меньше или равен versionNumber. Работает как versionAtLeast().
warning(string)
Всегда успешно выполняется и отображает string как сообщение об ошибке пользователю.
write_file(filename, [variablename, [mode]])
Записывает значения variablename в файл с именем filename, каждое значение на новой строке. Если variablename не указано, создаёт пустой файл. Если mode равно append, а файл уже существует, добавляет в него, а не перезаписывает.
Библиотека тестирующих функций
Сложные тестирующие функции реализованы в библиотеке .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 проекту, подготавливая целевую функцию, которая перебирает все подкаталоги. Например:
TEMPLATE = subdirs SUBDIRS = one two three prepareRecursiveTarget(check)
Подкаталоги с have_no_default или no_<target>_target в .CONFIG исключаются из этой цели:
two.CONFIG += no_check_target
Вы должны вручную добавить подготовленную цель в QMAKE_EXTRA_TARGETS:
QMAKE_EXTRA_TARGETS += check
Чтобы сделать цель глобальной, код выше должен быть включен в каждый подпроекту подкаталога. Кроме того, чтобы эти цели что-то делали, подпроекты, которые не являются подкаталогами, должны включать соответствующий код. Самый простой способ достичь этого — создание пользовательского файла функций. Например:
END_OF_DOCUMENT_MARKER# <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
qtCompileTest(тест)
Создаёт проект теста. Если тест пройден, возвращается 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)
Если проект теста успешно скомпилирован, тест пройден.
Результаты тестов автоматически кэшируются, что делает их доступными для всех подпроектов. Поэтому рекомендуется запускать все конфигурационные тесты в файле верхнего уровня проекта.
Чтобы подавить повторное использование кэшированных результатов, передайте CONFIG+=recheck в qmake.
См. также load().
qtHaveModule(имя)
Проверяет, присутствует ли модуль Qt, указанный name. Список возможных значений см. в QT.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/archives/qt-5.11/qmake-test-function-reference.html