Swift Package Managerとは
Swift製のパッケージマネージャでSwiftPMと呼ばれたりします。
CocoaPodsやCarthageとは違ってCLIアプリケーションやサーバサイドSwiftで利用されることが多い状況です。
バージョン3の情報はある程度増えてきてはいますが、現在の最新バージョンである4.0.0の情報はまだまだ少ないので、今回はSwiftPM 4を使ってCLIをツールを作ってみたいと思います。
何を作るか
こんな感じであいさつするやつを作りたいと思います。
$ hello-swift-pm
Hello, SwiftPM!
$ hello-swift-pm --name Tom
Hello, Tom!
$ hello-swift-pm --name Tom --time morning
Good morning, Tom!
$ hello-swift-pm --time evening
Good evening, SwiftPM!
やっていき
バージョンの確認
SwiftとSwiftPMのバージョンは次のような感じです。
$ swift --version
Apple Swift version 4.0.3 (swiftlang-900.0.74.1 clang-900.0.39.2)
$ swift package --version
Apple Swift Package Manager - Swift 4.0.0-dev (swiftpm-13752)
プロジェクトの新規作成
今回はhello-swift-pm
というディレクトリに作っていきます。
$ mkdir hello-swift-pm
$ cd hello-swift-pm
$ swift package init --type executable
$ tree
.
├── Package.swift
├── README.md
├── Sources
│ └── hello-swift-pm
│ └── main.swift
└── Tests
3 directories, 3 files
ビルドしてみる
デフォルトで生成されているHello, world!
アプリをビルドしてみましょう。
$ swift build
$ ./.build/debug/hello-swift-pm
Hello, world!
Xcodeプロジェクトの生成
コードの編集はXcodeでやりたいってことでXcodeプロジェクトを生成します。
しかし、これはコードからいい感じにXcodeプロジェクトを生成しているだけなので、Xcodeからはコードの編集のみを行うようにしてください。
ファイルやディレクトリを追加する場合はコマンドラインから作成し、Xcodeプロジェクトを再度生成したほうが良いです。
$ swift package generate-xcodeproj
$ open hello-swift-pm.xcodeproj/
外部依存ライブラリの指定
今回はCommander
というライブラリを用いてCLIアプリケーションを作りたいと思います。
次のような変更を加えて依存パッケージをビルドします。
// 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: "hello-swift-pm",
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
+ .package(url: "https://github.com/kylef/Commander.git", from: "0.8.0"),
],
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: "hello-swift-pm",
- dependencies: []),
+ dependencies: ["Commander"]), // ここはimportするときのパッケージ名を書く
]
)
$ swift package update
Fetching https://github.com/kylef/Commander
Fetching https://github.com/kylef/Spectre.git
Cloning https://github.com/kylef/Spectre.git
Resolving https://github.com/kylef/Spectre.git at 0.8.0
Cloning https://github.com/kylef/Commander
Resolving https://github.com/kylef/Commander at 0.8.0
ちなみに、targets
の中のdependencies
に書く名前は、リポジトリ名ではなく、import
するときのパッケージ名を書く必要があることに注意してください。
ライブラリ名とパッケージ名は同じことが多いのでハマりポイントだと思います。
(例: SwiftYaml
-> Yaml
( https://github.com/behrang/YamlSwift ))
main.swift
の実装
CLIアプリケーションのメイン部分を作っていきましょう。
Commander
がimport
できないときはXcodeプロジェクトを再生成してみると直るかも。
import Commander
enum Greeting {
enum ParseError: Error, CustomStringConvertible {
case invalidTime
var description: String {
switch self {
case .invalidTime:
return "Invalid time option"
}
}
}
static func validator(time: String) throws -> String {
switch time {
case "morning": return "Good morning, "
case "evening": return "Good evening, "
default: throw ParseError.invalidTime
}
}
}
let main = command(
Option("name", default: "SwiftPM"),
Option("time", default: "daytime", description: "morning or evening", validator: Greeting.validator)
) { name, time in
let greeting = time == "daytime" ? "Hello, " : time
print(greeting + name + "!")
}
main.run()
最後にリリースビルドして完了
$ swift build -c release
$ ./.build/release/hello-swift-pm --name Tom --time morning
Good morning, Tom!
完成品
完成品のコードはGitHubに置いています。
おわりに
今回はSwift Package Manager 4.0を使ってCLIアプリケーションを作ってみました。
最後まで読んでいただきありがとうございました。
今回はあまり難しいことはしていませんが、Package.swift
の書き方がバージョン3から少し変更されていてしっかり最新情報を追っていないとハマりそうだと思いました。
間違いや追加情報などあればコメントしていただけると嬉しいです。