Переход c Cocoapods на Swift Package Manager

в 10:31, , рубрики: dependency manager, iOS, Migration, SPM, swift, swift package manager, xcode, Блог компании Tinkoff.ru, разработка под iOS

Переход c Cocoapods на Swift Package Manager - 1

Cocoapods считается наиболее популярным менеджером зависимостей для iOS. Последние годы Apple работает над развитием своего нативного менеджера зависимостей Swift Package Manager (SPM).

Изначально его использование было возможно только для server-side Swift или приложений для терминала. На таких приложениях обкатывали и дорабатывали SPM, комьюнити знакомилось с его работой, а команда Apple получила бета тестеров.

С релизом Xcode 11 SPM начал приходить и в мир разработки под iOS. Сейчас это уже полноценный инструмент, который можно использовать, но пока с ограничениями.

В актуальной версии SPM не поддерживает ресурсы (ждем SE-0271). У нас каждый модуль является атомарной самодостаточной зависимостью, которую можно подключить к проекту, так что ресурсы необходимы (локализации, ассеты).

А пока мы ждем, можно подготовиться к миграции: понять, насколько это сложно, можно ли это автоматизировать и с какими проблемами можно столкнуться.

Зачем мигрировать с Cocoapods на SPM?

  • Нативность и интеграция в экосистему. Уже сейчас Xcode предлагает создать или добавить SPM Package.
  • В отличие от Cocoapods, больше не обязательно иметь workspace для работы над проектом с зависимостями.
  • Добавив новую зависимость, не нужно делать pod install и пересобирать весь проект.
  • Удобно использовать локальные зависимости: не меняется структура папок, быстрее пересобирается.
  • SPM не меняет структуру файла проекта, как это делает Cocoapods, не требует зависимости от Ruby и даже может сгенерировать файл проекта сам (пока недоступно для iOS-проектов).
  • Cocoapods не успевает справляться с нововведениями в Xcode и компилятор Swift.
  • Не нужно создавать проект Example для каждого репозитория: Xcode умеет открывать Package.swift файл как проект.
  • Не нужно оптимизировать дерево зависимостей при помощи abstract_target: SPM из коробки умеет не перекомпилировать код для разных таргетов с общими зависимостями.
  • Можно смотреть blame в зависимостях, а не только в основном проекте.
  • Не нужно писать скрипты на Ruby, чтобы починить конфигурацию проекта.

Как выглядит миграция?

Если ваш проект имеет достаточно много зависимостей, то процесс миграции не сделать за один день. Количество зависимостей в Podfile не равно общему количеству зависимостей, так как одна зависимость может идти в комплекте с еще десятью. Даже если у вас не много зависимостей, но вы разрабатываете свои зависимости, возможно, даже в приватных репозиториях, быстро не мигрировать. К счастью, SPM отлично уживается с Cocoapods, и процесс миграции можно вести итерационно. Главное — учесть нюансы:

  • Не должно быть пересечений между зависимостями SPM и Cocoapods.
  • Миграция должна быть встроена в процесс развития компонентов. Если компонент развивается, поднятие версии должно выполняться как для Cocoapods, так и для SPM.
  • Сложностей для команды быть не должно, а значит, нужно внедрить установку всех зависимостей через единую cli-команду.
  • Миграция должна быть встроена в CI CD. Проект должен собираться как локально так и на агентах CI, во всех конфигурациях.

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

Прежде всего собираем полный список ваших зависимостей — он представлен в Podfile.lock. Для этого можно использовать утилиты, например SPMReady.

Переход c Cocoapods на Swift Package Manager - 2

Далее группируем их по связям. Например, от SMENetwork у нас зависят почти все компоненты, а значит, мы не сможем мигрировать их на SPM, пока не мигрирует сам SMENetwork.

Затем выделяем один модуль, от которого зависит больше всего модулей, — SMENetwork.
И наконец переходим в репозиторий этого модуля, чекаутим его в папку и создаем в руте этой папки модуль.

git clone ssh://.../smenetwork.git Developer/SMENetwork
cd Developer/SMENetwork
swift package init
Creating library package: SMENetwork
Creating Package.swift
Creating Sources/
Creating Sources/SMENetwork/SMENetwork.swift
Creating Tests/
Creating Tests/LinuxMain.swift
Creating Tests/SMENetworkTests/
Creating Tests/SMENetworkTests/SMENetworkTests.swift
Creating Tests/SMENetworkTests/XCTestManifests.swift

В результате мы получаем основной файл Package.swift и папки Sources и Tests. Если они у вас уже были, их не перетрет. Файлы SMENetwork.swift, SMENetworkTests.swift, XCTestManifests.swift, LinuxMain.swift созданы для примера работы Package, их можно удалить.

Файл Package.swift выглядит следующим образом:

Переход c Cocoapods на Swift Package Manager - 3

Теперь посмотрим на файл SMENetwork.podspec:

Переход c Cocoapods на Swift Package Manager - 4

Как видно, Sources и Tests лежат в других папках. Перенесем файлы и проверим работоспособность Cocoapods Example проекта.

Переход c Cocoapods на Swift Package Manager - 5

Добавляем в Package.swift платформу разработки и переносим зависимости из podspec файла сюда. Убеждаемся, что они поддерживают SPM: для этого достаточно проверить, что в Гитхабе есть файл Package.swift. Если его нет и даже нет PR с ним, сделаем PR и поможем Open-Source community.

Переход c Cocoapods на Swift Package Manager - 6

Переход c Cocoapods на Swift Package Manager - 7

Для SPM не нужно создавать Example проект: достаточно открыть Package.swift в Xcode и он сам скачает и подключит зависимости, создаст таргеты согласно нашей спецификации. Нам остается только запустить.

Переход c Cocoapods на Swift Package Manager - 8

В нашем случае почти все заработало из коробки, за исключением одного места, где забыли import Foundation: iOS-разработчики привыкли, что UIKit и Foundation необязательны, ведь работает и без них. Пора отучаться от этой привычки.

Переход c Cocoapods на Swift Package Manager - 9

Package компилируется, тесты компилируются, но не проходят.

Переход c Cocoapods на Swift Package Manager - 10

И тут мы упираемся в ограничение отсутствия ресурсов в Package, тесты основаны на моках, которые лежат в json ждем SE-0271

Итог

Переехать с Cocoapods на SPM несложно. Шаги понятны, но flow монотонен и требует автоматизации.

Без особых усилий исходя из .podspec файла можно создать Package и закоммитить его в репозиторий. А самое главное — можно переехать одним проектом, а другой останется на Cocoapods. Если захочет, конечно.

Автор: Андрей

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js