Язык qmake
Многие файлы проектов qmake просто описывают исходные файлы и заголовочные файлы, используемые проектом, с помощью списка определений name = value и name += value. qmake также предоставляет другие операторы, функции и области, которые могут использоваться для обработки информации, предоставленной в объявлениях переменных. Эти расширенные возможности позволяют генерировать файлы Make для нескольких платформ из одного файла проекта.
Операторы
Во многих файлах проектов операторы присваивания (=) и добавления (+=) могут использоваться для включения всей информации о проекте. Типичный шаблон использования заключается в присвоении списка значений переменной и добавлении дополнительных значений в зависимости от результата различных проверок. Поскольку qmake определяет некоторые переменные с помощью значений по умолчанию, иногда необходимо использовать оператор удаления (-=) для фильтрации не требуемых значений. В следующих разделах описывается, как использовать операторы для манипулирования содержимым переменных.
Присвоение значений
Оператор = присваивает значение переменной:
TARGET = myapp
Вышеприведенная строка устанавливает переменную TARGET в значение myapp. Это перезапишет любые ранее заданные значения для TARGET на myapp.
Добавление значений
Оператор += добавляет новое значение в список значений переменной:
DEFINES += USE_MY_STUFF
Вышеприведенная строка добавляет USE_MY_STUFF в список препроцессорных определений, которые должны быть помещены в сгенерированный файл Makefile.
Удаление значений
Оператор -= удаляет значение из списка значений в переменной:
DEFINES -= USE_MY_STUFF
Вышеприведенная строка удаляет USE_MY_STUFF из списка препроцессорных определений, которые должны быть помещены в сгенерированный файл Makefile.
Добавление уникальных значений
Оператор *= добавляет значение в список значений в переменной, только если оно еще не присутствует. Это предотвращает включение значений многократно в переменную. Например:
DEFINES *= USE_MY_STUFF
В приведенной выше строке USE_MY_STUFF будет добавлен в список препроцессорных определений только в том случае, если он еще не определен. Обратите внимание, что функция unique() также может использоваться для обеспечения того, что переменная содержит только по одному экземпляру каждого значения.
Замена значений
Оператор ~= заменяет все значения, соответствующие регулярному выражению, на указанное значение:
DEFINES ~= s/QT_[DT].+/QT
В приведенной выше строке все значения в списке, начинающиеся с QT_D или QT_T, заменяются на QT.
Расширение переменных
Оператор $$ используется для извлечения содержимого переменной и может использоваться для передачи значений между переменными или для их передачи функциям:
EVERYTHING = $$SOURCES $$HEADERS
message("The project contains the following files:")
message($$EVERYTHING) Переменные могут использоваться для хранения содержимого переменных среды. Они могут быть оценены в момент запуска qmake или включены в сгенерированный файл Makefile для оценки при построении проекта.
Чтобы получить содержимое значения переменной среды при запуске qmake, используйте оператор $$(...):
DESTDIR = $$(PWD) message(The project will be installed in $$DESTDIR)
В приведенном выше присваивании значение переменной среды PWD считывается при обработке файла проекта.
Чтобы получить содержимое значения переменной среды в момент обработки сгенерированного файла Makefile, используйте оператор $(...):
DESTDIR = $$(PWD) message(The project will be installed in $$DESTDIR) DESTDIR = $(PWD) message(The project will be installed in the value of PWD) message(when the Makefile is processed.)
В приведенном выше присваивании значение PWD считывается сразу при обработке файла проекта, но $(PWD) присваивается DESTDIR в сгенерированном файле Makefile. Это делает процесс сборки более гибким, если переменная среды установлена правильно при обработке файла Makefile.
Доступ к свойствам qmake
Специальный оператор $$[...] может использоваться для доступа к свойствам qmake:
message(Qt version: $$[QT_VERSION]) message(Qt is installed in $$[QT_INSTALL_PREFIX]) message(Qt resources can be found in the following locations:) message(Documentation: $$[QT_INSTALL_DOCS]) message(Header files: $$[QT_INSTALL_HEADERS]) message(Libraries: $$[QT_INSTALL_LIBS]) message(Binary files (executables): $$[QT_INSTALL_BINS]) message(Plugins: $$[QT_INSTALL_PLUGINS]) message(Data files: $$[QT_INSTALL_DATA]) message(Translation files: $$[QT_INSTALL_TRANSLATIONS]) message(Settings: $$[QT_INSTALL_CONFIGURATION]) message(Examples: $$[QT_INSTALL_EXAMPLES])
Дополнительную информацию см. в разделе Настройка qmake.
Свойства, доступные с помощью этого оператора, обычно используются для включения плагинов и компонентов сторонних производителей в Qt. Например, плагин Qt Designer можно установить вместе с встроенными плагинами Qt Designer, если в файле проекта сделать следующее объявление:
target.path = $$[QT_INSTALL_PLUGINS]/designer INSTALLS += target
Области
Области похожи на операторы if в процедурных языках программирования. Если определенное условие истинно, объявления внутри области обрабатываются.
Синтаксис области
Области состоят из условия, за которым в той же строке следует открывающая фигурная скобка, последовательности команд и определений и закрывающая фигурная скобка в новой строке:
<condition> {
<command or definition>
...
} Открывающая фигурная скобка должна быть записана в той же строке, что и условие. Области могут быть объединены, чтобы включить более одного условия, как описано в следующих разделах.
Области и условия
Область записывается как условие, за которым следует ряд объявлений, заключенных в пару фигурных скобок. Например:
win32 {
SOURCES += paintwidget_win.cpp
} Вышеприведенный код добавит файл paintwidget_win.cpp к исходным файлам, перечисленным в сгенерированном файле Makefile при построении для платформы Windows. При построении для других платформ определение будет проигнорировано.
Условия, используемые в данной области, также могут быть отрицаемы, чтобы предоставить альтернативный набор объявлений, которые будут обработаны только в случае, если исходное условие ложно. Например, чтобы обработать что-либо при построении на всех платформах, *кроме* Windows, отрицайте область следующим образом:
!win32 {
SOURCES -= paintwidget_win.cpp
} Области могут быть вложены, чтобы объединить более одного условия. Например, чтобы включить определенный файл для определенной платформы только в том случае, если включено отладка, запишите следующее:
macx {
CONFIG(debug, debug|release) {
HEADERS += debugging.h
}
} Чтобы не писать много вложенных областей, вы можете вложить области с использованием оператора :. Вложенные области в приведенном выше примере можно переписать следующим образом:
macx:CONFIG(debug, debug|release) {
HEADERS += debugging.h
} Вы также можете использовать оператор : для выполнения условных присваиваний в одной строке. Например:
win32:DEFINES += USE_MY_STUFF
Вышеприведенная строка добавляет USE_MY_STUFF к переменной DEFINES только при построении для платформы Windows. В общем, оператор : ведет себя как логический оператор И, объединяющий несколько условий и требующий, чтобы все они были истинными.
Также существует оператор |, который ведет себя как логический оператор ИЛИ, объединяющий несколько условий и требующий, чтобы хотя бы одно из них было истинным.
win32|macx {
HEADERS += debugging.h
} Если вам нужно комбинировать оба оператора, вы можете использовать функцию if для задания приоритета операторов.
if(win32|macos):CONFIG(debug, debug|release) {
# Do something on Windows and macOS,
# but only for the debug configuration.
}
win32|if(macos:CONFIG(debug, debug|release)) {
# Do something on Windows (regardless of debug or release)
# and on macOS (only for debug).
} Условие принимает символ подстановки для сопоставления семейства значений CONFIG или имен mkspec.
win32-* {
# Matches every mkspec starting with "win32-"
SOURCES += win32_specific.cpp
} Примечание: Исторически qmake использовал проверку имени mkspec с подстановкой символов, как показано выше, для проверки платформы. В настоящее время мы рекомендуем использовать значения, определенные mkspec в переменной QMAKE_PLATFORM.
Вы также можете предоставить альтернативные объявления тем, которые находятся внутри области, используя область else. Каждая область else обрабатывается, если условия для предыдущих областей ложны. Это позволяет записывать сложные проверки в сочетании с другими областями (разделенными оператором : как описано выше). Например:
win32:xml {
message(Building for Windows)
SOURCES += xmlhandler_win.cpp
} else:xml {
SOURCES += xmlhandler.cpp
} else {
message("Unknown configuration")
} Настройка и области
Значения, хранящиеся в переменной CONFIG, обрабатываются qmake особым образом. Каждое из возможных значений может использоваться в качестве условия для области. Например, список значений, содержащихся в CONFIG, можно расширить значением opengl:
CONFIG += opengl
В результате этой операции будут обработаны любые области, проверяющие значение opengl. Мы можем использовать эту функцию, чтобы придать конечному исполняемому файлу подходящее имя:
opengl {
TARGET = application-gl
} else {
TARGET = application
} Эта функция упрощает изменение конфигурации проекта без потери всех пользовательских настроек, которые могут потребоваться для определенной конфигурации. В приведенном коде обрабатываются объявления в первой области, и конечный исполняемый файл будет называться application-gl. Однако, если opengl не указано, обрабатываются объявления во второй области, и конечный исполняемый файл будет называться application.
Поскольку вы можете добавлять собственные значения в строку CONFIG, это предоставляет удобный способ настройки файлов проекта и тонкой настройки сгенерированных файлов Makefile.
Значения области платформы
В дополнение к значениям win32, macx, и unix используемым во многих условиях области, могут быть проверены и другие встроенные значения, специфичные для платформы и компилятора. Они основаны на спецификациях платформы, предоставленных в каталоге mkspecs Qt. Например, следующие строки из файла проекта показывают используемую в данный момент спецификацию и проверяют спецификацию linux-g++:
message($$QMAKESPEC)
linux-g++ {
message(Linux)
} Вы можете проверить любую другую комбинацию платформа-компилятор, если для нее существует спецификация в каталоге mkspecs.
Переменные
Многие переменные, используемые в файлах проектов, являются специальными переменными, которые qmake использует при генерации файлов Makefile, такими как DEFINES, SOURCES и HEADERS. Кроме того, вы можете создавать переменные для собственного использования. qmake создаёт новые переменные с заданным именем при обнаружении присваивания этому имени. Например:
MY_VARIABLE = value
Нет ограничений на то, что вы делаете со своими переменными, так как qmake проигнорирует их, если только ему не нужно оценить их при обработке области.
Вы также можете присвоить значение текущей переменной другой переменной, добавив $$ перед именем переменной. Например:
MY_DEFINES = $$DEFINES
Теперь переменная MY_DEFINES содержит то, что содержится в переменной DEFINES на этом этапе файла проекта. Это также эквивалентно:
MY_DEFINES = $${DEFINES} Вторая запись позволяет добавить содержимое переменной к другому значению без разделения пробелом. Например, следующее гарантирует, что конечному исполняемому файлу будет присвоено имя, включающее используемый шаблон проекта:
TARGET = myproject_$${TEMPLATE} Функции замены
qmake предоставляет набор встроенных функций для обработки содержимого переменных. Эти функции обрабатывают переданные им аргументы и возвращают значение или список значений в качестве результата. Для присвоения результата переменной используйте оператор $$ с этим типом функции, как и при присвоении содержимого одной переменной другой:
HEADERS = model.h HEADERS += $$OTHER_HEADERS HEADERS = $$unique(HEADERS)
Этот тип функций следует использовать в правой части присваивания (то есть, в качестве операнда).
Вы можете определить свои собственные функции для обработки содержимого переменных следующим образом:
defineReplace(functionName){
#function code
} Следующий пример функции принимает имя переменной в качестве единственного аргумента, извлекает список значений из переменной с помощью встроенной функции eval() и компилирует список файлов:
defineReplace(headersAndSources) {
variable = $$1
names = $$eval($$variable)
headers =
sources =
for(name, names) {
header = $${name}.h
exists($$header) {
headers += $$header
}
source = $${name}.cpp
exists($$source) {
sources += $$source
}
}
return($$headers $$sources)
} Функции проверки
qmake предоставляет встроенные функции, которые могут использоваться в качестве условий при написании блоков кода. Эти функции не возвращают значение, а вместо этого указывают успех или неудачу:
count(options, 2) {
message(Both release and debug specified.)
} Этот тип функций следует использовать только в условных выражениях.
Можно определить свои собственные функции для задания условий для блоков кода. Следующий пример проверяет, существует ли каждый файл в списке, и возвращает true, если все файлы существуют, или false, если нет:
defineTest(allFiles) {
files = $$ARGS
for(file, files) {
!exists($$file) {
return(false)
}
}
return(true)
}
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.1/qmake-language.html