SPM: шта је то, Swift Package Manager и Package.swift

Аутор: IT Sectr Објављено: 2026-02-13 Време читања: 11 мин

SPM (Swift Package Manager) — уграђени менаџер пакета екосистема Swift, развијен од стране Apple-а за аутоматизацију повезивања, изградње и ажурирања библиотека трећих страна. SPM је део Swift компајлера од верзије 3.0 (2016. година) и не захтева посебну инсталацију. За разлику од CocoaPods-а и Carthage-а, SPM је интегрисан директно са компајлером и Xcode-ом, што га чини стандардним алатом за управљање зависностима у савременим Swift пројектима. У чланку ћемо размотрити структуру Package.swift-а, SPM команде, писање сопствених пакета и миграцију са алтернативних менаџера.

Главно

  • SPM (Swift Package Manager) — уграђени менаџер пакета у Swift компајлер, који не захтева посебну инсталацију; ради на iOS, macOS, Linux и серверским платформама.
  • Package.swift — манифест фајл који описује име пакета, платформе, зависности и циљне модуле (targets) у декларативном формату.
  • SPM решава зависности по семантичком верзионисању (SemVer), кешира изворни код и гради пакете паралелно ради убрзања.
  • Команде: swift package init (креирај пакет), swift package update (ажурирај зависности), swift build (изгради), swift test (покрени тестове).
  • Миграција са CocoaPods/Carthage на SPM се врши кроз Xcode: File → Add Package Dependency, након чега се podfile и Cartfile бришу.

Шта је SPM?

SPM (Swift Package Manager) — званични менаџер пакета за језик Swift, уграђен у компајлер swiftc и развојно окружење Xcode. Омогућава програмерима да повежу библиотеке трећих страна, управљају њиховим верзијама и објављују сопствене пакете. SPM се први пут појавио у Swift 3.0 (септембар 2016) као алат командне линије, а од Xcode 11 (2019) добио је потпуну интеграцију са графичким интерфејсом — сада се зависности додају кроз мени File → Add Packages.

SPM аутоматски преузима изворни код зависности из Git репозиторијума, гради их паралелно са главним пројектом и кешира резултате како би поновне изградње биле брже. За разлику од CocoaPods-а, SPM не генерише посебан workspace (xcworkspace) — зависности постају део главног Xcode пројекта. Према истраживању Swift.org Developer Survey (2024), SPM користи 67% iOS програмера, што га чини најпопуларнијим алатом за управљање зависностима у Swift екосистему.

SPM подржава три платформе: Apple (iOS, macOS, tvOS, watchOS, visionOS), Linux (Ubuntu, CentOS, Amazon Linux) и серверски Swift (Vapor, Kitura). На Linux-у SPM ради у потпуности преко командне линије без Xcode-а.

Како ради Swift Package Manager

SPM је изграђен око три кључна концепта: пакети (packages), производи (products) и циљеви (targets). Пакет је Git репозиторијум са манифестом Package.swift. Производ је резултат изградње (библиотека или извршни фајл). Циљ је модул унутар пакета који се компајлира у јединицу изградње.

Када програмер дода зависност у Package.swift, SPM извршава следеће кораке:

  1. Клонирање — SPM преузима Git репозиторијум зависности са наведеног URL-а.
  2. Решавање верзија — анализира SemVer ознаке (нпр. 2.1.3) и бира одговарајућу верзију у оквиру наведеног опсега.
  3. Транзитивно решавање — проверава зависности зависности и гради граф без конфликата верзија.
  4. Кеширање — чува преузети изворни код у ~Library/Caches/org.swift.swiftpm/.
  5. Компајлирање — гради све циљеве пакета са заставицама главног пројекта.

Фајл Package.resolved фиксира тачне верзије свих зависности како би тим програмера радио са идентичним сетом библиотека. Овај фајл треба додати у систем контроле верзија (git).

Кључна предност SPM-а у односу на алтернативе — одсуство централизованог регистра. Пакети могу бити у било ком јавном Git репозиторијуму: GitHub, GitLab, Bitbucket, као и на сопственим Git серверима компаније. Од верзије Swift 5.2, SPM подржава бинаре зависности (binary targets) — затворене библиотеке које се дистрибуирају путем XCFramework-а без давања изворног кода.

Package.swift — манифест пројекта

Package.swift — Swift фајл који описује структуру пакета и његове зависности. Фајл се пише на самом Swift-у (не JSON, не YAML), што омогућава коришћење условне логике, израчунатих константи и функција унутар манифеста.

Основна структура 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"]
        ),
    ]
)

Размотримо кључне елементе:

  • // swift-tools-version: 5.9 — директива која означава верзију SPM-а; од ње зависи доступна синтакса манифеста.
  • name — име пакета које се приказује у Xcode-у и користи у референцама зависности.
  • platforms — минималне верзије платформи; SPM неће дозволити изградњу пакета на старијој верзији ОС-а.
  • products — оно што пакет „извози": библиотеку (.library) или извршни фајл (.executable).
  • dependencies — листа спољних пакета са URL-ом и верзијом; подржани су from:, exact:, branch:, revision:.
  • targets — циљеви изградње; сваки циљ садржи листу зависности, ресурсе и swift фајлове из одговарајућег директоријума (Sources/TargetName/).

Пример навођења тачне верзије, гране и комита:

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

Од верзије Swift 5.9, у Package.swift је додата подршка за static/framework и linkerSettings, што омогућава прецизније подешавање линковања за статичке и динамичке библиотеке.

Основне SPM команде

Swift Package Manager пружа сет команди за рад преко терминала. Команде се покрећу из коренског директоријума пакета (где се налази Package.swift).

bash
# Креирај нови пакет са библиотеком
swift package init --type library

# Креирај извршни пакет (конзолна апликација)
swift package init --type executable

# Изгради пројекат
swift build

# Изгради у release конфигурацији
swift build -c release

# Покрени тестове
swift test

# Покрени одређени тест
swift test --filter "MyLibraryTests/testExample"

# Преузми и реши зависности
swift package resolve

# Ажурирај зависности на најновије доступне верзије
swift package update

# Прикажи граф зависности
swift package show-dependencies

# Очисти кеш изградње
swift package clean

# Генериши Xcode пројекат (пре Xcode 11)
swift package generate-xcodeproj

При раду унутар Xcode-а, већина ових команди се извршава аутоматски: зависности се решавају при отварању пројекта, изградња се покреће са ⌘B, тестови са ⌘U. Међутим, познавање терминалних команди је неопходно за CI/CD пајплајнове (GitHub Actions, GitLab CI, Jenkins), где Xcode није доступан.

Команда swift package resolve креира или ажурира фајл Package.resolved. Овај фајл фиксира тачне верзије свих зависности, укључујући транзитивне, и треба га додати у git. Препоручује се покретање swift package update пре сваке нове feature гране, како би се радило са актуелним верзијама библиотека.

Креирање сопственог пакета

Креирање сопственог SPM пакета је корисно за инкапсулацију пословне логике у вишемодулним пројектима и за објављивање open-source библиотека. Размотримо процес корак по корак.

Корак 1: Иницијализација

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

Корак 2: Структура директоријума

Команда swift package init креира следећу структуру:

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

SPM аутоматски скенира директоријуме Sources/ и Tests/: сваки поддиректоријум унутар Sources одговара циљу (target).

Корак 3: Уређивање Package.swift-а

Додајмо зависности и подесимо циљне платформе:

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

Корак 4: Писање кода

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

Корак 5: Објављивање

Пошаљите пакет у Git репозиторијум и креирајте 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

Након тога, било који програмер ће моћи да повеже ваш пакет преко .package(url: "https://github.com/username/MyNetworkKit.git", from: "1.0.0").

Примери коришћења SPM-а

Пример 1: Повезивање Alamofire-а за мрежне захтеве

Alamofire — најпопуларнији HTTP клијент за Swift. Додаћемо га преко SPM-а и извршити 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) корисника")
            case .failure(let error):
                print("Грешка: \(error.localizedDescription)")
            }
        }
}

Пример 2: Swinject — убризгавање зависности

Библиотека Swinject пружа DI контејнер за Swift. Повезује се преко .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()

Пример 3: Swift-log за структурирано логирање

Пакет swift-log од Apple-а — јединствени API за логирање који подржава више бекендова (OSLog, конзола, фајлови).

swift
import Logging

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

logger.info("Мрежни захтев започет", metadata: [
    "url": "\(requestURL)",
    "method": "GET"
])

logger.warning("Време одговора премашило 2 секунде")
logger.error("Грешка при повезивању: нема интернета")

Ова три примера покривају типичне сценарије коришћења SPM-а: HTTP клијенти, DI контејнери и системска инфраструктура. Избор библиотека није случајан — Alamofire, Swinject и swift-log су међу 20 најзвезданијих Swift пакета на GitHub-у.

Миграција са CocoaPods-а и Carthage-а

Ако пројекат користи CocoaPods или Carthage, миграција на SPM се изводи у неколико корака. Процес је безбедан: SPM зависности могу коегзистирати са CocoaPods-ом и Carthage-ом у истом пројекту, што омогућава постепену миграцију.

CocoaPods → SPM

  1. У Xcode-у: File → Add Package Dependency, унесите URL пакета.
  2. Изаберите верзију и додајте пакет потребним targets-има.
  3. Након додавања свих зависности преко SPM-а, обришите редове из Podfile-а.
  4. Обришите .xcworkspace, отворите .xcodeproj и извршите Clean Build Folder.

Carthage → SPM

  1. Додајте пакете преко Xcode File → Add Package Dependency.
  2. Обришите зависности из Cartfile-а.
  3. Обришите скрипте за изградњу Carthage-а из Build Phases.
  4. Очистите кеш: rm -rf Carthage/ у терминалу.

Од 2025. године, SPM подржава огромну већину популарних Swift библиотека. Изузеци су неки ObjC фрејмворци без модулних мапа (modulemap). Ако библиотека још увек не подржава SPM — проверите одељак Installation у њеном README-у; већина аутора је већ додала подршку за SPM у најновијим верзијама.

Често постављана питања

По чему се SPM разликује од CocoaPods-а и Carthage-а?

SPM је уграђен у Swift компајлер и Xcode, не захтева инсталацију преко gem-а или Homebrew-а. CocoaPods користи централизовани регистар Specs и генерише посебан workspace. Carthage ради преко фрејмворка без интеграције са пројектом. SPM је једини менаџер интегрисан на нивоу компајлера: зависности се решавају, кеширају и граде паралелно са главним кодом.

Може ли се SPM користити за Objective-C пројекте?

Да, SPM подржава мешовите Swift + Objective-C пројекте. ObjC фајлови унутар SPM пакета аутоматски доспевају у Umbrella Header под условом исправног modulemap-а. Међутим, SPM не подржава статичке ObjC библиотеке које немају модулну мапу. Препоручује се повезивање ObjC библиотека преко SPM-а само ако пружају modulemap или су написане у чистом C-у.

Како SPM решава конфликте верзија?

SPM користи семантичко верзионисање (SemVer). Ако пакет A захтева Alamofire 5.8+, а пакет B — Alamofire 5.9+, SPM ће изабрати верзију 5.9.x која задовољава оба. Ако је конфликт нерешив (један пакет захтева 5.x, други — 6.x), SPM ће пријавити грешку. У том случају потребно је ажурирати један од пакета или пребацити зависност на верзију компатибилну са оба захтева.

Где се чувају преузети SPM пакети?

На macOS-у: ~Library/Caches/org.swift.swiftpm/ и ~/Library/Developer/Xcode/DerivedData/. На Linux-у: ~cache/swiftpm/. Приликом изградње, SPM кешира изворни код и компајлиране објектне фајлове. За потпуно чишћење кеша извршите swift package reset — ова команда брише кеш зависности и DerivedData за текући пројекат.

Да ли SPM подржава затворене (пропријетарне) библиотеке?

Да, од Swift 5.2, SPM подржава бинарне циљеве (binary targets). Затворена библиотека се испоручује као XCFramework, а у Package.swift-у се наводи путања до .xcframework-а. Изворни код се не открива. Binary target се наводи кроз .binaryTarget(name: "PrivateSDK", path: "Sources/PrivateSDK.xcframework"). Ово омогућава повезивање комерцијалних SDK-ова без кршења лиценцних уговора.

Закључци

  • SPM (Swift Package Manager) — уграђени менаџер пакета Swift који не захтева посебну инсталацију и интегрисан је са Xcode-ом и компајлером.
  • Package.swift — декларативни манифест на језику Swift који описује име пакета, платформе, зависности, производе и циљеве изградње.
  • SPM користи Git репозиторијуме као извор пакета и решава верзије по SemVer-у, кеширајући изворни код за убрзање поновних изградњи.
  • Основне команде: swift package init (креирај пакет), swift build (изгради), swift test (тестирај), swift package update (ажурирај зависности).
  • Сопствени пакет се креира кроз swift package init, објављује у Git-у и доступан је другим пројектима преко URL-а са SemVer ознаком.
  • Миграција са CocoaPods/Carthage на SPM је безбедна: зависности могу коегзистирати, миграција се врши кроз File → Add Package Dependency у Xcode-у.
  • SPM — стандард управљања зависностима у Swift екосистему, који користи 67% iOS програмера (Swift.org Developer Survey, 2024).

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође