Рекурсивная сборочная подсистема ЗОСРВ "Нейтрино"

Описание состава и механизмов использования набора рекурсивных Makefile'ов.

Общее описание
Структура и основные компоненты
Описание переменных
Поддержка внешних сборочных систем
Поддержка сборочной системы GNU Autotools
Поддержка сборочной системы CMake
Поддержка сборочной системы Meson
Поддержка сборочной системы qmake
Общие переменные и функции
Подключаемые модули
Подключаемые модули qtargets.mk
cppcheck.mk - статический анализ исходного кода
postinstall.mk - отложенная пост-обработка проектов
Подключаемые модули qconfig.mk
bsp_buildtargets.mk - поддержка Make Targets в QNX Momentics IDE 7.0
Выбор драйвера компиляции
Другие возможности
Поддержка варианта сборки проектов с покрытием кода
Параллельная сборка
Механизм OVERRIDE
Прочие замечания и рекомендации
Примеры использования
Версионирование

Общее описание

Рекурсивная сборочная подсистема ЗОСРВ "Нейтрино" представляет собой набор расширений инструмента GNU Make, позволяющий решать ряд задач, связанных со сборкой приложений (драйверов, утилит и т.д.), в т.ч. специфичных для данной операционой системы:

Структура и основные компоненты

Компоненты сборочной системы находятся в каталоге ${KPDA_HOST}/mk.


Caution: Утилита GNU make из состава Комплекта разработчика поддерживает автоматическое добавление каталогов, содержащих компоненты рекурсивной сборочной системы, в список поиска (cм. описание утилиты make), поэтому использование переменной MAKEFLAGS становится необязательным. При этом графическая среда разработки QNX Momentics IDE в любом случае автоматически добавляет опцию -I$QNX_TARGET/usr/include к переменной MAKEFLAGS в процессе сборки проектов. Соответственно, фактически используемая рекурсивная сборочная подсистема определяется тем, какая операционная система (и, соответственно, набор компонентов) выбраны в меню "Window -> Preferences -> QNX -> SDK".

Корневым файлом сборочной системы является файл qconfig.mk, его подключение осуществляется из файлов Makefile с помощью директивы include. Пример:

$ cat common.mk
ifndef QCONFIG
QCONFIG=qconfig.mk
endif
include $(QCONFIG)
INSTALLDIR=usr/bin
include $(MKFILES_ROOT)/qtargets.mk

В данном примере местоположение файла qconfig.mk может быть переопределено с помощью переменной QCONFIG. Явное переопределение используется редко, и в подавляющем большинстве случаев в результате подключается файл, доступный по умолчанию (т.е. ${KPDA_HOST}/mk/qconfig.mk).


Caution: Переменная MKFILES_ROOT в примере выше становится доступна после подключения файла qconfig.mk, который является главным (корневым) подключаемым файлом сборочной системы.

Описание переменных

В данном разделе перечислены некоторые переменные сборочной подсистемы ЗОСРВ "Нейтрино":

USE_LIST
Предназначена для выборочной сборки проектов, входящих в определённые списки (LIST=<имя_списка>). Т.е., например, в результате выполнения команды make USE_LIST=LIB install будет выполнена сборка тех проектов, в родительском (на уровень выше) каталоге которых присутствует файл Makefile, содержащий запись "LIST=LIB". Переменная USE_LIST поддерживает возможность задания множественных значений как через пробел, так и через запятую:
make "USE_LIST=LIB UTILS" install

make USE_LIST=LIB,UTILS install

Note: Переменная USE_LIST не предназначена для использования на уровнях OS, CPU и VARIANT, т.е. её использование допустимо только на вышестоящих уровнях рекурсивного дерева каталогов проектов (например, для сборки какого-либо подмножества проектов).

SKIP_LIST
Предназначена для исключения частей дерева исходных кодов из процесса рекурсивной сборки. Т.е., например, если выполнить команду make SKIP_LIST=LIB install на исходниках "Нейтрино", то рекурсивная сборка доберётся до всех ветвей дерева проектов, в файлах Makefile которых есть запись LIST=LIB, и дальше не пойдёт (при этом все остальные ветви исходного кода будут построены). Поддерживает возможность задания множественных значений как через пробел, так и через запятую (напр. make SKIP_LIST=MISC,DEPRECATED install).
RECURSE_FAST
Предназначена для переключения сборочной системы ЗОСРВ "Нейтрино" в т.н. legacy-режим параллельной сборки (распараллеливание сборки только в пределах одной ветки проекта). Основным (используемым по умолчанию) в настоящий момент является нативный рекурсивный режим утилиты GNU make, управление которым осуществляется с помощью опции -j (распараллеливание всего сборочного дерева, начиная с корня; см. раздел "Общие замечания и рекомендации"). Переключение в legacy-режим выполняется путём установки любого значения, отличного от yes (напр. make RECURSE_FAST=no install). Значение по умолчанию: yes
MV_HOST
Переменная MV_HOST объявлена в файле qconfig.mk и содержит имя команды, предназначенной для перемещения файлов. Переменная добавлена в качестве расширения к набору переменных CP_HOST, LN_HOST, RM_HOST и т.д.
FINDUP_HOST
Переменная FINDUP_HOST объявлена в файле qconf-linux64.mk и содержит имя служебной утилиты findup-unix, предназначенной для поиска указанного каталога вверх по дереву каталогов относительно текущего уровня. Пример:
$ pwd /home/user/proj1/nto/x86/o $ $KPDA_HOST/mk/findup-unix proj1 /home/user/proj1 $ echo $? 0 $ $KPDA_HOST/mk/findup-unix nonexistent $ echo $? 1
EXTRA_CLEAN_<variant>
Позволяет в процессе выполнения команды make clean удалять из директории сборки проекта файлы, специфичные для данного варианта проекта. Пример (реализован в qmacros.mk):

LDVFLAG_gcov = -fprofile-arcs
CCVFLAG_gcov = -O0 -Wc,-fprofile-arcs -Wc,-ftest-coverage
EXTRA_CLEAN_gcov = *.gcno

Т.е. в результате по команде make clean помимо стандартных объектных файлов (*.o) будут также удалены файлы *.gcno, создаваемые компилятором при в режиме покрытия кода (GNU gcov).

Поддержка внешних сборочных систем

С помощью рекурсивной сброчной подсистемы ЗОСРВ "Нейтрино" можно выполнять сборку проектов, построенных на базе некоторых популярных в настоящее время систем: GNU Autotools (autoconf/automake), CMake, Meson, qmake (Qt). Подход к построению проектов примерно одинаков и состоит из нескольких шагов:

  1. Добавление к проекту иерархии сборочных каталогов и управляющих файлов (Makefile) для требуемых целевых платформ
  2. Настройка проекта (указание опций, параметров компиляции и т.д.)

Добавление иерархии сборочных каталогов можно выполнить как вручную, так и с помощью утилиты addvariant (далее приведены примеры её использования в зависимости от типа проекта). Настройка проекта выполняется с помощью редактированя файла common.mk, который обычно создаётся в корневом каталоге проекта. Перечень поддерживаемых файлом common.mk конструкций (переменных, функций) зависит от используемой системы и будет рассмотрен далее.

Задание значений переменных осуществляется согласно правилам GNU make. Общие рекомендации:

Переопределение функций осуществляется с помощью директивы define. Пример (переопределение функции POST_INSTALL):

define POST_INSTALL
$(shell echo "VAR1=Value" > $(DESTDIR)/usr/bin/app.cfg)
endef

Поддержка сборочной системы GNU Autotools

Поддержка сборочной системы GNU Autotools обеспечивается модулем autotools.mk. Данный модуль поддерживает сборку как проектов, исходный код которых заранее подготовлен с помощью инструментов Autotools (т.е. содержит готовый скрипт configure), так и проектов, требующих предварительной подготовки (например, с помощью утилиты autoreconf или встроенного скрипта autogen.sh).

Caution: Предыдущая версия средств поддержки сборочной системы GNU Autotools аналогична реализованной в QNX SDP и состоит из двух компонентов: подключаемого модуля qmake-cfg.mk и исполняемого файла build-cfg. С точки зрения сборочной системы ЗОСРВ "Нейтрино" модуль qmake-cfg.mk является устаревшим и не рекомендуется к использованию в новых проектах.

Пример файла common.mk для проекта на базе сборочной системы Autotools:

ifndef QCONFIG
QCONFIG=qconfig.mk
endif
include $(QCONFIG)
#CONFIGUREFLAGS += <configure_option>
#LIBS += mylib
#USEFILE=%1>%C --help
#USETARGET=$(DESTDIR)/usr/bin/$(NAME)
#PINFOTARGET=$(DESTDIR)/usr/lib/lib1.so
#PINFOTARGET+=$(DESTDIR)/usr/lib/lib2.so
include $(MKFILES_ROOT)/autotools.mk
include $(MKFILES_ROOT)/qtargets.mk



Конфигурационные переменные модуля autotools.mk

AUTORECONFOPTS
Опции для передачи утилите autoreconf, если в проекте отсутствуют (или не предусмотрены) скрипты bootstrap, autogen.sh и buildconf.sh.
BOOTSTRAPOPTS
Опции для передачи в скрипты $(PROJECT_ROOT)/bootstrap или $(PROJECT_ROOT)/autogen.sh, если они имеются. Пример:

# Не использовать проект po4a (PO for anything) при первичной (bootstrap) конфигурации проекта
BOOTSTRAPOPTS=--no-po4a

CONFIGUREFLAGS
Опции для передаче главному скрипту confiugure, выполняющему настройку проекта перед сборкой.

Note: Список параметров, поддерживаемых скриптом configure, в общем случае индивидуален для каждого проекта и может быть уточнён с комощью команды ./configure --help

Пример (для проекта библиотеки libxml2):

CONFIGUREFLAGS += -C
CONFIGUREFLAGS += -prefix=/usr
CONFIGUREFLAGS += --with-threads --with-history --without-python
CONFIGUREFLAGS += --without-lzma
CONFIGUREFLAGS += --without-zlib

force
Необходимо установить переменную force=1 для обновления уже созданного файла .tarball-version (см. описание цели update-gnu-version).



Функции модуля autotools.mk

TARGET_BOOTSTRAP
Выполняет инициализацию проекта; может быть переопределена.
TARGET_CONFIGURE
Выполняет конфигурацию проекта; может быть переопределена. По умолчанию TARGET_CONFIGURE содержит вызовы функци PRE_CONFIGURE и POST_CONFIGURE, которые также могут быть определены в common.mk.

Модуль также позволяет использовать переменные и функции, описанные в разделе Общие переменные и функции.



Цели (targets) модуля autotools.mk

update-gnu-version
Создание файла .tarball-version. Файл .tarball-version нужен для корректной сборки проектов, которые получают информацию о своей версии из git-репозитория с помощью утилиты gnulib/build-aux/git-version-gen. При обновлении таких проектов необходимо с помощью данной цели обновлять файл .tarball-version.

Note: В т.н. "релизных" (Release) версиях проектов, использующих gnulib, git-version-gen не применяется, и файл .tarball-version создавать или обновлять не требуется.

Пример: make update-gnu-version

Поддержка сборочной системы CMake

Поддержка сборочной системы CMake обеспечивается модулем cmake.mk.

Caution: Предыдущая реализация, состоящая из модуля cmake-cfg.mk и исполнямого файла build-cmake, в настоящий момент считается устаревшей и не рекомендуется к использованию в новых проектах.

Пример файла common.mk для проекта на базе сборочной системы CMake:

ifndef QCONFIG
QCONFIG=qconfig.mk
endif
include $(QCONFIG)
#CMAKEFLAGS += -DCMAKE_OPTION=value
#LIBS += mylib
#USEFILE=%1>%C --help
#USETARGET=$(DESTDIR)/usr/bin/$(NAME)
#PINFOTARGET=$(DESTDIR)/usr/lib/lib1.so
#PINFOTARGET+=$(DESTDIR)/usr/lib/lib2.so
include $(MKFILES_ROOT)/cmake.mk
include $(MKFILES_ROOT)/qtargets.mk



Конфигурационные переменные модуля cmake.mk

CMAKEFLAGS
Опции для передачи утилите cmake



Функции модуля cmake.mk

TARGET_BOOTSTRAP
Инициализация проекта; функция может быть переопределена.

Модуль также позволяет использовать переменные и функции, описанные в разделе Общие переменные и функции.

Поддержка сборочной системы Meson

Поддержка сборочной системы Meson обеспечивается модулем meson.mk.

Пример файла common.mk для проекта на базе сборочной системы Meson:

ifndef QCONFIG
QCONFIG=qconfig.mk
endif
include $(QCONFIG)
#MESONFLAGS += -Doption=value
#LIBS += mylib
#USEFILE=%1>%C --help
#USETARGET=$(DESTDIR)/usr/bin/$(NAME)
#PINFOTARGET=$(DESTDIR)/usr/lib/lib1.so
#PINFOTARGET+=$(DESTDIR)/usr/lib/lib2.so
include $(MKFILES_ROOT)/meson.mk
include $(MKFILES_ROOT)/qtargets.mk



Конфигурационные переменные модуля meson.mk

MESONFLAGS
Опции для передачи утилите meson

Модуль также позволяет использовать переменные и функции, описанные в разделе Общие переменные и функции.

Поддержка сборочной системы qmake

Поддержка сборочной системы Qt обеспечивается модулем qmake.mk.

Пример файла common.mk для проекта на базе сборочной системы qmake:

ifndef QCONFIG
QCONFIG=qconfig.mk
endif
include $(QCONFIG)
# Использовать qmake5-*
#QMAKEVERSION = 5
#QMAKEFLAGS += <QMAKE OPTION>
# default use qmake .pro file $(PROJECT_ROOT)/$(NAME).pro
QMAKEPROFILE = $(PROJECT_ROOT)/$(NAME).pro
#USEFILE=%1>%C --help
#USETARGET=$(DESTDIR)/usr/bin/$(NAME)
#PINFOTARGET=$(DESTDIR)/usr/lib/lib1.so
#PINFOTARGET+=$(DESTDIR)/usr/lib/lib2.so
include $(MKFILES_ROOT)/qmake.mk
include $(MKFILES_ROOT)/qtargets.mk



Конфигурационные переменные модуля qmake.mk

QMAKEVERSION
Версия платформы Qt, которая требуется для данного проекта. Возможные значения: 5. Значение по умолчанию: отсутствует (пустое значение соответствует Qt версии 4)
QMAKEFLAGS
Дополнительные опции, передаваемые утилите qmake.
QMAKEPROFILE
Имя файла конфигурации проекта (обычно имеет расширение ".pro").

Note: По умолчанию используется файл <имя_проекта>.pro ( <имя_проекта> определяется через служебную переменную "$(NAME)" рекурсивной сборочной подсистемы).

Модуль также позволяет использовать переменные и функции, описанные в разделе Общие переменные и функции.

Общие переменные и функции

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



Универсальные переменные файла common.mk

Данные переменные поддерживаются всеми модулями поддержки внешних сборочных систем (если в примечании не указано иное).

LIBS
Список дополнительных библиотек, требуемых при линковке исполняемых файлов и разделяемых библиотек данного проекта. Пример:

# Линкеру будут переданы дополнительные аргументы -lsocket -lm
LIBS += socket m

LDFLAGS
Дополнительные опции линкера. Пример:

# Подробный диагностический вывод процесса линковки
LDFLAGS += -Wl,--verbose

LDVFLAG
Дополнительные опции линкера (с учётом варианта). Пример:

# Для проектов, собираемых с отладочной информацией (вариант g), будет подключена дополнительная библиотека
LDVFLAG_g += -lmydebug

CCFLAGS
Дополнительные опции компилятора. Пример:

# Компилятору будет передан дополнительный аргумент -std=c++11
CCFLAGS += -Wc,-std=c++11

CCVFLAG
Дополнительные опции компилятора (с учётом варианта). Пример:

# Для проектов, собираемых с отладочной информацией (вариант g), будет использован дополнительный макрос
CCVFLAG_g += -DMY_DEBUG

PINFOTARGET
Список исполняемых файлов и разделяемых библиотек, в которые нужно включить информационное сообщение PINFO, отображаемое с помощью команды use с параметром -i.

Note: Содержимое PINFO-сообщения определяется содержимым макроопределения PINFO. Пример:

define PINFO
PINFO DESCRIPTION=library for XML processing
endef


Пример (для проекта библиотеки libxml2):

define PINFO
PINFO DESCRIPTION=library for XML processing
endef
PINFOTARGET=$(DESTDIR)/usr/lib/libxml2.so.11

USETARGET
Список исполняемых файлов, в которые нужно включить информационное сообщение (т.н. use message), отображаемое с помощью команды use.

Note: Содержимое сообщения должно быть задано в файле, на который ссылается стандартная переменная $USEFILE

Пример (для проекта архиватора xz):

USETARGET =$(DESTDIR)/usr/bin/lzmadec
USETARGET+=$(DESTDIR)/usr/bin/lzmainfo
USETARGET+=$(DESTDIR)/usr/bin/xz
USETARGET+=$(DESTDIR)/usr/bin/xzdec



Универсальные функции

POST_INSTALL
Вызывается после сборки проекта; может быть переопределена. Поддерживает т.н. отложенный (delayed) режим (см. модуль postinstall.mk.)
TARGET_MAKE
Выполняет непосредственно сборку проекта; может быть переопределена. По умолчанию, TARGET_MAKE содержит вызовы функций PRE_INSTALL, PRE_MAKE, ADD_USAGE_TARGET, POST_INSTALL и POST_MAKE, которые также могут быть переопределены в файле common.mk.

Подключаемые модули

Подключаемые модули позволяют динамически расширять функциональность сборочной системы. Реализованы в виде отдельных файлов, имеющих расширение ".mk" и подключаемых с помощью директивы include из родительских файлов. В настоящий момент модули поддерживаются следующими файлами:


Caution: Все модули, перечисленные в данном разделе, автоматически подключаются из родительских файлов и, соответствено, не требуют повторного подключения из common.mk

Подключаемые модули разделены по подсистемам и находятся в соответствующих подкаталогах $KPDA_HOST/mk/inc.

Подключаемые модули qtargets.mk

Данные модули предназначены для расширения списка поддерживаемых целей (target'ов) команды make, что позволяет автоматизировать выполнение наиболее часто решаемых задач.

cppcheck.mk - статический анализ исходного кода

Модуль cppcheck.mk реализует поддержку статического анализа исходного кода проекта на языках C и C++ с помощью статического анализатора cppcheck, входящего в состав инструментальных средств Комплекта разработчика для ЗОСРВ "Нейтрино".


Caution: В настоящее время модуль cppcheck.mk поддерживает только статический анализ следующих типов проектов:
  • Рекурсивные проекты (драйверы, утилиты, прикладное ПО), использующие только базовые модули сборочной системы (recurse.mk, qconfig.mk).
  • Проекты BSP (статический анализ может быть выполнен в подкаталоге src, содержащем компоненты в исходных кодах)

Статический анализ проектов, построенных на базе внешних сборочных систем (таких, как Autotools, CMake, qmake и т.д.), не поддерживается.




Цели (targets) модуля cppcheck.mk

make cppcheck
Выполнение статического анализа. В результате в корневом каталоге проекта создаются файлы с расширением .cppcheck, содержащие сведения об обнаруженных ошибках. Удалить эти файлы можно с помощью вызова make clean.
make cppcheck_raw
Выполнение статического анализа. Результаты выводятся в консоль (по умолчанию используется поток stderr).



Управляющие переменные модуля cppcheck.mk

V
Управление подробностью вывода (verbosity); примеры использования:
$ make V=1 cppcheck # отображает значние CPPCHECK_SRCS в заголовке $ make V=2 cppcheck # V=1 + отображение полной строки запуска cppcheck (со всеми результирующими параметрами)
CPPCHECK_EXTRA_LIBRARIES
Подключение дополнительных конфигурационных библиотек (например, специфичных для проверяемого проекта). Пример использования в файле common.mk (подключение дополнительного конфигурационного файла project-cppcheck.cfg):

CPPCHECK_EXTRA_LIBRARIES:=$(PROJECT_ROOT)/project-cppcheck.cfg


Note: Дополнительная информация о создании пользовательских конфигурационных файлов и библиотек собрана в статье Использование статического анализатора cppcheck

CPPCHECK_FLAGS
Указание дополнительных опций cppcheck. Примеры использования:
  1. Игнорировать предупреждение allocaCalled:
    $ make CPPCHECK_FLAGS=--suppress=allocaCalled cppcheck
  2. Запустить статический анализ в 8 потоков, выводить только сообщения об ошибках:
    $ make "CPPCHECK_FLAGS=-j8 -q" cppcheck
  3. Запустить в режиме формирования dump-файлов с последующим их анализом на соответствие стандартам MISRA (средствами misra.py):
    $ make CPPCHECK_FLAGS=--dump cppcheck
CPPCHECK_DESTDIR
Указание каталога для сохранения отчётов cppcheck. По умолчанию отчёты помещаются в корневой каталог проекта (см. PROJECT_ROOT). Примеры использования:
  1. Переменная не задана (режим по умолчанию). Все отчёты будут помещены в корневой каталог проекта (используются платформо-специфичные имена):
    $ make cppcheck $ pwd /home/user/project $ ls -l *.cppcheck project_nto_x86.cppcheck project_nto_arm_le_v7.cppcheck
  2. Переменная задана (значение /tmp). Все отчёты будут помещены в каталог /tmp (используются платформо-специфичные имена):
    $ make CPPCHECK_DESTDIR=/tmp cppcheck $ ls -l /tmp *.cppcheck project_nto_x86.cppcheck project_nto_arm_le_v7.cppcheck
  3. Переменная задана (пустое значение). Отчёты будут формироваться непосредственно в сборочных каталогах (напр. nto/x86/o); используются универсальные имена ($(NAME).cppcheck, где $(NAME) - служебная переменная, содержащая имя исполняемого файла или библиотеки):
    $ make CPPCHECK_DESTDIR= cppcheck $ pwd /home/user/project $ find nto/ -name "*.cppcheck" nto/x86/o/project.cppcheck nto/arm/o.le.v7/project.cppcheck

postinstall.mk - отложенная пост-обработка проектов

Назначение: выполнение отложенного POST_INSTALL путём запуска скрипта do-pinstall.sh (расположен в корневом каталоге сборочной системы, является её частью и в общем случае не требует модификации). Данный механизм позволяет выполнить действия, описанные в функциях POST_INSTALL различных проектов, после выполнения всех остальных действий (т.е., например, после выполнения команды make install). Основное назначение механизма отложенного POST_INSTALL - уменьшение вероятности возникновения т.н. "гонок" (race conditions) при одновременной сборке и инсталляции проекта для нескольких целевых архитектур.



Цели (targets) модуля postinstall.mk

make pinstall
Выполнение отложенного POST_INSTALL.

Note: Для выполнения данной команды должна быть предварительно установлена или явно задана переменная DELAYED_POST_INSTALL_DIR. Пример:

$ make DELAYED_POST_INSTALL_DIR=/tmp pinstall



Управляющие переменные модуля postinstall.mk

DELAYED_POST_INSTALL_DIR
Имя каталога, где будут располагаться скрипты отложенного POST_INSTALL. Пользователь, от имени которого выполняется команда make pinstall, должен обладать правами на запись в данный каталог. Пример:

$ export DELAYED_POST_INSTALL_DIR=/tmp
$ make install
$ make pinstall

Пример задания функции POST_INSTALL с поддержкой режима отложенного выполнения в файле common.mk:

define POST_INSTALL
# 1. Выполнение действий с файлами в целевом каталоге
$(call MAKE_DELAYED_POST_INSTALL,$(RM_HOST) $(DESTDIR)/unneeded/files)
# 2. skip: блокирование действий для файлов (актуально для автоматического перемещения заголовочных и shared-файлов из CPU-специфичных каталогов)
$(call MAKE_DELAYED_POST_INSTALL,$(DESTDIR)/usr/include/<cpu_header>,skip)
# 3. prune: удаление пустых каталогов (по умолчанию: только $(DESTDIR)"/usr/share и $(DESTDIR)/usr/include).
# Каталоги могут стать пустыми, например, после выполнения других действий из POST_INSTALL.
$(call MAKE_DELAYED_POST_INSTALL,$(DESTDIR)/<empty dir1> $(DESTDIR)/<empty dir1>,prune)
endef


Note:
  • Перечень действий, выполняемых по умолчанию (например, перенос CPU-зависимых каталогов usr/include и usr/share на уровень выше) задан в файле do-pinstall.sh (см. списой функций do_*, вызываемых в конце функции main).
  • При использовании сложных конструкций в качестве аргументов необходимо использовать экранирование. Примеры:

    $(call MAKE_DELAYED_POST_INSTALL,printf \"WARNING: no .... (экранирование двойных кавычек)
    $(call MAKE_DELAYED_POST_INSTALL,if [ -d \"$(gcc_header_dir)\" ]; then .... (экранирование двойных кавычек)
    $(call MAKE_DELAYED_POST_INSTALL,if [ ! -d \"$(gcc_header_dir)/\$${mldir}\" ]; then .... (экранирование shell-переменных, т.е. \$${имя_переменной}

    Также не рекомендуется использовать символы ";" и круглые скобки (в частности, из-за этого наблюдаются проблемы с использованием конструкции case ... esac).


Подключаемые модули qconfig.mk

Данные модули предназначены для расширения и переопределения штатных механизмов сборочной системы.

bsp_buildtargets.mk - поддержка Make Targets в QNX Momentics IDE 7.0

Данный модуль предназначен для автоматического добавления объектов Build Targets в проекты BSP, импортированные в среду QNX Momentics IDE (т.к. загрузка и сохранение Build Targets не поддерживаются штатными средствами IDE, в т.ч. операциями Import/Export).

Порядок использования:


Note: Сообщение

NOT AN ERROR - new "<имя_цели>" build target created; please restart IDE or re-open project.

в окне "Problems" среды разработки свидетельствует о том, что добавление описания цели в конфигурацию проекта выполнено успешно, и не является признаком какой-либо ошибки (несмотря на то, что среда разработки помещает его в раздел "Errors").


Также можно добавлять Build Targets с помощью команды make и управляющих переменных. Пример:

$ make BUILD_TARGET=custom BUILD_ARGS=-Cimages

В результате выполнения данной команды в проект будет добавлен Build target с именем custom, соответствующей команде make -Cimages custom.

Выбор драйвера компиляции

При сборке рекурсивных проектов существует возможность выбора т.н. драйвера компиляции (COMPILER_DRIVER), а также типа компилятора (COMPILER_TYPE). Пример:

$ make COMPILER_DRIVER=qcc install # для большинства архитектур аналогично make install (см. файл qconfig.mk) $ make COMPILER_DRIVER=kcc COMPILER_TYPE=gcc # использовать конфигурацию gcc для драйвера kcc $ make COMPILER_DRIVER= install # выполнить сборку проекта без использования драйвера (т.е. непосредственно используя gcc)

В настоящее время механизм выбора драйвера компиляции и типа компилятора в значительной степени утратил свою актуальность по причине наличия единственного возможного драйвера ( kcc/ qcc), а также по причине перехода на использование компилятора gcc в качестве основного.


Note: Для сборки проектов под архитектуру e2kle (платформа "Эльбрус") в настоящее время в рекурсивной сборочной системе используются промежуточные врапперы ntoe2k-*, предоставляющие интерфейс к оригинальному компилятору lcc. Соответственно, вариант COMPILER_TYPE=lcc в качестве самостоятельного значения не используется.

Соответственно, актуальными для прикладного использования являются два варианта:

Значение по умолчанию для переменной COMPILER_DRIVER вычисляется в файле qconfig.mk. Оно зависит от текущих значений переменных OS и CPU, описывающих целевую систему, а также от значения COMPILER_TYPE.

Значение по умолчанию для переменной COMPILER_TYPE может быть задано следующими способами:

Другие возможности

Поддержка варианта сборки проектов с покрытием кода

Данная возможность позволяет осуществлять сборку рекурсивных проектов с поддержкой анализа покрытия кода (Code Coverage). Для этого предназначен вариант gcov. Пример:

$ addvariant -i OS nto x86 o $ addvariant o.gcov $ make VARIANTLIST=gcov

В результате будет собрано приложение, способное в процессе работы генерировать данные в формате GNU Code Coverage (gcov), которые далее могуть быть пронанализированы, например, средствами QNX Momentics IDE (подробнее: Using Code Coverage).


Note: При сборке проекта в варианте gcov к имени результирующих исполняемых файлов и библиотек будет добавлен суффикс -gcov (т.е., например, для проекта test в каталоге nto/x86/o.gcov* будет создан исполняемый файл test-gcov)

Параллельная сборка

Параллельная (многопоточная) сборка позволяет сократит время построения проекта путём одновременной обработки нескольких translation units на разных ядрах центрального процессора. Рекурсивная сборочная подсистема ЗОСРВ "Нейтрино" поддерживает два режима параллельной сборки:


Note: Принудительной переключение сборочной системы в режим совместимости (legacy) следует выполнять только в экспериментальных целях (например, при при некорректном завершении процесса сборки проектов, изначально разработанных в среде QNX SDP, а также в процессе миграции с ОСРВ QNX Neutrino 6.x на ЗОСРВ "Нейтрино"); в любом случае, рекомендуем в подобных ситуациях обращаться в службу Технической поддержки.

Рекомендации:

Механизм OVERRIDE

Данный механизм используется для переопределения значения управляющих переменных для индивидуального проекта или группы проектов.


Note: В начало override-файлов рекомендуется добавлять конструкции вида

$(info This is <имя_и_путь_к_файлу> override file)

для контроля использования и порядка подключения (т.к. в случае наличия нескольких override-файлов в проекте они могут взаимно переопределять значения переменных с одинаковыми именами).


Прочие замечания и рекомендации

Примеры использования

Пошаговое создание рекурсивного проекта "Hello World!"

$ mkdir HelloWorldProj $ cd HelloWorldProj $ cat > HelloWorld.c <<EOF #include <stdio.h> int main(void) { printf("Hello, World!\n"); return 0; }EOF $ echo -e "This is Hello World Application" > HelloWorldProj.use $ mkdir -p nto/x86/o $ echo -e "LIST=OS\ninclude recurse.mk" > Makefile $ echo -e "LIST=CPU\ninclude recurse.mk" > nto/Makefile $ echo -e "LIST=VARIANT\ninclude recurse.mk" > nto/x86/Makefile $ echo -e "include ../../../common.mk" > nto/x86/o/Makefile $ cat > common.mk <<EOF include qconfig.mk include $(MKFILES_ROOT)/qtargets.mk EOF $ ls nto/x86/o Makefile $ make ... $ ls -l nto/x86/o HelloWorld.o HelloWorldProj Makefile

Версионирование

Информация о версии рекурсивной сборочной подсистемы (ветка, commit id, вариант сборки) содержится в файле ${KPDA_HOST}/mk/REVISION.complete.




Предыдущий раздел: Сборочное окружение