🍁
Swift Package Manager で Command Line Tool を作る【基礎】
-
GitHub でリポジトリを新規に作って、ローカルに
clone
する -
clone
したリポジトリのルートディレクトリで SPM の初期化をする$ swift package init --type executable
-
Package.swift
を編集するPackage.swiftの例// swift-tools-version: 6.0 import PackageDescription let package = Package( name: "LineCounter", products: [ .executable( name: "lc", // コマンド名はここで決められる targets: ["LineCounter"] ) ], targets: [ .executableTarget(name: "LineCounter") ] )
-
Command Line Tool を実装する
LineCounter/main.swiftimport Foundation guard CommandLine.arguments.count == 2 else { print("usage: lc [absolute path of a file]") exit(1) } let fileURL = URL(fileURLWithPath: CommandLine.arguments[1]) guard let file = try? String(contentsOf: fileURL, encoding: .utf8) else { print("Error: could not read \(fileURL.absoluteString)") exit(2) } print(file.components(separatedBy: CharacterSet.newlines).count)
-
ローカルで動作確認をする
$ swift run lc ${PWD}/Package.swift 20
-
リモートリポジトリに push して tag を打つ
tagを打つ$ git tag 0.0.1 $ git push origin 0.0.1
- tag で Command Line Tool のバージョン管理をすることになる
- GitHub の Release で Change Log をしっかり書くと良い
本例のソースコード
プロジェクトに作った Command Line Tool を追加してビルド時に実行する
-
任意のプロジェクトで
File -> Swift Packages -> Add Package Dependency...
を開く -
作った Command Line Tool のリポジトリ URL で検索して Swift Package を追加する
- この時、Target の中で Command Line Tool を使うわけではないので Target には追加しないようにする
-
TARGETS -> Build Phases
でRun Script
を追加する例# build lc xcrun --sdk macosx swift build -c release \ --package-path ${BUILD_DIR%Build/*}SourcePackages/checkouts/LineCounter \ --product lc # run lc ${BUILD_DIR%Build/*}SourcePackages/checkouts/SwiftLint/.build/release/lc ${SRCROOT}/[目的のファイルのパス]
-
swift build
だと実行できないため、xcrun --sdk maxosx swift build
を利用する -
--package-path
でツールのパスを指定する - 相対パスよりも絶対パスを使い、Xcode の環境変数を上手く使う
これで、Target をビルドするたびにコマンドが実行される
-
備考: Terminal でコマンドが使えるようにする
リポジトリを任意の場所に git clone して、リリースビルドし、成果物を/usr/local/bin/
の中に入れればいい
例
$ git clone https://github.com/Owner/LineCounter.git
$ cd LineCounter
$ swift build -c release
$ cp .build/release/lc /usr/local/bin/lc
Discussion
成果物
swift-argument-parserを使い、テストもしっかり買いてあるものなので、色々と参考になると思います。