Carthageの作り方を紐解いてみる~Makefile編~
SwiftがLinuxで動かせるようになりはや数ヶ月、そろそろSwift製のツールを自分で作って使って行きたいなぁと思っています。
そこでSwift製のプロダクトで一番使われているんじゃないか?と思われるCarthage
の作り方について調べてみました。
Makefileを見る
なにはともあれまずはMakefileを読んでみます。
とりあえず $ make install
すると使えるようになりそうな雰囲気を感じるので一旦インストールしてみます。
$ make install rm -f "Carthage.pkg" rm -f "CarthageKit.framework.zip" rm -rf "/tmp/Carthage.dst" xcodebuild -workspace 'Carthage.xcworkspace' -scheme 'carthage' DSTROOT=/tmp/Carthage.dst clean Build settings from command line: DSTROOT = /tmp/Carthage.dst 〜(中略)〜 Sudo installer -pkg Carthage.pkg -target / Password: installer: Package name is Carthage installer: Installing at base path / installer: The install was successful.
xcodebuild
とpkgbuild
が走り、生成物であるCarthage.pkg
をインストールしました。
$ carthage Available commands: archive Archives built frameworks into a zip that Carthage can use bootstrap Check out and build the project's dependencies build Build the project's dependencies checkout Check out the project's dependencies copy-frameworks In a Run Script build phase, copies each framework specified by a SCRIPT_INPUT_FILE environment variable into the built app bundle fetch Clones or fetches a Git repository ahead of time help Display general or command-specific help update Update and rebuild the project's dependencies version Display the current version of Carthage
正しくインストールされていますね。
中で何が起きているか追うためにMakefile
の依存関係を整理してみます。
install
install: package
sudo installer -pkg Carthage.pkg -target /
install
はpackage
に依存していて、最終的にinstaller
を走らせてCarthage.pkg
をインストールするためのターゲットのようです。
package
package: installables pkgbuild \ --component-plist "$(COMPONENTS_PLIST)" \ --identifier "org.carthage.carthage" \ --install-location "/" \ --root "$(TEMPORARY_FOLDER)" \ --version "$(VERSION_STRING)" \ "$(OUTPUT_PACKAGE)" (cd "$(TEMPORARY_FOLDER)$(FRAMEWORKS_FOLDER)" && zip -q -r --symlinks - "$(OUTPUT_FRAMEWORK)") > "$(OUTPUT_FRAMEWORK_ZIP)"
package
はinstallables
に依存していて、pkgbuild
でCarthage.pkg
を生成するためのターゲットのようです。
引数のTEMPORARY_FOLDER
にはinstallables
でビルドされた生成物が配置されてそうです。
ちなみに最終行のCarthageKit.framework.zip
は何目的で作っているのかよくわかりませんでした。
intallables
installables: clean bootstrap $(BUILD_TOOL) $(XCODEFLAGS) install mkdir -p "$(TEMPORARY_FOLDER)$(FRAMEWORKS_FOLDER)" "$(TEMPORARY_FOLDER)$(BINARIES_FOLDER)" mv -f "$(CARTHAGEKIT_BUNDLE)" "$(TEMPORARY_FOLDER)$(FRAMEWORKS_FOLDER)/$(OUTPUT_FRAMEWORK)" mv -f "$(CARTHAGE_EXECUTABLE)" "$(TEMPORARY_FOLDER)$(BINARIES_FOLDER)/carthage" rm -rf "$(BUILT_BUNDLE)"
installables
はclean
とbootstrap
に依存していて、pkgbuild
で利用するコマンドやフレームワークを生成し、必要な箇所に配置するためのターゲットのようです。
実際に叩かれてるコマンドは xcodebuild -workspace 'Carthage.xcworkspace' -scheme 'carthage' DSTROOT=/tmp/Carthage.dst install
で、xcodebuild
のinstall
は指定されたDSTROOT
に対してビルドしたターゲットをインストールするアクションです。
今回で言うと /tmp/Carthage.dst
にCarthage
のビルド結果であるCarthageKit.framework
と、carthage
のバイナリ本体を配置しています。
clean & bootstrap
bootstrap: script/bootstrap clean: rm -f "$(OUTPUT_PACKAGE)" rm -f "$(OUTPUT_FRAMEWORK_ZIP)" rm -rf "$(TEMPORARY_FOLDER)" $(BUILD_TOOL) $(XCODEFLAGS) clean
clean
は過去の生成物の削除、bootstrap
はルート以下のscript/bootstrap
を叩いており、どちらも他のターゲットには依存していませんでした。
script/bootstrap
は、Carthage
プロジェクトが利用している外部ライブラリをgit
のsubmodule
で管理するためのスクリプトでした。
まとめ
フローを整理します。
- 過去の生成物を削除する
Carthage
のビルドに必要なライブラリを取得/更新するxcodebuild
を利用してCarthage
をビルドし、CarthageKit.framework
とcarthage
のバイナリを生成し特定の箇所に配置する- 特定の箇所に配置された生成物を
Carthage.pkg
にパッケージ化する Carthage.pkg
をインストールする
以上のフローで、Carthage
が手元で利用できるようになりました。
次回はCarthage
をビルドする周りを詳しく見てみようと思います。