SPM: o que é, Swift Package Manager e Package.swift

Autor: IT Sectr Publicado: 2026-02-13 Tempo de leitura: 11 min

SPM (Swift Package Manager) é um gerenciador de pacotes integrado ao ecossistema Swift, desenvolvido pela Apple para automatizar a conexão, compilação e atualização de bibliotecas de terceiros. O SPM faz parte do compilador Swift desde a versão 3.0 (2016) e não requer instalação separada. Ao contrário do CocoaPods e Carthage, o SPM se integra diretamente ao compilador e ao Xcode, tornando-se a ferramenta padrão de gerenciamento de dependências em projetos Swift modernos. Neste artigo, analisaremos a estrutura do Package.swift, comandos do SPM, criação de pacotes próprios e migração de gerenciadores alternativos.

Pontos principais

  • SPM (Swift Package Manager) é um gerenciador de pacotes integrado ao compilador Swift que não requer instalação separada; funciona em iOS, macOS, Linux e plataformas servidor.
  • Package.swift é um arquivo de manifesto que descreve o nome do pacote, plataformas, dependências e módulos alvo (targets) em formato declarativo.
  • SPM resolve dependências por versionamento semântico (SemVer), armazena em cache o código fonte e compila pacotes em paralelo para maior velocidade.
  • Comandos: swift package init (criar pacote), swift package update (atualizar dependências), swift build (compilar), swift test (executar testes).
  • A migração de CocoaPods/Carthage para SPM é feita via Xcode: File → Add Package Dependency, após o que o podfile e o Cartfile são removidos.

O que é SPM?

SPM (Swift Package Manager) é o gerenciador oficial de pacotes para a linguagem Swift, integrado ao compilador swiftc e ao ambiente de desenvolvimento Xcode. Ele permite que desenvolvedores adicionem bibliotecas de terceiros, gerenciem suas versões e publiquem seus próprios pacotes. O SPM apareceu pela primeira vez no Swift 3.0 (setembro de 2016) como ferramenta de linha de comando e, a partir do Xcode 11 (2019), recebeu integração completa com a interface gráfica — as dependências agora são adicionadas através do menu File → Add Packages.

O SPM baixa automaticamente o código fonte das dependências de repositórios Git, compila-os em paralelo com o projeto principal e armazena em cache os resultados para que compilações subsequentes sejam mais rápidas. Ao contrário do CocoaPods, o SPM não gera um workspace separado (xcworkspace) — as dependências se tornam parte do projeto principal do Xcode. De acordo com a pesquisa Swift.org Developer Survey (2024), 67% dos desenvolvedores iOS usam o SPM, tornando-o a ferramenta de gerenciamento de dependências mais popular do ecossistema Swift.

O SPM suporta três plataformas: Apple (iOS, macOS, tvOS, watchOS, visionOS), Linux (Ubuntu, CentOS, Amazon Linux) e Swift do lado do servidor (Vapor, Kitura). No Linux, o SPM funciona inteiramente via linha de comando sem Xcode.

Como funciona o Swift Package Manager

O SPM é construído em torno de três conceitos-chave: pacotes (packages), produtos (products) e alvos (targets). Um pacote é um repositório Git com um manifesto Package.swift. Um produto é o resultado da compilação (uma biblioteca ou um executável). Um alvo é um módulo dentro do pacote que compila em uma unidade de compilação.

Quando um desenvolvedor adiciona uma dependência ao Package.swift, o SPM executa as seguintes etapas:

  1. Clonagem — o SPM baixa o repositório Git da dependência a partir da URL especificada.
  2. Resolução de versões — analisa as tags SemVer (por exemplo, 2.1.3) e seleciona a versão apropriada dentro do intervalo especificado.
  3. Resolução transitiva — verifica as dependências das dependências e constrói um grafo de versões sem conflitos.
  4. Cache — salva o código fonte baixado em ~Library/Caches/org.swift.swiftpm/.
  5. Compilação — compila todos os alvos do pacote com as flags do projeto principal.

O arquivo Package.resolved fixa as versões exatas de todas as dependências para que a equipe de desenvolvimento trabalhe com um conjunto idêntico de bibliotecas. Este arquivo deve ser adicionado ao controle de versão (git).

Uma vantagem chave do SPM sobre alternativas é a ausência de um registro centralizado. Os pacotes podem residir em qualquer repositório Git público: GitHub, GitLab, Bitbucket, bem como em servidores Git privados da empresa. Desde o Swift 5.2, o SPM suporta dependências binárias (binary targets) — bibliotecas fechadas distribuídas como XCFramework sem fornecer código fonte.

Package.swift — manifesto do projeto

Package.swift é um arquivo Swift que descreve a estrutura do pacote e suas dependências. O arquivo é escrito no próprio Swift (não JSON ou YAML), o que permite usar lógica condicional, constantes calculadas e funções dentro do manifesto.

Estrutura básica do 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"]
        ),
    ]
)

Vamos analisar os elementos-chave:

  • // swift-tools-version: 5.9 — diretiva que especifica a versão do SPM; a sintaxe disponível do manifesto depende dela.
  • name — nome do pacote, exibido no Xcode e usado nos links de dependências.
  • platforms — versões mínimas das plataformas; o SPM não permitirá compilar o pacote em uma versão de SO mais antiga.
  • products — o que o pacote "exporta": uma biblioteca (.library) ou um executável (.executable).
  • dependencies — lista de pacotes externos com URL e versão; suporta from:, exact:, branch:, revision:.
  • targets — alvos de compilação; cada alvo contém uma lista de dependências, recursos e arquivos swift do diretório correspondente (Sources/TargetName/).

Exemplo de especificação de versão exata, branch e 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"),
]

Desde o Swift 5.9, o Package.swift adicionou suporte para static framework e linkerSettings, permitindo uma configuração mais precisa do linker para bibliotecas estáticas e dinâmicas.

Comandos básicos do SPM

O Swift Package Manager fornece um conjunto de comandos para trabalhar através do terminal. Os comandos são executados a partir do diretório raiz do pacote (onde o Package.swift está localizado).

bash
# Criar um novo pacote com uma biblioteca
swift package init --type library

# Criar um pacote executável (aplicativo de console)
swift package init --type executable

# Compilar o projeto
swift build

# Compilar em configuração de release
swift build -c release

# Executar testes
swift test

# Executar um teste específico
swift test --filter "MyLibraryTests/testExample"

# Baixar e resolver dependências
swift package resolve

# Atualizar dependências para as últimas versões disponíveis
swift package update

# Mostrar grafo de dependências
swift package show-dependencies

# Limpar cache de compilação
swift package clean

# Gerar projeto Xcode (antes do Xcode 11)
swift package generate-xcodeproj

Ao trabalhar dentro do Xcode, a maioria desses comandos é executada automaticamente: as dependências são resolvidas ao abrir o projeto, a compilação inicia com ⌘B, os testes com ⌘U. No entanto, conhecer os comandos de terminal é necessário para pipelines de CI/CD (GitHub Actions, GitLab CI, Jenkins) onde o Xcode não está disponível.

O comando swift package resolve cria ou atualiza o arquivo Package.resolved. Este arquivo fixa as versões exatas de todas as dependências, incluindo as transitivas, e deve ser adicionado ao git. Recomenda-se executar swift package update antes de cada nova branch de funcionalidade para trabalhar com versões atualizadas das bibliotecas.

Criação do seu próprio pacote

Criar seu próprio pacote SPM é útil para encapsular lógica de negócios em projetos multimódulo e para publicar bibliotecas de código aberto. Vamos ver o processo passo a passo.

Passo 1: Inicialização

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

Passo 2: Estrutura de diretórios

O comando swift package init cria a seguinte estrutura:

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

O SPM examina automaticamente os diretórios Sources/ e Tests/: cada subdiretório dentro de Sources corresponde a um alvo (target).

Passo 3: Editar Package.swift

Vamos adicionar dependências e configurar as plataformas alvo:

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

Passo 4: Escrever código

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

Passo 5: Publicação

Envie o pacote para um repositório Git e crie uma 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

Depois disso, qualquer desenvolvedor pode adicionar seu pacote usando .package(url: "https://github.com/username/MyNetworkKit.git", from: "1.0.0").

Exemplos de uso do SPM

Exemplo 1: Adicionar Alamofire para requisições de rede

Alamofire é o cliente HTTP mais popular para Swift. Vamos adicioná-lo via SPM e fazer uma requisição 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("Recebidos (users.count) usuários")
            case .failure(let error):
                print("Erro: (error.localizedDescription)")
            }
        }
}

Exemplo 2: Swinject — injeção de dependência

A biblioteca Swinject fornece um contêiner DI para Swift. É adicionada 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()

Exemplo 3: Swift-log para registro estruturado

O pacote swift-log da Apple fornece uma API de registro unificada que suporta múltiplos backends (OSLog, console, arquivos).

swift
import Logging

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

logger.info("Requisição de rede iniciada", metadata: [
    "url": "(requestURL)",
    "method": "GET"
])

logger.warning("Tempo de resposta excedeu 2 segundos")
logger.error("Erro de conexão: sem internet")

Estes três exemplos cobrem cenários típicos de uso do SPM: clientes HTTP, contêineres DI e infraestrutura de sistema. A seleção de bibliotecas não é acidental — Alamofire, Swinject e swift-log estão entre os 20 pacotes Swift com mais estrelas no GitHub.

Migração do CocoaPods e Carthage

Se seu projeto usa CocoaPods ou Carthage, a migração para SPM é feita em poucos passos. O processo é seguro: as dependências do SPM podem coexistir com CocoaPods e Carthage no mesmo projeto, permitindo migração gradual.

CocoaPods → SPM

  1. No Xcode: File → Add Package Dependency, insira a URL do pacote.
  2. Selecione a versão e adicione o pacote aos targets necessários.
  3. Após adicionar todas as dependências via SPM, remova as linhas do Podfile.
  4. Remova o .xcworkspace, abra o .xcodeproj e execute Clean Build Folder.

Carthage → SPM

  1. Adicione os pacotes via Xcode File → Add Package Dependency.
  2. Remova as dependências do Cartfile.
  3. Remova os scripts de compilação do Carthage do Build Phases.
  4. Limpe o cache: rm -rf Carthage/ no terminal.

A partir de 2025, o SPM suporta a grande maioria das bibliotecas Swift populares. Exceções são alguns frameworks ObjC sem mapas de módulo. Se uma biblioteca ainda não suporta SPM — verifique a seção Installation no README dela; a maioria dos autores já adicionou suporte SPM nas versões mais recentes.

Perguntas frequentes

Como o SPM difere do CocoaPods e Carthage?

O SPM está integrado ao compilador Swift e ao Xcode, não requer instalação via gem ou Homebrew. O CocoaPods usa um registro centralizado Specs e gera um workspace separado. O Carthage funciona através de frameworks sem integração com o projeto. O SPM é o único gerenciador integrado no nível do compilador: as dependências são resolvidas, armazenadas em cache e compiladas em paralelo com o código principal.

Posso usar SPM para projetos Objective-C?

Sim, o SPM suporta projetos mistos Swift + Objective-C. Arquivos ObjC dentro de um pacote SPM são automaticamente incluídos em um Umbrella Header desde que exista um modulemap correto. No entanto, o SPM não suporta bibliotecas estáticas ObjC que não possuam um mapa de módulo. Recomenda-se conectar bibliotecas ObjC via SPM apenas se elas fornecerem um modulemap ou forem escritas em C puro.

Como o SPM resolve conflitos de versão?

O SPM usa versionamento semântico (SemVer). Se o pacote A requer Alamofire 5.8+ e o pacote B requer Alamofire 5.9+, o SPM selecionará a versão 5.9.x que satisfaz ambos. Se o conflito for irreconciliável (um pacote requer 5.x, outro requer 6.x), o SPM reportará um erro. Nesse caso, você precisa atualizar um dos pacotes ou alterar a dependência para uma versão compatível com ambos os requisitos.

Onde os pacotes SPM baixados são armazenados?

No macOS: ~Library/Caches/org.swift.swiftpm/ e ~/Library/Developer/Xcode/DerivedData/. No Linux: ~cache/swiftpm/. Durante as compilações, o SPM armazena em cache o código fonte e os arquivos objeto compilados. Para limpar totalmente o cache, execute swift package reset — este comando remove o cache de dependências e o DerivedData do projeto atual.

O SPM suporta bibliotecas fechadas (proprietárias)?

Sim, desde o Swift 5.2 o SPM suporta alvos binários (binary targets). Uma biblioteca fechada é distribuída como XCFramework, e o caminho para o .xcframework é especificado no Package.swift. O código fonte não é exposto. Um alvo binário é especificado via .binaryTarget(name: "PrivateSDK", path: "Sources/PrivateSDK.xcframework"). Isso permite conectar SDKs comerciais sem violar acordos de licença.

Resumo

  • SPM (Swift Package Manager) é um gerenciador de pacotes integrado ao Swift que não requer instalação separada e é integrado ao Xcode e ao compilador.
  • Package.swift é um manifesto declarativo escrito em Swift que descreve o nome do pacote, plataformas, dependências, produtos e alvos de compilação.
  • SPM usa repositórios Git como fontes de pacotes e resolve versões via SemVer, armazenando em cache o código fonte para compilações subsequentes mais rápidas.
  • Comandos principais: swift package init (criar pacote), swift build (compilar), swift test (testar), swift package update (atualizar dependências).
  • Um pacote personalizado é criado via swift package init, publicado no Git e disponibilizado para outros projetos via URL com tag SemVer.
  • A migração de CocoaPods/Carthage para SPM é segura: as dependências podem coexistir, a migração é feita via File → Add Package Dependency no Xcode.
  • SPM é a ferramenta padrão de gerenciamento de dependências no ecossistema Swift, usada por 67% dos desenvolvedores iOS (Swift.org Developer Survey, 2024).

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também