qmake: начальные значения переменных

К началу обработки собственно .pro файла многие переменные уже будут иметь какие-то значения. Рассмотрим все механизмы, с помощью которых это происходит, в порядке их влияния на конечный результат.

mkspecs

.pro файл должен быть насколько возможно кроссплатформенным, а значит, он не должен содержать настроек конкретных тулчейнов. Также, настройки компилятора для проекта должны быть совместимыми с теми настройками, которые использовались при компиляции Qt и других используемых библиотек. Заставлять пользователя следить за этим вручную есть решение явно плохое. Напрашивается вынести все эти настройки куда-то в сторонку и только ссылаться на них; qmake так и делает.

Специальное место — это каталог mkspecs в установочном каталоге Qt (у меня это C:\Qt\Qt5.0.1\5.0.1\mingw47_32\mkspecs\). Почти все подкаталоги этого каталога — это различные конфигурации различных тулчейнов для различных платформ, например win32-msvc2010 или linux-g++-64. В каждом таком каталоге есть файл qmake.conf в формате обычного .pro файла, в котором перечислены все настройки, т.е. начальные значения специальных переменных qmake для компилятора, линкера и других утилит тулчейна. Если вам интересно, например, с какими конкретно настройками запускается ваш компилятор, то здесь их можно посмотреть.

qmake узнаёт mkspec через параметр командной строки, например -spec win32-msvc2008. В самом .pro файле нет механизма выбрать желаемый mkspec — они и понятно, в идеале .pro файл должен быть насколько возможно независим от конкретной платформы. Для тех случаев, когда необходимо обрабатывать различия платформ, предусмотрены конструкции проверки условий, с помощью которых можно узнать, с каким конкретно mkspec сейчас обрабатывается .pro файл.

Настройка mkspec в Kits

Настройка mkspec в Kits

Можно написать свой mkspec (обычно модификацию существующего mkspec), с другими настройками компилятора и тому подобное. Самый правильный способ использовать такой mkspec — это создать под него свой Kit и в его настройках прописать свой mkspec. Можно и в настройках проекта прописать, добавив нужный параметр в вызов qmake, но по многим причинам это не самое лучшее решение.

Выше я написал, что mkspec передается через командную строку qmake, но на самом деле так редко происходит. Очень часто используется mkspec по умолчанию, который равен тому mkspec, который использовался при построении qmake, т.е. mkspec той Qt, которую использует программист. Практически наверняка программисту дефолтовый mkspec и нужен. Поэтому, если не указать параметр -spec, то будет использован именно он (если, правда, не установлена переменная окружения QMAKESPEC, которая, если существует, будет использована в таком случае).

Узнать дефолтовый mkspec можно с помощью команды qmake -query:

QMAKE_SPEC или QMAKE_XSPEC содержат дефолтовый mkspec. Я не смог выяснить, в чем между ними разница.

Кстати, все эти значения, выводимые по qmake -query, доступны в .pro файлах с помощью специального синтаксиса:

Можно также создавать свои «qmake переменные» (persistent properties называются), присваивать им значения и ссылаться на них в .pro файлах с помощью этого специального синтаксиса. Без понятия, зачем это все может быть нужно.

В любом случае указания mkspec (командная строка, переменная окружения QMAKESPEC, дефолтовый mkspec qmake) значение должено быть указано или в виде полного пути к каталогу mkspec (в котором лежит qmake.conf), или в виде только имени этого каталога; в последнем случае он должен находиться в описанном выше специальном каталоге mkspecs.

В .pro файле mkspec можно узнать с помощью переменной QMAKESPEC, которая всегда содержит полный путь:

.qmake.cache

Файл .qmake.chache — это файл такого же синтаксиса, что и .pro файл, который включается (include) неявным образом во все .pro файлы, которые находятся во всех каталогах уровнем ниже (но не в каталоге, где находится файл .qmake.chache, заметьте). Такой механизм позволяет задать значения по умолчанию для каких-то своих переменных для всего дерева исходников, причем сам .qmake.chache также является частью исходников. Для некоторых применений — незаменимая вещь.

qmake ищет .qmake.chache начиная с родительского каталога .pro файла и выше, пока не встретит его. И на этом поиск заканчивается. Если выше уровнем тоже есть .qmake.chache, то он включен не будет. Поэтому, к сожалению, фичей кэша нужно пользоваться аккуратно. Фактически, лучше всего ограничиться одним файлом .qmake.chache на самом верхнем уровне дерева каталогов исходников.

qmake поддерживает опцию -cache filename для переопределения имени файла кэша на какое-то другое, а также -nocache для запрета всего механизма кэшей. Вижу от них пользу только для очень редких ситуаций.

Командная строка qmake

Значение переменной можно передать через командную строку qmake. Причем можно не только просто передать значение, но и изменить значение переменной любым допустимым выражением:

Двойные кавычки нужны, если есть пробелы.

При использовании Qt Creator параметры командной строки qmake можно прописать в проекте, но нужно иметь в виду, что они сохраняются в файле настроек проекта Qt Creator *.pro.user. Последний по определению привязан к локальной машине и не является частью исходников. Таким образом, при таком сценарии использования qmake польза от передачи значений через командную строку сомнительна.

Переменные окружения

В качестве значений, полученных снаружи .pro файла, можно рассматривать также переменные окружения (environment). В .pro файле можно получить к ним доступ с помощью специального синтаксиса:

Чтение переменной окружения происходит во время обработки .pro файла (т.е. выполнения qmake). Если необходимо получать это значение во время выполнения make при обработке Makefile, то этот синтаксис не годится. В интернете полно инфы, что для этого подойдет синтаксис в виде $(ENV_VAR), но в моих экспериментах такой синтаксис тоже раскрывался в qmake, кроме некоторых специфических случаев. В код qmake мне лень смотреть, так что я не знаю, когда раскрытие на стороне qmake происходит, а когда нет.

Цикл: qmake

  4 comments for “qmake: начальные значения переменных

  1. zenwarr
    31.07.2013 at 09:09

    Касательно .qmake.cache — столкнулся с тем, что qmake, как оказалось, ищет его не относительно .pro (в исходниках), а относительно сгенерированного Makefile. То есть если у нас in-source сборка, то вроде все нормально, out-of-source (shadow build в Qt Creator), то .qmake.cache нужно вручную копировать, что не совсем удобно.

    • mgsxx
      31.07.2013 at 09:38

      Если это так, то это баг qmake. Не буду удивлен, если так оно и есть — подобных ошибок с путаницей OUT_PWD и PWD в qmake хватает.

      Лично я с именно этой проблемой не сталкиваюсь, т.к. на все мои исходники у меня только один .qmake.cache в самом верхнем каталоге, и все in-source и out-source каталоги находятся ниже него.

  2. Grunelf
    21.11.2014 at 18:04

    Похоже, никакого бага нет. Проверил на Windows 7 x64, Qt 5.3.2, MS VC++ 2013.
    Выяснил:
    1. qmake ищет .qmake.cache в том же каталоге, что и pro-файл и в каталогах выше, до первой находки. У меня он нашёл его тремя «этажами» выше. Дальше тестировать поленился.

    2. У меня информация из .qmake.cache была видна в pro-файле, который лежал в том же каталоге. То есть информация была включена в этот pro-файл, а не только в pro-файлы подкаталогов, как написано в посте.

    3. qmake не бегает по подкаталогам, а тупо из списка subdirs набивает цели в Makefile и каждая цель содержит 1 команду — запуск qmake в конкретном подкаталоге. То есть pro-файлы в подкаталогах обрабатываются потом — во время запуска (n)make из корневого каталога, а не во время работы «корневого» qmake. И каждый qmake, запущенный в подкаталоге ищет .qmake.cache относительно pro-файла этого подкаталога по правилам выше. Возможно, так и получается эффект, описанный zenwarr.

    4. Следствие из п.1 и п.3 — если в подкаталоге с pro-файлом обнаружится .qmake.cache, то все настройки «корневого» .qmake.cache потеряются. Будут взяты настройки только из обнаруженного .qmake.cache.

Добавить комментарий