# Сгенерированный проект Xcode {#generated-xcode-project}

::: code-group

```text [Agent prompt]
Help me get started with Tuist. Follow the setup at:
https://tuist.dev/en/docs/guides/get-started/generated-xcode-project
```

:::

Выбирайте этот путь, если хотите, чтобы Tuist описывал и генерировал ваш проект Xcode на основе манифестов Swift. Сгенерированный проект сжимает сложность модульного проекта Xcode в лаконичное декларативное описание графа. Это также строгое требование для кэша модулей и выборочного тестирования.

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

## Предварительные требования

- macOS с установленным Xcode.
- <.localized_link href="/guides/install-tuist">Интерфейс командной строки Tuist</.localized_link>.

## Создание проекта

Самый быстрый способ увидеть это в работе — создать новый проект. В пустой директории выполните `tuist init`, выберите **Создать сгенерированный проект**, укажите платформу, подтвердите имя, затем пройдете аутентификацию и выберите аккаунт, которому должен принадлежать проект.

```bash
mkdir MyApp && cd MyApp
tuist init
```

Если вы управляете этим процессом из агента для написания кода или скрипта, сначала выполните `tuist auth login` (браузерный поток ждет, пока вы нажмете Enter), затем используйте неинтерактивную форму:

```bash
tuist init --build-system generated-xcode --name MyApp --platform ios --account <account>
```

Когда инициализация завершится, выполните `tuist generate`. Tuist создаст файл `.xcworkspace` рядом с вашими манифестами и откроет его в Xcode. Соберите и запустите таргет. Вы должны увидеть запуск примера приложения в симуляторе.

Это состояние «подключено + генерация». Все остальное ниже является опциональным и независимым.

Если вы переносите существующее приложение, сначала подключите его, следуя [руководству по миграции проектов Xcode](https://tuist.dev/en/docs/guides/features/projects/adoption/migrate/xcode-project), затем вернитесь сюда и продолжите с разделами, которые подходят для вашей задачи.

## Генерация проекта

Файл `.xcodeproj` упаковывает структуру вашего приложения в XML: ссылки на файлы, фазы сборки, зависимости таргетов, схемы и настройки сборки находятся в одном дереве, без примитивов для анализа графа как графа. По мере роста проекта эту структуру становится все сложнее держать в голове, а у Xcode нет стабильного идентификатора, который позволял бы инструментам хешировать его и пропускать работу, если ничего не изменилось.

Сгенерированные проекты сжимают граф в декларативный Swift. Файл `Project.swift` напрямую описывает таргеты, зависимости и ресурсы, а Tuist поддерживает стабильную модель графа за ним. Именно эта модель открывает доступ к разделам ниже: кэширование модулей хеширует ее для повторного использования бинарных файлов, а выборочное тестирование хеширует ее, чтобы пропускать тесты, входные данные которых не изменились.

```swift
import ProjectDescription

let project = Project(
    name: "MyApp",
    targets: [
        .target(
            name: "MyApp",
            destinations: .iOS,
            product: .app,
            bundleId: "dev.tuist.MyApp",
            sources: ["MyApp/Sources/**"],
            dependencies: []
        )
    ]
)
```

Каждый вызов `tuist generate` создает детерминированное рабочее пространство на основе манифестов. Добавьте `.xcodeproj` и `.xcworkspace` в `.gitignore`.

## Кэш модулей

Компиляция модульного проекта Xcode с нуля — это затраты для каждой машины. Каждый член команды и каждый CI-раннер создает свою собственную копию одних и тех же объектных файлов. Кэш компиляции Xcode сокращает внутренний цикл разработки, но не устраняет необходимость сборки каждого таргета на каждой машине и не может заменить целый фреймворк предварительно собранным бинарным файлом.

Кэш модулей делает это. Он собирает каждую кешируемую зависимость в вашем графе один раз (фреймворки, библиотеки, bundles), сохраняет полученные бинарные файлы, привязывая их к хешу входных данных таргета, и заменяет таргет его бинарным файлом при последующих генерациях. Неизмененные модули перестают компилироваться:

```bash
tuist cache
```

Первый запуск компилирует все и загружает бинарные файлы в ваш аккаунт. При следующем вызове `tuist generate` неизмененные зависимости заменяются их кэшированными бинарными файлами, и Xcode линкуется с `.xcframework` вместо компиляции из исходного кода.

## Выборочное тестирование

`xcodebuild test` не знает, какие тесты затрагивает изменение, поэтому CI запускает весь набор при каждом пуше. По мере роста набора разрыв между тем, что действительно нужно запустить, и тем, что запускается, увеличивается от минут до десятков минут.

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

```bash
tuist test
```

Первый вызов `tuist test` запускает все и сохраняет хеши для каждого таргета. Последующие запуски пропускают таргеты, входные данные которых не изменились. Перенесите `tuist test` в CI вместо `xcodebuild test`, и обратная связь будет поступать за секунды, а не за минуты.

## Реестр пакетов

Swift Package Manager разрешает зависимости путем глубокого клонирования git-истории каждого пакета, потому что пакеты адресуются по URL, а не через реестр. В проекте с десятками транзитивных пакетов разрешение зависимостей занимает минуты на чистой checkout-версии и повторяется в каждой задаче CI.

Реестр пакетов Tuist предоставляет те же пакеты, которые отслеживает Swift Package Index, но в виде настоящего реестра, поэтому SwiftPM загружает только тот коммит, который вам действительно нужен. Включите его один раз, установив `registryEnabled: true` в вашем `Tuist.swift`:

```swift
let tuist = Tuist(
    project: .tuist(
        generationOptions: .options(
            registryEnabled: true
        )
    )
)
```

Выполните повторную генерацию. Разрешение зависимостей пакетов сокращается с минут до секунд.

## Аналитика сборок

Xcode записывает длительность сборки для каждого таргета в лог и в отчет о сборке. Ни то, ни другое не агрегируется across запусков или машин, поэтому регрессия времени сборки обычно проявляется только как общее замедление CI.

Аналитика сборок автоматически записывает длительность каждой сборки и время выполнения фаз для сгенерированных схем. Ничего дополнительно настраивать не нужно. Откройте вкладку **Сборки** в дашборде после следующего цикла `tuist generate` + сборки.

## Аналитика тестов

Xcode сообщает результаты по каждому тесту по одному запуску за раз. Он не агрегирует межзапусковые сигналы, которые вам действительно нужны: уровень нестабильности, изменение длительности от недели к неделе, какие варианты симуляторов дают сбои.

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

## Подключите команду

Кэш модулей и выборочное тестирование дают наибольший эффект, когда вся команда работает с одной общей поверхностью. Пригласите своих коллег в организацию через настройки аккаунта в дашборде и настройте <.localized_link href="/guides/integrations/authentication/sso">Единый вход (SSO)</.localized_link> (Google, Okta, Microsoft), чтобы онбординг занимал один клик, а не требовал индивидуального `tuist auth login` для каждого человека.
