Xcode 11 перекомпилирует (почти?) Весь мой проект, даже если я просто изменяю локальную частную переменную или меняю значение константы в локальной области видимости, иногда даже в области локальной приватной функции. Иногда я могу получить 2 или 3 изменения с быстрой сборкой, как и ожидалось, но достаточно скоро он решает перекомпилировать все заново (что занимает слишком много времени).
Есть идеи, что может происходить? Разве Xcode не может определить, что изменилось, почему он перекомпилирует так много других вещей (даже других модулей).
Любой совет высоко ценится, спасибо!
Ответы:
У нас была такая же проблема, и мы ее исправили. Дважды.
Инкрементная сборка (то же строение):
до: ~ 10м после: ~ 35с
КАК?
Давайте начнем с нашего опыта в первую очередь. У нас был крупный проект Swift / Obj-C, и это было главной заботой: время сборки было медленным, и вам пришлось создавать новый проект для реализации новой функции (буквально). Бонусные баллы за неработающую подсветку синтаксиса.
теория
Чтобы действительно это исправить, вы должны по- настоящему понять, как работает система сборки. Например, давайте попробуем этот фрагмент кода:
и представьте, что вы используете все эти операции импорта в своем файле. А также этот файл зависит от другого файла, который зависит от других библиотек, которые в свою очередь используют другие библиотеки и т. Д.
Таким образом, чтобы скомпилировать ваш файл, XCode должен скомпилировать каждую упомянутую вами библиотеку и каждый файл, от которого он зависит, поэтому, если вы измените один из «основных» файлов, XCode должен перестроить буквально весь проект.
Сборка Xcode является многопоточной , но состоит из множества однопоточных деревьев .
Таким образом, на первом шаге каждой инкрементной сборки XCode решает, какие файлы необходимо перекомпилировать, и создает дерево AST . Если вы изменяете файл, который действует как « надежный » для других файлов, то каждый другой файл, который действует как « зависимый », должен быть перекомпилирован.
Поэтому первый совет - снизить сцепление . Части вашего проекта должны быть независимы друг от друга.
Obj-C / Swift Bridge
Проблема с этими деревьями, если вы используете мост Obj-C / Swift, Xcode должен пройти больше фаз, чем обычно:
Безупречный мир:
Obj-C / Swift Bridge:
Так что если вы что-то измените с шага 1 или 2, у вас возникнут проблемы. Лучшее решение - минимизировать Obj-C / Swift Bridge (и удалить его из вашего проекта).
Если у вас нет моста Obj-C / Swift, это здорово, и вы можете перейти к следующему шагу:
Swift Package Manager
Пора переходить на SwiftPM (или, по крайней мере, лучше настраивать свои Cocoapods).
Дело в том, что большинство фреймворков с конфигурацией по умолчанию Cocoapods тянут за собой множество вещей, которые вам не нужны.
Чтобы проверить это, создайте пустой проект с одной зависимостью, например PinLayout, и попробуйте написать этот код с Cocoapods (конфигурация по умолчанию) и SwiftPM.
Спойлер: Cocoapods скомпилирует этот код, потому что Cocoapods будет импортировать КАЖДЫЙ ИМПОРТ PinLayout (включая UIKit), а SwiftPM - нет, потому что SwiftPM импортирует фреймворки атомарно.
Грязный хак
Вы помните, что сборка Xcode является многопоточной?
Что ж, вы можете злоупотребить этим, если вам удастся разделить ваш проект на множество независимых частей и импортировать их все как независимые фреймворки в ваш проект. Это снижает связь, и это было фактически первое решение, которое мы использовали, но на самом деле оно не было очень эффективным, потому что мы могли только сократить время инкрементной сборки до ~ 4-5 м, что НИЧЕГО по сравнению с первым методом.
источник
Здесь нет золотой пули, но есть много вещей, которые нужно проверить:
Убедитесь, что вы действительно используете конфигурацию Debug в своей схеме
Ниже показано, как убедиться, что вы используете инкрементные сборки по сравнению с целым модулем согласно совету Мэтта. Также убедитесь, что ваш уровень оптимизации для отладочных сборок не равен.
Если вы используете тяжелые фреймворки с выводом типов, такие как RxSwift, добавление явных аннотаций типов может ускорить время сборки.
Если проект очень большой, вы можете рассмотреть возможность реорганизации логических групп исходных файлов в каркасы, но это может быть слишком радикальным изменением, чем вы предпочитаете
Это может помочь, если вы предоставите более подробную информацию о проекте: статически ли вы связываете какие-либо библиотеки? Это фреймворк или цель приложения? Насколько большой и какой быстрой версией вы пользуетесь? Есть ли у вас какие-либо пользовательские фазы сборки, такие как линтеры или генерация кода, которые иногда можно пропустить?
источник