Swiftが3系から4系に上がる現時点での各種パッケージマネージャを比較
Swiftが3系から4系に上がる現時点での各種パッケージマネージャを比較
iOS11が発表されXcode 9 betaをダウンロードでき、公式でSwift4.0が目前の中ついこの間にSwift.orgからマイグレーションガイドの項目が追加されていました。
Swift.org - Migrating to Swift 4
ここによるとSwift3.2、またはSwift4.0でのライブラリ配布でない場合はソースコードから直接依存させた方が良いとあります。
というのもSwift3.2からSwift4.0は互換性はあるのですが、Swift3.1以前は互換性が無いとのこと。
またSwift周りの環境が変わってきそうな中でライブラリ管理で使えるパッケージマネージャの予習・復習がてらに比較してみました。
iOS / macOSから始まりOSSになったSwiftですが、パッケージマネージャとして有名なのは以下3種類になります。
- CocoaPods
- Carthage
- Swift Package Manager
それぞれ用途ごとに3つを比較しながら詳解していきます。
前提
- Swift 4.0
- Apple Swift version 4.0 (swiftlang-900.0.43 clang-900.0.22.8)
- Xcode 9 beta 2
- coocapods 1.3.0.beta.2
- carthage 0.23.0
ソースコードの公開先
Swiftの各種パッケージマネージャは全てOSSとして公開されていて、GitHubからソースコードを確認することができます。
CocoaPods
Rubyで実装されていて、そのためかCocoaPods自体もRubyGemsの文化がそのまま引き継がれた形式になっています。
CocoaPods専用の巨大なリポジトリが存在しており、そこから指定のライブラリを取得してくる流れになっています。
Carthage
Swiftで実装されており、CocoaPodsが中央集権型のパッケージマネージャならCarthageは対照的でよりシンプルにライブラリを提供するためにGit経由でライブラリを導入します。
Swift Package Manager
Swift自体に内包されている言語として公式のパッケージマネージャになり、仕組み的にはCarthageに近くGit経由でライブラリを導入します。
他のパッケージマネージャとして違う点はiOS / macOSなどのAppleのプラットフォームには対応しておらずLinuxのみに対応しているのが大きな違いになります。
導入
CocoaPods
$ gem install cocoapods
gemからインストールします、gemの依存性を気にして間にbundlerを入れて管理するパターンも多いです。
(bundlerについては割愛)
Carthage
HomeBrew
$ brew install carthage
HomeBrewからインストールできます、他の方法だと.pkgを公開しているのでこちらからもインストールできます。
Swift Package Manager
Swift Package ManagerはSwift公式のパッケージマネージャとして言語自体に内包されているため特に導入の手順なくとも、Swiftの環境があれば使うことができます。
提供側のパッケージファイル
CocoaPods
{ライブラリ名}.podspec
https://guides.cocoapods.org/syntax/podspec.html
Pod::Spec.new do |spec| spec.name = '{ライブラリ名}' spec.version = '{Semantic Versioningなgit tag}' spec.license = { :type => '{ライセンス形式}' } spec.homepage = '{ライブラリのホームページURL}' spec.authors = { '{作成名}' => '作成者のメールアドレス' } spec.summary = '{ライブラリの概要}' spec.source = { :git => '{ソースコードのURL}', :tag => '#{spec.version}' } spec.source_files = '{ライブラリのディレクトリ内でソースコードのパスを指定}' # Sourcesの下にあるコードを指定する場合はこうなる 'Sources/**/*.{swift,h,m}' spec.dependency = '{依存するライブラリ名}' # 複数ある場合は続けて 'spec.dependency = ...' と複数行に分けて書く spec.ios.deployment_target = "{対応してる中で最低なiOS version}" spec.osx.deployment_target = "{対応してる中で最低なmacOS version}" if spec.respond_to?(:watchos) spec.watchos.deployment_target = "{対応してる中で最低なwatchOS version}" end if spec.respond_to?(:tvos) spec.tvos.deployment_target = "{対応してる中で最低なtvOS version}" end end
あとはここに記載したライブラリ名でCocoaPods側に登録をすることで
pod '{ライブラリ名}'
でCocoaPodsからライブラリを利用することができるようになります。
CocoaPods側に登録しない場合は直接GitのURLを指定することでライブラリを入れることができます。
Carthage
Swiftのdynamic libraryの仕組みを利用した配布方法を取るため提供側のパッケージファイルはありません。
なので配布する条件としては、
- ライブラリのリポジトリのrootに
{ライブラリ名}.xcproject
を用意する - dynamic framework用のスキームを用意する
- Semantic Versioningのフォーマットに沿ったgit tagを打っておく
上記を満たしていることでライブラリ利用側からCarthageを経由してライブラリを導入することができます。
Swift Package Manager
Swift Package Managerはライブラリの提供側も利用側も同じフォーマットで扱うことができます。
提供側のリポジトリのルートにPackage.swiftがあれば利用側はライブラリをSwift Package Manager経由で利用することが可能になります。
利用側のパッケージファイル
どのパッケージマネージャもパッケージング用のファイルと、その依存を固定するためのロックファイルがペアで存在しています。
それぞれ表でまとめたものがこちら
パッケージマネージャ | CocoaPods | Carthage | Swift Package Manager |
---|---|---|---|
パッケージファイル | Podfile | Cartfile | Package.swift |
ロックファイル | Podfile.lock | Cartfile.resolved | Package.pins |
それでは実際にライブラリを導入する際にどう記載していくのかを試します。
ここでは一般的によく使われる通信用のライブラリであるAlamofireのSwift4対応branch導入を例にしていきます。
CocoaPods
Podfile
target 'SampleProject' do # Comment the next line if you're not using Swift and don't want to use dynamic frameworks use_frameworks! # Pods for SampleProject pod 'Alamofire/Alamofire', :git => 'https://github.com/Alamofire/Alamofire', :branch => 'swift4' target 'SampleProjectTests' do inherit! :search_paths # Pods for testing end end
Carthage
https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile
Cartfile
github 'Alamofire/Alamofire' 'swift4'
Swift Package Manager
Package.swift
// swift-tools-version:4.0 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription let package = Package( name: "SamplePackage", products: [ // Products define the executables and libraries produced by a package, and make them visible to other packages. .library( name: "SamplePackage", targets: ["SamplePackage"]), ], dependencies: [ // Dependencies declare other packages that this package depends on. .package(url: "https://github.com/Alamofire/Alamofire.git", .branch("swift4")) ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. // Targets can depend on other targets in this package, and on products in packages which this package depends on. .target( name: "SamplePackage", dependencies: ["Alamofire"]), .testTarget( name: "SamplePackageTests", dependencies: ["SamplePackage"]), ] )
Swift4.0からSwift Package Managerのフォーマットが変わりました、従来のPackage.swiftと違う部分として新たにtargets
とproducts
が増えています。
上記はswift package init
のコマンドで生成したPackage.swiftを編集しています。
もし古いPackage.swiftも使いつつSwift4.0のPackage.swiftにも対応する場合は古いPackage.swiftには swift-tools-version
の記述を行わず新しいPackage.swiftの名前を
Package@swift-4.swift
の名前にすることでSwift3.2以前のSwiftでもそのパッケージを利用することが可能になります。
コマンド比較
一般的に使うであろうコメントでそれぞれ比較して見ました。
こうしてみるとCocoaPodsは1つのbranchで管理してるのもあり割とコマンドが充実してます。
操作 | CocoaPods | Carthage | Swift Package Manager |
---|---|---|---|
基本コマンド | pod | carthage | swift package |
インストール | pod install | carthage bootstrap | swift package resolve |
アップデート確認 | pod outdated | carthage outdated | - |
アップデート | pod update | carthage update | swift package update |
パッケージの表示 | - | - | swift package show-dependencies |
パッケージの検索 | pod search | - | - |
利用可能なパッケージの表示 | pod list | - | - |
リセット | pod deintegrate | - | swift package reset |
終わりに
段々とSwiftの環境が充実していくことが実感できますね、最近は3種のパッケージマネージャに対応してるライブラリもよく見ます。
Swift Package ManagerがAppleのプラットフォームに対応すればまた情勢が変わりそうですが、それぞれのプロジェクト用途に合わせて選択できたら良いですね。