SwiftPM Add Target Plugin Command
01 何が問題だったのか
SwiftPM にはこれまで、Package.swift をコマンドラインから編集するためのサブコマンドが一通り揃ってきました。SE-0301 で導入された swift package add-dependency / add-target / add-target-dependency / add-product がそれです。これらを使うと、エディタで直接マニフェストに手を入れなくても、依存関係やターゲット、プロダクトを追加できます。
一方で、既存のターゲットに対して プラグインの使用(plugin usage)を追加する コマンドはまだ用意されていませんでした。ビルドツールプラグインは、たとえば swift-openapi-generator のようにエコシステム全体で広く使われるようになっており、「このターゲットでこのプラグインを使う」という宣言をマニフェストに書き足す機会も増えています。しかし現状では、次のような記述を自分で正しい位置に差し込まなければなりません。
.target(
name: "MyTarget",
dependencies: [...],
plugins: [
.plugin(name: "OpenAPIGenerator", package: "swift-openapi-generator")
]
)
plugins: の引数の正確な形、.plugin(name:package:) の書式、同じパッケージ内プラグインでは package: を付けない、といった細かな約束を覚えていないとうまく書けず、タイプミスで壊すリスクもあります。SwiftPM が「マニフェスト編集コマンドを一通り揃える」ことを目指している以上、プラグイン追加だけ手作業というのは一貫性に欠けた状態でした。
02 どのように解決されるのか
SwiftPM に、既存ターゲットへプラグインの使用を追加する swift package add-target-plugin コマンドを新設します。既存の add-target-dependency と同じく「すでにあるターゲットに項目を足す」タイプのコマンドで、add-target(新しいターゲット定義そのものを作る)とは役割を分けます。
使い方
基本の書式は次の通りです。
swift package add-target-plugin <plugin-name> <target-name> [--package <package>]
たとえば swift-openapi-generator パッケージが提供する OpenAPIGenerator プラグインを、既存のターゲット MyTarget で使えるようにするには次のように実行します。
swift package add-target-plugin OpenAPIGenerator MyTarget --package swift-openapi-generator
実行後、Package.swift の MyTarget 定義は次のように書き換えられます。
.target(
name: "MyTarget",
dependencies: [...],
plugins: [
.plugin(name: "OpenAPIGenerator", package: "swift-openapi-generator")
]
)
同じパッケージ内で定義されているプラグイン(internal plugin)を追加する場合は、--package を省略します。
swift package add-target-plugin MyPlugin MyTarget
動作
コマンドは次のように振る舞います。
- ターゲットの検証: 指定した
<target-name>がマニフェストに存在しなければエラーになります。 - 冪等性: 追加しようとしたプラグインがすでにそのターゲットの
pluginsにある場合は、重複エントリを作らずに成功で終わります。 - マニフェストの書き換え:
Package.swiftをパースして書き換えつつ、既存のフォーマットやコメントは可能な範囲で保持します。 - 出力: 既定では加えた変更内容を標準出力に表示します。
--quietで抑制できます。
Package.swift が見つからない・パースできない、書き戻せない、といった場合は適切なエラーメッセージとともに失敗します。
なぜ既存コマンドの拡張ではないのか
設計の選択として、swift package add-target --type plugin のように既存の add-target を拡張する案もありました。しかし add-target は「新しいターゲット定義を作る」コマンドで、今回の機能は「既存ターゲットにプラグインの 使用 を追加する」もので、意味合いが違います。既存ターゲットに項目を足すという点で add-target-dependency と同じ構造を持つため、同じ粒度で別コマンドとして用意するほうが分かりやすい、という判断です。同様に add-target-dependency を拡張してプラグインも扱わせる案も、依存関係とプラグインはマニフェスト上の構文も役割も異なるため採用されていません。