qmake позволяет писать навороченные скрипты, средства для этого есть.
В самом простом случае проверка выполнения некоторого условия (в документации именуется scopes) выглядит следующим образом:
scope { # скобка обязательно в этой же строке! ... }
1 2 3 4 5 |
То, что внутри, отработает только в том случае, если scope истинно. В качестве scope может выступать:
Примеры:
win32-msvc* { # что-то специфическое для Visual C++ 2005-2012 под win32 LIBS += advapi32.lib shell32.lib win32-msvc2012 { # в добавок что-то сугубо для 2012 } } *msvc2010 { # что-то для Visual C++ 2010 под любые платформы # вряд ли практический смысл в этом есть } macx { # что-то OSX специфическое } CONFIG += console console { # что-то только для консольных приложений DEFINES += _CONSOLE_ } exists(version.h) { # встроенная функция проверки # существования файла HEADERS += version.h }
Если условие нужно только на одну строку, то можно записать scope в сокращенном варианте, через двоеточие. Например:
console: DEFINES += _CONSOLE_
1 2 3 |
Вложенные условия тоже можно сокращать:
Можно сокращать вложенные условия
win32 { console { DEFINES += _CONSOLE_ } } # можно записать как win32:console { DEFINES += _CONSOLE_ } # и даже как win32:console: DEFINES += _CONSOLE_
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Фактически, двоеточие работает как логическое И. Логическое ИЛИ тоже присутствует и в более привычном для сишников виде, равно как и отрицание:
win32-msvc2005|win32-msvc2008 { # что-то только для Visual C++ 2005 или 2008 } !exists(version.h) { error(version.h is not found) # qmake завершиться с ошибкой }
1 2 3 4 5 6 7 8 9 |
win32-msvc2005|win32-msvc2008 { # что-то только для Visual C++ 2005 или 2008 |
Чтобы в одном условии объединить И и ИЛИ, нужны скобки. Их предоставляет конструкция if. Вот пример, взятый из документации:
Можно сокращать вложенные условия
# debug режим на linux или OSX if(linux-g++*|macx-g++*):CONFIG(debug, debug|release) { message("We are on Linux or Mac OS, and we are in debug mode.") }
1 2 3 4 5 6 |
# debug режим на linux или OSX if(linux-g++*|macx-g++*):CONFIG(debug, debug|release) { message("We are on Linux or Mac OS, and we are in debug mode.") |
Также в синтаксисе ветвления присутствует else, причем даже в виде, напоминающем else-if:
win32:xml { # xml под win32 SOURCES += xmlhandler_win.cpp } else:xml { # xml под юниксы SOURCES += xmlhandler.cpp } else { # а без xml низзя error("Unknown configuration") }
1 2 3 4 5 6 7 8 9 10 11 12 |
Цикл for
Цикл выполняется для каждого значения в переменной:
# Цикл выполняется для каждого значения из listVar for(valueVar, listVar) { # скобка обязательно в этой же строке! ... }
1 2 3 4 5 6 7 |
# Цикл выполняется для каждого значения из listVar for(valueVar, listVar) { # скобка обязательно в этой же строке! |
Пример: директории из списка EXTRAS добавляются в SUBDIRS, если они существуют.
EXTRAS = handlers tests docs for(dir, EXTRAS) { exists($$dir) { SUBDIRS += $$dir } }
1 2 3 4 5 6 7 8 |
Обратите внимание: вторым параметром в цикле for может быть только имя переменной.
EXTRAS = handlers tests docs # $$unique убирает дубликаты for(dir, $$unique(EXTRAS)) { # бананас exists($$dir) { SUBDIRS += $$dir } } # Это досадное ограничение можно обойти с помощью # встроенной функции list. Она принимает одно значение и # создает переменную с уникальным именем, содержащим это значение. EXTRAS = handlers tests docs # $$unique убирает дубликаты for(dir, $$list($$unique(EXTRAS))) { # работает! exists($$dir) { SUBDIRS += $$dir } }
Даже ошибки не выдается, тело цикла просто не выполнится ни разу.
Существуют аналоги сишных операторов continue и break, это функции next() и break():
LIST = 1 2 3 for(a, LIST) { equals(a, 1): next(); equals(a, 3): break(); message($$a) } # вывод цикла будет следующим: # Project MESSAGE: 2
1 2 3 4 5 6 7 8 9 10 |
Поддерживается забавное сокращение: использование цикла for в виде условной функции. Следующий фрагмент выведет на консоль то же, что и предыдущий:
LIST = 1 2 3 for(a, LIST):equals(a, 2):message($$a)
1 2 3 4 |