# ya make - система сборки для Аркадии

ya make — это система сборки общего назначения для Аркадии - монорепозитория компании Яндекс. Раньше в Аркадии использовался CMake, но с ростом репозитория его производительности и масштабируемости стало недостаточно и появился `ya make`. Наша система сборки использует простой язык, похожий на `CMakeLists.txt`. Она позволяет быстро строить и тестировать большие проекты на нескольких языках под множество платформ.

## Общие сведения

Базовые сведения по нашей системе сборки приведены на этой странице ниже, более подробно познакомиться с системой сборки ya make можно в следующих разделах документации.
- [Что такое вообще система сборки ya make](general/about.md)
- [Что есть что в системе сборки ya make](general/base_concepts.md)
- [Как начать ею пользоваться](general/getting_started.md)
- [Как работает наша система сборки](general/how_it_works.md)
- [Какие у нас есть правила и ограничения](general/rules.md)

## С чего начать

Утилита `ya`, необходимая для запуска сборки, всегда находится в корне репозиториия Аркадия. Поэтому [получив себе Аркадию](https://docs.yandex-team.ru/arcadia/). сборку можно запускать сразу же командой `ya make <project_dir>` в корне репозитория. Переместившись в директорию проекта, сборку можно запустить командой `ya make`. Для запуска тестов надо выполнить команду `ya make -t` для запуска только маленьких (small) тестов, `ya make -tt` для средних, `ya make -ttt` или `ya make -A` для всех тестов.

По умолчанию код собирается под локальную платформу (под Linux на Linux, под macOS на macOS и т.д.) и в отладочной конфигурации. Для сборки в релизной конфигурации надо запускать `ya make -r`. У `ya make` достаточно [много опций](usage/ya_make/index.md). Кроме собственно команды `ya make`, система сборки предоставляет ещё ряд команд для пакетирования, генерации проектов IDE и анализа. Подробнее про это [в соответствующем разделе](usage/index.md).

Чтобы начать создавать проекты для ya make можно почитать [про описание сборки](manual/index.md) или про то, [как читать и писать ya.make](manual/syntax.md), а можно сразу перейти к пошаговым руководствам:

- [Как начать пользоваться ya make](general/getting_started.md)
- [Как писать и читать ya.make](manual/syntax.md)
- [Руководство по созданию проекта на С++ (WiP)](tutorials/cpp.md)
- [Руководство по созданию проекта на Python](tutorials/python.md)
- [Руководство по созданию проекта на Java (WiP)](tutorials/java.md)
- [Руководство по созданию проекта на Go](tutorials/go.md)
- [Руководство по созданию библиотеки protobuf (WiP)](tutorials/protobuf.md)
- [Руководство по созданию проекта документации](tutorials/doc.md)
- [Руководство по созданию тестов (WiP)](tutorials/tests.md)


## Использование системы сборки

Система сборки ya make предоставляет богатые возможности сборки и тестирования кода на 4х основных языках С++, Python, Java и Go с использованием примерно 10 тестовых фреймворков. Она обеспечивает
интеграцию в сборку множества кодогенерирующих технологий, включая protobuf, ragel и собственные наработки проектов Яндекс.
 
Кроме непосредственно сборки и тестирования она также предоставляет команды для пакетирования, экспорта проектов для нескольких IDE и средства анализа зависимостей.
Подробней изучить её возможности помогут следующие разделы документации

- [Команды системы сборки](usage/index.md)
- [Описание сборки](manual/index.md)
- [Тестирование](manual/tests/index.md)
- [Настройка и расширение](extension/index.md)


## В чём преимущества ya make

**Простой и понятный язык описания сборки.** Язык описания сборки является наследником `CMakeLists.txt`. Описание сборки делается в `ya.make`-файлах и, как и с CMake всё описание — это вызовы определённых макросов с параметрами. Для лучшего структурирования в описании выделены *модули* - специальные макросы, определяющие тип проекта `PROGRAM`, `LIBRARY`, [`PY3_PROGRAM`](manual/python/modules.md#py_program), [`PY3_LIBRARY`](manual/python/modules.md#py3_library) и т.п. Другие макросы, размещённые между таким макросом и `END()`, собственно, и составляют описание сборки модуля. Описание сборки очень высокоуровневое: в большинстве случаев нужно описывать что собирать, но не как. Для корректной работы наша система сборки должна знать всё, от чего *зависит* её результат, существенную часть информации она в состоянии получить сама, анализируя исходный код, в сложных случаях ей надо подсказать.

**Сборки ya make воспроизводимы.** Система сборки ya make полагается на то, что она знает всё, от чего *зависит* её результат. В ней невозможно обратиться к внешним и меняющимся данным и программам. Система не умеет привозить пакеты из внешних хранилищ или вызывать программы из системы, на которой запущена. Вместо этого она собирает инструменты либо привозит их из специального, неизменяемого хранилища. Это делает сборку полностью воспроизводимой для фиксированного состояния рабочей копии (ревизия Аракадии + локальные изменения) и фиксированной конфигурации (параметров запуска `ya make`). Это позволяет легко воспроизводить ошибки из CI локально.

**ya make кроссплатформенный.** Система сборки работает на Linux, Windows и macOS. Она поддерживает сборку одного и того же проекта под множество различных платформ, включая мобильные и во множестве различных конфигураций включая, например, санитайзеры. Большинство целевых платформ доступы при сборке на всех локальных платформах через кросс-компиляцию.

**Априорный анализ зависимостей.** Всё, что может повлиять на результат сборки ya make выясняет заранее. Это позволяет уже после анализа зависимостей точно знать, что именно задето изменениями и запускать пересборку только нужных файлов и модулей.

**ya make масштабируется.** Используя `ya make` можно собрать как отдельный небольшой проект на ноутбуке, так и весь код в Аркадии на кластере из 1000 серверов. Мощный, масштабируемый и эффективный анализ зависимостей позволяет сконфигурировать сборку всей Аркадии меньше, чем за 15 минут под основную платформу + 50+ дополнительных. Априорный анализ зависимостей позволяет сократить объём необходимых пересборок, а воспроизводимость даёт широкие возможности для кэширования между сборками. Это позволяет эффективно использовать ya make для CI-проверок на всей Аркадии несмотря на 100000+ проектов, миллионы файлов и 10+ проверок в минуту в часы пик.

**ya make гибко конфигурируется и расширяется.** БОльшая часть из 300+ макросов и 70+ модулей для `ya make` не вшита, а сконфигурирована на специальном языке или плагинами на Python. Систему можно настроить на очень широкий спектр применений без изменения кода самой системы сборки. Но если прямо очень надо, код самой системы сборки доступен в Аркадии.

## Что может показаться непривычным

**Декларативное описание сборки.** Большая часть конструкций `ya.make`-файлов не исполняется последовательно. Они описывают разнообразные параметры сборки, и эта информация будет учтена при конфигурировании или исполнении сборки. Исполнение некоторых макросов упорядочено, но в большинстве случаев полагаться на порядок для разрешения неоднозначностей не стоит. Тоже самое относится к списочным свойствам - порядок элементов внутри них может сохраняться, но не стоит на него полагаться. Старайтесь избегать неоднозначностей в описании сборки.

**Одна директория — одна цель.** В каждой директории может быть только один файл описания сборки (`ya.make`) и в каждом `ya.make` может быть только один модуль. Это правило не всегда удобно и не всем нравится, но оно сильно упрощает работу с системой сборки: для указания цели сборки достаточно директории, для указания зависимости - тоже. Не надо думать как сослаться на конкретную цель. Сами `ya.make`-файлы остаются небольшими, легко обозреваемыми и понятными.

**Все входы, результаты и зависимости должны быть известны системе.** При описании сборки невозможно использовать неопределённый состав файлов (например директорию целиком) как для описания входов, так и результатов (в тех, случаях, когда результат описывается явно). Это важно для воспроизводимости: результат не будет различаться локально и в CI, если в рабочей копии затесался файл от какого-то эксперимента или если какой-то файл забыли закоммитить. Система сборки ограниченно поддерживает glob-ы для случаев, когда входных файлов может быть много. Однако в случае их использования возможны проблемы, описанные выше. Кроме того, glob-ы замедляют анализ зависимостей из-за необходимости следить не только за изменением файлов, но и за составом директорий на файловой системе.

## Как работает ya make

Подробно о том, как устроена и работает система сборки можно прочитать [здесь](general/how_it_works.md).
В очень общих словах система сборки ya make работает следующим образом:

- Читает и анализирует `ya.make`-файлы в соответствии со своей конфигурацией и переданными параметрами.
- Анализирует исходные файлы, перечисленные в `ya.make`на предмет зависимостей между файлами.
- На основании этой информации строит внутренний *граф зависимостей*.
- На графе зависимостей делает ряд проверок и собирает *транзитивную информацию*.
- Превращает граф зависимостей в *граф команд* сборки. Каждому узлу *графа команд* на основе *графа зависимостей* и *транзитивной информации* рассчитывает уникальный идентификатор *UID*. Этот *UID* включает в себя всё, что влияет на результат команды. Если *UID* не меняется, то результат считается *функционально эквивалентным* (но не обязательно *бинарно эквивалентным* — наша система сборки не обеспечивает бинарную воспроизводимость и не опирается на неё).
- Граф команд обогащается, например, в него добавляется запуск тестов.
- После этого граф команд исполняется *локально* или на *кластере распределённой сборки*. При любом исполнении *UID* узла служит ключом в кэше. Это обеспечивает инкрементальность сборки. Кэш может быть как локальным, так и в базе данных YT (при использовании параметра `--yt-store`).
- В соответствии с параметрами, часть узлов *графа команд* считаются *результирующими узлами*. Сборка всегда начинается с них и распространяется по зависимостям, если *UID* узла нет в кэше. 
- Каждый узел выполняется в своей сборочной директории, в которую перед запуском помещаются (ссылками) результаты зависимых узлов. Это обеспечивает изоляцию узлов для воспроизводимости.
- По окончании сборки выходы *результирующих узлов* или помещаются в рабочую копию символьными ссылками или складываются в выходную директорию, заданную параметром `--output`.






