Предотвращаем мерж-конфликты с XcodeGen

от автора

Привет, Хабр! В преддверии старта курса «iOS Developer. Professional» подготовили для вас традиционный перевод полезного материала. Также приглашаем желающих на онлайн-встречу с преподавателем курса, на которой можно задать преподавателю интересующие вас вопросы об обучении.

И напоследок, предлагаем посмотреть запись вебинара «Пишем приложение на SwiftUI и Combine».


I — Введение

В этой статье мы рассмотрим решение для мгновенного разрешения мерж-конфликтов в файле .xcodeproj, что является одной из самых трудоемких проблем, с которыми сегодня сталкиваются команды iOS и macOS разработчиков.

Источник изображения: https://medium.com/@kautilyasave/xcode-merge-conflict-debugging-5904c7e0cc59
Источник изображения: https://medium.com/@kautilyasave/xcode-merge-conflict-debugging-5904c7e0cc59

К концу этой статьи у вас будет рабочая среда, обеспечивающая бесконфликтное слияние.

II — Прежде чем мы начнем

1. Знакомство с XcodeGen

yonaskolb/XcodeGen

github.com

XcodeGen — это консольная утилита, написанная на Swift, которая генерирует Xcode-проект на основе вашей структуры папок и спецификации проекта.

Для установки XcodeGen мы будем использовать Brew. Просто запустите в терминале brew install xcodegen (дополнительные параметры установки и инструкции можно найти здесь).

2. Проект

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

В этом руководстве вы узнаете, как шаг за шагом настроить проект, который достаточно прост, чтобы объяснить суть XcodeGen, и в то же время достаточно сложен, чтобы охватить достаточно широкий диапазон вариантов использования.

Пример структуры проекта
Пример структуры проекта

Как мы видим выше, проект содержит:

  • Зависимости фреймворков

  • Сборочные скрипты

III — Настройка

Образцы экранов приложения
Образцы экранов приложения

1. Настраиваем проект

Проект (sample project), который мы будем использовать в этом туториале, имеет carthage-зависимости. Просто запустите makeProject.sh в терминале. Это настроит проект со всеми его зависимостями, и мы сможем начать туториал.

Установка проекта (Brew, Carthage, XcodeGen, зависимости…)
Установка проекта (Brew, Carthage, XcodeGen, зависимости…)

2. Создание файла спецификаций проекта XcodeGen

В корневом каталоге проекта создайте папку с именем XcodeGen (имя папки необязательно должно быть таким) с файлом названным project.yml (это имя файла тоже опционально).

Этот файл будет служить спецификацией нашего .xcodeproj
Этот файл будет служить спецификацией нашего .xcodeproj

XcodeGen/project.yml: Первоначальная настройка:

name: GoodToGo options:   bundleIdPrefix: com.GoodToGo   xcodeVersion: '12.0.1'   deploymentTarget: '12.0'   groupSortPosition: top   generateEmptyDirectories: true   findCarthageFrameworks: true   minimumXcodeGenVersion: '2.18.0'

 Во время нашей первоначальной настройки для файла .xcodeproj мы выбираем имя GoodToGo — , префикс пакета — com.GoodToGo — , версию Xcode, целевую платформу развертывания…

3. Первый запуск XcodeGen

Используя описанную выше конфигурацию, мы можем создать наш новый проект, запустив xcodegen -s ./XcodeGen/project.yml -p ./ в терминале.

Обратите внимание, что ./XcodeGen/project.yml — это путь к файлу спецификации нашего проекта. Если вы выберете другое имя папки/файла, вам также необходимо будет подправить их здесь.

XcodeGen/project.yml: Первый запуск
XcodeGen/project.yml: Первый запуск

Зеленое сообщение говорит о том, что проект был создан. Ура, мы успешно создали наш проект!

Теперь давайте откроем его и посмотрим, как он выглядит:

Не то, что мы ожидали… Отсутствуют все наши схемы, все фреймворки, вообще все. Они отсутствуют, потому что мы не определили их в нашем файле project.yml.

4. Добавление конфигураций и основного таргета проекта

XcodeGen/project.yml: Добавление конфигураций. Просто добавьте это в свой файл project.yml:

configs:   Debug.Dev: debug      Debug.Prod: debug   Release: release  targets:   GoodToGo:     type: application     platform: iOS     deploymentTarget: 12.0     settings:       base:         MARKETING_VERSION: 1.0     sources:        - path: ../GoodToGo

По сути, мы создаем 3 конфигурации — Debug.Dev, Debug.Prod и Release, и заявляем что основной таргет нашего приложения будет называться GoodToGo, с целевой платформой iOS 12 (минимальная версия), а файлы исходного кода находятся в папке GoodToGo.

Папка должна существовать в системных папках, иначе у вас будет следующая ошибка:

Spec validation error: Target “GoodToGo” has a missing source directory  “/Users/ricardosantos/Desktop/GitHub/RJPS_Articles/7/sourcecode/THE_FOLDER_THAT_DOES_NOT_EXISTS_NAME”

Попробуйте снова с нашей обновленной конфигурацией (предыдущее изображение) и…

… теперь у нас есть (предыдущее изображение) схемы, конфигурации и таргет приложения!

5. Добавление фреймворков

Следующее, что нам нужно сделать, — это добавить зависимости наших фреймворков. Для каждого из них нам нужно выбрать платформу, тип, таргет и другие параметры.

Мы знаем с самого начала, что обычно все фреймворки имеют одни и те же настройки, поэтому мы создадим шаблон и назовем его Framework.

Ниже вы можете увидеть простой шаблон, на который мы будем ссылаться в нашем основном файле project.yml, а затем и там, где это необходимо.

XcodeGen/project.yml: Создание шаблона:

targetTemplates:   Framework:     type: framework     platform: iOS     deploymentTarget: 11.0     settings:       base:         MARKETING_VERSION: 1.0

В этом шаблоне указано, что все целевые объекты будут иметь следующие условия:

  • тип framework,

  • платформа iOS,

  • версию 1.0,

  • целевую платформу для развертывания, равную или выше, iOS 11.0.

В нашем образце проекта у нас были следующие зависимости фреймворков (смотрите ниже).

Мы добавим парочку для проверки: AppTheme и AppResources.

Начиная с нашего файла project.yml в разделе таргетов мы добавим 2 новые записи (AppTheme и AppResources). Для этих таргетов мы должны определить исходную папку и имя шаблона, как объяснялось в предыдущем шаге.

 AppTheme:     templates:        - Framework     sources:        - path: ../AppTheme   AppResources:     templates:        - Framework     sources:        - path: ../AppResources

XcodeGen/project.yml: Добавление таргетов с помощью шаблона

Попробуем еще раз с нашей обновленной конфигурацией (предыдущее изображение) и…

… теперь у нас есть основной таргет нашего приложения и 2 зависимости, которые мы только что добавили в наш файл спецификации.

Небольшое резюме: раздел таргетов в нашем project.yml должен выглядеть так:

targets:   GoodToGo:     type: application     platform: iOS     deploymentTarget: 12.0     settings:       base:         MARKETING_VERSION: 1.0     sources:        - path: ../GoodToGo   AppTheme:     templates:        - Framework     sources:        - path: ../AppTheme   AppResources:     templates:        - Framework     sources:        - path: ../AppResources

Для завершения настройки нам нужно добавить остальные фреймворки, после чего наш файл project.yml должен выглядеть следующим образом:

name: GoodToGo  ## options section ##  options:   bundleIdPrefix: com.GoodToGo   xcodeVersion: '12.0.1'   deploymentTarget: '12.0'   groupSortPosition: top   generateEmptyDirectories: true   findCarthageFrameworks: true   minimumXcodeGenVersion: '2.18.0'  ## configs section ##  configs:   Debug.Dev: debug   Debug.Prod: debug   Release: release  ## targetTemplates section ##  targetTemplates:   Framework:     type: framework     platform: iOS     deploymentTarget: 11.0     settings:       base:         MARKETING_VERSION: 1.0  ## targets section ##          targets:   GoodToGo:     type: application     platform: iOS     deploymentTarget: 11.0     settings:       base:         MARKETING_VERSION: 1.0     sources:        - path: ../GoodToGo   AppTheme:     templates:        - Framework     sources:        - path: ../AppTheme   AppResources:     templates:        - Framework     sources:        - path: ../AppResources   AppConstants:     templates:        - Framework     sources:        - path: ../AppConstants   Core:     templates:        - Framework     sources:        - path: ../Core   Core.GalleryApp:     templates:        - Framework     sources:        - path: ../Core.GalleryApp   Domain:     templates:        - Framework     sources:        - path: ../Domain   Core.GalleryApp:     templates:        - Framework     sources:        - path: ../Core.GalleryApp   Designables:     templates:        - Framework     sources:        - path: ../Designables       DevTools:     templates:        - Framework     sources:        - path: ../DevTools      Extensions:     templates:        - Framework     sources:        - path: ../Extensions      Factory:     templates:        - Framework     sources:        - path: ../Factory      PointFreeFunctions:     templates:        - Framework     sources:        - path: ../PointFreeFunctions      Repositories:     templates:        - Framework     sources:        - path: ../Repositories       Repositories.WebAPI:     templates:        - Framework     sources:        - path: ../Repositories.WebAPI            UIBase:     templates:        - Framework     sources:        - path: ../UIBase      Test.GoodToGo:     type: bundle.unit-test     platform: iOS     sources:        - path: ../Test.GoodToGo     scheme: {}

XcodeGen/project.yml: Полная конфигурация (пока)

https://seattle.eater.com/2019/7/2/20679237/july-4th-seattle-where-to-eat-drink-and-watch-the-fireworks
https://seattle.eater.com/2019/7/2/20679237/july-4th-seattle-where-to-eat-drink-and-watch-the-fireworks

На этом этапе после запуска XcodeGen у нас должен получиться проект со всеми фреймворками!

Настраивая подобные вещи, мы всегда натыкаемся на некоторые неровности на дороге. Одна из них — пропавшая ссылка на файл .plist. Это можно исправить 2-мя способами: первый заключается в указании в project.yml пути к файлу .plist, а второй вариант заключается в переименовании GoodToGo-info.plist в Info.plist.

6. Подтягиваем зависимости фреймворков

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

Например, мы заметили, что Domain зависит от RxCocoa и RxSwift, а эти зависимости разрешаются с помощью carthage.

Во-первых, нам нужно найти таргет Domain в нашем файле project.yml
XcodeGen/project.yml: Таргет Domain без зависимостей:

  Domain:     templates:        - Framework     sources:        - path: ../Domain

… а затем добавить недостающие (carthage) зависимости. Вот так просто!
XcodeGen / project.yml: Таргет Domain с зависимостями:

Domain:     templates:        - Framework     sources:        - path: ../Domain     dependencies:       - carthage: RxSwift       - carthage: RxCocoa

Для добавления зависимостей у нас есть несколько вариантов, но в нашем проекте мы используем всего 3:

  • Добавить carthage-зависимость,

  • Добавить зависимость проекта с привязкой (link: true),

  • Добавить зависимость проекта без привязки (link: false).

    XcodeGen/project.yml: Пример трех вариантов зависимостей (carthage, с привязкой и без):

 dependencies:       - carthage: RxSwift       - carthage: RxCocoa       - target: BaseUI         link: false       - target: DevTools         link: true       - target: UICarTrack         link: false

Вы можете узнать больше о добавлении зависимостей здесь.

Пришло время подтянуть все зависимости в нашем проекте, и в целом все готово! «В целом» — это просто способ сказать, что эта задача, вероятно, является наиболее трудоемкой, т.к. она состоит из цикла:

  • 1. Создание .xcodeproject и его открытие,

  • 2. Компиляция проекта и определение недостающих зависимостей,

  • 3. Добавление недостающих зависимостей в project.yml,

  • 4. Возвращение к шагу 1.

7. Дополнительно: скрипты сборки

В исходном проекте у нас было несколько скриптов сборки (как мы видим на изображении ниже):

Мы можем добиться того же результата, добавив чайлда postCompileScript.

GoodToGo:     type: application     platform: iOS     deploymentTarget: 12.0     settings:       base:         MARKETING_VERSION: 1.0     sources:        - path: ../GoodToGo     dependencies:        ...     postCompileScripts:       - script: |                 if which swiftlint >/dev/null; then                    swiftlint                 else                    echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"                 fi         name: Run SwiftLint

8. Дополнительно: папка Documents

Мы также можем добавить папку Documents. Файлы внутри этой папки не будут добавлены ни в какой таргет и, следовательно, не будут обрабатываться как часть сборки. Просто добавьте путь к папке с документами в раздел fileGroups (подробнее о fileGroups здесь).

fileGroups:   - ../Documents

IV — Резюме

  • Мы создали базовый файл project.yml и использовали XcodeGen, чтобы он сгенерировал наш проект (подробнее здесь)

  • Мы добавили некоторые конфигурации проекта (подробнее здесь)

  • Мы добавили все необходимые нам таргеты

  • Мы подтянули зависимости наших таргетов (подробнее здесь)

  • Мы добавили папку с документами (подробнее здесь)

  • Мы добавили скрипты сборки

1. Проблемы, с которыми вы можете столкнуться при настройке проекта в первый раз: Потерянные файлы

Иногда такое может случится с каждым из нас. При удалении некоторых старых/устаревших файлов из проекта мы выбираем опцию Remove Reference вместо перемещения файла в корзину. Эти файлы появятся снова, когда мы будем использовать XcodeGen (помните, что все файлы внутри папки будут добавлены в таргет). Если вы действительно хотите сохранить эти файлы, поместите их в папку Documents.

2. Проблемы, с которыми вы можете столкнуться при настройке проекта в первый раз: Разные файлы внутри папок

Иногда внутри папок наших таргетов лежат разные файлы. Опять же, помните, что все файлы внутри папки таргета будут добавлены в таргет и, следовательно, скомпилированы. Вы можете избежать этого, поместив эти файлы в папку Documents.

V — Ссылки

  • Проект перед преобразованием можно найти здесь.

  • Код финального проекта можно найти здесь.

  •  Финальный project.yml можно найти здесь.

  • Больше примеров подобных проектов можно найти здесь.


Узнать подробнее о курсе «iOS Developer. Professional».

Смотреть запись вебинара «Пишем приложение на SwiftUI и Combine».

ссылка на оригинал статьи https://habr.com/ru/company/otus/blog/543260/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *