Xcode 11 recompile (presque?) Tout mon projet, même si je change juste une variable privée locale, ou change une valeur d'une constante dans la portée locale, parfois même dans la portée de la fonction privée locale. Je peux parfois obtenir 2 ou 3 changements avec des builds rapides comme prévu, mais assez tôt, il décide de tout recompiler à nouveau (ce qui prend trop de temps).
Quelques idées sur ce qui pourrait se passer? Est-ce que Xcode n'est pas en mesure de déterminer ce qui a changé, pourquoi recompile-t-il tant d'autres choses (même d'autres modules).
Tout conseil est très apprécié, merci!
Réponses:
Nous avons eu le même problème et nous l'avons résolu. Deux fois.
Construction incrémentielle (même machine de construction):
avant: ~ 10m après: ~ 35s
COMMENT?
Commençons par notre expérience d'abord. Nous avions un énorme projet Swift / Obj-C et c'était la principale préoccupation: les temps de construction étaient lents et vous deviez créer un nouveau projet pour implémenter une nouvelle fonctionnalité (littéralement). Points bonus pour une coloration syntaxique qui ne fonctionne jamais.
Théorie
Pour vraiment résoudre ce problème, vous devez vraiment comprendre comment fonctionne le système de génération. Par exemple, essayons cet extrait de code:
et imaginez que vous utilisez toutes ces importations dans votre fichier. Et aussi ce fichier dépend d'un autre fichier, qui dépend d'une autre bibliothèque, qui à son tour utilise une autre bibliothèque, etc.
Donc, pour compiler votre fichier, Xcode doit compiler chaque bibliothèque que vous avez mentionnée et chaque fichier dont il dépend, donc si vous changez l'un des fichiers "de base", Xcode doit reconstruire littéralement le projet entier.
La construction Xcode est multithread , mais elle se compose de nombreuses arborescences monothread .
Donc, à la première étape de chaque construction incrémentielle, Xcode décide quels fichiers doivent être recompilés et crée une arborescence AST . Si vous modifiez un fichier qui agit comme " fiable " sur d'autres fichiers, tous les autres fichiers qui agissent comme " dépendants " doivent être recompilés.
Le premier conseil est donc de réduire le couplage . Les parties de votre projet doivent être indépendantes les unes des autres.
Pont Obj-C / Swift
Problème avec ces arbres si vous utilisez un pont Obj-C / Swift, Xcode doit passer par plus de phases que d'habitude:
Monde parfait:
Pont Obj-C / Swift:
Donc, si vous changez quelque chose de l'étape 1 ou 2, vous êtes fondamentalement en difficulté. La meilleure solution consiste à minimiser Obj-C / Swift Bridge (et à le supprimer de votre projet).
Si vous n'avez pas de pont Obj-C / Swift, c'est génial et vous êtes prêt à passer à l'étape suivante:
Swift Package Manager
Il est temps de passer à SwiftPM (ou au moins de mieux configurer vos Cocoapods).
Le fait est que la plupart des frameworks avec la configuration par défaut des Cocoapods traînent avec eux-mêmes beaucoup de choses dont vous n'avez pas besoin.
Pour tester cela, créez un projet vide avec une seule dépendance comme PinLayout, par exemple et essayez d'écrire ce code avec Cocoapods (configuration par défaut) et SwiftPM.
Spoiler: Cocoapods compilera ce code, car Cocoapods importera CHAQUE IMPORTATION de PinLayout (y compris UIKit) et SwiftPM ne le fera pas parce que SwiftPM importe les frameworks atomiquement.
Hack sale
Vous souvenez-vous que la construction Xcode est multi-thread?
Eh bien, vous pouvez en abuser si vous pouvez diviser votre projet en plusieurs éléments indépendants et les importer tous en tant que cadres indépendants dans votre projet. Cela réduit le couplage et c'était en fait la première solution que nous avons utilisée, mais ce n'était pas très efficace, car nous ne pouvions réduire le temps de construction incrémentiel qu'à ~ 4-5 m, ce qui n'est RIEN par rapport à la première méthode.
la source
Il n'y a pas de solution miracle ici, mais beaucoup de choses à vérifier:
Assurez-vous que vous utilisez réellement la configuration de débogage dans votre schéma
Voir ci-dessous pour savoir comment vous assurer que vous utilisez des versions incrémentielles par rapport au module entier selon les conseils de matt. Assurez-vous également que votre niveau d'optimisation pour les versions de débogage est nul.
Si vous utilisez des frameworks lourds d'inférence de type comme RxSwift, l'ajout d'annotations de type explicites peut accélérer les temps de construction.
Si le projet est très important, vous pouvez envisager de refactoriser des groupes logiques de fichiers source dans des frameworks, mais cela peut être un changement trop radical que vous ne préférez
Cela pourrait être utile si vous fournissiez des détails supplémentaires sur le projet: liez-vous statiquement des bibliothèques? Est-ce un cadre ou une cible d'application? Quelle est la taille et quelle version rapide utilisez-vous? Avez-vous des phases de construction personnalisées comme des linters ou la génération de code qui pourraient parfois être ignorées?
la source