qmake позволяет писать навороченные скрипты, средства для этого есть.

Ветвление

В самом простом случае проверка выполнения некоторого условия (в документации именуется scopes) выглядит следующим образом:

Синтаксис

scope { # скобка обязательно в этой же строке! ... }


1

2

3

4

5

 

scope { # скобка обязательно в этой же строке!

  ...

}

 

То, что внутри, отработает только в том случае, если 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 }


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

 

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

 

console: DEFINES += _CONSOLE_

 

Вложенные условия тоже можно сокращать:

Можно сокращать вложенные условия

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 {

  console {

     DEFINES += _CONSOLE_

  }

}

 

# можно записать как

win32:console {

     DEFINES += _CONSOLE_

}

 

# и даже как

win32:console: DEFINES += _CONSOLE_

 

Фактически, двоеточие работает как логическое И. Логическое ИЛИ тоже присутствует и в более привычном для сишников виде, равно как и отрицание:

Логические операции

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

}

 

!exists(version.h) {

  error(version.h is not found) # qmake завершиться с ошибкой

}

 

Чтобы в одном условии объединить И и ИЛИ, нужны скобки. Их предоставляет конструкция 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:

else

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

 

win32:xml {

    # xml под win32

    SOURCES += xmlhandler_win.cpp

} else:xml {

    # xml под юниксы

    SOURCES += xmlhandler.cpp

} else {

   # а без xml низзя

   error("Unknown configuration")

}

 

Цикл for

Цикл выполняется для каждого значения в переменной:

Синтаксис

# Цикл выполняется для каждого значения из listVar for(valueVar, listVar) { # скобка обязательно в этой же строке! ... }


1

2

3

4

5

6

7

 

# Цикл выполняется для каждого значения из listVar

for(valueVar, listVar) { # скобка обязательно в этой же строке!

                        

   ...

}

 

Пример: директории из списка EXTRAS добавляются в SUBDIRS, если они существуют.

Пример for

EXTRAS = handlers tests docs for(dir, EXTRAS) { exists($$dir) { SUBDIRS += $$dir } }


1

2

3

4

5

6

7

8

 

EXTRAS = handlers tests docs

for(dir, EXTRAS) {

    exists($$dir) {

        SUBDIRS += $$dir

    }

}

 

Обратите внимание: вторым параметром в цикле for может быть только имя переменной.

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 } }


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

 

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():

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

 

LIST = 1 2 3

for(a, LIST) {

  equals(a, 1): next();

  equals(a, 3): break();

  message($$a)

}

# вывод цикла будет следующим:

# Project MESSAGE: 2

 

Поддерживается забавное сокращение: использование цикла for в виде условной функции. Следующий фрагмент выведет на консоль то же, что и предыдущий:

for как условная функция

LIST = 1 2 3 for(a, LIST):equals(a, 2):message($$a)


1

2

3

4

 

LIST = 1 2 3

for(a, LIST):equals(a, 2):message($$a)