モチベーション
(コミット数と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自体がバイナリ互換性がないことを考えると筋が悪い