やること
- Swiftでコマンドラインツールを作る
- プロジェクト構成などがCarthageとだいたい同じものを作る
- 依存管理にCarthageを使用する
やらないこと
- 自分で作ったコマンドを
brew install出来るようにする
Github
大体同じ手順で作業してcommitしたので、多少参考になるかもしれない。
XcodeでProjectを作る
最初に作るのはCocoa Applicationです。
今回は凄いツールを作ります。適宜自分が作るプロジェクトに置き換えて下さい。
Cocoa FrameworkのTargetを追加する
Frameworkの名前はプロジェクト名にKitを付けたやつにします。適宜変更したりいろいろして下さい。
作ったTargetのschemeを共有設定にする
方法は適宜ぐぐって下さい。
全てをまとめるWorkspaceを作る
さっき作ったxcodeprojを一旦閉じてSugoiTool.xcworkspaceを作り、SugoiTool.xcodeprojを追加します。
ここからはWorkspaceを見て作業します。
Carthage
github "Carthage/Commandant"
$ carthage update --use-submodules --platform mac
carthage updateしてCheckoutされたプロジェクトをSugoiTool.xcworkspaceに追加します。
SugoiToolKitにFrameworkを追加する
Carthage/Build/Macの中の**.framework*をSugoiToolKitのGeneral -> Linked Frameworks and Librariesにドラッグアンドドロップする。
↓Build PhasesにCopy Filesを追加してFrameworkがコピーされるようにする。
SugoiToolのファイルを一通り消す
プロジェクトをここまで手順通りにやっていればInfo.plistを残して全て消す。
main.swiftを追加する
SugoiToolにmain.swiftを追加する。
main.swiftにprint("Hello")とか書いて、Cmd+RでHelloって出力されるはず。
コマンドを実装する
プロジェクトの構成的に、SugoiToolKitにコマンドの実装とテストを置いて、SugoiToolの方からそれを使うというような感じにする。
SugoiToolKitにコマンドの中身を実装する
public struct Sugoi {
public let isSugoi: Bool
public init(isSugoi: Bool) {
self.isSugoi = isSugoi
}
public func command() -> String {
if isSugoi {
return "凄い"
}
return "普通"
}
}
適宜テストを書いて下さい。
テストを実行する
import XCTest
@testable import SugoiToolKit
class SugoiTests: XCTestCase {
func testSugoi() {
let sugoi = Sugoi(isSugoi: true)
XCTAssertEqual(sugoi.command(), "凄い")
}
func testSugokunai() {
let sugoi = Sugoi(isSugoi: false)
XCTAssertEqual(sugoi.command(), "普通")
}
}
SugoiToolKitTestsのGeneral -> Host ApplicationをNoneにするとテスト実行できるようになる
SugoiToolにコマンドを実装する
import Commandant
import SugoiToolKit
import Result
public struct SugoiCommand: CommandType {
public let verb = "sugoiCommand"
public let function = "このコマンドが凄いかどうかを表示する"
let sugoi = Sugoi(isSugoi: true)
public func run(options: NoOptions<NSError>) -> Result<(), NSError> {
print(sugoi.command())
return .Success(())
}
}
main.swiftでコマンドを登録する
import Commandant
let registry = CommandRegistry<NSError>()
registry.register(SugoiCommand())
let helpCommand = HelpCommand(registry: registry)
registry.register(helpCommand)
registry.main(defaultVerb: "help") { error in
fputs("\(error)\n", stderr)
}
ここまで来たら、ビルドは通るけど実行するとUnrecognized commandとか表示される状態になってると思います。
コマンドラインから実行できるようにする
Makefileを追加する
これを追加します。
SugoiToolにComponents.plistを追加する
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>BundleIsVersionChecked</key>
<false/>
<key>BundleOverwriteAction</key>
<string>upgrade</string>
<key>ChildBundles</key>
<array>
<dict>
<key>BundleOverwriteAction</key>
<string></string>
<key>RootRelativeBundlePath</key>
<string>Library/Frameworks/SugoiToolKit.framework/Versions/A/Frameworks/Commandant.framework</string>
</dict>
<dict>
<key>BundleOverwriteAction</key>
<string></string>
<key>RootRelativeBundlePath</key>
<string>Library/Frameworks/SugoiToolKit.framework/Versions/A/Frameworks/Result.framework</string>
</dict>
</array>
<key>RootRelativeBundlePath</key>
<string>Library/Frameworks/SugoiToolKit.framework</string>
</dict>
</array>
</plist>
XcodeからComponents.plistを追加して、↑これと同じ状態になるようにして下さい。
ChildBundlesは適宜変更して下さい。
make installしてみる
$ make install
$ /usr/local/bin/SugoiTool
dyld: Library not loaded: @rpath/Commandant.framework/Commandant
Referenced from: /usr/local/bin/SugoiTool
Reason: image not found
[1] 55628 trace trap /usr/local/bin/SugoiTool
😵
SugoiTool, SugoiToolKitの設定を変える
SugoiToolKit
Build Settings -> Embedded Content Contains Swift Code
Yesにする
Build Settings -> Runpath Search Paths
$(inherited)@executable_path/../Frameworks@loader_path/../Frameworks
の3つを設定する
SugoiTool
Build Settings -> Runpath Search Paths
@executable_path/.@executable_path/SugoiToolKit.framework/Versions/Current/Frameworks/Library/Frameworks/Library/Frameworks/SugoiToolKit.framework/Versions/Current/Frameworks$(inherited)
の5つを設定する。SugoiToolKitの部分は適宜変更する
make installしてみる
$ make install
$ /usr/local/bin/SugoiTool
Available commands:
help Display general or command-specific help
sugoiCommand このコマンドが凄いかどうかを表示する
$ /usr/local/bin/SugoiTool sugoiCommand
凄い
すごい!!!!!!!!!!!!!!!!!!!!!!!!!!
参考
-
https://github.com/Carthage/Carthage
- Runpathはまるっとそのままコピペしたので、不要な設定もあるかもしれない
- Makefileを編集して使った
-
Components.plistを編集して使った



