こんにちは。withでiOSエンジニアをしている長尾( @zrn-ns )です。
突然ですが、最近Xcodeを14.3以上にアップデートしたらCarthageのビルド(carthage bootstrap)が通らなくなった... って方、結構多いんじゃないでしょうか。
今回はこの問題について、弊社で行った対応についてお話します。
どんなエラーが出るのか
今回解説する問題については、既にCarthage公式でIssueが起票されています。
しかし現状その対処方法について、公式からのアナウンスはありません。コラボレーターの方も忙しいんでしょうね...。
具体的な現象としては carthage bootstrap
を実行すると下記のようなエラーが発生します。(上記Issueから引用です)
Build Failed
Task failed with exit code 65:
/usr/bin/xcrun xcodebuild -workspace /Users/jadian/Git_Project/Company/tmp_vietnam_ios/Carthage/Checkouts/Masonry/Masonry.xcworkspace -scheme Masonry\ iOS -configuration Release -derivedDataPath /Users/jadian/Library/Caches/org.carthage.CarthageKit/DerivedData/14.3_14E222b/Masonry/v1.1.0 -sdk iphoneos ONLY_ACTIVE_ARCH=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= CARTHAGE=YES archive VALIDATE_WORKSPACE=NO -archivePath /var/folders/05/cy4ywfcd4l99__z394q_cskw0000gn/T/Masonry SKIP_INSTALL=YES GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=NO CLANG_ENABLE_CODE_COVERAGE=NO STRIP_INSTALLED_PRODUCT=NO (launched in /Users/jadian/Git_Project/Company/tmp_vietnam_ios/Carthage/Checkouts/Masonry)
This usually indicates that project itself failed to compile. Please check the xcodebuild log for more details: /var/folders/05/cy4ywfcd4l99__z394q_cskw0000gn/T/carthage-xcodebuild.0A2id9.log
ほぼこのエラーに情報はないので、指示の通り詳細ログを見に行きます、すると下記のようなエラーが発生してビルドが停止していることが分かります。
ld: file not found: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphoneos.a
エラーの内容から、ビルド時に必要なXcodeのファイル libarclite_iphoneos.a
が存在しない、というエラーのようです。
なぜこのエラーが発生するのか
Issueを見ていくと、どうやらiOS11未満のOSをサポートする(Deployment Targetに含む)プロジェクトをビルドする場合に使用されるARC関連のファイル libarclite_iphoneos.a
が、Xcode14.3からバンドルされなくなったようです。
Appleのサポートページを見ると、Xcode14.0のリリース時点でiOS11未満向けのビルドは既にできなくなっており、その後Xcode14.3のリリース時点で libarclite_iphoneos.a
が削除されたように見えます。
これにより、iOS11未満をサポートするサードパーティ製ライブラリをCarthageでビルドしようとした場合、ビルドが通らなくなってしまったということのようです。
対応方針の選択肢
iOSエンジニアがとれる選択肢を列挙します。
案A. Carthageの開発に参加し、この問題を修正する
エンジニアとして最も正しいと思うのはこの方法です。
しかし正直ハードルは高いので今回は避けたいです。
案B. 限界まで何もしない
Xcodeを14.3未満を使い続けていれば、この問題は発生しません。
待っている間にCarthageのアップデートが提供され、問題が解消する可能性があります。
上に記載したIssueでも話されているように、Carthage側でDeployment Targetを任意のバージョンに変更できる機能が提供されるようになれば、問題は解消するでしょう。
しかし具体的にいつ修正が提供されるかは不明です。
案C. Carthageを使うのをやめる
Carthageを使うのをやめ、すべてのライブラリをCocoaPodsやSwift Package Managerに移動すれば、この問題を回避できます。
(ただしCocoaPodsに移す場合は、CocoaPods側でも同じ問題は発生するはずなので、minimum_deployment_targetをiOS11以上で上書きする必要がある気がします)
案D. ワークアラウンドαを行う
そもそもこの問題は、Xcode11未満をDeployment Targetに含む場合にのみ発生するので、Carthageでチェックアウトしたライブラリをビルドする前に、各ライブラリの最小サポートバージョンをiOS11以上に上書くようなスクリプトを書くことで、解消が見込まれます。
参考:
案E. ワークアラウンドβを行う
libarclite_iphoneos.a
等の不足したファイルを古いXcodeから新しいXcodeにコピーすれば、この問題は解消します。
参考:
どの選択肢を選ぶのか
上記の案の中で、僕は 案E を選択しました。
最初は案Bでいこうと考えていたのですが、早くXcodeをアップデートして最新の言語機能も使いたいですし、何より最新のXcodeがないと最新のiOS端末でデバッグビルドができないので、あまり長く待機し続けることはできませんでした。
また案Cについては、対応コストがまあまあ大きいですし、弊社ではCarthageのビルド済みバイナリをキャッシュすることでCIを高速化しているため、Carthageを捨てるのはなるべく避けたいと考えました。
具体的にどのように対応するのか
案Eの対応手順をざっくり説明すると、
- Xcode14.3から削除されるファイルを手元に残しておく
- 各自Xcodeを更新したら、ファイルを新しいXcodeにコピーする
以上です。
Xcode14.3で削除されたファイルは、下記のパス(arcディレクトリ)に格納されているファイル群です。
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc
プロジェクトの各メンバーは古いバージョンのXcodeをバックアップしておき、Xcode14.3をインストール後、上記ディレクトリのファイルをXcode14.3の同一階層にコピーしてあげれば、問題を解消できます。
もっと簡単にならないの?
Xcodeをアップデートする度に毎回この手順を踏むのは面倒だという場合には、以下のようなスクリプトを組む事もできます。
#!/bin/bash
# 古いXcodeからarcディレクトリの中身をコピーして任意のパスに保存し、ここにそのパスを宣言しておく
ARC_DIR_BACKUP_PATH="/path/to/directory/arc/"
set -eu
cd `dirname $0`
if [[ "`whoami`" != "root" ]]; then
echo 'Please execute with root user.'
exit
fi
XCODE_PATH=`xcode-select -p`
ARC_DIR_PATH="$XCODE_PATH/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc"
# arcディレクトリがない場合だけ処理を行う(既にある場合は実行しない)
if [ -d $ARC_DIR_PATH ]; then
echo 'arc directory exists. Workaround script skipped.'
exit 0
fi
sudo mkdir -p "$ARC_DIR_PATH"
sudo cp "$ARC_DIR_BACKUP_PATH/*" "$ARC_DIR_PATH"
これは arc
ディレクトリのバックアップ(事前に指定)を現在アクティブになっているXcodeにコピーするスクリプトです。
弊社ではCarthageやCocoaPods、Bundlerで管理しているライブラリを一括でインストールしてくれるスクリプトを用意しているので、その中で上記のスクリプトを実行するようにすることで、Xcodeのアップデート時などにも忘れることなく手軽にワークアラウンドを実行する事ができるようになりました。
なお上記スクリプトはを動かすには、事前にいくつか準備が必要です。
- 事前に古いXcodeから
arc
ディレクトリをコピーし、任意の場所(ホームディレクトリとか)にコピーしておき、そのパスをスクリプト内のARC_DIR_BACKUP_PATH
に代入しておく必要がある - このスクリプトはrootで実行する必要がある。sudoをつけて実行するか、rootユーザで実行する
- macOS Mojave以降では、
sudo
するためにはターミナルエミュレータに「フルディスクアクセス」を許可する必要がある。こちらの記事を参考に、事前に権限を付与する → Macでsudoが効かないのはMojaveのせいかもしれない | eureka
最後に
少しでも参考になれば幸いです。
内容に間違いなどあればご指摘いただけると助かります。
「うちではこうやってる!」のような情報提供もお待ちしております。
これを期にSwift Package Managerに移行するのも良いとは思いますが、なかなか手間がかかるので、一旦ワークアラウンドで回避するのはアリだと思います。
なお上記の手順を行ったことで発生した不利益について、筆者及び弊社は一切責任を負いません。ご自身の判断でご対応ください。念のため。
PR
withではエンジニアの採用を行っています。
興味があれば、ぜひお問い合わせください!