🍁
Swift Package Manager で Command Line Tool を作る
-
GitHub でリポジトリを新規に作って、ローカルに
clone
する -
clone
したリポジトリのルートディレクトリで SPM の初期化をする$ swift package init --type executable
-
Package.swift
を編集するPackage.swiftの例// swift-tools-version:5.5 import PackageDescription let package = Package( name: "LineCounter", platforms: [ .macOS(.v10_15) ], products: [ .executable(name: "lc", // コマンド名はここで決められる targets: ["LineCounter"]) ], targets: [ .target(name: "LineCounter"), .testTarget(name: "LineCounterTests", dependencies: ["LineCounter"]) ] )
-
Command Line Tool を実装する
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
成果物