SPM : qu'est-ce que c'est, Swift Package Manager et Package.swift

Auteur : IT Sectr Publié le : 2026-02-13 Temps de lecture : 11 min

SPM (Swift Package Manager) est un gestionnaire de paquets intégré à l'écosystème Swift, développé par Apple pour automatiser la connexion, la compilation et la mise à jour des bibliothèques tierces. SPM fait partie du compilateur Swift depuis la version 3.0 (2016) et ne nécessite aucune installation séparée. Contrairement à CocoaPods et Carthage, SPM s'intègre directement au compilateur et à Xcode, ce qui en fait l'outil standard de gestion des dépendances dans les projets Swift modernes. Dans cet article, nous analyserons la structure de Package.swift, les commandes SPM, la création de paquets personnalisés et la migration depuis les gestionnaires alternatifs.

Points clés

  • SPM (Swift Package Manager) est un gestionnaire de paquets intégré au compilateur Swift qui ne nécessite aucune installation séparée ; il fonctionne sous iOS, macOS, Linux et les plates-formes serveur.
  • Package.swift est un fichier manifeste qui décrit le nom du paquet, les plates-formes, les dépendances et les modules cibles (targets) dans un format déclaratif.
  • SPM résout les dépendances par versionnement sémantique (SemVer), met en cache le code source et compile les paquets en parallèle pour plus de rapidité.
  • Commandes : swift package init (créer un paquet), swift package update (mettre à jour les dépendances), swift build (compiler), swift test (exécuter les tests).
  • La migration de CocoaPods/Carthage vers SPM se fait via Xcode : File → Add Package Dependency, après quoi le podfile et le Cartfile sont supprimés.

Qu'est-ce que SPM ?

SPM (Swift Package Manager) est le gestionnaire de paquets officiel pour le langage Swift, intégré au compilateur swiftc et à l'environnement de développement Xcode. Il permet aux développeurs d'ajouter des bibliothèques tierces, de gérer leurs versions et de publier leurs propres paquets. SPM est apparu pour la première fois dans Swift 3.0 (septembre 2016) en tant qu'outil en ligne de commande, et à partir de Xcode 11 (2019), il a reçu une intégration complète avec l'interface graphique — les dépendances sont désormais ajoutées via le menu File → Add Packages.

SPM télécharge automatiquement le code source des dépendances depuis les dépôts Git, les compile en parallèle du projet principal et met en cache les résultats pour que les compilations ultérieures soient plus rapides. Contrairement à CocoaPods, SPM ne génère pas d'espace de travail séparé (xcworkspace) — les dépendances font partie du projet Xcode principal. Selon l'enquête Swift.org Developer Survey (2024), 67 % des développeurs iOS utilisent SPM, ce qui en fait l'outil de gestion des dépendances le plus populaire de l'écosystème Swift.

SPM prend en charge trois plates-formes : Apple (iOS, macOS, tvOS, watchOS, visionOS), Linux (Ubuntu, CentOS, Amazon Linux) et Swift côté serveur (Vapor, Kitura). Sous Linux, SPM fonctionne entièrement en ligne de commande sans Xcode.

Comment fonctionne Swift Package Manager

SPM est construit autour de trois concepts clés : les paquets (packages), les produits (products) et les cibles (targets). Un paquet est un dépôt Git avec un manifeste Package.swift. Un produit est le résultat de la compilation (une bibliothèque ou un exécutable). Une cible est un module à l'intérieur du paquet qui se compile en une unité de construction.

Lorsqu'un développeur ajoute une dépendance à Package.swift, SPM effectue les étapes suivantes :

  1. Clonage — SPM télécharge le dépôt Git de la dépendance depuis l'URL spécifiée.
  2. Résolution de versions — il analyse les tags SemVer (par exemple 2.1.3) et sélectionne la version appropriée dans la plage spécifiée.
  3. Résolution transitive — il vérifie les dépendances des dépendances et construit un graphe de versions sans conflit.
  4. Cache — il enregistre le code source téléchargé dans ~Library/Caches/org.swift.swiftpm/.
  5. Compilation — il compile toutes les cibles du paquet avec les drapeaux du projet principal.

Le fichier Package.resolved fige les versions exactes de toutes les dépendances afin que l'équipe de développement travaille avec un ensemble identique de bibliothèques. Ce fichier doit être ajouté au contrôle de version (git).

Un avantage clé de SPM par rapport aux alternatives est l'absence de registre centralisé. Les paquets peuvent résider dans n'importe quel dépôt Git public : GitHub, GitLab, Bitbucket, ainsi que sur les serveurs Git privés de l'entreprise. Depuis Swift 5.2, SPM prend en charge les dépendances binaires (binary targets) — des bibliothèques fermées distribuées sous forme de XCFramework sans fournir de code source.

Package.swift — manifeste du projet

Package.swift est un fichier Swift qui décrit la structure du paquet et ses dépendances. Le fichier est écrit en Swift lui-même (pas en JSON ni YAML), ce qui permet d'utiliser la logique conditionnelle, les constantes calculées et les fonctions à l'intérieur du manifeste.

Structure de base de Package.swift :

swift
// swift-tools-version: 5.9
import PackageDescription

let package = Package(
    name: "MyLibrary",
    platforms: [
        .iOS(.v16),
        .macOS(.v13)
    ],
    products: [
        .library(
            name: "MyLibrary",
            targets: ["MyLibrary"]
        ),
    ],
    dependencies: [
        .package(url: "https://github.com/Alamofire/Alamofire.git",
                 from: "5.9.0"),
        .package(url: "https://github.com/onevcat/Kingfisher.git",
                 from: "7.12.0"),
    ],
    targets: [
        .target(
            name: "MyLibrary",
            dependencies: [
                "Alamofire",
                "Kingfisher"
            ]
        ),
        .testTarget(
            name: "MyLibraryTests",
            dependencies: ["MyLibrary"]
        ),
    ]
)

Analysons les éléments clés :

  • // swift-tools-version: 5.9 — directive spécifiant la version de SPM ; la syntaxe disponible du manifeste en dépend.
  • name — nom du paquet, affiché dans Xcode et utilisé dans les liens de dépendances.
  • platforms — versions minimales des plates-formes ; SPM ne permettra pas de compiler le paquet sur une version d'OS plus ancienne.
  • products — ce que le paquet « exporte » : une bibliothèque (.library) ou un exécutable (.executable).
  • dependencies — liste des paquets externes avec URL et version ; prend en charge from:, exact:, branch:, revision:.
  • targets — cibles de compilation ; chaque cible contient une liste de dépendances, de ressources et de fichiers Swift du répertoire correspondant (Sources/TargetName/).

Exemple de spécification d'une version exacte, d'une branche et d'un commit :

swift
dependencies: [
    .package(url: "https://github.com/pointfreeco/swift-snapshot-testing.git",
             exact: "1.17.3"),
    .package(url: "https://github.com/pointfreeco/swift-composable-architecture.git",
             branch: "main"),
    .package(url: "https://github.com/apple/swift-log.git",
             revision: "e5c6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4"),
]

Depuis Swift 5.9, Package.swift a ajouté la prise en charge de static framework et de linkerSettings, permettant une configuration plus précise de l'éditeur de liens pour les bibliothèques statiques et dynamiques.

Commandes SPM de base

Swift Package Manager fournit un ensemble de commandes pour travailler via le terminal. Les commandes sont exécutées depuis le répertoire racine du paquet (où se trouve Package.swift).

bash
# Créer un nouveau paquet avec une bibliothèque
swift package init --type library

# Créer un paquet exécutable (application console)
swift package init --type executable

# Compiler le projet
swift build

# Compiler en configuration de release
swift build -c release

# Exécuter les tests
swift test

# Exécuter un test spécifique
swift test --filter "MyLibraryTests/testExample"

# Télécharger et résoudre les dépendances
swift package resolve

# Mettre à jour les dépendances vers les dernières versions disponibles
swift package update

# Afficher le graphe des dépendances
swift package show-dependencies

# Vider le cache de compilation
swift package clean

# Générer le projet Xcode (avant Xcode 11)
swift package generate-xcodeproj

Lorsqu'on travaille dans Xcode, la plupart de ces commandes s'exécutent automatiquement : les dépendances sont résolues à l'ouverture du projet, la compilation démarre avec ⌘B, les tests avec ⌘U. Cependant, la connaissance des commandes terminal est nécessaire pour les pipelines CI/CD (GitHub Actions, GitLab CI, Jenkins) où Xcode n'est pas disponible.

La commande swift package resolve crée ou met à jour le fichier Package.resolved. Ce fichier fige les versions exactes de toutes les dépendances, y compris transitives, et doit être ajouté à git. Il est recommandé d'exécuter swift package update avant chaque nouvelle branche de fonctionnalité pour travailler avec des versions à jour des bibliothèques.

Création de votre propre paquet

Créer votre propre paquet SPM est utile pour encapsuler la logique métier dans des projets multi-modules et pour publier des bibliothèques open source. Examinons le processus étape par étape.

Étape 1 : Initialisation

bash
mkdir MyNetworkKit
cd MyNetworkKit
swift package init --type library

Étape 2 : Structure des répertoires

La commande swift package init crée la structure suivante :

text
MyNetworkKit/
├── Package.swift
├── README.md
├── Sources/
│   └── MyNetworkKit/
│       └── MyNetworkKit.swift
└── Tests/
    └── MyNetworkKitTests/
        └── MyNetworkKitTests.swift

SPM analyse automatiquement les répertoires Sources/ et Tests/ : chaque sous-répertoire dans Sources correspond à une cible (target).

Étape 3 : Modifier Package.swift

Ajoutons les dépendances et configurons les plates-formes cibles :

swift
// swift-tools-version: 5.9
import PackageDescription

let package = Package(
    name: "MyNetworkKit",
    platforms: [
        .iOS(.v15),
        .macOS(.v12)
    ],
    products: [
        .library(
            name: "MyNetworkKit",
            targets: ["MyNetworkKit"]
        ),
    ],
    dependencies: [
        .package(url: "https://github.com/Alamofire/Alamofire.git",
                 from: "5.9.0"),
    ],
    targets: [
        .target(
            name: "MyNetworkKit",
            dependencies: ["Alamofire"]
        ),
        .testTarget(
            name: "MyNetworkKitTests",
            dependencies: ["MyNetworkKit"]
        ),
    ]
)

Étape 4 : Écrire le code

swift
// Sources/MyNetworkKit/MyNetworkKit.swift
import Foundation
import Alamofire

public struct NetworkClient {
    private let session: Session

    public init() {
        let configuration = URLSessionConfiguration.default
        configuration.timeoutIntervalForRequest = 30
        self.session = Session(configuration: configuration)
    }

    public func fetchData(from url: String) async throws -> Data {
        let response = try await session.request(url).serializingData().value
        return response
    }
}

Étape 5 : Publication

Poussez le paquet vers un dépôt Git et créez un tag SemVer :

bash
git init
git add .
git commit -m "Initial commit: MyNetworkKit"
git remote add origin https://github.com/username/MyNetworkKit.git
git push -u origin main
git tag 1.0.0
git push --tags

Après cela, tout développeur peut ajouter votre paquet en utilisant .package(url: "https://github.com/username/MyNetworkKit.git", from: "1.0.0").

Exemples d'utilisation de SPM

Exemple 1 : Ajouter Alamofire pour les requêtes réseau

Alamofire est le client HTTP le plus populaire pour Swift. Ajoutons-le via SPM et effectuons une requête GET.

swift
import Alamofire

func fetchUsers() {
    AF.request("https://jsonplaceholder.typicode.com/users")
        .validate()
        .responseDecodable(of: [User].self) { response in
            switch response.result {
            case .success(let users):
                print("(users.count) utilisateurs reçus")
            case .failure(let error):
                print("Erreur : (error.localizedDescription)")
            }
        }
}

Exemple 2 : Swinject — injection de dépendances

La bibliothèque Swinject fournit un conteneur DI pour Swift. Elle s'ajoute via .package(url: "https://github.com/Swinject/Swinject.git", from: "2.8.0").

swift
import Swinject

let container = Container()
container.register(NetworkServiceProtocol.self) { _ in NetworkService() }
container.register(DataRepositoryProtocol.self) { r in
    DataRepository(networkService: r.resolve(NetworkServiceProtocol.self)!)
}

let repository = container.resolve(DataRepositoryProtocol.self)
repository?.loadData()

Exemple 3 : Swift-log pour la journalisation structurée

Le paquet swift-log d'Apple fournit une API de journalisation unifiée prenant en charge plusieurs backends (OSLog, console, fichiers).

swift
import Logging

var logger = Logger(label: "com.myapp.network")
logger.logLevel = .debug

logger.info("Requête réseau démarrée", metadata: [
    "url": "(requestURL)",
    "method": "GET"
])

logger.warning("Le temps de réponse a dépassé 2 secondes")
logger.error("Erreur de connexion : pas d'internet")

Ces trois exemples couvrent les scénarios typiques d'utilisation de SPM : clients HTTP, conteneurs DI et infrastructure système. La sélection des bibliothèques n'est pas fortuite — Alamofire, Swinject et swift-log font partie des 20 paquets Swift les plus étoilés sur GitHub.

Migration depuis CocoaPods et Carthage

Si votre projet utilise CocoaPods ou Carthage, la migration vers SPM se fait en quelques étapes. Le processus est sûr : les dépendances SPM peuvent coexister avec CocoaPods et Carthage dans le même projet, ce qui permet une migration progressive.

CocoaPods → SPM

  1. Dans Xcode : File → Add Package Dependency, entrez l'URL du paquet.
  2. Sélectionnez la version et ajoutez le paquet aux cibles nécessaires.
  3. Après avoir ajouté toutes les dépendances via SPM, supprimez les lignes du Podfile.
  4. Supprimez le .xcworkspace, ouvrez le .xcodeproj et effectuez Clean Build Folder.

Carthage → SPM

  1. Ajoutez les paquets via Xcode File → Add Package Dependency.
  2. Supprimez les dépendances du Cartfile.
  3. Supprimez les scripts de compilation Carthage de Build Phases.
  4. Videz le cache : rm -rf Carthage/ dans le terminal.

En 2025, SPM prend en charge la grande majorité des bibliothèques Swift populaires. Les exceptions sont quelques frameworks ObjC sans cartes de modules. Si une bibliothèque ne prend pas encore en charge SPM — consultez la section Installation de son README ; la plupart des auteurs ont déjà ajouté la prise en charge de SPM dans les dernières versions.

Questions fréquentes

En quoi SPM diffère-t-il de CocoaPods et Carthage ?

SPM est intégré au compilateur Swift et à Xcode, il ne nécessite pas d'installation via gem ou Homebrew. CocoaPods utilise un registre centralisé Specs et génère un espace de travail séparé. Carthage fonctionne via des frameworks sans intégration au projet. SPM est le seul gestionnaire intégré au niveau du compilateur : les dépendances sont résolues, mises en cache et compilées en parallèle du code principal.

Peut-on utiliser SPM pour des projets Objective-C ?

Oui, SPM prend en charge les projets mixtes Swift + Objective-C. Les fichiers ObjC dans un paquet SPM sont automatiquement inclus dans un Umbrella Header à condition qu'un modulemap correct existe. Cependant, SPM ne prend pas en charge les bibliothèques statiques ObjC sans carte de module. Il est recommandé de connecter les bibliothèques ObjC via SPM uniquement si elles fournissent un modulemap ou sont écrites en C pur.

Comment SPM résout-il les conflits de versions ?

SPM utilise le versionnement sémantique (SemVer). Si le paquet A nécessite Alamofire 5.8+ et le paquet B nécessite Alamofire 5.9+, SPM sélectionnera la version 5.9.x satisfaisant les deux. Si le conflit est irrésoluble (un paquet nécessite 5.x, un autre 6.x), SPM signalera une erreur. Dans ce cas, vous devez mettre à jour l'un des paquets ou modifier la dépendance vers une version compatible avec les deux exigences.

Où sont stockés les paquets SPM téléchargés ?

Sous macOS : ~Library/Caches/org.swift.swiftpm/ et ~/Library/Developer/Xcode/DerivedData/. Sous Linux : ~cache/swiftpm/. Lors des compilations, SPM met en cache le code source et les fichiers objet compilés. Pour vider complètement le cache, exécutez swift package reset — cette commande supprime le cache des dépendances et DerivedData pour le projet actuel.

SPM prend-il en charge les bibliothèques fermées (propriétaires) ?

Oui, depuis Swift 5.2, SPM prend en charge les cibles binaires (binary targets). Une bibliothèque fermée est distribuée sous forme de XCFramework, et le chemin vers le .xcframework est spécifié dans Package.swift. Le code source n'est pas divulgué. Une cible binaire est spécifiée via .binaryTarget(name: "PrivateSDK", path: "Sources/PrivateSDK.xcframework"). Cela permet de connecter des SDK commerciaux sans violer les accords de licence.

Résumé

  • SPM (Swift Package Manager) est un gestionnaire de paquets intégré à Swift qui ne nécessite aucune installation séparée et est intégré à Xcode et au compilateur.
  • Package.swift est un manifeste déclaratif écrit en Swift décrivant le nom du paquet, les plates-formes, les dépendances, les produits et les cibles de compilation.
  • SPM utilise les dépôts Git comme sources de paquets et résout les versions par SemVer, mettant en cache le code source pour des compilations ultérieures plus rapides.
  • Commandes principales : swift package init (créer un paquet), swift build (compiler), swift test (tester), swift package update (mettre à jour les dépendances).
  • Un paquet personnalisé est créé via swift package init, publié sur Git et rendu disponible aux autres projets via URL avec un tag SemVer.
  • La migration de CocoaPods/Carthage vers SPM est sûre : les dépendances peuvent coexister, la migration se fait via File → Add Package Dependency dans Xcode.
  • SPM est l'outil standard de gestion des dépendances dans l'écosystème Swift, utilisé par 67 % des développeurs iOS (Swift.org Developer Survey, 2024).

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi