Swift Digest
SE-0179 | Swift Evolution

Swift run Command

Proposal
SE-0179
Authors
David Hart
Review Manager
Daniel Dunbar
Status
Implemented (Swift 4.0)

01 何が問題だったのか

Swift Package Manager(SwiftPM)では、パッケージ内で定義した実行可能ファイル(executable product)を開発中に動かす際、次のように2段階の操作が必要でした。まず swift build でビルドし、そのあと生成されたバイナリを .build/debug/ 以下から直接実行する、という手順です。

$ swift build
$ .build/debug/myexecutable

さらに Swift 4 では、SwiftPM の出力先にプラットフォーム別のサブフォルダが入るようになり、実行パスが macOS では .build/macosx-x86_64/debug/、Linux では .build/linux-x86_64/debug/ と、OSごとに違う形に変わりました。その結果、コマンドラインから実行ファイルを叩くのがこれまで以上に面倒になり、開発中の「ビルドして動かす」ループの体験が悪化してしまいます。

パッケージ内の実行可能ファイルをサクッと起動する、SwiftPM としての統一された入り口が必要だったのが、この提案の背景です。

02 どのように解決されるのか

SwiftPM にトップレベルのサブコマンドとして swift run が追加されます。これは、必要なら事前にビルドを行ったうえで、Package.swift で定義された実行可能プロダクトを起動するコマンドです。

基本的な使い方

最も単純なケースでは、パッケージに実行可能プロダクトがひとつだけ定義されていれば、名前を省略してそのまま起動できます。

$ swift run            # .build/debug/exe を起動
$ swift run exe        # 実行ファイル名を明示
$ swift run exe arg1 arg2  # 引数はそのまま実行ファイルに渡される

実行ファイル名を明示した場合、それより後ろに書いた引数はすべて実行ファイル側にそのまま渡されます。引数とオプションの境界を意識せずに渡せる点がポイントです。

実行ファイル名を省略できるのは、パッケージに実行可能プロダクトが ちょうど1つだけ 定義されているときに限られます。0個、あるいは2個以上あるのに名前を指定しなかった場合はエラーになります。実行可能プロダクトの定義は SE-0146(Package Manager Product Definitions)で導入された仕組みに従います。

ビルド関連のオプション

swift run は起動前に必要に応じてビルドを行うため、swift build が受け取るオプションをそのまま渡せます。たとえば --configuration-c)で debug / release を切り替えたり、-Xcc / -Xlinker / -Xswiftc でコンパイラやリンカへフラグをパススルーしたりできます。

すでにビルド済みだとわかっているときは、swift test と同様に --skip-build を渡すことでビルドフェーズをスキップできます。

$ swift run -c release myexec       # release 構成でビルドして実行
$ swift run --skip-build myexec     # ビルドをスキップして既存のバイナリを実行

これにより、「ビルドしてから .build/... 以下のパスを思い出して叩く」という二段構えの操作が、swift run 一発に置き換わります。Swift 4 でビルド出力先にプラットフォーム別のサブフォルダが入っても、ユーザー側はパスの違いを意識せずに開発サイクルを回せます。