# ya make: основной сборочный инструмент

Чтобы запустить сборку на своём ноутбуке или виртуалке достаточно выполнить команду `ya make <target>`, где `<target>` — директория проекта, который хочется построить.

Сборка может быть *локальной* или *распределённой*. Бóльшая часть возможностей доступна как локально, так и в распределённой сборке, однако есть ряд особенностей, связанных с тем, как выполняется сборка.

* Локальная сборка выполняется полностью на той машине (ноутбуке, виртуалке, хосте в Sandbox), где её запустили. [Подробнее об особенностях локальной сборки](local.md)
* Распределённая сборка конфигурируется локально (там, где запущена команда `ya make`), но выполняется на специальном сборочном кластере *Distbuild*. [Подробнее об особенностях распределённой сборки](dist.md)

`ya make` позволяет очень гибко настраивать параметры сборки. Список настраиваемых возможностей включает:

- [Выбор типа и вида сборки](#build_type) — debug/release, LTO, sanitizers и т. п.
- [Параметры платформ](#platforms) — целевые аппаратная платформа и OS, настройки сборочной платформы и т. п.
- [Установку сборочных переменных](#D) — Например, `-DCFLAGS=-Wall`, `-DDEBUGINFO_LINES_ONLY` и т. п.
- [Настройки сборки](#options) — строить по максимуму или до первой ошибки, выбор дополнительных результатов сборки и т. п.
- [Запуск и работу с тестами](#tests)

## Пользовательские настройки и умолчания { #defaults }

По умолчанию (без дополнительных опций) команда `ya make` работает в соответствии c

- локальными настройками, описанными в файлах [`ya.conf`](https://docs.yandex-team.ru/yatool/commands/gen_config),
- указанными переменными среды,
- настройками в глобальном [ya.conf](https://a.yandex-team.ru/arc/trunk/arcadia/ya.conf),
- глобальными умолчаниями
- умолчаниями для системы, на которой запускается сборка.

**Глобальные умолчания:**

- [Локальная сборка](local.md) без использования [распределённого кэша](yt_store.md);
- Тип сборки: [Debug](#build_type) (без оптимизаций и с ассёртами);
- Сборка до первого падения;
- Запуск тестов: отключен;
- Вывод на консоль перезатирает предыдущий, вывод в файл добавляет строки.

{% note tip %}

Набор умолчаний для всех параметров можно посмотреть, сгенерировав файл `ya.conf` командой [`ya gen-config`](https://docs.yandex-team.ru/yatool/commands/gen_config)

{% endnote %}

**Умолчания для системы**

- [Целевая платформа](../../general/base_concepts.md#configs): такая же как та, на которой запущена сборка;
- [Сборочная конфигурация](../../general/base_concepts.md#configs): платформа такая же как та, на которой запущена сборка + Release без отладочной информации.
  В режиме `--dist` сборочной платформой будет `Linux`;
- [Локальный параллелизм](local.md#par): число параллельных компиляций равно числу логически ядер системы, где запускается сборка.
- На Linux и macOS результаты складываются символьными ссылками в дерево исходных файлов, на Windows - нет, нужно указывать директорию для результатов [явно](#results)

## Популярные рецепты

* `ya make -r` - собрать код c оптимизациями и отладочной информацией ([Release](#build_type))
* `ya make -v` - собрать в verbose-режиме. **Обратите внимание:** `ya -v make` и `ya make -v` имеют разный эффект. Первая добавляет вывод утилиты `ya`, вторая — сборки.
* `ya make -T` - собрать, не перезатирая выполняемые команды в выводе
* `ya make --dist` - собрать код на кластере [распределённой сборки](dist.md)
* `ya make --add-result=".h" --add-result=".cpp"` - собрать, добавив в результаты сгенерированные в процессе сборки cpp- и h-файлы.
* `ya make --add-result=".pb.h" --add-result=".pb.cc" --replace-result`- запустить только кодогенерацию протобуфов.
* `ya make -t`  - запустить только [быстрые тесты](#tests)
* `ya make -tL` - вывести список [быстрых тестов](#tests)
* `ya make -A`  - запустить [все тесты](#tests)
* `ya make -h`  - посмотреть справку по всем опциям


## Типы сборок { #build-type }

По умолчанию код в Аркадии собирается в конфигурации *Debug* — без оптимизаций, с отладочной информацией и ассёртами.
Для типов сборок доступны следующие варианты:

- `-d`, `--debug`, `--build debug` (по умолчанию) - сборка без оптимизаций (для C++ уровень оптимизаций `-O0`), с отладочной информацией и ассёртами. Для С++ добавляет `-fstack-protector`.
- `-r`, `--release`, `--build release` - Сборка *Release* — с оптимизациями (для C++ уровень оптимизаций `-O3`). Для кода на C++ она включает отладочную информацию.
- `--build relwithdebinfo` - Релизная сборка с включенными ассёртами для C++. Используется для основных проверок в CI поскольку debug слишком медленно, а ассёрты дают больше полезной информации.
- `--build minsizerel` - Сборка с оптимизацией по размеру бинарного кода (для C++ уровень оптимизаций `-Oz` или `-Os` в зависимости от компилятора)
- `--build debugnoasserts` - Сборка без оптимизаций, но с выключенными ассёртами.
- `--build fastdebug` - Более производительная отладочная сборка, включает оптимизации, не усложняющие отладку (для C++ уровень оптимизаций `-Og`).
- `--build profile` - Релизная сборка, упрощающая профилировку — для C++ добавляет `-fno-omit-frame-pointer`.
- `--build valgrind`/`--build valgrind-release` - Инструментированная сборка для профилирования памяти с помощью valgrind.
- `--build coverage` - Сборка с инструментированием для подсчёта покрытия кода.


{% note tip %}

Полный актуальный список вариантов сборки можно посмотреть, выполнив `ya make --help | grep 'Build type'` или `ya make --build help`.

{% endnote %}

Кроме параметра `--build` есть ещё ряд флагов, влияющих на тип сборки:

- `--lto`/`--thinlto` - сборка с глобальными оптимизациями (оптимизациями во время линковки, LTO) для C++;
- `--sanitize <sanitizer>` - сборка с санитайзером для С++;
- `--race` - сборка с race detector для Go.
- `--hardening` - сборка с более строгими проверками в коде
- `--musl` - сборка C/С++ c MUSL вместо glibc
- `--cuda=<optional|required|disabled>` - сборка с CUDA
- `--lipo` - сборка мультиплатформенной программы macOS

- Сборка с профилировкой

    {% cut "Подробнее" %}

    С помощью `ya make` можно собирать проекты с использованием  [Profile-guided optimization](https://ru.wikipedia.org/wiki/Profile-guided_optimization).

    * Сборка исполняемого файла со включенным инструментированием: `--pgo-add`. При работе исполняемого файла собираемая статистика сохраняется в файл профиля. Его имя по умолчанию — `default.profraw`.
        В переменной среды `LLVM_PROFILE_FILE` можно указать шаблон пути и имени профиля. В шаблоне можно использовать подстановку `%p`, которая будет заменена на PID исполняемого файла,
        а также другие (см. [документацию](http://clang.llvm.org/docs/UsersManual.html#profiling-with-instrumentation)).
        **Внимание**: запись профайла происходит только в случае **успешного** завершения программы.
    * Сборка и оптимизация исполняемого файла с учётом собранной статистики: `--pgo-use=<profile>`.
        * `<profile>` — путь к файлу (или файлам) с собранной статистикой. В пути допускается использовать [glob-шаблоны](https://docs.python.org/2/library/glob.html#glob.glob).

    Для оптимизации можно использовать произвольное количество полученных профилей. Также формат профиля, используемого при оптимизации, отличается от формата профилей, которые сохраняют инструментированные программы. Поэтому перед сборкой с оптимизацией полученные профили нужно объединить и сконвертировать их в конечный формат, даже если был получен всего один профиль. При использовании `--pgo-use` такое объединение и конвертация происходит автоматически, и объединённый файл сохраняется в текущей директории. Путь к этому файлу выводится в консоль. Если передан один файл и он уже конечного формата, например, получен ранее при помощи `llvm-profdata`, то будет использован именно он, без создания дополнительного файла.

    Можно указать несколько флагов `--pgo-use`. В этом случае при оптимизации будут использованы все профили из каждого флага.

    * Полученные после работы инструментированного кода профили можно также вручную объединить и сконвертировать утилитой `llvm-profdata`: `ya tool llvm-profdata merge -output {output file} {input1} {input2}...`

        * `{input*}` — профили, полученные при работе исполняемого файла, собранного с использованием `--pgo-add`.
        * `{output file}` — путь, куда будет сохранён объединённый профиль. Этот профиль можно использовать в `--pgo-use`.


    {% endcut %}

## Платформы { #platforms }

При сборке кода под платформой обычно понимают 
аппаратную платформу (CPU, набор машинных инструкций, которые должны быть использованы в бинарном коде), 
операционную систему, на который должна работать программа,
и программные средства, которые должны быть использованы для сборки (компилятор и т. п.).
Система сборки `ya make` не исключение. Платформа для неё — это тройка *<компилятор, OS, архитектура>*,
например *<clang11, Windows, x86_64>* или *<clang10, Android, armv8a>*.

{% note info %}

Среди языков, разрешенных в Аркадии, Python и Java могут собираться кроссплатформенно, т. е. результаты их сборки могут не зависеть от платформы. Однако,

- в Аркадии принята бинарная сборки Python, да и многие Python-библиотеки содержат бинарный исполняемый код. Поэтому сборка Python в Аркадии зависит от платформы.
- У Java бинарных зависимостей заметно меньше и потому существенная её часть действительно кроссплатформенна. Исключение составляют динамические библиотеки, в которые могут быть биндинги у Java.
  На данный момент платформой для Java скорее можно назвать версию JDK, используемую для сборки. Однако она задаётся [`-D`-флагом](#D) `JDK_VERSION`, и в смысле параметров ya make частью платформы не является.

{% endnote %}


По умолчанию в качестве [целевой и сборочной платформ](../../general/base_concepts.md#configs) выбирается та, где запущена сборка. Т. е. в качестве операционной системы будет выбрана та, где вы работаете (Linux, Darwin (macOS) или Windows), в качестве архитектуры
x86_64 или arm64 (для маков на процессоре m1), а в качестве компилятора будет использован вариант по умолчанию (*default*) для данной OS.

Поменять целевую платформу можно флагом `--target-platform`.
В качестве значения нужно указать тройку *<компилятор, OS, архитектура>*, соединив значения через дефис.
Также можно указать какое-то подмножество компонент этой тройки (остальные элементы подставятся по умолчанию).
Для выбора компилятора по умолчанию можно указать специальное значение `DEFAULT`.

**Примеры:**

- `--target-platform clang-win-x86_64`  — собрать по Intel 64bit Windows компилятором Clang;
- `--target-platform default-android-armv8a` — собрать под Android на ARM (в версии armv8a) компилятором по умолчанию;
- `--target-platform windows` — собрать под Windows (и архитектуру по умолчанию x86-64) компилятором по умолчанию.

{% note tip %}

Пара замечаний по сборке под maсOS:

1. При указание платформы для macOS указывается название ядра OS — `DARWIN`
2. Для сборки под ARM-платформу от Apple (m1) нужно указать `default-darwin-arm64`, так как по умолчанию на macOS используется x86-64.

{% endnote %}


{% note tip %}

Система сборки ya make поддерживает достаточно большое количество целевых платформ, архитектур и компиляторов. Однако, далеко не все их сочетания могут быть использованы.
В случае ошибки в указании платформы ya make попробует подсказать близкие доступные варианты, но это не будет списком вообще всех доступных вариантов.

{% endnote %}


{% note alert %}

Система сборки ya make поддерживает *одновременную сборку* под несколько платформ (`--target-platform` можно указать несколько раз).
Более того, для каждой целевой платформы доступны разные дополнительные настройки (`--target-platform-flags`  позволяет задать [`-D`-флаги](#D),
а `--target-platform-build-type` — [тип сборки](#build-type) для платформы, указанной перед этими опциями). Однако

- Для каждой платформы будет получен отдельный артефакт. ya make не поддерживает *мультиплатформенную сборку* — результаты не будут запакованы в fat binary для macOS или Android APK.
- Артефакты для разных платформ могут иметь одинаковые имена, при складывании результатов они могут наложиться друг на друга и результат будет непредсказуем.

Используйте [ya package](../ya_package) для предсказуемой сборки под несколько платформ.

{% endnote %}

Система сборки ya make позволяет отделить процесс [конфигурирования](../../general/base_concepts.md#conf) от сборки и потому кроме задания *целевой платформы* можно указать *сборочную платформу* (опция `--host-platform`).
Однако, эта возможность вам вряд ли понадобится в повседневной работе: для локальной сборки это имеет мало смысла, а для сборки на кластере распределённой сборки (`--dist`) сборочная платформа
автоматически меняется на ту, которая используется на кластере (Linux, x86-64).

Несколько больше смысла имеет указание дополнительных флагов для сборочной платформы (`--host-platform-flags`). Обычные [флаги](#D) действуют на сборку для *целевой платформы*, но иногда хочется поменять то, как
собираются инструменты (в Аркадии разрабатывается большое их число). В этом случае `--host-platform-flags` придётся кстати, например:

- `--host-platform-flags MUSL` позволяет попробовать сборку с инструментами построенными с musl libc вместо glibc.
- `-DUSE_PREBUILT_TOOLS=no --host-platform-flag=USE_PREBUILT_TOOLS=no` позволяет отключить использование [предпостроенных инструментов](local.md#prebuilt_tools) (собирать все доступные в Аркадии инструменты из исходного кода).

## Сборочные переменные { #D }

В команде `ya make` можно указать дополнительные флаги (переменные) с помощью опции `-DVAR[=VALUE]`. Если не указывать значение переменной, по умолчанию оно будет выставлено в `yes`.

Можно определить:

* Предопределённые переменные, позволяющие передать флаги для сборки `ya make -DLDFLAGS="-fblabla=foo -fbar"`, `ya make -DCFLAGS="-DNN_DOUBLE_PRECISION -Wno-strict-aliasing"` и т. п.
* Предопределённые переменные, управляющие конфигурацией, например `ya make -DCATBOOST_OPENSOURCE` (сборка как для open source) или `ya make -DCUDA_VERSION=10.1` (сборка с CUDA).
* Переменные для использования в ya.make `ya make -DMACRO1 -DMACRO2=42`, где в `ya.make` написано, например `IF (MACRO1)`.

Список доступных переменных достаточно большой и часто меняется. Самые часто используемые переменные можно найти в соответствующих разделах [руководства по системе сборки](../../manual/index.md):

- [Переменные общие для всех языков](../../manual/common/vars.md#D)
- [Переменные для С/С++](../../manual/cpp/vars.md#D)
- [Переменные для Python](../../manual/python/vars.md#D)
- [Переменные для Java](../../manual/java/vars.md#D)
- [Переменные для Go](../../manual/go/vars.md#D)


{% note warning %}

Настоятельно не рекомендуется описывать сборку проектов таким образом, чтобы она для нормальной работы требовала каких-то флагов. В автосборке CI в норме никакие проектно-специфичные переменные не выставляются.
Если у вас на столько сложный случай, что требуется изменение поведения системы сборки обратитесь в [поддержку devtools](https://st.yandex-team.ru/createTicket?queue=DEVTOOLSSUPPORT), вам помогут
как с описанием сборки, так и с настройкой CI-процессов.

{% endnote %}

## Настройки исполнения сборки { #options }

При исполнении сборки можно настроить довольно много параметров, включая

- [Отображение прогресса](#progress)
- [Управление результатами сборки](#results)
- [Локальное кэширование](./local_ya_cache.md)
- [Локальное исполнение сборки](./local.md)
- [Исполнение сборки на кластере распределённой сборки](./dist.md)
- [Использование распределённого кэша](./yt_store.md)

### Общие настройки

По умолчанию сборка исполняется до первой ошибки, чтобы построить как можно больше (и увидеть как можно больше ошибок) используйте опцию `-k`/`--keep-going`.

{% note alert %}

Опция `-k`/`--keep-going` продолжает сборку даже в присутствии ошибок конфигурирования. Однако, корректность такой сборки не гарантируется.

{% endnote %}

По умолчанию все результаты локальной сборки (как промежуточные, так и финальные кэшируются). Кэширование результатов сборки описывается в разделе [результаты сборки](local_ya_cache.md#local-results).
Если хочется полностью отключить кэширование и перестроить код полностью с нуля используйте опцию `--rebuild`.


### Отображения прогресса { #progress }

По умолчанию `ya make` выводит прогресс на консоль в стиле `ninja`, т. е. по возможности использует одну строку под статус сборки. Поскольку сборка распараллеливается статус отображается только для
одной из исполняющихся параллельно сборочных команд, про остальные в конце строки написано `+X more`.

Вывод по умолчанию выгляди следующим образом

```
 |99.3%| [JV] {debug} $(B)/devtools/ya/test/tests/tags/data/java/data-java.jar                                       +12 more / 76.8GiB
  ^^^^        ^^^^^^^                                                                                                ^^^^^^^^   ^^^^^^^
Прогресс     Конфигурация и платформа                                                                                сколько    занято
         ^^^          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                           ещё    сборкой
         Тип          Вход или результат, идентифицирующий команду,                                                исполняется    место в кэше
       команды                                                                                                        команд
```

Кроме исполнения команд система сборки может исполнять вспомогательные процессы, если одновременно с ними не исполняются сборочные команды, то статус отображает их исполнение. Например

Конфигурирование:
```
Configuring dependencies for platform tools
```

Или управление кэшем (например очистка):

```
|99.3%| AUXILARY TASKS
```


{% note tip %}

При выводе чего-то кроме статуса, а также если статус не влезает в ширину терминала вывод переходит на другую строку. По умолчанию `ya make` выводит на консоль stderr исполняющихся команд,
а обрезать строку статуса по ширине пока не умеет.

{% endnote %}

Изменить вывод статуса на построчный можно опцией `-T`. Этот же режим включается при перенаправлении вывода команды `ya make` в файл.

Вывод команды ya make можно расширить следующими опциями:

- `-v, --verbose` — выводить текст исполнившихся сборочных команд
- `--do-not-output-stderrs` — не выводить stderr команд
- `--show-timings` — выводить времена исполнения команд в статус **Работает только с `-T`**
- `--show-extra-progress` — выводить расширенный прогресс (количество исполненных команд) в статус. **Работает только с `-T`**
- `--cache-stat` — перед сборкой выдать статистику по наполнению локального кэша
- `--stat` — в конце сборки выдать статистику по сборке. Статистика включает использование кэшей, критический путь, самые долгие сборочные шаги и т.п.

  **Пример статистики**

    ```
    Cache hit ratio is 66.67% (2 of 3). Local: 2 (66.67%), dist: 0 (0.00%)

    Dist cache download: count=0, size=0 bytes, speed=0.0 bytes/s

    Disk usage for tools/sdk 3.57 GiB
    Additional disk space consumed for build cache 0 bytes

    Critical path:
    [1800 ms] [TS] [rnd-6fhs6g7mena0lj3a default-linux-x86_64 release]: devtools/ymake/ut/unittest [started: 0 (1655207840079), finished: 1800 (1655207841879)]
    Time from start: 1800 ms, time elapsed by graph 1800 ms, time diff 0 ms.

    The longest 10 tasks:
    [1800 ms] [TS] [rnd-6fhs6g7mena0lj3a default-linux-x86_64 release]: devtools/ymake/ut/unittest [started: 1655207840079, finished: 1655207841879]
    [ 736 ms] [prepare:FromCache(W09-1vAMmTiIUbzkgxWf-w$(BUILD_ROOT)/devtools/ymake/ut/devtools-ymake-ut)] local [started: 1655207839338, finished: 1655207840074]
    [ 465 ms] [prepare:clean symres] local [started: 1655207839212, finished: 1655207839677]
    [ 176 ms] [prepare:$(yt-store-get-meta)] local [count: 1, cps: 5.68, ave time 176.00 msec]
    [  80 ms] [prepare:$(AC-has)] local [count: 2, cps: 25.00, ave time 40.00 msec]
    [  40 ms] [prepare:$(JDK-893501938)] local [started: 1655207839350, finished: 1655207839390]
    [  38 ms] [prepare:$(JDK17-893501938)] local [started: 1655207839359, finished: 1655207839397]
    [  33 ms] [prepare:$(JDK11-3963791836)] local [started: 1655207839362, finished: 1655207839395]
    [  31 ms] [prepare:$(WITH_JDK-sbr:3195072371)] local [started: 1655207839348, finished: 1655207839379]
    [  31 ms] [prepare:$(WITH_JDK11-sbr:3064614561)] local [started: 1655207839357, finished: 1655207839388]

    Total time by type:
    [TS] - 1800 ms.
    [prepare:get from local cache] - 741 ms.
    [prepare:tools] - 469 ms.
    [prepare:clean] - 469 ms.
    [prepare:yt-store] - 176 ms.
    [prepare:AC] - 84 ms.

    Total tasks times:
    Total failed tasks time - 0 ms (0.00%)
    Total tests tasks time - 1800 ms (100.00%)
    Total run tasks time - 1800 ms

    Configure time - 3.3 s

    Statistics overhead 118 ms
    Ok
    ```
### Результаты сборки { #results }

Результаты сборки формируются на основании файлов `ya.make`, собранных командой `ya make`, исходя

- из значений опций `--target/-C`,
- свободных опций,
- рабочей директории,
- путей в макросах `RECURSE` и `DEPENDS`.

По умолчанию **целями сборки** являются *модули*, непосредственно указанные в `ya.make` директорий в командной строке, а также рекурсивно во всех
макросах `RECURSE` достижимых из `ya.make` директорий в командной строке.

Это поведение может быть изменено следующими опциями:

- `-t или -A` - запуск тестов добавляет к сборке то, что достижимо из макросов `RECURSE_FOR_TESTS` и `DEPENDS`. Правила поиска тестов такие же, как описано выше,
  т. е. `RECURSE_FOR_TESTS` в `ya.make` модулей достижимых по PEERDIR не учитываются. Кроме добавления модулей к сборке эти макросы приводят к запуску тестов.

- `--force-build-depends` - добавить в сборку всё, что нужно для запуска тестов (как с опциями `-t/-A`) но тесты не запускать.

- `-DTRAVERSE_RECURSE_FOR_TESTS` - трактовать `RECURSE_FOR_TESTS` при поиске сборочных целей как обычный `RECURSE`.

- `--ignore-recurses` - не использовать `RECURSE`, строить только модули, непосредственно указанные в командной строке

Результаты сборки могут быть сложены на постоянное хранение в **выходную директорию**, указанную с помощью опции ```-o/--output <path>```. Система сборки никак не отслеживает
файлы в директории `<path>`, и удалять их надо вручную.

На Linux/MacOS, если не указана опция `--no-src-links`, результаты будут сложены во временное хранилище, кэш результатов. В этом случае файлы и
директории из кэша результатов доступны по символическим ссылкам из рабочей копии репозитория.

{% note alert %}

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

Иногда нужно сохранить файлы прямо там, где исполнялась сборка (в сборочных директориях), например, чтобы воспроизвести
отдельные команды сборки. Чтобы добиться этого есть опция `--keep-temps`.

О том, где и как хранятся локальные результаты и какие есть настройки локального кэширования можно прочитать на [отдельной странице]](local_ya_cache.md)

{% endnote %}

В множество результатов сборки по умолчанию попадают только конечные артефакты для *целей сборки* такие, как программа, результат запуска теста и т. п.
Важно понимать, что только результаты и всё, что нужно для их построение реально строится. Поэтому если что-то не достижимо из результатов сборки строиться оно не будет.

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

- Файлы, доступные как символические ссылки на Linux и macOS (если не указана опция `--no-src-links`);
- Файлы, попадающие в директорию *результатов сборки*;
- Файлы, скачиваемые с кластера распределённой сборки при сборке с ключами `--dist -E` (сборка на кластере распределённой сборки с подвозом результатов).

Чтобы расширить множество привозимых результатов, можно использовать опцию `--add-result=.<suff>`.  В конфигурационном файле `ya.conf` можно задать `add_result = [".suff"]`.
Важно понимать, что эта опция ничего не добавляет к сборке, она лишь влияет на то, что окажется в *выходной директории* и символическими ссылками в рабочей копии. Опция действует
только на результаты сборки в *целевой платформе* чтобы избежать неоднозначности если одни и те же файлы результатов (но потенциально с разным содержимым) могут быть получены и в
целевой и в сборочной платформах.

Например, команда

```
ya make -o=<output> <target> --add-result=.o --add-result=.obj
```

сложит объектные файлы в директорию `<output>` и (на Linux и MacOS) создаст ссылки на файлы из кэша результатов в директории с исходниками.

Для упрощения работы в частых случаев есть несколько дополнительных опций:

- `--add-protobuf-result` — Добавить все результаты генерации для `Protobuf`.
- `--add-flatbuf-result` — Добавить результаты генерации `Flatbuffers`.
- `--add-modules-to-results` — Сделать все модули (включая зависимые по PEERDIR) результатами сборки.
- `--add-host-result=.<suff>` — Добавить выбранные результаты из сборочной платформы.
- `--all-outputs-to-result` — Не фильтровать результаты команд. Обычно `--add-result` фильтрует результаты команд по расширениям, с помощью этой опции можно запросить все результаты для команд,
подходящих под `--add-result`.
   Например:
   ```bash
   $ ya make --add-result=.pb.h
   ```
   привезёт только файлы `.pb.h`, а
   ```bash
   $ ya make --add-result=.pb.h --all-outputs-to-result
   ```
   привезёт как `.pb.h`, так и `.pb.cc`. Это, в частности, может быть полезно при привозе результатов от сборки на кластере распределённой сборки, когда для локального кэширования важно привезти
   именно полный, а не фильтрованный результат.

Иногда хочется построить только генерируемые файлы, но не библиотеки/программы. Для этого служит опция `--replace-result`. Она оставит в *результатах сборки* только то, что выбрано
в `--add-result`, всё остальное будет удалено и не будет строиться совсем.

Множество отображаемых результатов можно сузить с помощью опции `--no-output-for=.<suff>` или параметра конфигурационного файла `suppress_outputs = [".suff"]`.
Сужение не исключает файлы из сборки, оно лишь говорит системе сборки, что результаты не надо складывать в рабочую копию и выходную директорию. Это, в частности, означает, что

- Опция `--no-output-for` никак не взаимодействует с `--replace-result`. Файлы, исключённые из подвоза всё равно будут построены и останутся в кэше.
- Опция `--no-output-for` не сужает набор файлов, привозимых с кластера распределённой сборки. Они будут скачаны и сложены в кэш, но не будут отображены как результаты сборки.

## Работа с тестами { #tests }

ya make предоставляет развитые возможности запуска тестов.

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

- `-t`/`-tt`/`-ttt` — запустить тесты. `-t` - только SMALL, `-tt` - SMALL и MEDIUM, `-ttt` - тесты всех размеров.
- `A`, `--run-all-tests` — запустить тесты всех размеров (тоже, что что и `-ttt`).

**Пример**

```bash
[arcadia]$ ya make -t devtools/examples/tutorials/python
```

Запустит все тесты, которые найдёт по `RECURSE`/`RECURSE_FOR_TESTS` от `devtools/examples/tutorials/python`, включая тесты стиля и тесты импорта для Python. При этом будут использованы умолчания для сборки:

- Платформа будет определена по *реальной платформе* на которой запущена команда `ya make` (кроме систем на базе процессора M1, для них сборка происходит под `x86_64`). Для того, чтобы запустить сборку под платформу m1, нужно указать `--target-platform default-darwin-arm64`.
- Тесты будут собраны в режиме `debug` — он используется по умолчанию.
- Кроме тестов будут собраны все остальные цели (библиотеки и программы), достижимые по `RECURSE`/`RECURSE_FOR_TESTS` от `devtools/examples/tutorials/python`. Это включает сборку всех необходимых зависимостей.

Более подробно о запуске тестов можно прочитать на [отдельной странице](./tests.md)
