Pull to refresh

Comments 16

UFO just landed and posted this here

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

Как анализируете связи между фреймворками?

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

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

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

Я пишу утилиту для анализа, мой комментарий это такой каст-дев :-) Могу потом прислать бета-билд

Если при объявлении продукта-библиотеки ничего не указано, будет собираться статическая, а динамическая — только если указан тип .dynamic.

Документация:

Leave this parameter unspecified to let the Swift Package Manager choose between static or dynamic linking (recommended).

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

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

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

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

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

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

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

Согласен, проблемы начинаются, когда появляются тесты.
Я делал простые эксперименты без тестов: создавал проект с несколькими фреймворками, подключал SPM библиотеку в одному фреймворку, затем к нескольким. Поведение было корректное, как описано в документации, на любом Xcode начиная с 12.5.

Carthage только скачивает и собирает зависимости, но не встраивает их в проектный файл. Соответственно, это простой и гибкий инструмент

А скоро мы совсем избавимся от Carthage, что давно хотели сделать.

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

Вопрос №1: Может быть стоило написать свою систему управления линковкой?) Некую генерацию конфигов для XcodeGen-а. ИМХО - это заняло бы намного меньше времени, чем переезжать на новый пакетный менеджер (как я понял еще и не закончили переезд).

Вопрос №2: SPM складывает все в DerivedData. У iOS-разработчиков, со временем, вырабатывается привычка делать clean проекта / чистить кеш XCode. Соответсвенно все 40+ (!) зависимостей (пока их 25, но когда-то же там будут все, видимо) зачищаются и происходит их вытягивание по-новой + переиндексация проекта. Как живется с этим?)
И сюда же - как правило, на CI перед сборкой тестов/прогоном сборки обязательно зачищается DerivedData. Каждый раз вытягиваете, или филигранно кешируете только то, что нужно?)

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

Да, звучит слегка контринтуитивно) Но гибкость как раз и состоит в том, что часть работы по настройке 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.

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

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

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

Опять же, не хочется додумывать за вас, но по всей видимости, если я правильно понял, то появились проблемы с тем, как линкуются статические и динамические зависимости, и что нужно в XCodeGen-конфиге руками указывать какую встраивать в ваш модуль/фреймворк, а какую нет например. И со временем, и кол-вом сторонних зависимостей становится сложно регулировать, что куда и как линковать.
На что я и предложил, как идею, написать вспомогательное решение, которое занималось бы генерацией конфигов для XcodeGen-а (и как следствие проверкой что куда и как слинкованно в проекте).

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

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

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, но решались быстрее. А делать и в будущем такую двойную работу больше не хотелось

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

В SPM можно настроить директорию где хранить зависимости, и ни чего вытягивать каждый раз не придется

А можете рассказать, как это сделать?)

Sign up to leave a comment.