Dynamic Library Builder

Вопросы можно задавать: a.zarembo@tinkoff.ru

Это пара скриптов, которые помогают делать динамические библиотеки из статических. Они делают многое, но слишком сильно зависят от того, что собирается, поэтому часто приходится залезать внутрь и делать какие-то доработки и хаки.

Это не универсальное решение, просто помощник, не надо ждать от него слишком многого.

Как использовать

  1. Нужно апустить скрипт
./makeDynamic.sh AppsFlyerFramework 4.7.11
  1. Он должен выполниться без ошибок и дойти до пункта Running podspec lint quick и Done, на это уйдет около минуты. Если в логе есть ошибки, значит что-то пошло не так и надо ознакомиться с соответствующим разделом этого файла.

  2. Если все ок, будет создана папка AppsFlyerFramework, внутри неё папка 4.7.11 и в ней будет лежать

  • AppsFlyerFrameworkDynamic.framework - это динамическая библиотека, которая нужна и
  • AppsFlyerFrameworkDynamic.podspec.json - это Podpec-файл, в который надо прописать путь к git-репозиторию, где будет лежать эта библиотека. Нужно указывать http/https, иначе будет warning и Lint не сработает.
  1. Надо открыть папку framework и убедиться, что там есть бинарник библиотеки, а также что его размер примерно соответствует размеру исходной статической библиотеки.

     Если чего-то нет, надо читать раздел "Если что-то пошло не так".
    
  2. Дальше нужно залить библиотеку в репозиторий, проставить тег и проверить pod spec lint

  3. После чего надо залить спеку в репозиторий с помощью pod repo push ИМЯ_РЕПОЗИТОРИЯ ИМЯСПЕКИ.podspec.json

Как использовать для сильных духом

Можно попробовать одной командой библиотеку собрать и залить в репозиторий. Но риск, что что-то пойдет не так очень высок. Команда выглядит так:

./makeDynamic.sh AppsFlyerFramework 4.7.11 "https://stash.tcsbank.ru/scm/mip/appsflyerframeworkdynamic.git"

Если все пройдет хорошо, скрип сам проставит путь в pod spec, все зальет и сделает tag.

Если что-то пошло не так

Как это все работает

  1. Сначала bash-скрипт makeDynamic.sh выполняет настройку среды Ruby. Создает Gemfile, ставит RVM, Ruby и Bundler, после чего ставит cocoa pods.

      Делает он это от имени root, поэтому спросит системный пароль. 
    
  2. Когда среда настроена, запускается скрипт makeDynamic.rb

  3. Этот скрипт создает папки по имени библиотеки и её версии. Если папка уже была, она сначала удаляется.

  4. В папке с версией создает Xcode-проект

  5. В проекте создает таргет для динамической библиотеки. Имя библиотеки такое же + Dynamic

  6. Генерирует Info.plist

  7. Создает .h-файл для динамической библиотеки

  8. Создает Podfile и добавляет туда имя библиотеки и версию, которые передали в параметрах

  9. Запускает pod install

  10. Открывает созданный Workspace, в нем Pods-проект и ищет заголовочные файлы статической библиотеки

  11. Все найденные .h-файлы добавляет в динамическую библиотеку как public

  12. Потом все найденные .h-файлы добавляет в .h-файл динамической библиотеки

  13. Снова запускает pod Install. Не знаю, в чем дело, но первый раз он не проставляет связи на статическую библиотеку

  14. Создает Shared-схему для сборки проекта

  15. Дальше запускается скрипт buildLib.rb

  16. Этот скрипт собирает библиотеку для симулятора

  17. После чего собирает библиотеку для устройств

  18. Склеивает их через lipo

  19. Копирует framework устройства в папку, созданную в п.3 и заменяет бинарник на объединенный

  20. Дальше удаляются все вспомогательные файлы и папки, остается только .framework

  21. Из списка репозиториев выгружается оригинальный podspec библиотеки

  22. В него прописывается новый vendored_framework, preserve_paths, обновляется версия iOS до 8, меняется имя и удаляется поле Source

  23. И он сохраняется в папку

  24. Если был указан путь к git-репозиторию, он прописывается в pod spec поле source и заливается в git

Какие бывают проблемы

Ошибка с Ruby на этапе 1.

Надо гуглить, увы.

Ошибка при работе скрипта где-то 146-150 строки

Это значит, что в проекте используется какая-то хитрая схема расположения библиотек. Например такая есть в GoogleMaps. Тут нужно руками поправить пути в скрипте, сделать что-то вроде

frameworks_group = library_group['Maps']['Frameworks']

И перезапустить скрипт.

.framework есть, а внутри пусто

Скорее всего не прошла сборка. Поэтому нужно закомментировать в скрипте блок Cleanup в районе 195-205 строк и перезапустить скрипт. После сборки в папке будет два файла:

buildlog_simulator.txt
buildlog_device.txt

Нужно их открыть и посмотреть что пошло не так, поправить. После чего можно запустить скрипт buildLib.sh с теми же параметрами, что были в makeDynamic.sh и должен собраться .framework c библиотекой. Podpec придется сделать руками

Ошибки при загрузке сразу в репозиторий

Надо смотреть в консоле. У меня было так, что swap-файл поломался, помогло переписать.

Что было бы круто улучшить

  1. Сделать нормальную работу с ключами командной строки
  2. Добавить ключ --no-cleanup, чтобы скрипт не править
  3. Добавить ключ --rebuild-only, чтобы проект не пересозавался, а только пересобирался и перепаковывался
  4. Понять, почему приходится два раза делать pod install и обойтись одним
  5. Добавить ключ --source-git, чтобы в него указывать путь к репозитория
  6. Добавить ключ --pod-repo, чтобы сразу делать Lint и заливать pod spec
  7. Добавить ключ --group-path, чтобы такие вещи, как GoogleMaps можно было собирать без правки скрипта
  8. Добавить сборку в отдельную папку, а также gitignore на неё, чтобы скрипты не попадали в git Status скриптов