Миграция Xcode-проекта
Если вы не
создаёте новый проект с помощью Tuist, где всё настраивается автоматически, вам придётся описать свои Xcode-проекты, используя примитивы Tuist. Насколько утомительным будет этот процесс, зависит от сложности ваших проектов.Как вы, вероятно, знаете, со временем Xcode-проекты могут становиться запутанными и сложными: группы не соответствуют структуре каталогов, одни и те же файлы используются в разных targets, а ссылки на файлы указывают на несуществующие объекты (и это лишь некоторые примеры). Вся эта накопившаяся сложность не позволяет реализовать команду, которая могла бы надёжно выполнить миграцию проекта.
Более того, ручная миграция – это отличный способ провести очистку и упростить ваши проекты. Этому будут рады не только разработчики, работающие над проектом, но и сам Xcode, который будет быстрее обрабатывать и индексировать их. После полного перехода на Tuist он гарантирует, что проекты будут определены единообразно и останутся простыми.
С целью упростить этот процесс мы подготовили несколько рекомендаций, основанных на отзывах пользователей.
Создание структуры проекта
Прежде всего создайте структуру (scaffold) для вашего проекта, добавив следующие файлы Tuist:
import ProjectDescription
let tuist = Tuist()
import ProjectDescription
let project = Project(
name: "MyApp-Tuist",
targets: [
/** Targets will go here **/
]
)
// swift-tools-version: 5.9
import PackageDescription
#if TUIST
import ProjectDescription
let packageSettings = PackageSettings(
// Customize the product types for specific package product
// Default is .staticFramework
// productTypes: ["Alamofire": .framework,]
productTypes: [:]
)
#endif
let package = Package(
name: "MyApp",
dependencies: [
// Add your own dependencies here:
// .package(url: "https://github.com/Alamofire/Alamofire", from: "5.0.0"),
// You can read more about dependencies here: https://docs.tuist.io/documentation/tuist/dependencies
]
)
Project.swift
– это файл манифеста, в котором вы будете описывать свой проект, а Package.swift
– файл манифеста, в котором определяются зависимости. Файл Tuist.swift
используется для задания настроек Tuist, относящихся к вашему проекту.
ИМЯ ПРОЕКТА С СУФФИКСОМ -TUIST
Чтобы избежать конфликтов с существующим Xcode-проектом, мы рекомендуем добавить суффикс -Tuist
к имени проекта. После полной миграции проекта на Tuist этот суффикс можно удалить.
Сборка и тестирование проекта Tuist в CI
Чтобы убедиться, что каждое изменение, внесённое в процессе миграции, корректно, мы рекомендуем расширить процесс непрерывной интеграции (CI), добавив сборку и тестирование проекта, сгенерированного Tuist из манифеста:
tuist install
tuist generate
tuist build -- ...{xcodebuild flags} # or tuist test
Вынос настроек сборки проекта в файлы .xcconfig
Вынесите настройки сборки из проекта в файл .xcconfig
, чтобы сделать проект легче и упростить его миграцию. Вы можете использовать следующую команду, чтобы извлечь настройки сборки из проекта в файл .xcconfig
:
mkdir -p xcconfigs/
tuist migration settings-to-xcconfig -p MyApp.xcodeproj -x xcconfigs/MyApp-Project.xcconfig
Затем обновите файл Project.swift
, указав в нём путь к только что созданному файлу .xcconfig
:
import ProjectDescription
let project = Project(
name: "MyApp",
settings: .settings(configurations: [
.debug(name: "Debug", xcconfig: "./xcconfigs/MyApp-Project.xcconfig"),
.release(name: "Release", xcconfig: "./xcconfigs/MyApp-Project.xcconfig"),
]),
targets: [
/** Targets will go here **/
]
)
Затем расширьте пайплайн непрерывной интеграции, добавив выполнение следующей команды, чтобы убедиться, что изменения настроек сборки вносятся непосредственно в файлы .xcconfig
:
tuist migration check-empty-settings -p Project.xcodeproj
Вынос зависимостей пакетов
Вынесите все зависимости вашего проекта в файл Tuist/Package.swift
:
// swift-tools-version: 5.9
import PackageDescription
#if TUIST
import ProjectDescription
let packageSettings = PackageSettings(
// Customize the product types for specific package product
// Default is .staticFramework
// productTypes: ["Alamofire": .framework,]
productTypes: [:]
)
#endif
let package = Package(
name: "MyApp",
dependencies: [
// Add your own dependencies here:
// .package(url: "https://github.com/Alamofire/Alamofire", from: "5.0.0"),
// You can read more about dependencies here: https://docs.tuist.io/documentation/tuist/dependencies
.package(url: "https://github.com/onevcat/Kingfisher", .upToNextMajor(from: "7.12.0"))
]
)
ТИПЫ ПРОДУКТОВ
Вы можете переопределить тип продукта для конкретного пакета, добавив его в словарь productTypes
внутри структуры PackageSettings
. По умолчанию Tuist предполагает, что все пакеты являются статическими фреймворками.
Определение порядка миграции
Мы рекомендуем выполнять миграцию targets, начиная с тех, от которых зависят другие, и заканчивая теми, которые зависят меньше всего. Вы можете использовать следующую команду, чтобы вывести список targets проекта, отсортированный по количеству зависимостей:
tuist migration list-targets -p Project.xcodeproj
Начните миграцию targets с верхней части списка, так как именно от них зависит наибольшее количество других targets.
Миграция targets
Мигрируйте targets по одной. Мы рекомендуем создавать отдельный pull request для каждого target, чтобы убедиться, что изменения были проверены и протестированы перед их слиянием.
Вынос настроек сборки targets в файлы .xcconfig
Так же, как и с настройками сборки проекта, вынесите настройки сборки target в файл .xcconfig
, чтобы сделать target проще и облегчить её миграцию. Вы можете использовать следующую команду, чтобы извлечь настройки сборки target в файл .xcconfig
:
tuist migration settings-to-xcconfig -p MyApp.xcodeproj -t TargetX -x xcconfigs/TargetX.xcconfig
Определение target в файле Project.swift
Определите target в Project.targets
:
import ProjectDescription
let project = Project(
name: "MyApp",
settings: .settings(configurations: [
.debug(name: "Debug", xcconfig: "./xcconfigs/Project.xcconfig"),
.release(name: "Release", xcconfig: "./xcconfigs/Project.xcconfig"),
]),
targets: [
.target(
name: "TargetX",
destinations: .iOS,
product: .framework, // [!code ++] // or .staticFramework, .staticLibrary...
bundleId: "dev.tuist.targetX",
sources: ["Sources/TargetX/**"],
dependencies: [
/** Dependencies go here **/
/** .external(name: "Kingfisher") **/
/** .target(name: "OtherProjectTarget") **/
],
settings: .settings(configurations: [
.debug(name: "Debug", xcconfig: "./xcconfigs/TargetX.xcconfig"),
.debug(name: "Release", xcconfig: "./xcconfigs/TargetX.xcconfig"),
])
),
]
)
ТЕСТОВЫЕ TARGETS
Если у target есть связанная тестовая target, её также следует определить в файле Project.swift
, повторив те же шаги.
Проверка миграции target
Выполните команды tuist build
и tuist test
, чтобы убедиться, что проект успешно собирается и все тесты проходят. Кроме того, вы можете использовать xcdiff для сравнения сгенерированного Xcode-проекта с существующим, чтобы проверить корректность изменений.
Повторение
Повторяйте процесс, пока все targets не будут полностью мигрированы. После завершения мы рекомендуем обновить пайплайны CI и CD, чтобы сборка и тестирование проекта выполнялись с помощью команд tuist build
и tuist test
– это позволит воспользоваться скоростью и надёжностью, которые предоставляет Tuist.
Устранение неполадок
Ошибки компиляции из-за отсутствующих файлов.
Если файлы, связанные с targets вашего Xcode-проекта, не находятся в отдельной директории файловой системы, соответствующей каждой target, проект может не скомпилироваться. Убедитесь, что список файлов после генерации проекта с помощью Tuist совпадает со списком файлов в Xcode-проекте, и воспользуйтесь этой возможностью, чтобы привести структуру файлов в соответствие со структурой targets.