# Описание пакетов и объединённых целей

## Зачем и что нужно

Основным средством пакетирования в системе сборки является команда [`ya package`](../../usage/ya_package). Пакет для неё описывается в формате JSON, а не ya.make и позволяет среди прочего,
задать параметры сборки определённых артефактов и их раскладку в конечном пакете. `ya package` очень мощный инструмент, поддерживающий создание пакетов в нескольких форматах, сборку 
мультиплатформенных пакетов (таких, в которых разные артефакты собраны под разные платформы), публикацию артефактов и многое другое.

К сожалению, в силу гибкости и широты возможностей пакеты, собранные `ya package`, практически невозможно встроить в тестирование `ya make`. По сути, такое тестирование требовало бы
конфигурирования всех пакетируемых артефактов в описанных в `package.json` конфигурациях, а также объединение всех таких сборок в один сборочный граф. Это бы привело к неконтролируемому 
росту конфигураций для часто используемых библиотек, а также к неконтролируемой сложности и объёму сборки, в среде CI.

В отличие от `ya package` при сборке `ya make` целевая платформа фиксируется параметрами запуска, а не описанием. Технически `ya make` может собрать код под несколько платформ одновременно,
но артефакты разных платформ не могут взаимодействовать между собой (кроме редких, специально поддержанных случаев вроде `lipo`). Это обеспечивает конфигурирование каждой общей библиотеки в 
рамках одной платформы/конфигурации ровно один раз.

Для совмещения тестирования и пакетирования `ya.make` предоставляет специальные модули [`PACKAGE`](./modules#package) и [`UNION`](./modules#union). Они не предоставляют средств создания пакетов
даже для одной платформы, а должны скорее рассматриваться как средство агрегации целей. В некоторых случаях модуля [`PACKAGE`](./modules#package) будет достаточно для реального пакетирования и
деплоя, однако его средства по управлению размещением файлов ограничены, а средства пост-обработки не поддерживаются вовсе в силу требований герметичности и воспроизводимости сборки.

Результатами сборки этих модулей является либо просто набор всех файлов, полученных при сборке, либо архив с этими файлами (при использовании макроса [`PACK`](./macros#pack). Файлы получаются как результаты сборки зависимостей, скажем программ,
а также исполнения макросов вроде [`RUN_PROGRAM`](../common/macros#run_program) или [`FROM_SANDBOX`](../common/data#from_sandbox).

## Отношение между `PACKAGE` и `UNION`

В мире агрегации модуль [`PACKAGE`](./modules#package) выступает в роли чего-то вроде *программы в мире С++*. Это конечный модуль, замыкающий (как бы линкующий) все свои зависимости.
В свою очередь [`UNION`](./modules#union) выступает в роли чего-то вроде *библиотеки на C++*. Он может зависеть от других [`UNION`](./modules#union), но при его сборке зависимые
модули собираться не будут, они будут предоставлены замыкающему [`PACKAGE`](./modules#package). Кроме модуля [`PACKAGE`](./modules#package), зависимости модуля [`UNION`](./modules#union)
замыкаются макросом [`DEPENDS`](../tests/common#depends). Это позволяет использовать структуру модулей [`UNION`](./modules#union) для подвоза одинаковых [тестовых данных](../common/data)
в несколько тестов.

Зависимости между [`PACKAGE`](./modules#package) и [`UNION`](./modules#union) описываются также, как и зависимости любых других модулей макросом [`PEERDIR`](../common/macros#peerdir).
Кроме зависимостей между собой и [`PACKAGE`](./modules#package) и [`UNION`](./modules#union) могут иметь зависимости от любых других сборочных модулей. Зависимости от библиотек обычно имеют мало смысла,
поскольку библиотеки не самодостаточны, но зависимости на программы — это распространённый сценарий использования этого типа модулей.

{% note tip %}

[`UNION`](./modules#union) не замыкает никакие свои зависимости, в том числе программы. Т.е. при сборке [`UNION`](./modules#union) программа, на которую в нём есть [`PEERDIR`](../common/macros#peerdir)
строиться не будет. Она будет построена только при сборке [`PACKAGE`](./modules#package), зависящего от этого [`UNION`](./modules#union). Если необходимо сделать программу самого [`UNION`](./modules#union),
используйте макрос [`BUNDLE`](../common/macros#bundle), он привозит артефакт сборки модуля, на который ссылается в сборку модуля, в котором указан макрос.

{% endnote %}

## Размещение файлов

Помимо работы с зависимостями важным отличием [`PACKAGE`](./modules#package) от [`UNION`](./modules#union) является размещение файлов. Поскольку [`UNION`](./modules#union) собирает
в себя только свои собственные файлы, то в результате его сборки образуются файлы непосредственно директории модуля или его поддиректориях, указанных в параметрах макросов `OUT`/`OUT_NOAUTO` и подобных.

[`PACKAGE`](./modules#package) замыкает в себя результаты всех своих модулей-зависимостей и потому, чтобы избежать неоднозначностей результаты каждого такого модуля-зависимости попадают внутрь
[`PACKAGE`](./modules#package) со своим *namespace*, т.е. путём от корня Аркадии.


## Подробности

- [Модули `PACKAGE` и `UNION`](./modules)
- [Макросы используемые в модулях агрегации](./macros)
