Xcode 11 перекомпілює занадто багато


12

Xcode 11 перекомпілює (майже?) Весь мій проект, навіть якщо я просто змінюю локальну приватну змінну або змінюю значення константи в локальному масштабі, іноді навіть у локальній області приватних функцій. Я колись можу отримати 2 або 3 зміни з швидкими побудовами, як очікувалося, але досить скоро він вирішить перекомпілювати все заново (що займає занадто багато часу).

Якісь ідеї, що може відбуватися? Чи Xcode не в змозі визначити, що змінилося, чому він перекомпілює так багато інших матеріалів (навіть інших модулів).

Будь-яка порада високо цінується, дякую!


2
Я б радив: Переконайтеся, що ви займаєтеся налагодженнями з нарощенням, а не оптимізацією всього модуля. Закрийте та очистіть DerivedData. І оновлення до Xcode 11.4, інколи збирається так швидко, що я навіть не бачу цього.
мат

1
Ця нитка може відповісти на ваше запитання: stackoverflow.com/questions/25537614 / ...
Endanke

Це дуже залежить від проекту, йому потрібно проаналізувати журнал побудови того, що відбувається. Я не спостерігаю такої поведінки з Xcode 11.2+, хоча у мене дуже великі проекти. Ви б хоч якось надали доступ до джерел свого проекту, інакше всі поради безглузді?
Аспер

Перевірте властивість Legacy Build System, його слід зняти, якщо ви не
змінюєте

Відповіді:


8

У нас була така ж проблема, і ми її вирішили. Двічі.

Поступова збірка (та сама машина для складання):

до: ~ 10м після: ~ 35с

ЯК?

Почнемо спочатку з нашого досвіду. У нас був масштабний проект Swift / Obj-C, і це було головним питанням: час збирання був повільним, і вам довелося створити новий проект, щоб реалізувати нову функцію (буквально). Бонусні бали за неробоче виділення синтаксису.

Теорія

Щоб справді це виправити, ви повинні по- справжньому зрозуміти, як працює система побудови. Наприклад, спробуємо цей фрагмент коду:

import FacebookSDK
import RxSwift
import PinLayout

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

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

Дерево залежності

Збірка Xcode багатопотокова , але вона складається з багатьох однониткових дерев .

Отже, на першому кроці кожної інкрементальної збірки Xcode вирішує, які файли потрібно перекомпілювати та будує дерево AST . Якщо ви зміните файл, який діє як " надійний " для інших файлів, тому кожен інший файл, який діє як " залежний ", повинен бути перекомпільований.

Зчеплення

Тому перша порада - знизити з'єднання . Ваші частини проекту повинні бути незалежними одна від одної.

Об'є-С / Швидкий міст

Проблема з тими деревами, якщо ви використовуєте міст Obj-C / Swift, Xcode повинен пройти більше фаз, ніж зазвичай:

Ідеальний світ:

  1. Створює код Obj-C
  2. Створіть код Swift

Швидкий / Obj-C міст

Obj-C / Свіфт-міст:

  1. [ПОВТОРЕННИЙ КРОК] Побудуйте код Swift, який необхідний для компіляції коду Obj-C
  2. [ПОВТОРЕННИЙ КРОК] Побудуйте код Obj-C, який необхідний для компіляції коду Swift
  3. Повторюйте 1 і 2, поки у вас не залишиться лише незалежний код Swift & Obj-C
  4. Побудувати код Obj-C
  5. Створіть код Swift

Об'є-С / Швидкий міст

Тож якщо ви змінили щось із кроку 1 або 2, ви, в основному, переживаєте проблеми. Найкраще рішення - мінімізувати Obj-C / Swift Bridge (і видалити його зі свого проекту).

Якщо у вас немає Obj-C / Swift Bridge, це приголомшливо, і ви можете перейти до наступного кроку:

Швидкий менеджер пакетів

Час перейти до SwiftPM (або принаймні краще налаштувати ваші Cocoapods).

Справа в тому, що більшість фреймворків із конфігурацією Cocoapods за замовчуванням тягнуть разом із собою безліч речей, які вам не потрібні.

Щоб перевірити це, створіть порожній проект із лише однією залежністю, наприклад PinLayout, і спробуйте написати цей код за допомогою Cocoapods (конфігурація за замовчуванням) та SwiftPM.

import PinLayout

final class TestViewController: UIViewController {

}

Спойлер: Cocoapods буде компілювати цей код, тому що Cocoapods імпортує ВСІЙ ІМПОРТ PinLayout (включаючи UIKit), а SwiftPM не тому, що SwiftPM імпортує рамки атомним шляхом.

Брудний злом

Ви пам'ятаєте, що збірка Xcode є багатопотоковою?

Що ж, ви можете зловживати цим, якщо вам вдасться розділити ваш проект на безліч незалежних фрагментів та імпортувати їх як незалежні рамки до свого проекту. Це знижує з'єднання, і це насправді було першим нами застосованим рішенням, але насправді воно не було дуже ефективним, оскільки ми могли лише скоротити час нарощування до ~ 4-5 м, що НІЧОГО в порівнянні з першим методом.


Удачі, приятелю. Поділіться своїм досвідом, як ви знизили з'єднання у своєму проекті. До побачення!
x0 z1

3

Тут немає жодної золотої кулі, але все, що потрібно перевірити:

  • Переконайтеся, що ви фактично використовуєте конфігурацію налагодження у вашій схеміРедактор схем Xcode за допомогою конфігурації налагодження

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

  • Якщо ви використовуєте важкі рамки типу виводу, як-от RxSwift, додавання явних приміток типу може пришвидшити час збирання.

  • Якщо проект дуже великий, ви можете розглянути можливість рефакторингу логічних груп вихідних файлів у рамки, але це може бути занадто кардинально зміни, ніж ви хотіли б.

Це може допомогти, якщо ви надали ще деякі конкретні відомості про проект: чи є ви статично пов’язаними будь-якими бібліотеками? Це рамка або ціль програми? Наскільки велика і яка швидка версія ви використовуєте? Чи є у вас спеціальні фази збірки, такі як лінери або генерація коду, які іноді можна пропустити?

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.