SPM: co to jest, Swift Package Manager i Package.swift

Autor: IT Sectr Opublikowano: 2026-02-13 Czas czytania: 11 min

SPM (Swift Package Manager) — wbudowany menedżer pakietów ekosystemu Swift, opracowany przez Apple do automatyzacji podłączania, budowania i aktualizowania bibliotek zewnętrznych. SPM wchodzi w skład kompilatora Swift od wersji 3.0 (2016 rok) i nie wymaga osobnej instalacji. W przeciwieństwie do CocoaPods i Carthage, SPM jest zintegrowany bezpośrednio z kompilatorem i Xcode, co czyni go standardowym narzędziem do zarządzania zależnościami w nowoczesnych projektach Swift. W artykule omówimy budowę Package.swift, polecenia SPM, tworzenie własnych pakietów i migrację z alternatywnych menedżerów.

Najważniejsze

  • SPM (Swift Package Manager) — wbudowany w kompilator Swift menedżer pakietów, niewymagający osobnej instalacji; działa na iOS, macOS, Linux i platformach serwerowych.
  • Package.swift — plik manifestu, opisujący nazwę pakietu, platformy, zależności i moduły docelowe (targets) w formacie deklaratywnym.
  • SPM rozwiązuje zależności według semantycznego versionowania (SemVer), buforuje kod źródłowy i buduje pakiety równolegle dla przyspieszenia.
  • Polecenia: swift package init (utwórz pakiet), swift package update (aktualizuj zależności), swift build (buduj), swift test (uruchom testy).
  • Migracja z CocoaPods/Carthage na SPM odbywa się przez Xcode: File → Add Package Dependency, po czym podfile i Cartfile są usuwane.

Co to jest SPM?

SPM (Swift Package Manager) — oficjalny menedżer pakietów dla języka Swift, wbudowany w kompilator swiftc i środowisko programistyczne Xcode. Pozwala programistom podłączać biblioteki zewnętrzne, zarządzać ich wersjami i publikować własne pakiety. SPM pojawił się po raz pierwszy w Swift 3.0 (wrzesień 2016) jako narzędzie wiersza poleceń, a od Xcode 11 (2019) uzyskał pełną integrację z interfejsem graficznym — teraz zależności dodaje się przez menu File → Add Packages.

SPM automatycznie pobiera kod źródłowy zależności z repozytoriów Git, buduje je równolegle z głównym projektem i buforuje wyniki, aby kolejne kompilacje były szybsze. W przeciwieństwie do CocoaPods, SPM nie generuje osobnego workspace (xcworkspace) — zależności stają się częścią głównego projektu Xcode. Według ankiety Swift.org Developer Survey (2024), SPM używa 67% programistów iOS, co czyni go najpopularniejszym narzędziem do zarządzania zależnościami w ekosystemie Swift.

SPM obsługuje trzy platformy: Apple (iOS, macOS, tvOS, watchOS, visionOS), Linux (Ubuntu, CentOS, Amazon Linux) i serwerowy Swift (Vapor, Kitura). Na Linuxie SPM działa w pełni przez wiersz poleceń bez Xcode.

Jak działa Swift Package Manager

SPM jest zbudowany wokół trzech kluczowych koncepcji: pakiety (packages), produkty (products) i cele (targets). Pakiet to repozytorium Git z manifestem Package.swift. Produkt to wynik kompilacji (biblioteka lub plik wykonywalny). Cel to moduł wewnątrz pakietu, który jest kompilowany jako jednostka.

Gdy programista dodaje zależność w Package.swift, SPM wykonuje następujące kroki:

  1. Klonowanie — SPM pobiera repozytorium Git zależności pod wskazanym URL.
  2. Rozwiązywanie wersji — analizuje tagi SemVer (np. 2.1.3) i wybiera odpowiednią wersję w zadanym zakresie.
  3. Rozwiązywanie tranzatywne — sprawdza zależności zależności i buduje graf bez konfliktów wersji.
  4. Buforowanie — zapisuje pobrany kod źródłowy w ~Library/Caches/org.swift.swiftpm/.
  5. Kompilacja — buduje wszystkie cele pakietu z flagami głównego projektu.

Plik Package.resolved ustala dokładne wersje wszystkich zależności, aby zespół programistów pracował z identycznym zestawem bibliotek. Ten plik powinien być dodany do systemu kontroli wersji (git).

Kluczową zaletą SPM w porównaniu z analogami jest brak scentralizowanego rejestru. Pakiety mogą znajdować się w dowolnym publicznym repozytorium Git: GitHub, GitLab, Bitbucket, a także na własnych serwerach Git firmy. Od wersji Swift 5.2 SPM obsługuje zależności binarne (binary targets) — zamknięte biblioteki dystrybuowane przez XCFramework bez udostępniania kodu źródłowego.

Package.swift — manifest projektu

Package.swift — to plik Swift, który opisuje strukturę pakietu i jego zależności. Plik jest pisany w samym Swift (nie JSON, nie YAML), co umożliwia używanie logiki warunkowej, obliczanych stałych i funkcji wewnątrz manifestu.

Podstawowa struktura 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"]
        ),
    ]
)

Omówimy kluczowe elementy:

  • // swift-tools-version: 5.9 — dyrektywa wskazująca wersję SPM; od niej zależy dostępna składnia manifestu.
  • name — nazwa pakietu, wyświetlana w Xcode i używana w odnośnikach zależności.
  • platforms — minimalne wersje platform; SPM nie pozwoli zbudować pakietu na starszej wersji systemu.
  • products — co pakiet „eksportuje": bibliotekę (.library) lub plik wykonywalny (.executable).
  • dependencies — lista pakietów zewnętrznych z URL i wersją; obsługiwane są from:, exact:, branch:, revision:.
  • targets — cele kompilacji; każdy cel zawiera listę zależności, zasoby i pliki swift z odpowiedniego katalogu (Sources/TargetName/).

Przykład podania dokładnej wersji, gałęzi i commita:

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"),
]

Od wersji Swift 5.9 w Package.swift dodano obsługę static/framework i linkerSettings, co pozwala precyzyjniej konfigurować linkowanie dla bibliotek statycznych i dynamicznych.

Podstawowe polecenia SPM

Swift Package Manager udostępnia zestaw poleceń do pracy przez terminal. Polecenia uruchamia się z katalogu głównego pakietu (tam, gdzie znajduje się Package.swift).

bash
# Utwórz nowy pakiet z biblioteką
swift package init --type library

# Utwórz pakiet wykonywalny (aplikacja konsolowa)
swift package init --type executable

# Zbuduj projekt
swift build

# Zbuduj w konfiguracji release
swift build -c release

# Uruchom testy
swift test

# Uruchom konkretny test
swift test --filter "MyLibraryTests/testExample"

# Pobierz i rozwiąż zależności
swift package resolve

# Aktualizuj zależności do najnowszych dostępnych wersji
swift package update

# Pokaż graf zależności
swift package show-dependencies

# Wyczyść cache kompilacji
swift package clean

# Wygeneruj projekt Xcode (przed Xcode 11)
swift package generate-xcodeproj

Podczas pracy w Xcode większość tych poleceń jest wykonywana automatycznie: zależności są rozwiązywane przy otwieraniu projektu, kompilacja uruchamiana przez ⌘B, testy przez ⌘U. Jednak znajomość poleceń terminalowych jest niezbędna w pipeline'ach CI/CD (GitHub Actions, GitLab CI, Jenkins), gdzie Xcode nie jest dostępny.

Polecenie swift package resolve tworzy lub aktualizuje plik Package.resolved. Ten plik ustala dokładne wersje wszystkich zależności, w tym tranzatywnych, i powinien być dodany do git. Zaleca się uruchamianie swift package update przed każdą nową gałęzią feature, aby pracować z aktualnymi wersjami bibliotek.

Tworzenie własnego pakietu

Tworzenie własnego pakietu SPM jest przydatne do enkapsulacji logiki biznesowej w projektach wielomodułowych oraz do publikowania bibliotek open-source. Omówimy proces krok po kroku.

Krok 1: Inicjalizacja

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

Krok 2: Struktura katalogów

Polecenie swift package init tworzy następującą strukturę:

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

SPM automatycznie skanuje katalogi Sources/ i Tests/: każdy podkatalog wewnątrz Sources odpowiada celowi (target).

Krok 3: Edycja Package.swift

Dodamy zależności i skonfigurujemy platformy docelowe:

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"]
        ),
    ]
)

Krok 4: Pisanie kodu

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
    }
}

Krok 5: Publikacja

Wypchnij pakiet do repozytorium Git i utwórz 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

Po tym każdy programista będzie mógł podłączyć Twój pakiet przez .package(url: "https://github.com/username/MyNetworkKit.git", from: "1.0.0").

Przykłady użycia SPM

Przykład 1: Podłączenie Alamofire do zapytań sieciowych

Alamofire — najpopularniejszy klient HTTP dla Swift. Dodamy go przez SPM i wykonamy zapytanie 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("Pobrano \(users.count) użytkowników")
            case .failure(let error):
                print("Błąd: \(error.localizedDescription)")
            }
        }
}

Przykład 2: Swinject — wstrzykiwanie zależności

Biblioteka Swinject udostępnia kontener DI dla Swift. Podłączana przez .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()

Przykład 3: Swift-log do strukturalnego logowania

Pakiet swift-log od Apple — jednolite API logowania, obsługujące wiele backendów (OSLog, konsola, pliki).

swift
import Logging

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

logger.info("Zapytanie sieciowe rozpoczęte", metadata: [
    "url": "\(requestURL)",
    "method": "GET"
])

logger.warning("Czas odpowiedzi przekroczył 2 sekundy")
logger.error("Błąd połączenia: brak internetu")

Te trzy przykłady pokrywają typowe scenariusze użycia SPM: klienty HTTP, kontenery DI i infrastrukturę systemową. Wybór bibliotek nie jest przypadkowy — Alamofire, Swinject i swift-log znajdują się w top 20 najpopularniejszych pakietów Swift na GitHub.

Migracja z CocoaPods i Carthage

Jeśli projekt używa CocoaPods lub Carthage, migracja na SPM odbywa się w kilku krokach. Proces jest bezpieczny: zależności SPM mogą współistnieć z CocoaPods i Carthage w jednym projekcie, co pozwala na stopniową migrację.

CocoaPods → SPM

  1. W Xcode: File → Add Package Dependency, wprowadź URL pakietu.
  2. Wybierz wersję i dodaj pakiet do odpowiednich targets.
  3. Po dodaniu wszystkich zależności przez SPM usuń linie z Podfile.
  4. Usuń .xcworkspace, otwórz .xcodeproj i wykonaj Clean Build Folder.

Carthage → SPM

  1. Dodaj pakiety przez Xcode File → Add Package Dependency.
  2. Usuń zależności z Cartfile.
  3. Usuń skrypty budowania Carthage z Build Phases.
  4. Wyczyść cache: rm -rf Carthage/ w terminalu.

Na 2025 rok SPM obsługuje zdecydowaną większość popularnych bibliotek Swift. Wyjątkiem są niektóre frameworki ObjC bez map modułów (modulemap). Jeśli biblioteka jeszcze nie obsługuje SPM — sprawdź sekcję Installation w jej README; większość autorów dodała już obsługę SPM w najnowszych wersjach.

Często zadawane pytania

Czym SPM różni się od CocoaPods i Carthage?

SPM jest wbudowany w kompilator Swift i Xcode, nie wymaga instalacji przez gem lub Homebrew. CocoaPods używa scentralizowanego rejestru Specs i generuje osobny workspace. Carthage działa przez frameworki bez integracji z projektem. SPM to jedyny menedżer zintegrowany na poziomie kompilatora: zależności są rozwiązywane, buforowane i budowane równolegle z głównym kodem.

Czy można używać SPM dla projektów Objective-C?

Tak, SPM obsługuje projekty mieszane Swift + Objective-C. Pliki ObjC wewnątrz pakietu SPM automatycznie trafiają do Umbrella Header pod warunkiem poprawnego modulemap. Jednak SPM nie obsługuje statycznych bibliotek ObjC, które nie mają mapy modułów. Zaleca się podłączanie bibliotek ObjC przez SPM tylko jeśli udostępniają modulemap lub są napisane w czystym C.

Jak SPM rozwiązuje konflikty wersji?

SPM używa semantycznego versionowania (SemVer). Jeśli pakiet A wymaga Alamofire 5.8+, a pakiet B — Alamofire 5.9+, SPM wybierze wersję 5.9.x spełniającą oba wymagania. Jeśli konflikt jest nierozwiązywalny (jeden pakiet wymaga 5.x, drugi — 6.x), SPM zgłosi błąd. W takim przypadku należy zaktualizować jeden z pakietów lub przełączyć zależność na wersję kompatybilną z oboma wymaganiami.

Gdzie przechowywane są pobrane pakiety SPM?

Na macOS: ~Library/Caches/org.swift.swiftpm/ i ~/Library/Developer/Xcode/DerivedData/. Na Linux: ~cache/swiftpm/. Podczas budowania SPM buforuje kod źródłowy i skompilowane pliki obiektowe. Aby całkowicie wyczyścić cache, wykonaj swift package reset — to polecenie usuwa cache zależności i DerivedData dla bieżącego projektu.

Czy SPM obsługuje zamknięte (proprietarne) biblioteki?

Tak, od Swift 5.2 SPM obsługuje cele binarne (binary targets). Zamknięta biblioteka jest dostarczana jako XCFramework, a w Package.swift podaje się ścieżkę do .xcframework. Kod źródłowy nie jest ujawniany. Binary target jest określany przez .binaryTarget(name: "PrivateSDK", path: "Sources/PrivateSDK.xcframework"). Pozwala to podłączać komercyjne SDK bez naruszania umów licencyjnych.

Podsumowanie

  • SPM (Swift Package Manager) — wbudowany menedżer pakietów Swift, który nie wymaga osobnej instalacji i jest zintegrowany z Xcode i kompilatorem.
  • Package.swift — deklaratywny manifest w języku Swift, opisujący nazwę pakietu, platformy, zależności, produkty i cele kompilacji.
  • SPM używa repozytoriów Git jako źródła pakietów i rozwiązuje wersje według SemVer, buforując kod źródłowy dla przyspieszenia kolejnych kompilacji.
  • Podstawowe polecenia: swift package init (utwórz pakiet), swift build (zbuduj), swift test (przetestuj), swift package update (aktualizuj zależności).
  • Własny pakiet tworzy się przez swift package init, publikuje w Git i jest dostępny dla innych projektów przez URL z tagiem SemVer.
  • Migracja z CocoaPods/Carthage na SPM jest bezpieczna: zależności mogą współistnieć, migracja odbywa się przez File → Add Package Dependency w Xcode.
  • SPM — standard zarządzania zależnościami w ekosystemie Swift, używany przez 67% programistów iOS (Swift.org Developer Survey, 2024).

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również