Система складання Xcode: визначаємося з поняттями

image
Що потрібно знати розробнику для ефективної роботи? Йому буде корисно знання алгоритмів і структур даних, знання про процес компіляції, лінкування, виділення пам'яті, знання платформи і мови, які він використовує, знання різних парадигм мов програмування і патернів проектування, знання систем багтрекинга і контролю версій, знання баз даних і мережевої моделі OSI, знання… Потрібно знати багато.Однак якщо б доскональне розуміння всіх цих областей знань і технологій було необхідною умовою для написання першої програми, в світі, ймовірно, було б лише кілька сотень неймовірно посидючих програмістів.

На щастя, як правило, ми можемо почати використовувати якусь технологію, інструмент або область знань, просто розібравшись в основних принципах, тобто як на якусь «магію». Однак чим частіше ми вдаємося до подібної «магії», тим менш ефективні рішення приймаємо. Тому наша мета, як хороших розробників, — мінімізувати використання незрозумілих технологій, інструментів і областей знань.

Однією з таких неявних для багатьох iOS-розробників технологій є система складання нашій IDE, за замовчуванням — Xcode. Чи часто люди розуміють, як вона працює, але плутають терміни, називаючи конфігурації складання таргетами, таргети воркспейсами і т. д. Зараз ми спробуємо розібратися, які терміни нам важливо знати, коли ми говоримо про Xcode, що вони означають і як пов'язані між собою.

Не сказати, що тема свіжа — Apple висвітлювала її ще в 2011 році на wwdc. І ще раз в цьому році.
Тому, щоб додати статті свіжості, використовуємо в якості аналогії якусь модну технологію. Наприклад, уявімо, що Xcode — 3d-принтер, здатний друкувати їжу. І ми вирішили використовувати його в якості кухні для точки громадського харчування.

Project

Наприклад, ми хочемо годувати людей піцою і тому створюємо для нашого 3d-принтера спеціальний модуль, Pizza.project, який містить інформацію про те, як готувати абстрактну піцу (форма, час приготування, можливі інгредієнти і т. д.).

image
Документація:
Project — це сховище для файлів і ресурсів, необхідних для складання програмного продукту. Проект містить всі елементи, використовувані для складання ваших продуктів і підтримує зв'язки між цими елементами. Проект визначає налаштування за замовчуванням для всіх таргетов у проекті.
Функції project'a:
  • Містить посилання на файли вихідного, бібліотеки і фреймворки, зображення, файли Interface Builder'а (ксибки, сторіборди).
  • Описує групи для структурування файлів в Project Navigator'е (це ті, які збивають з пантелику псевдопапки, які не мають нічого спільного зі структурою проекту на диску).
  • Описує конфігурації збірки (про це далі)
  • Містить опис таргетов (про це далі)
Під капотомФайл з розширенням .xcodeproj — це папка, яку ми можемо відкрити у файндере і подивитися, як Project реалізує покладені на нього функції.
Ось так:
image
Всередині ми можемо побачити наступне:
  1. Файл .pbxproj. Рідкісного iOS-розробнику не доводилося мержить його. Всі ми знаємо, що це здоровенний файл, який постійно змінюється, оскільки містить в собі майже всю інформацію про проект. Посилання на джерело і ресурси, опис угруповання файлів, список таргетов, залежностей таргетов, конфігурації складання проектів, конфігурації складання таргетов і не тільки. Загалом, опис функцій і внутрішнього устрою цього файлу гідно окремої статьи.

  2. Папка xcuserdata. У ній зберігається інформація про стан проекту (який файл відкритий, який таргет обраний тощо), брейкпоинты та схеми для поточного користувача Xcode. Цю папку варто додати в ваш .gitignor-файл, якщо ви цього ще не зробили.
  3. Папка xcshareddata. Як можна здогадатися з назви, папка відрізняється від попередньої тим, що в ній зберігаються налаштування (схеми і брейкпоинты), якими ми хочемо поділитися зі своїми товаришами по розробці програми.
    • Щоб поділитися брейкпоинтом: потрібно зайти в брейкпоинт-навігатор, натиснути правою клавішею на той брейкпоинт, який ви хочете розшарити, і натиснути Share Breakpoint.
    • Щоб поділитися схемою, потрібно зайти в Product —> Scheme —> Manage schemes і поставити галочку в стовпці Shared навпаки схеми, якою ви хочете поділитися.

  4. Файл .xcworkspace(внутрішній workspace).

Target

Оскільки абстрактну піцу у нас ніхто не купить, нам потрібно додатково завантажити в наш 3d-принтер кілька моделей конкретних піц, які, на основі нашого Pizza.project буде описувати 3d-принтера, як друкувати конкретну піцу (які з наявних інгредієнтів використовувати, яку температуру тримати при готуванні, який повинен бути розмір). Такою моделлю буде таргет.

image

Документація:
Таргет точно визначає, який продукт буде зібраний, і містить інструкції для складання проекту із набору файлів воркспейса або проекту.
Як можна здогадатися з назви, таргет описує мету, до якої ми рухаємося у своїй роботі. Це може бути додаток під одну з чотирьох осей, бібліотека або фреймворк, экстеншн або віджет, набір тестів. В Swift кожен Xcode-таргет представляється як окремий модуль, який можна імпортувати і звертатися до нього через його публічний API. Найважливіше: ми можемо мати відразу кілька таргетов на одній кодовій базі, які можуть використовувати одні й ті ж вихідні матеріали і ресурси. В залежності від типу кінцевого продукту і операційної системи, на якій він буде працювати, таргет може нести різний набір відповідальностей.
Функції target'a:
  • Визначає набір джерел і ресурсів, використовуваних для складання продукту. Ми можемо включати в проект і виключати з нього конкретний ресурс або файл із вихідним кодом (у розділі Compile Sources у Build Phases, або в Inspector File, вибравши потрібний файл).
  • Зберігає настройки складання проекту. Ми можемо поміняти для якогось продукту якусь налаштування, не змінюючи налаштувань для складання інших продуктів.
  • Описує фази складання. Це набір упорядкованих дій (на зразок копіювання файлів в бандл, лінкування фреймворків збірка ресурсів і джерел), які xcode буде робити, щоб отримати продукт. Ми можемо змінювати цей порядок, а так само додавати свої фази у вигляді shellscript'ів. Часто буває потрібно правильно вибрати місце для свого скрипта в порядку виконання фаз, наприклад, якщо ми хочемо модифікувати якийсь файл з бандлу, нам потрібно застосувати відповідний скрипт після того, як Xcode скопіює файли у бандл.
Також ми можемо додати до таргету залежності, допомагаючи Xcode визначити порядок складання продуктів. Повертаючись до нашого прикладу з піцою, ми можемо запропонувати нашим клієнтам комбо з двох піц, додавши таргет PizzaCombo.
image
Як видно на скріншоті, для цього нам довелося створити таргети для Гавайської піци і Маргарити у вигляді фреймворків. Тепер нам залишилося лише додати їх у вигляді залежностей до таргету PizzaCombo, і ми зможемо користуватися цими продуктами всередині іншого продукту.

image

Build Settings

Крім правильних інгредієнтів для приготування правильної піци наш 3d-принтер повинен дотримуватися ряду правил. Деякі з них специфічні для проекту піци взагалі (наприклад, всі піци повинні друкуватися однієї форми) деякі специфічні для конкретної піци (наприклад, Гавайська піца повинна готуватися при іншій температурі, ніж Маргарита, інакше ананаси будуть сухими).

Документація:
Налаштування збірки — це змінна, яка містить інформацію про те, як повинен бути виконаний якийсь конкретний аспект процесу складання.
Коли я вперше заглянув в розділ Build Settings, моєю першою асоціацією було:
image
Однак на щастя, нам не обов'язково в повсякденному розробці знати всі наявні налаштування та їхні ключі, а постійно ми використовуємо лише деякі.
Кожна настройка складається з ключа, значення і заголовка для ключа в человекочитаемом форматі (щоб можна було вмістити у вкладці Build Settings).
Значення для налаштування може бути встановлено як на рівні проекту, так і на рівні таргету. Якщо на якомусь із рівнів значення для налаштування не було встановлено, вона успадковує значення з попереднього рівня.
Спадкування здійснюється в наступному порядку (від меншого до більшого):
  • Базове значення для платформи
  • Значення з xcconfig-файлу проекту
  • Значення, встановлене в проекті
  • Значення з xcconfig-файлу таргету
  • Значення, встановлене в таргете
Зрозуміти, на якому рівні встановлено значення для тієї чи іншої установки в Xcode можна за допомогою кнопки Levels в розділі Build Settings. Зеленим кольором відзначено значення, яке буде встановлено при збірці.
image
Важливо знати, що ми можемо додавати свої User-Defined налаштування і використовувати їх, наприклад, в фазах складання або Info.plist-файлі (хоча і з деякими обмеженнями).
Також варто згадати про можливості виставлення умовних налаштувань. Тобто мати різні значення для однієї і тієї ж параметри в залежності від платформи, для яких продукт буде зібраний. Для «розумного» і гнучкого поділу налаштувань нам слід скористатися конфігураціями складання.

Build Configuration

Наприклад, ми вирішили, що кожна піца буде представлена в звичайному і дієтичному варіанті. Дієтичний варіант піци буде не таким підсмаженими, смажена шинка буде замінена на варену, тісто буде без солі. Тоді два варіанти однієї і тієї ж піци будуть відрізнятися цілим набором налаштувань нашого принтера. Щоб не створювати нові таргети для кожної з вже наявних піц, а застосовувати лише різні набори налаштувань для друкування, ми використовуємо конфігурації збірки.

Документація:
Конфігурація збірки визначає набір налаштувань збирання, використовуваних для складання продукту таргету певним чином.
За замовчуванням Xcode створює нам дві конфігурації Debug і Release, проте ми можемо додати стільки конфігурацій, скільки нам буде потрібно.
Таким чином, створивши конфігурації для звичайної та дієтичної піци, ми можемо виставити для кожної відрізняється налаштування два значення, відповідних кожній з конфігурацій, а при складанні просто встановлювати потрібну в даний момент конфігурацію.
Так можна, наприклад, розділяти складання програми для роботи з тестовим і продуктивним серверами.
Ми можемо винести конфігурації збірки в xcconfig-файли, щоб зняти одну з відповідальностей .pbxproj-файлу і полегшити мердж при одночасному зміні налаштувань. Це можна зробити, наприклад, за допомогою цього інструменту.

Workspace

Ось ми почали друкувати свою піцу, додали пару варіантів піц, зібрали зворотний зв'язок з наших клієнтів і виявилося, що більшості з них подобається наша піца, однак вони б хотіли є її разом з ролами. На основі Pizza.project зробити рол в нас не вийде, тому ми додаємо в наш 3d-принтер проект Sushi.project, створюємо на його основі пару моделей (таргетов) для конкретних ролів. Тепер ми можемо друкувати і піцу, і роли, проте раз наші клієнти хочуть їсти їх разом, зробимо їм таку пропозицію. Ми створюємо Pizza.workspace, в який включаємо проект з суші. Тепер ми можемо сформувати таргети для комбінованих бізнес-ланчів, в які будуть включені як конкретна піца, так і конкретний рол. Також у цей проект ми можемо включити сторонню бібліотеку з друку кальянів, яку будемо використовувати і при друку піци, і при друку ролів, і при друку комбінованих бізнес-ланчів. Наприклад, нехай перший варіант бізнес-ланчу буде включати в себе гавайську, роли «Філадельфія» і кальян сторонньої бібліотеки:

image

image

Документація:
Workspace — Xcode-документ, группирующий проекти та інші документи для роботи з ними як з єдиним цілим.
Простіше кажучи, воркспейс дозволяє нам об'єднати будь-яку кількість проектів і відносяться до них файлів в єдиному контейнері. Що це нам дає?
Функції workspace'a:
  • Надає доступ до кожного файлу в кожному включеному проекті.
  • Розширює область видимості. Завдяки цьому автодоповнення, пошук і перехід до визначення працюють по всьому включеним у workspace проектів.
  • Допомагає Xcode розрулити залежності таргетов і збирає проекти у відповідній послідовності. Наприклад, ми можемо імпортувати Swift-модуль таргету одного проекту в іншому проекті, якщо ці проекти лежать в одному воркспейсе.
Під капотомВоркспейс — package з розширенням .xcworkspace.
Давайте заглянемо всередину .xcworkspace, як ми це зробили .xcodeproj. Першим ділом ми там побачимо contents.xcworkspacedata — XMLку, що описує включені в воркспейс проекти і файли.

Також ми можемо побачити вже знайомі нам папки .xcuserdata і .xcshareddata. Ми можемо самі вирішувати, куди, наприклад, зберегти схему: рівень проекту або на рівень воркспейса. В залежності від нашого вибору вона з'явиться або в одній з папок .xcodeproj, або в одній з папок .xcworkspace.


Що в підсумку

Сьогодні ми дізналися, що проект — це сховище для файлів проекту, таргетов, конфігурацій і базових налаштувань. Що таргет — це набір інструкцій для складання продукту на основі проекту, яким цей таргет належить. Налаштування збірки — це пари ключ-значення, які описують якийсь аспект складання і можуть виставлятися як на рівні проекту, так і на рівні таргету. Що конфігурація збірки — набір значень для кожної налаштування збірки, об'єднаних якоюсь загальною ідеєю. І нарешті, що воркспейс — контейнер для зручного спільного використання декількох проектів. Сподіваюся, прочитавши цю статтю, ви не будете плутатися в термінології і згадувати хто ж відповідає за фази збирання: воркспейс або таргет?
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.