この記事の要点
swift runコマンドに--replオプションが追加され、パッケージのライブラリターゲットを import できる状態で Swift REPL を起動できるようになりました。捨てるためのパッケージや Xcode プロジェクトを用意しなくても、ライブラリの動作を REPL で手軽に試せます。- Swift REPL はもともと
FoundationやDispatchなどのコアライブラリや、macOS のDarwin/ Linux のGlibcといったシステムモジュールを import できます。さらに、適切なコンパイラ引数を与えればあらゆる Swift モジュールを読み込めます。Swift Package Manager はこの仕組みを活用し、パッケージのライブラリターゲットを import するのに必要なコンパイラ引数を REPL に渡して起動します。 - 仕組みとしては、ライブラリターゲットとその依存のヘッダ検索パスを REPL に与え、あわせてすべてのライブラリターゲットを含む共有動的ライブラリを構築して、実行時にシンボルを読み込めるようにしています。
swift run –repl の使い方
パッケージのディレクトリで swift run --repl を実行すると、パッケージがコンパイルされ、そのライブラリターゲットを import できる状態で Swift REPL が起動します。
例として、YAML を扱うパッケージ Yams を試してみます。
$ git clone https://github.com/jpsim/Yams
$ cd Yams
$ swift run --repl
REPL が起動したら、ターゲットを import してそのまま API を呼び出せます。次は dump メソッドでオブジェクトを YAML 文字列に変換し、load メソッドで元に戻す例です。
import Yams
let yaml = try Yams.dump(object: ["foo": [1, 2, 3, 4], "bar": 3])
// "bar: 3\nfoo:\n- 1\n- 2\n- 3\n- 4\n"
let object = try Yams.load(yaml: yaml)
// Optional([AnyHashable("bar"): 3, AnyHashable("foo"): [1, 2, 3, 4]])
依存パッケージを持つターゲットでも同様です。たとえば SwiftNIO 上に構築された Vapor の HTTP パッケージなら、HTTPClient で GET リクエストを送り、その場でレスポンスを確認できます。
import HTTP
let worker = MultiThreadedEventLoopGroup(numberOfThreads: 1)
let client = HTTPClient.connect(hostname: "httpbin.org", on: worker).wait()
let httpReq = HTTPRequest(method: .GET, url: "/json")
let httpRes = try client.send(httpReq).wait()
print(httpRes)
Foundation などのコアライブラリも併用できるため、得られたレスポンスを JSONSerialization でパースする、といったこともそのまま試せます。
仕組み
パッケージとともに REPL を使うには、REPL に渡す引数を組み立てるために 2 つの情報が必要です。
1 つは、ライブラリターゲットとその依存のヘッダ検索パスです。Swift のターゲットならモジュールの .swiftmodule ファイルへのパス、C のターゲットなら modulemap ファイルを含むディレクトリのパスが該当します。
もう 1 つは、すべてのライブラリターゲットを含む共有動的ライブラリです。これにより REPL が実行時に必要なシンボルを読み込めるようになります。Swift Package Manager は、ルートパッケージのすべてのライブラリターゲットを含む特別な product を内部的に合成してこれを実現します。この product は --repl オプションを使ったときだけビルドされ、ほかの Package Manager の操作には影響しません。
まとめ
swift run --repl によって、ライブラリパッケージの作者と利用者の双方が、パッケージのライブラリを REPL 上で手軽に試せるようになりました。新しいパッケージや Xcode プロジェクトを作らずに動作を確認できるため、ライブラリの実験や学習が容易になります。
関連リンク
- Swift Package Manager — Package Manager の概要とドキュメント
- Swift Package Manager のマニフェスト API 再設計 —
Package.swiftのマニフェスト API に関する解説