anz blog

archiveしたものをexportする処理がエラーでコケる

いつものように作業をして後は Bitrise に AppStoreConnect 提出までよろしくという感じで放置していたら、Xcode Archive & Export iOS ステップがコケているのに気づきました。

ということで、今回はその内容と回避する方法のお話です。
ちなみに、Carthage が絡んでくるので、導入していない人には関係のない話になります。

問題

Bitrise 上で失敗している Xcode Archive & Export iOS ステップあたりのログをみてみると、どうやら archive は無事に成功したものの、その生成物である xcarchvie ファイルを ipa に export するコマンドでエラー担っているようでした。

この export でコケるというので発見が遅れてしまいました。
ビルドは普通にできるし、Simulator での動作確認も普通にできるのです。

具体的な理由が知りたい場合は log ファイルをみろとあるので、そちらを見てみると内容はこんな感じ。

-[NSNull path]: unrecognized selector sent to instance 0x7fff806efeb0
** INTERNAL ERROR: Uncaught exception **
Uncaught Exception: -[NSNull path]: unrecognized selector sent to instance 0x7fff806efeb0
Stack:
  0   __exceptionPreprocess (in CoreFoundation)
  1   objc_exception_throw (in libobjc.A.dylib)
  2   -[NSObject(NSObject) __retain_OA] (in CoreFoundation)
  3   ___forwarding___ (in CoreFoundation)
  4   _CF_forwarding_prep_0 (in CoreFoundation)
  5   -[IDEDistributionProcessingPipeline process:] (in IDEFoundation)
  6   -[IDEDistributionPackagingStep loadFromExportOptions:error:] (in IDEFoundation)
  7   -[IDEDistributionDriver runWithDestinationPath:error:] (in IDEFoundation)
  8   -[Xcode3CommandLineBuildTool _distributeArchiveAndExit] (in Xcode3Core)
  9   -[Xcode3CommandLineBuildTool run] (in Xcode3Core)
 10   main (in xcodebuild)
 11   start (in libdyld.dylib)

どうやら NSNull のものにたいして メソッドを呼び出そうとしたので落ちている感じです。
ただ、なんで NSNull になっているんだ。そもそも何が?という感じで今ひとつ根本原因がわかりません。

結論

ログだけを見るとパッとわからなかったのですが、いろいろごにょごにょ(後述)した結果、Carthgae でビルドして生成された xcframework を設定する方法がまずかった事がわかりました。

Carthage の README Quick Start にあるステップ 6,7の記述がソレです。

  1. Drag the built .xcframework bundles from Carthage/Build into the "Frameworks and Libraries" section of your application’s Xcode project.
  2. If you are using Carthage for an application, select "Embed & Sign", otherwise "Do Not Embed".

ここらへんを僕は雑にやったため、組み込んだ xcframework が Do Not Embed になっていたのです。
これがどういう悪さをして export でコケる原因なっているかはわかっていませんが、こちらを Embed & Sign にすると無事に export ができるようになりました。
ここらへんを設定ミスって提出できないみたいな記事はいくつか見かけたので、Carthage の xcframework 対応するにあたっては割とあるあるなものを踏んだ気がしますね(汗)

ドキュメントは流し読みじゃなくてちゃんとよみましょう!

調査という名の右往左往(笑)

以下はその結論に達するまでの右往左往です。
別に得るものはないかと思うのですが、なんとなく残しておきます(笑)

Bitrise の該当ステップのバグでは?

今回対応したものにでここらに影響がありそうもの…と考えてすぐに思い当たったのが、Xcode 13.1 対応したのでそこらでなにか起きているのでは?というものです。
Xcode 13.1 で何かの挙動が変わったのだけれど、そのステップがその変更に対応できていないため失敗しているのでは…という思考の流れです。
さっそく該当ステップの GitHub リポに飛んだのですが、issue はとても静かなものでなにも騒がれていません。
ですが、自分が Workflow で設定しているステップのバージョンが 3.2.2 と古く、最新のものは v4.x なので、もしかしたら上げたら通るかもとおもってやってみたのですが、変わらず export で失敗しました。

Xcode のバージョンを上げたということがあって雑に Bitrise で何かあるのでは?と考えたのですが、ローカルでも export コマンドを叩いてみることにしました。
Bitrise でログを確認したらどのようなコマンドかはわかるので同じように叩いてみるだけです。
書いておくとこんな感じ。
xcodebuild "-exportArchive" "-archivePath" "生成されたxcarchiveパス" "-exportPath" "出力先のパス" "-exportOptionsPlist" "設定plistのパス"

結果は、おなじく export でコケて同じログが吐かれました。
Bitrise は全く関係ない事がわかりました。(Bitrise さんスマン 🙏)

変更点を追ってく

ということで、対応したものから一つ一つ追っていってどの段階で export コマンドがコケるのかを調べることにしました。
まずは最も怪しい(?)と思った Xcode 13.1 に上げたときの対応です、ところがこのタイミングでは export コマンドは失敗すること無く普通に通り無事に ipa が生成されました。

ということで、次に大きなものとして考えたのが、 Carthage の xcframework 対応です。 いままでは特に不都合がなかったので回避策でずっとやっていて、あとでやろうやろうと先延ばしにしていたのを今回やっと対応したという感じです。
先に結論で書いた通り、この変更で export がコケるようになっていました。
ということで、ドキュメントの導入手順を一から読み直したりして、Do Not Embed に気づいたというわけです…。
埋め込まないという意味合いでしょうし、NSNull になっているというログともなんとなくつながっている感がありますよね。

ちなみに、自分のプロジェクトではEmbeddedFrameworkを使っているのだけれど、そっちにXCFrameworkを入れる時に脳死で Embed & Sign にするとそれはそれで問題になります。本体に同じものがある場合は、EmbeddedFrameworkにいれるときは Do Not Embed でやる必要があるみたいな感じです。

参考