Search
Write a publication
Pull to refresh
5
0
Елена Гордиенко @le-go

iOS-разработчик

Send message

С визуализацией графа зависимостей были трудности: во-первых, из-за того, что объявление зависимостей у нас в проекте размазано по Podfile и yml-конфигам модулей для XcodeGen, а во-вторых, существующие решения с открытым кодом не всегда работают так, как хотелось бы (например, не поддерживают какой-то из менеджеров зависимостей; строят неинформативный граф; и тд)

Склоняюсь к тому, что для этой задачи потребуется реализовать собственную утилиту, как это например сделали в Badoo.

Может быть, у вас есть какие-то рекомендации на этот счет?

если я правильно понял, то появились проблемы с тем, как линкуются статические и динамические зависимости, и что нужно в XCodeGen-конфиге руками указывать какую встраивать в ваш модуль/фреймворк

Нет, с самим XcodeGen, к счастью, проблем вообще не возникло, там и поддержка xcframework быстро появилась (мы в итоге зависимости из Carthage перевели на xcframework-и для Xcode 12.5), и можно легко выбрать нужный способ интеграции зависимости:

dependencies:
# можно так
  - carthage: Alamofire
# или так
  - package: Alamofire
# или так
  - framework: ${C_BUILD_PATH}/Alamofire.xcframework
# или вот так
  - framework: ${C_BUILD_PATH}/Alamofire.xcframework
  - linkType: dynamic # | static

А каких именно проблем, если не секрет?)

Из того, что первым приходит на ум:

1) при переезде на Xcode 12 Carthage не мог собрать ни одну зависимость, их сборки падали с ошибкой: "the same architectures (arm64) and can't be in the same fat output file". Исправилось все вот этим костылем, потому что мы не были готовы перевести зависимости в xcframework-и на тот момент.

2) при переезде на Xcode 12.3 перестали собираться тестовые таргеты на симулятор, вылезала ошибка:

Building for iOS Simulator but the linked library was built for Mac OS + iOS

Связано это было с тем, что зависимости собирались в universal framework-и, и для тестовых таргетов из них не убирались слайсы для лишних архитектур. Самостоятельно доработать в разумные сроки шаг удаления лишних архитектур не удалось, поэтому ждали обновления Carthage, чтобы поднять версию Xcode.

Также в большей части зависимостей был конфликт ключа VALID_ARCHS (deprecated с Xcode 12) и нового ключа EXCLUDED_ARCHS. Это была проблема самих зависимостей, но так вышло, что именно те, что были подключены через Carthage, еще долго не поддерживали Xcode 12 и нам приходилось использовать форки с исправлениями.

Какие-то проблемы с переездом были у CocoaPods, но решались быстрее. А делать и в будущем такую двойную работу больше не хотелось

Получается вы давно мечтали избавиться от гибкого инструмента?) (шутка)

Да, звучит слегка контринтуитивно) Но гибкость как раз и состоит в том, что часть работы по настройке Carthage мы выполняли сами. Какое-то время он не требовал особых доработок, но уже ближе к Xcode 12 регулярно начали возникать проблемы, решение которых требовало бОльших временных затрат. Вот и решили от него избавиться.

Вопрос №1: Может быть стоило написать свою систему управления линковкой?)

Не очень поняла вопрос: что подразумевается под системой управления линковкой и какие конкретно проблемы она должна решить?

Вопрос №2: SPM складывает все в DerivedData. ... Как живется с этим?)


Локальная сборка:

При холодной сборке шаг Resolve Swift Packages занимает в среднем около 70 сек. Чистить Derived Data нашим разработчикам требуется не часто, и пока что жалоб не было.

Сборка на CI:

Для команды xcodebuild можно указать путь, куда будут загружаться пакеты spm (это слепки репозиториев и артефакты):

-clonedSourcePackagesDirPath PATH                        specifies the directory to which remote source packages are fetch or expected to be found

Это и будет кэшом наших пакетов.

Если используется Fastlane, то эту настройку можно передать прямо команде gym или в Gymfile (cloned_source_packages_path "PATH"). Для CI мы используем связку Fastlane + Github Actions, работа с кэшом производится с помощью экшена actions/cache@v2, которому мы передаем путь, указанный в cloned_source_packages_path. Так что этот кэш не затирается при очистке DerivedData.

Спасибо за замечание!

Действительно, большинство сторонних решений, которые поддерживают интеграцию через SwiftPM, следуют этой рекомендации и используют тип .automatic: он выбирается по умолчанию, если не указан явно тип .static или .dynamic.

Но (как минимум, начиная с Xcode 11.4) в таком случае выбиралась статическая линковка и этому даже посвящено несколько тредов на форумах Swift, вот например, один из них. Мы сами столкнулись с проблемой, что даже при линковке зависимости с несколькими нашими таргетами автоматически выбиралась статическая, что приводило к ошибке дублирования символов. И чтобы исправить эту ошибку приходилось заворачивать зависимость в модуль, который бы линковался динамически. Я даже находила описание такого решения на GitHub.

Вероятно, такое поведение могло быть исправлено в новых версиях Xcode, но на момент доклада мы использовали Xcode 12.5.1.

А в какой версии Xcode удалось получить такое поведение?

На практике SPM выберет динамику, если библиотека слинкована с несколькими таргетами

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

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Registered
Activity