Swift Package Manager の実装を追ってみる (`swift package` 編)
Swift Package Manager の挙動を確認するため、実装を追ってみる。
リポジトリ
追ってみる対象の revision
開始時点での Swift 5.8 の最新のタグ
swift-5.8-DEVELOPMENT-SNAPSHOT-2023-03-17-a
まずは簡単そうなところからで swift package
と打った時のコードを追ってみることにする。
上記コマンドを打った時の挙動としては、コマンドのヘルプが表示される。それがどのような実装になっているかを追ってみる。
エントリーポイントを見つけるため、ひとまず Sources/
を探す。
↓っぽい
Commands
というモジュールを import しているので、そこに SwiftPackageTools
型が定義されていそう。
/Sources/Commands/
ディレクトリを探す。
Sources/Commands/PackageTools/SwiftPackageTool.swift
で SwiftPackageTool
型が定義されている。
コマンドのパースは Swift Argument Parser を使っている。
これは Swift Package Manager 側の dependencies を見ても分かる。
再掲 Sources/Commands/PackageTools/SwiftPackageTool.swift
SwiftPackageTool.main()
の main
は Swift Argument Parser の ParsableCommand
protocol で定義されているものと思われるので、ここでは定義されていない。
swift package
と打った時の挙動としては、 swift package hogehoge
という感じでサブコマンドを指定していないので、Swift Argument Parser でパースされると CommandConfiguration
の defaultSubCommand
で指定したサブコマンドが使用される。
ここでは DefaultCommand
が指定されている。
DefaultCommand
の定義を調べてみると、同じファイルの中に定義されていることが分かる。
Swift Argument Parser でパースするコマンドなので、 ParsableCommand
に準拠しているかと思いきや SwiftCommand
なるものに準拠しているようなので、先にこちらが何かを調べる。
Swift Argument Parser で定義されている型ではないので、 Swift Package Manager の方で定義しているはず。
/Sources/CoreCommands
モジュールの中に定義されている様子。
ParsableCommand
に準拠した protocol のようで、利用する Swift の設定やワークスペースの設定など、各コマンドで共通になるように用意されているように見える。
Swift Argument Parser では run()
が走るが、 run(_ swift: SwiftTool)
を新たに定義し、SwiftCommand.run()
の中で SwiftTool を生成し、 SwiftCommand
に準拠した各サブコマンドで実装される run(_ swift: SwiftTool)
を呼び出すようにしている。
DefaultCommand
に戻る。
SwiftCommand.run()
を経由して DefaultCommand.run(_ swiftTool: SwiftTool)
が呼び出されることが分かったので、 DefaultCommand.run()
が定義されていない理由が分かった。
DefaultCommand.run(_ swiftTool: SwiftTool)
を見ていく。
初っ端に remaining
を取り出している。
remaining
は swift package foo bar
と打った時に foo
と bar
が配列で格納されるように Swift Argument Parser によってパースされる。
そして、これがなかった時、つまり swift package
だけの時に SwiftPackageTool.helpMessage()
を出力して終了していそう。
これでヘルプが出力される挙動と一致しそうだが、 SwiftPackageTool.helpMessage()
も一応見ておく。
と思ったが、これはどうやら Swift Argument Parser 側で定義されているものの様子。
SwiftPackageTool
が準拠している ParsableArgument
protocol で実装されているものっぽい。
ということで、 swift package
と打った時の挙動を追うのは一旦ここまで。