モチベーション
(コミット数とforkでは)CocoaPods派のbanjunです。
今回はCocoaPodsにあるような外部ライブラリを含むSwiftスクリプトをつくります。
かつてはまさにそのあたりを支援するApousというツールがあったのですが,Swiftの進化に追いついていないので一旦忘れます。
https://github.com/owensd/apous
使ってみたい外部ライブラリは SourceKitten です。 SwiftLintのようなツールを作れるそうです。
導入
*.swiftはswiftコマンドで実行可能なので,shebangで*.swiftファイルの頭に付けてやれば起動はできます。
# !/usr/bin/swift
ただし,ここに import SourceKittenFramework を追加するには,フレームワークサーチパスの指定が必要になります。
そこで*.swiftファイルの隣りに Cartfile を書いて, carthage bootstrap します。CocoaPodsしか持っていない人は brew install carthage しましょう。
Cartfile
github "jpsim/SourceKitten"
すると Carthage/Build/Mac にframeworkがビルドされるので, swift -Fに渡すことでフレームワークサーチパスを指定できます。
それをshebangで指定しますが,*.swift自体はどこか別のディレクトリから,または ~/bin/* からシンボリックリンクでも起動できるようにします。
そのために一旦swiftではなくシェルスクリプトで受けたいので,*.swiftの頭を次のようにします。
# !/bin/sh
":" //#; exec swift -sdk $(xcrun --sdk macosx --show-sdk-path) -F "$(dirname $(readlink $0 || echo $0))/Carthage/Build/Mac" -target x86_64-apple-macosx10.10 "$0" "$@"
import Foundation
import SourceKittenFramework
(続く...)
:はshでnopなので,exec より前を無視します。ただちにexec swiftするのでシェルスクリプトの解釈はこの行でおしまいです。
引数には,起動されたパスから,Carthageでビルドしたframeworkのフルパスを解決して swift -F に渡しておきます。
さてexec swiftされると今度は同じファイルがSwiftスクリプトとして実行されます。一行目の":"はただの文字列であり, // はコメントなのでその行はなにもしません。続く行が実際のSwiftコードです。
ここでは import SourceKittenFramework したので,このSwiftスクリプト内ではSourceKittenを使ってコードを書けます。スクリプトに引数がほしい場合はexec swiftで"$@"したところから取得可能なので,それを使います。
例
SourceKittenを使うSwiftスクリプトの例です。
これは ./bansan.swift としても実行できますし,PATHを通した~/bin/bansanからシンボリックリンクを貼っておいて,どこからでもbansanで実行できます。
課題とworkaround
Carthageのバイナリインストール
Carthageにはバイナリインストールモードがあり,frameworkをビルドせずに,ビルド済みframeworkを置いてくれる仕組みがあるようです。
ただしSwiftが生成するバイナリはSwiftバージョンに対して互換性が悪いので(Swiftで静的ライブラリが作れなかったり,libDarwinとかをいつも付属させてたり,‥とかが関係する?),Xcodeのバージョンが変わるときにはハマります。
そんなときは carthage bootstrap か carthage checkout で --no-use-binaries を付けて,ソースからビルドしましょう。
swift -targetのデフォルト値
-target の引数はXcodeのバージョンで変わるかもしれません。これはXcode 7.3のものです。動かないときはswift -vで実行してみて,swiftコマンドが生成するオプションを見てみるといいかもしれません。
例えば x86_64-apple-macosx10.9 だと 10.10をminimum deployment targetにしているframeworkはimportできません。
まとめ
- 外部ライブラリを含む実行可能*.swiftを作りたいときはCarthageとexec swiftを使うことができる
- Carthageはその場にframeworkを作ってくれるのでべんり
- Carthageのバイナリインストールモードは,Swift自体がバイナリ互換性がないことを考えると筋が悪い