Перейти к содержимому

Сгенерированный проект Xcode

plaintext
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 в лаконичное декларативное описание графа. Это также строгое требование для кэша модулей и выборочного тестирования.

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

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

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

Самый быстрый способ увидеть это в работе — создать новый проект. В пустой директории выполните 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, затем вернитесь сюда и продолжите с разделами, которые подходят для вашей задачи.

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

Файл .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 запусков. Нестабильные тесты, медленные тесты и сбои отображаются на вкладке Тесты в дашборде. Когда количество нестабильных тестов накапливается, поместите их в карантин через дашборд, чтобы они перестали блокировать слияния.

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

Кэш модулей и выборочное тестирование дают наибольший эффект, когда вся команда работает с одной общей поверхностью. Пригласите своих коллег в организацию через настройки аккаунта в дашборде и настройте Единый вход (SSO) (Google, Okta, Microsoft), чтобы онбординг занимал один клик, а не требовал индивидуального tuist auth login для каждого человека.