Librairies et Frameworks, voyage dans le monde de la modularité
Dans mon dernier article sur l’utilisation de XcodeGen version multi framework, j’ai évoqué le sujet de librairie static et dynamique. Je pense que beaucoup de développeurs veulent connaître la différence concrète entre ses deux types de frameworks et même entre une framework et une librairie. C’est pour cela j’ai décidé de vous ramener dans ce voyage au terre de la modularité avec Apple.
Notre parcours sera divisé en deux grandes parties:
- Définitions d’une framework, librairie, linkage.
- les avantages et les inconvénients d’utiliser une framework/Librairie static ou dynamique.
- Définitions
Une librairie:
Pour simplifier une librairie c’est seulement du pure code, pas de ressources (assets,nib, fonts, localisations…). On distingue deux types de librairies static ou dynamique. Les librairies static ont comme extension *.a et pour les dynamiques *.dylib.
Une framework:
Elle peut contenir des librairies dynamiques ou static, du pure code et des ressources (Une framework c’est tout simplement un bundle) . Une framework peut être aussi dynamique ou static mais pour jouer entre ces deux types, on modifie l’attribut MachO-Type dans le build settings de notre framework. Une framework a comme extension .framework et depuis Xcode 11, Il y a eu l’introduction de .xcframework qui a l’avantage de rendre la framework utilisable sur les différents platforms Apple et s’adapter avec les nouveaux microprocesseurs Apple Silicon M1.
Pour plus d’informations sur les .xcframework vous pouvez checker ce tutoriel du WWDC 2019
2. Edition des liens (Linkage)
Quelque soit une librairie ou une framework, on aura deux types static ou dynamique, mais c’est quoi la différence: c’est tout simplement le linkage.
Le linkage ou l’édition des liens est l’étape qui intervient en cours ou après la compilation.
Le linkage static se fait au moment de la compilation pour construire un seul binaire composé de l’application et de ses dépendances static (frameworks et librairies). L’éditeur de lien static copie les binaires des modules static pour construire un seul binaire finale. Du coup, vous n’allez pas trouvé le binaire de la framework static dans le dossier Frameworks crée du binaire finale de l’application et il n’est pas recommandé de copier une framework/Librairie static parce qu’elle est par défaut copiée (Embed) et/ou signé dans le binaire de l’application finale.
NB: Il y a le cas particulier des librairies static qui peuvent intégrer un bundle de ressources dans ce cas il est recommandé de faire un embed with sign de votre librairie static.
Dans cette exemple, on a une framework static ViewModel et une framework dynamique Utils:
Le linkage dynamique se fait au moment de l’exécution (runtime). En effet, Le programme de linkage dynamique recherche la framework dynamique dans le dossier frameworks de .app finale. Par exemple, la framework dynamique Utils est bien dans le dossier Frameworks:
Il est nécessaire de ne pas oublier de copier une framework dynamique (Embed and Sign in) vue que le compilateur ne peut pas détecter son absence du binaire finale.
3. Avantages et Inconvénients du linkage static et dynamique:
Linkage static (Framework et librairie static) | Linkage dynamique (Framework et librairie static) |
Sécurité: Vu que la framework ou la librairie est embarqué dans le binaire finale de l’application dés la compilation, on n’aura pas la fameuse erreur du run: ld: framework not found …… clang: error: linker command failed with exit code 1 (use -v to see invocation). Temps de lancement de l’application: est plus rapide vu que les symboles des frameworks et les librairies sont déjà embarqués dans l’exécutable. Taille du binaire finale: Apple optimise la taille de l’exécutable final de l’application malgré qu’il contient à la fois le binaires de l’app et les symboles des frameworks et librairies static. | Sécurité: Possibilité de crash systématique si on effectue pas une copie de la framework/librairie dynamique (Le linker dynamique ne vas pas trouver les binaires dynamiques dans le dossier framework de .app final Temps de Lancement: Vu que le linkage dynamique se fait au niveau du runtime, alors le temps de lancement de l’application sera plus lent. Vous pouvez consulter cet article de Apple sur les recommendations de minimiser l’utilisation des frameworks dynamiques afin d’optimiser le temps de lancement. Taille du binaire finale: est plus important vu qu’on copie les frameworks/librairies dynamiques au niveau du .app finale de l’application mais la taille du binaire finale de l’application(exécutable) principal est évidement inférieur que celui qui intègre frameworks statics. |
L’avantage majeur des frameworks dynamiques se manifeste surtout après l’introduction de ABI Stability ou on peut linker dynamiquement vers une nouvelle version d’une framework dynamique genre CoreData sans être obligé de recompiler l’application
Conclusion
Surement que vous avez compris l’impact de votre décision de choisir entre une librairie/Framework static ou dynamique sur le processus de compilation et d’exécution de votre application. Certes vous pensez comme moi que le choix d’une framework static est plus adéquat vu la sécurité et l’optimisation de taille faite malgré le merge des binaires static avec celui de l’application mais ça n’empêche pas que l’utilisation peut être utile en terme de minimisation du temps de compilation (pas de linkage static).
Références:
https://holyswift.app/frameworks-embed-or-not-embed-thats-the-question
https://bpoplauschi.github.io/2021/10/25/Advanced-static-vs-dynamic-libraries-and-frameworks.html