SPM:Swift Package ManagerとPackage.swiftとは

著者: IT Sectr 公開日: 2026-02-13 読了時間: 11 分

SPM(Swift Package Manager)は、サードパーティライブラリの接続、ビルド、更新を自動化するためにAppleが開発した、Swiftエコシステムに組み込まれたパッケージマネージャーです。SPMはバージョン3.0(2016年)以降Swiftコンパイラの一部であり、別途インストールする必要はありません。CocoaPodsやCarthageとは異なり、SPMはコンパイラやXcodeと直接統合されているため、最新のSwiftプロジェクトにおける依存関係管理の標準ツールとなっています。この記事では、Package.swiftの構造、SPMコマンド、独自パッケージの作成、代替マネージャーからの移行について解説します。

重要なポイント

  • SPM(Swift Package Manager)はSwiftコンパイラに組み込まれたパッケージマネージャーで、別途インストールは不要です。iOS、macOS、Linux、サーバープラットフォームで動作します。
  • Package.swiftは、宣言形式でパッケージ名、プラットフォーム、依存関係、ターゲットモジュールを記述するマニフェストファイルです。
  • 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年9月)でコマンドラインツールとして初めて登場し、Xcode 11(2019年)以降はグラフィカルインターフェースと完全に統合され、File → Add Packagesメニューから依存関係を追加できるようになりました。

SPMはGitリポジトリから依存関係のソースコードを自動的にダウンロードし、メインプロジェクトと並行してビルドし、結果をキャッシュして後続のビルドを高速化します。CocoaPodsとは異なり、SPMは別個のワークスペース(xcworkspace)を生成せず、依存関係はメインのXcodeプロジェクトの一部になります。Swift.org Developer Survey(2024)によると、67%のiOS開発者がSPMを使用しており、Swiftエコシステムで最も人気のある依存関係管理ツールとなっています。

SPMは3つのプラットフォームをサポートしています:Apple(iOS、macOS、tvOS、watchOS、visionOS)、Linux(Ubuntu、CentOS、Amazon Linux)、サーバーサイドSwift(Vapor、Kitura)。Linuxでは、SPMはXcodeなしで完全にコマンドラインで動作します。

Swift Package Managerの仕組み

SPMは3つの主要な概念に基づいて構築されています:パッケージ(packages)、プロダクト(products)、ターゲット(targets)。パッケージはPackage.swiftマニフェストを持つGitリポジトリです。プロダクトはビルド結果(ライブラリまたは実行可能ファイル)です。ターゲットはパッケージ内のモジュールで、ビルド単位にコンパイルされます。

開発者がPackage.swiftに依存関係を追加すると、SPMは以下の手順を実行します:

  1. クローン — SPMは指定されたURLから依存関係のGitリポジトリをダウンロードします。
  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はバイナリ依存関係(バイナリターゲット)をサポートしています。これはソースコードを提供せずに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は古いOSバージョンでのパッケージビルドを許可しません。
  • products — パッケージが「エクスポート」するもの:ライブラリ(.library)または実行可能ファイル(.executable)。
  • dependencies — URLとバージョンを持つ外部パッケージのリスト。from:exact:branch:revision:をサポート。
  • targets — ビルドターゲット。各ターゲットには、対応するディレクトリ(Sources/TargetName/)からの依存関係、リソース、swiftファイルのリストが含まれます。

正確なバージョン、ブランチ、コミットを指定する例:

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 frameworklinkerSettingsのサポートを追加し、静的および動的ライブラリのより精密なリンカー設定が可能になりました。

SPMの基本コマンド

Swift Package Managerはターミナルで作業するためのコマンドセットを提供します。コマンドはパッケージのルートディレクトリ(Package.swiftがある場所)から実行します。

bash
# ライブラリ付きの新規パッケージを作成
swift package init --type library

# 実行可能パッケージを作成(コンソールアプリケーション)
swift package init --type executable

# プロジェクトをビルド
swift build

# リリース構成でビルド
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でテストが開始されます。ただし、Xcodeが利用できないCI/CDパイプライン(GitHub Actions、GitLab CI、Jenkins)ではターミナルコマンドの知識が必要です。

swift package resolveコマンドはPackage.resolvedファイルを作成または更新します。このファイルは推移的依存関係を含むすべての依存関係の正確なバージョンを固定し、gitに追加する必要があります。最新のライブラリバージョンで作業するために、新しい機能ブランチごとにswift package updateを実行することをお勧めします。

独自パッケージの作成

独自のSPMパッケージを作成すると、マルチモジュールプロジェクトでビジネスロジックをカプセル化したり、オープンソースライブラリを公開したりするのに便利です。ステップバイステップで見ていきましょう。

ステップ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内の各サブディレクトリがターゲットに対応します。

ステップ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はSwiftで最も人気のあるHTTPクライアントです。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ライブラリはSwift用のDIコンテナを提供します。.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

Appleのswift-logパッケージは、複数のバックエンド(OSLog、コンソール、ファイル)をサポートする統一ロギングAPIを提供します。

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("接続エラー:インターネットなし")

これら3つの例は、SPMの典型的な使用シナリオ(HTTPクライアント、DIコンテナ、システムインフラストラクチャ)をカバーしています。ライブラリの選択は偶然ではありません。Alamofire、Swinject、swift-logはGitHubで最もスターの多いSwiftパッケージトップ20に含まれています。

CocoaPodsおよびCarthageからの移行

プロジェクトがCocoaPodsまたはCarthageを使用している場合、SPMへの移行は数ステップで完了します。このプロセスは安全で、SPMの依存関係は同じプロジェクト内でCocoaPodsやCarthageと共存できるため、段階的な移行が可能です。

CocoaPods → SPM

  1. Xcodeで:File → Add Package Dependency、パッケージのURLを入力します。
  2. バージョンを選択し、必要なターゲットにパッケージを追加します。
  3. SPMですべての依存関係を追加した後、Podfileから行を削除します。
  4. .xcworkspaceを削除し、.xcodeprojを開いてClean Build Folderを実行します。

Carthage → SPM

  1. Xcode File → Add Package Dependencyからパッケージを追加します。
  2. Cartfileから依存関係を削除します。
  3. Build PhasesからCarthageビルドスクリプトを削除します。
  4. キャッシュをクリア:ターミナルでrm -rf Carthage/を実行します。

2025年現在、SPMは大多数の一般的なSwiftライブラリをサポートしています。例外は、モジュールマップのない一部のObjCフレームワークです。ライブラリがまだSPMをサポートしていない場合は、READMEのInstallationセクションを確認してください。ほとんどの作成者は最新バージョンでSPMサポートを既に追加しています。

よくある質問

SPMはCocoaPodsやCarthageとどう違うのですか?

SPMはSwiftコンパイラとXcodeに組み込まれており、gemやHomebrewによるインストールは不要です。CocoaPodsは集中型のSpecsレジストリを使用し、別個のワークスペースを生成します。Carthageはプロジェクトとの統合なしにフレームワークで動作します。SPMはコンパイラレベルで統合された唯一のマネージャーであり、依存関係はメインコードと並行して解決、キャッシュ、ビルドされます。

Objective-CプロジェクトでSPMを使用できますか?

はい、SPMはSwift + Objective-Cの混合プロジェクトをサポートしています。SPMパッケージ内のObjCファイルは、正しいmodulemapが存在すれば自動的にUmbrella Headerに含まれます。ただし、SPMはモジュールマップのない静的ObjCライブラリをサポートしていません。ObjCライブラリは、modulemapを提供するか純粋なCで書かれている場合にのみSPM経由で接続することをお勧めします。

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はバイナリターゲットをサポートしています。クローズドソースライブラリはXCFrameworkとして配布され、.xcframeworkへのパスがPackage.swiftで指定されます。ソースコードは公開されません。バイナリターゲットは.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に公開してSemVerタグ付きURLで他のプロジェクトが利用できるようにします。
  • CocoaPods/CarthageからSPMへの移行は安全です。依存関係は共存でき、移行はXcodeのFile → Add Package Dependencyから行います。
  • SPMはSwiftエコシステムの標準依存関係管理ツールで、iOS開発者の67%が使用しています(Swift.org Developer Survey 2024)。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください