Swift Macros : Le Guide Complet de la Métaprogrammation
Publié le · Mis à jour le · 22 min
Qu'est-ce qu'une macro Swift ?
Une macro est une transformation de code source qui s'exécute au moment de la compilation. Contrairement aux macros C qui effectuent de simples remplacements de texte, les macros Swift travaillent sur l'arbre syntaxique abstrait (AST) et sont entièrement type-safe.
Les caractéristiques principales :
Génération de code à la compilation, pas à l'exécution
Vérification de types complète sur le code généré
Exécution dans un environnement sandbox sécurisé
Possibilité d'inspecter le code généré dans Xcode
Intégration native avec SwiftPM
Les macros résolvent des problèmes que ni les génériques, ni les protocoles, ni les property wrappers ne pouvaient résoudre élégamment.
Avant les macros
Avant Swift 5.9, les développeurs utilisaient plusieurs approches pour réduire le boilerplate :
| Approche | Avantages | Inconvénients |
|---|---|---|
Property Wrappers | Intégrés au langage | Limités aux propriétés |
Sourcery | Très puissant | Outil externe, maintenance |
Protocoles + Extensions | Standard Swift | Pas de génération de code |
Code generation scripts | Flexible | Hors du compilateur |
Les macros combinent le meilleur : puissance de Sourcery, intégration native, et sécurité du compilateur.
Timeline des macros
Swift 5.9 — Septembre 2023
Introduction des macros avec trois proposals fondatrices :
SE-0382 : Expression Macros
SE-0389 : Attached Macros
SE-0397 : Freestanding Declaration Macros
Swift 6.0 — Septembre 2024
Stabilisation et adoption massive. Apple introduit @Observable et @Model.
Swift 6.1+ — 2025
Améliorations continues de SwiftSyntax et nouvelles proposals en discussion (Body Macros SE-0415).
Les deux familles de macros
Swift distingue deux types de macros selon leur syntaxe d'utilisation :
Freestanding Macros
Utilisent le préfixe # et peuvent apparaître comme expressions ou déclarations :
Attached Macros
Utilisent le préfixe @ et s'attachent à une déclaration existante :
Tableau des rôles de macros
| Rôle | Syntaxe | Description |
|---|---|---|
@freestanding(expression) | #macro() | Retourne une valeur |
@freestanding(declaration) | #macro() | Génère des déclarations |
@attached(peer) | @Macro | Ajoute des déclarations à côté |
@attached(accessor) | @Macro | Ajoute get/set/willSet/didSet |
@attached(memberAttribute) | @Macro | Ajoute des attributs aux membres |
@attached(member) | @Macro | Ajoute de nouveaux membres |
@attached(extension) | @Macro | Ajoute des conformances |
Une macro peut combiner plusieurs rôles.
Freestanding Expression Macros
Les expression macros (@freestanding(expression)) retournent une valeur utilisable dans le code :
Exemple : #stringify
La macro #stringify retourne un tuple avec la valeur et sa représentation textuelle :
Exemple : #URL avec validation
Exemple : #Predicate
Freestanding Declaration Macros
Les declaration macros (@freestanding(declaration)) génèrent de nouvelles déclarations :
Attached Peer Macros
Les peer macros ajoutent des déclarations "à côté" de la déclaration annotée :
Attached Accessor Macros
Les accessor macros ajoutent des accesseurs (get, set, willSet, didSet) :
Attached Member Macros
Les member macros ajoutent de nouveaux membres à un type :
Attached Extension Macros
Les extension macros ajoutent des conformances de protocoles :
Attached MemberAttribute Macros
Les memberAttribute macros appliquent des attributs à tous les membres :
Macros d'Apple dans la stdlib
Apple utilise massivement les macros dans ses propres frameworks :
@Observable (Observation framework)
@Model (SwiftData)
#expect et #require (Swift Testing)
#Predicate (Foundation)
Créer sa première macro — Pas à pas
Créons une macro @AutoDescription qui génère une description lisible.
Structure du package
Package.swift
Déclaration de la macro
Implémentation de la macro
Utilisation
SwiftSyntax — Le coeur des macros
SwiftSyntax est la bibliothèque qui permet de manipuler l'AST Swift.
Les protocoles principaux
Naviguer dans l'AST
SwiftSyntaxBuilder — Générer du code
SwiftSyntaxBuilder permet de construire du code avec une syntaxe expressive :
MacroExpansionContext
Le contexte fournit des informations utiles :
Debugging et tests
Expand Macro dans Xcode
Clic droit sur une macro → "Expand Macro" pour voir le code généré :
Tests unitaires de macros
SwiftSyntax fournit des utilitaires de test :
Diagnostics custom
Créez des messages d'erreur informatifs :
Macros populaires de l'écosystème
swift-dependencies (@Dependency)
swift-composable-architecture (@Reducer)
Autres macros populaires
La communauté a créé de nombreuses macros open source :
@CodableKey : Personnalisation des clés JSON
@Builder : Pattern builder automatique
@EnumSubset : Sous-ensembles d'enum type-safe
@Copyable : Méthode copy(with:) automatique
@DefaultValue : Valeurs par défaut pour Codable
Voir : Awesome Swift Macros
Bonnes pratiques
Quand utiliser les macros
Les macros sont appropriées pour :
Éliminer du boilerplate répétitif
Générer du code basé sur la structure existante
Ajouter des conformances automatiques
Valider des données à la compilation
Quand éviter les macros
Les macros ne sont pas idéales pour :
Logique métier complexe (préférer des fonctions)
Cas simples couverts par les protocoles
Transformations qui changent fréquemment
Performance de compilation
Les macros s'exécutent à chaque compilation. Gardez-les légères :
Versioning SwiftSyntax
SwiftSyntax évolue avec chaque version de Swift. Spécifiez une version compatible :
Limites et sécurité
Sandbox d'exécution
Les macros s'exécutent dans un environnement isolé :
Pas d'accès au système de fichiers
Pas de réseau
Pas d'exécution de code arbitraire
Mémoire et temps limités
Ce que les macros ne peuvent pas faire
Vérification à la compilation
Le code généré est entièrement vérifié :
Ressources officielles
Documentation Apple
Swift Evolution Proposals
| Proposal | Titre | Status |
|---|---|---|
SE-0382 | Expression Macros | Implémenté (Swift 5.9) |
SE-0389 | Attached Macros | Implémenté (Swift 5.9) |
SE-0394 | Package Manager Support for Custom Macros | Implémenté (Swift 5.9) |
SE-0397 | Freestanding Declaration Macros | Implémenté (Swift 5.9) |
SE-0415 | Function Body Macros | En discussion |
Communauté
Les Swift Macros représentent un outil puissant pour tout développeur Swift sérieux. Maîtrisées correctement, elles permettent d'écrire du code plus propre, plus sûr et plus maintenable.