iOSのCarthage導入手順と注意点

iOSのCarthage導入手順と注意点

Table of Contents

Carthageの導入はちょっとした漏れでエラーにハマります。

この記事は、iOSアプリにCarthage環境を導入する手順について説明します。

  1. MacにCarghageをインストールする
  2. Cartfileにライブラリを記入
  3. Cartfileからframework作成
  4. プロジェクトにframeworkをリンク
  5. ビルドフェイズにframeworkのコピースクリプトを作成

なお、チーム運用、git管理、ライブラリのバージョン運用など詳細は、
Carthageの使い方を体系的に理解する 」からまとめて知ることができます。

MacにCarghageをインストールする

CarthageはHomebrewでインストールできます。

$ brew install carthage

Homebrewの使い方に関しては「MacのHomebrewとは?仕組み・使い方と用語整理 」でまとめてあります。

Cartfileにライブラリを記入

CartfileとはCarthageのライブラリ管理ファイルです。
テキストファイルになってて、
この中にCarthageで管理したいライブラリをまとめます。

  • Cartfileファイルの用意
  • Cartfileの編集

Cartfileファイルの用意

Cartfileはプロジェクト毎に用意できます。
対象プロジェクトのディレクトリ上にCartfileを用意します。

$ cd ~/your/xcode/project/path
$ touch Cartfile

Cartfile編集

インストールしたいライブラリをCartfileに記入します。
例えばSwiftyJSONであればに次のように記入します。

github "SwiftyJSON/SwiftyJSON"

バージョン指定をしたい場合は「CarthageのCartfileの書き方と個別更新方法 」に書き方をまとめてあります。

Cartfileからframework作成

Cartfileの準備ができたらcarthage updateコマンドでフレームワークを作成します。
オプションに--platform--no-use-binariesをつけます。

オプション 説明
--platform 対象プラットフォーム指定。未指定は全環境のフレームワークを作成します
--no-use-binaries 予めビルドされたバイナリを使わずコードからビルドします

carthage updateコマンドを実行するとframework作成処理が走ります。

$ carthage update --platform iOS --no-use-binaries

*** Fetching SwiftyJSON
*** Checking out SwiftyJSON at "5.0.0"
*** xcodebuild output can be found in /var/folders/45/7f_wlrcs3xv6rmstcz2l5_000000gn/T/carthage-xcodebuild.IBF3eg.log
*** Building scheme "SwiftyJSON iOS" in SwiftyJSON.xcworkspace

成功するとCarthageディレクトリとCartfile.resolvedファイルが作成されます。

  • Cartfile.resolved
    • carthage updateで最終的な依存ライブラリ情報をまとめたテキストファイル
  • Carthage
    • carthage updateで作成されたライブラリのフレームワークが格納されたディレクトリ

Cartfile.resolvedの詳細については「Carthage bootstrapとGit管理をチーム運用観点で整理 」でまとめてあります。

プロジェクトにframeworkをリンク

frameworkはプロジェクトにリンクしないと使えません。
プロジェクトのTarget > General > Linked frameworks and Librariesを + ボタンを押してください。

フレームワーク/ライブラリの選択画面が出るので、Add Other... ボタンを押してください。

ここで先程作成したframeworkを指定します。
なおフレームワークは、Carthage/Build/iOSディレクトリの中にあります。

frameworkを選ぶとXcodeプロジェクトに追加されます。
このときDo Not Embedになってることを確認してください。

これでプロジェクトにframeworkがリンクされて、
コード上のimportで対象frameworkを見つけられるようになります。

なお、ボタンをポチポチせずにframeworkをドラッグ&ドロップでも追加できます。

注意:Embed Contentだとビルドエラーになる

frameworkのリンク経路は、Target > GeneralTarget > Build Phasesの2つあり
Generalからframeworkを追加すると、デフォルトではEmbed & Signになります。
このままビルドすると次のようなビルドエラーが起きます。

Multiple commands produce '.../YOUR-APP-NAME.app/Frameworks/<FRAMEWORK NAME>.framework':

1) Target '<YOUR TARGET NAME>' has copy command from
'/your/project/path/Carthage/Build/iOS/<FRAMEWORK NAME>.framework' to '.../YOUR-APP-NAME.app/Frameworks/<FRAMEWORK NAME>.framework'

2) That command depends on command in Target '<YOUR TARGET NAME>': script phase “Run Script”

Embedded Frameworkではないので、Do Not Embedに直してください。

ビルドフェイズにフレームワークのコピースクリプトを作成

リンクでビルドは通りますが、プロダクト内にframeworkが配置されていません。
ビルド時にframeworkをコピーするスクリプトを用意します。
コピー処理はcarthage copy-frameworksコマンドを使います。

  1. ビルドフェイズにスクリプトフェイズ追加
  2. carthage copy-frameworksコマンドをセット
  3. スクリプトの入力情報をセット
  4. スクリプトの出力情報をセット

1. ビルドフェイズにスクリプトフェイズ追加

Build Phases上の + ボタンを押してNew Run Script Phaseを選ぶとRun Scriptフェイズが作成されます。

2. carthage copy-frameworksコマンドをセット

Shellはシェルコマンドが呼べればいいので/bin/shのままです。
スクリプト内でcarthage copy-frameworksコマンドを追記します。
絶対パスでも相対パスでもパスが通っていればどちらでも大丈夫です。

3. スクリプトの入力情報をセット

carthage copy-frameworksはframeworkのパスを渡すと、ビルド対象プロジェクト内にコピーします。
厳密には$BUILD_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATHパスにコピーします。GitHub/Carthage

Carthage Xcode Build Phases Run Script Input Files

4. スクリプトの出力情報をセット

Output Filesはコピー先を指定します。

実はOutput Filesは指定せずとも動作に問題はありません。しかしビルドパフォーマンスに影響します。
詳しくは「CarthageのビルドフェイズでOutput Files指定による速度調査 」に調査結果をまとめてあります。

Carthage Xcode Build Phases Run Script Output Files

注意: carthage copy-frameworksを忘れるとランタイムエラー

carthage copy-frameworksコマンドを実行しなくてもビルドは通ります。
しかし実行すると次のようなにライブラリのロードエラーが起きます。

dyld: Library not loaded: @rpath/SwiftyJSON.framework/SwiftyJSON
  Referenced from: /Users/mothule/Library/Developer/CoreSimulator/Devices/1DB7E7C4-D7CD-44BA-B3F9-F66DC4E5EC51/data/Containers/Bundle/Application/6B0FDFCC-9D12-47D5-9B74-B837BE8FC983/UseCarthage.app/UseCarthage
  Reason: image not found

これはプロダクト内にframeworkが配置されてないことで、
実行環境にプロダクトがインストールされてもframeworkが見つからずdyldがランタイムエラーを起こすためです。

注意: Input Filesで渡すframeworkのパスを間違えるとビルドエラー

carthage copy-frameworksコマンドに渡すframeworkのパスが間違っているとビルドエラーが発生します。
Input FilesまたはInput File Listsで渡してるframeworkのパスが正しいか確認してください。

Could not find framework "<framework name>" at path <wrong framework path>.
Ensure that the given path is appropriately entered and that your "Input Files" and "Input File Lists" have been entered correctly.

フレームワークのパスはまとめて指定も可能

Input Filesに各フレームワークのパスをセットしなくても、xcfilelistという拡張子で指定することで一律管理も可能です。 詳細は「CarthageでInput File Listsにxcfilelistを渡す利点と方法 」にまとめてあります。

ライブラリを追加する

新しくframeworkを追加や更新する場合は、
carthage copy-frameworksコマンドの登録以外の作業をやります。
またupdateにオプションが一つ増えます

  1. Cartfileにライブラリ追加
  2. carthage updateでライブラリ個別更新
  3. リンクにframeworkを追加
  4. コピースクリプトのInput FilesとOutput Filesに追加

新しくビルドフェイズにスクリプトを追加はしません。

carthage updateでライブラリ個別更新

carthage updateとするとCartfileにかかれている全てのライブラリが対象となります。
他のライブラリのバージョンは更新せず追加したライブラリだけのframework作成をしたい場合は、
carthage updateにライブラリ名を渡します。

例えば新しく追加したライブラリがSDWebImageであれば、コマンドラインは次のようになります。

$ carthage update --platform iOS --no-use-binaries SDWebImage

これで既存ライブラリは更新されません。

もっと体系的に理解する

この記事では、記事の読みやすいよう導入に絞ってます。 もしチーム運用、git管理、ライブラリのバージョン運用など使い続けたら必要になる部分は別記事に分けており、
Carthageの使い方を体系的に理解する 」からまとめて知ることができます。

このエントリーをはてなブックマークに追加