Сборка группы проектов в qmake с помощью SUBDIRS

Представьте себе программу, имеющую плагинную архитектуру. Qt Creator тому хороший пример. Исходники таких программ должны состоять из нескольких отдельно компилируемых проектов: собственно программы и динамических библиотек плагинов. Прибавьте к этому тест-кейсы, и вполне можем получить пару десятков взаимосвязанных проектов.

Конечно, можно компилировать их по отдельности, но это неправильно. И дело здесь не только в том, что нужно нажать 5-10-20 раз на кнопку «build» вместо одного. Проекты может быть нужно строить в определенном порядке, да и банально можно пропустить какой проект. Ошибки в билде никому не нужны.

Поэтому, например, в Visual Studio для автоматизации построения группы проектов ввели понятие solution (решение), которое может содержать в себе проекты. Аналогом этого механизма в qmake является переменная SUBDIRS.

Базовый функционал SUBDIRS

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

Вид subdirs проекта в Qt Creator

Вид subdirs проекта в Qt Creator

qmake при обработке этого файла обработает — независимо друг от друга, но с одними и теми же настройками qmake — дочерние проекты в подкаталогах, после чего в каталоге программы создаст Makefile, который будет вызывать make для дочерних проектов. К примеру, make all в корневом каталоге вызовет make all во всех дочерних каталогах.

Qt Creator отлично поддерживает проекты типа subdirs. В интерфейсе Projects все наглядно отображается, можно добавлять новые проекты в контекстном меню subdirs-проекта (New Subproject…), но самое главное — это поддержка shadow builds. Весь проект типа subdirs вместе со своими дочерними проектами билдится в один shadow каталог — с повторением структуры каталогов исходников. Очень удобно.

Структура каталогов

Если дочерние проекты хочется организовать в иерархию, можно поступить двумя способами. Во-первых, можно дочерний проект сделать subdirs проектом, все будет работать. Во-вторых, можно просто указать в переменной SUBDIRS путь к подкаталогу подкаталога, например.

Но на этом история не заканчивается. Значения, перечисленные в переменной SUBDIRS, можно использовать как имена составных переменных. Если значения содержат символы, отличные от [a-zA-Z0-9_], они заменяются на -, например для dir/subdir1 имя переменной будет dir-subdir1. Странный выбор, т.к. переменные с - в имени не везде проходят мимо парсера без ошибки. Так что лучше вложенные пути не использовать напрямую, а задавать для них алиасы:

Вместо переменной .subdir (не одновременно с ней) можно использовать переменную .file, которая позволяет явно указать путь к .pro файлу дочернего проекта, и в этом случае его имя не должно совпадать с именем каталога проекта.

Зависимости между проектами

Есть два способа задать порядок билда проектов (их, при желании, можно использовать одновременно). Первый — это указать настойку в переменной CONFIG, которая означает, что проекты должны компилироваться в том порядке, в котором они указаны в переменной SUBDIRS:

Второй способ — это явно указать зависимости между проектами.

В .depends имена проектов должны указываться в том же виде, в каком они указаны в переменной SUBDIRS.

Makefile и subdirs

Для проекта можно указать нестандартное имя для Makefile файла.

При этом по неведомой мне причине стандартный файл с именем Makefile тоже формируется.

В корневом Makefile (который получается из .pro файла subdir-проекта) все дочерние проекты оформляются как набор отдельных целей. Префикс для этих целей имеет вид sub-имя_переменной_проекта. Например, для проекта prg1 цели будет иметь вид в духе sub-prg1-sub_Debug. Префикс для целей можно поменять:

И последнее. В корневой Makefile можно добавлять свои цели с помощью рассмотренного ранее механизма QMAKE_EXTRA_TARGETS. Просто цель не представляет собой интересна, но в режиме recursive этот механизм может быть полезен.

Чтобы это работало, в дочерних проектах должны быть определены цели check. После этого вызов make check в корневом каталоге выполнит make check для всех дочерних проектов. Можно в Qt Creator для этого отдельный конфиг настроить, например.

Небольшая автоматизация

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

Цикл: qmake

  2 comments for “Сборка группы проектов в qmake с помощью SUBDIRS

  1. dix75
    13.06.2013 at 22:28

    Спасибо.

  2. Grunelf
    21.11.2014 at 18:17

    В посте есть неточность, цитирую:
    «qmake при обработке этого файла обработает – независимо друг от друга, но с одними и теми же настройками qmake – дочерние проекты в подкаталогах, после чего в каталоге программы создаст Makefile, который будет вызывать make для дочерних проектов.»

    На самом деле qmake не бегает по подкаталогам, а тупо из списка SUBDIRS накидает цели в корневой Makefile и каждая цель содержит 1 команду – запуск qmake в конкретном подкаталоге. То есть pro-файлы в подкаталогах обработаются потом – во время запуска make из корневого каталога, а не во время работы “корневого” qmake. Иначе говоря, Makefile в каталоге программы будет вызывать qmake, а не make, для дочерних проектов.

    По крайней мере проверено на Windows 7 x64, Qt 5.3.2, MS VC++ 2013.

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