🥷

CocoaPodsのSpecを更新しようと思ったら、VisionOSが絡んでlintが通らなかった話

2024/03/15に公開

「よし。改修も終わり。あとはSpecファイルのバージョン更新を加えて公開するだけだな。」

pod spec lint …… ERROR

「🤔🤔🤔🤔🤔」

あらすじ

  • CocoaPodsへ登録する作業中にエラーが発生して進めなくなった
  • pod spec lint Example.podspec としたが、エラーが発生してしまって進行できない
 pod spec lint Example.podspec

-> Pod installation complete! There is 1 dependency from the Podfile and 1 total pod installed.
   Building with `xcodebuild`.
 -> Example (1.0.0)
    - ERROR | [iOS] unknown: Encountered an unknown error (unexpected token at 'objc[56344]: Class XROS1_0SimRuntime is implemented in both /Library/Developer/CoreSimulator/Volumes/xrOS_21N305/Library/Developer/CoreSimulator/Profiles/Runtimes/xrOS 1.0.simruntime/Contents/MacOS/xrOS 1.0 (0x104dd00e0) and /Library/Developer/CoreSimulator/Volumes/xrOS_21N5165g/Library/Developer/CoreSimulator/Profiles/Runtimes/xrOS 1.0.simruntime/Contents/MacOS/xrOS 1.0 (0x106dac0e0). One of the two will be used. Which one is undefined.
# 〜スタックトレース〜
'
) during validation.

エラーメッセージの解読

  • 不明なエラーに遭遇したらしい
    • 期待していないトークンとは?
  • Class XROS1_0SimRuntime is implemented in both
    • /Library/Developer/CoreSimulator/Volumes/xrOS_21N305/Library/Developer/CoreSimulator/Profiles/Runtimes/xrOS 1.0.simruntime/Contents/MacOS/xrOS 1.0 (0x104dd00e0)
    • /Library/Developer/CoreSimulator/Volumes/xrOS_21N5165g/Library/Developer/CoreSimulator/Profiles/Runtimes/xrOS 1.0.simruntime/Contents/MacOS/xrOS 1.0 (0x106dac0e0)
    • どちらかが使われるが未定義であるという文言
  • xrOSってAppleVision用のOSっぽい
    • iOS向けの改修しかしてないんですが…

スタックトレースを見る

/(省略)/gems/json-2.7.1/lib/json/common.rb:219:in `parse'
/(省略)/gems/json-2.7.1/lib/json/common.rb:219:in `parse'
/(省略)/gems/fourflusher-2.3.1/lib/fourflusher/find.rb:125:in `fetch_sims'
/(省略)/gems/fourflusher-2.3.1/lib/fourflusher/find.rb:101:in `usable_simulators'
/(省略)/gems/fourflusher-2.3.1/lib/fourflusher/find.rb:97:in `simulator'
/(省略)/gems/fourflusher-2.3.1/lib/fourflusher/xcodebuild.rb:7:in `destination'
/(省略)/gems/cocoapods-1.15.2/lib/cocoapods/validator.rb:1095:in `xcodebuild'
/(省略)/gems/cocoapods-1.15.2/lib/cocoapods/validator.rb:743:in `block in build_pod'
/(省略)/gems/cocoapods-1.15.2/lib/cocoapods/user_interface.rb:149:in `message'
/(省略)/gems/cocoapods-1.15.2/lib/cocoapods/validator.rb:723:in `build_pod'
/(省略)/gems/cocoapods-1.15.2/lib/cocoapods/validator.rb:410:in `block in perform_extensive_analysis'
/(省略)/gems/cocoapods-1.15.2/lib/cocoapods/validator.rb:398:in `each'
/(省略)/gems/cocoapods-1.15.2/lib/cocoapods/validator.rb:398:in `perform_extensive_analysis'
/(省略)/gems/cocoapods-1.15.2/lib/cocoapods/validator.rb:129:in `validate'
/(省略)/gems/cocoapods-1.15.2/lib/cocoapods/command/spec/lint.rb:90:in `block in run'
/(省略)/gems/cocoapods-1.15.2/lib/cocoapods/command/spec/lint.rb:71:in `each'
/(省略)/gems/cocoapods-1.15.2/lib/cocoapods/command/spec/lint.rb:71:in `run'
/(省略)/gems/claide-1.1.0/lib/claide/command.rb:334:in `run'
/(省略)/gems/cocoapods-1.15.2/lib/cocoapods/command.rb:52:in `run'
/(省略)/gems/cocoapods-1.15.2/bin/pod:55:in `<top (required)>'
/(省略)/bin/pod:23:in `load'
/(省略)/bin/pod:23:in `<top (required)>'
  • どうやら JSON parser に期待しないトークンが流れ込んだらしい
    • objc[~~] 以降のメッセージすべて
  • fourflusher/find.rb が JSON parser にわたす箇所に異常がある?

原因を調査する

fourflusher/find.rb を見る

    def fetch_sims
      device_list = JSON.parse(list(['-j', 'devices']))['devices']
      # 省略
    end

https://github.com/CocoaPods/fourflusher/blob/b1d9bbbdb35d577b2c6d7d77e3f7770b03d34ae1/lib/fourflusher/find.rb#L125

  • list 関数の結果がおかしいらしい
    • GitHubの補助いわく、この関数は fourflusher/simctr.rb に定義されているらしい

fourflusher/simctr.rb を見る

require 'fourflusher/executable'

module Fourflusher
  # Executes `simctl` commands
  class SimControl
    extend Executable
    executable :xcrun

    def list(args)
      simctl!(['list'] + args)
    end

    private

    def simctl!(args)
      xcrun!(['simctl'] + args)
    end
  end
end

https://github.com/CocoaPods/fourflusher/blob/b1d9bbbdb35d577b2c6d7d77e3f7770b03d34ae1/lib/fourflusher/simctl.rb#L9-L17

  • list(args) はどうやら simctl!(args) を呼び出すためのショートハンドらしい
  • そして simctl!(args)xcrun!(args) を呼び出すためのショートハンドらしい
  • この時点で、直感的には xcrun コマンドを叩いているものと想定できる
    • fourflusher/executable を確認したところ、コマンドを組み立てて実行し、結果を取り込んでいた

つまり、JSON parser に渡されている内容はコマンドの実行結果である。

コマンドを叩いてみる

xcrun simctl list -j devices > /dev/null

objc[56969]: Class XROS1_0SimRuntime is implemented in both /Library/Developer/CoreSimulator/Volumes/xrOS_21N305/Library/Developer/CoreSimulator/Profiles/Runtimes/xrOS 1.0.simruntime/Contents/MacOS/xrOS 1.0 (0x1033f80e0) and /Library/Developer/CoreSimulator/Volumes/xrOS_21N5165g/Library/Developer/CoreSimulator/Profiles/Runtimes/xrOS 1.0.simruntime/Contents/MacOS/xrOS 1.0 (0x1053d40e0). One of the two will be used. Which one is undefined.
  • 同コマンドの内容を jq に流したところ問題はなかった
    • つまり、標準出力の内容は問題なさそうだった
  • 標準エラー出力の内容が一致した

原因はどこであるか?

  • fourflusher/executable が標準出力も標準エラーもまとめて出力してるのは良くないんじゃないのか
  • そもそも Apple の提供するコマンドラインツール xcrun が重複したシミュレーターランタイムを埋め込んでしまうのが悪いんじゃないか

どうすべき

  • ダブってる xrOS を除去したいね
    • どこからインストールされたのだろう?
      • 環境に導入されているXcodeは
        • Xcode 14.1
        • Xcode 15.0.1
        • Xcode 15.2 (AppStore)
      • Xcode ごとにVisionOSシミュレーターを確認してみる
        • Xcode 15.2 でのみ、Device and Simulator から 21N305 を確認できた
          • つまりモデル名らしい
            • 21N5165g をかるく検索してみたところ、 VisionOS 1.0 Beta 1のモデル名らしい
  • 消せばなんとかなるのでは?
    • xcrun simctl list を眺めてみると、問題は Runtime にあるらしい
    • xcrun simctl help を叩いてみると、 runtime というサブコマンドがあった
    • xcrun simctl runtime help を叩いたところ、 add|delete|list が見受けられた

消そう、ランタイム。

xcrun simctl runtime list

== Disk Images ==
-- iOS --
iOS 17.2 (21C62) - D6D0354A-CFBA-4ACA-8822-0D5E24C33E9F (Ready)
iOS 17.0.1 (21A342) - C8355079-AB6B-4B44-98D7-3574515C8646 (Ready)
iOS 17.0 (21A5268h) - 6BA83493-ADA5-4D2C-B09F-1A5B7BDE5505 (Ready)
-- xrOS --
xrOS 1.0 (21N5165g) - A50B8FE4-D630-40F1-9E99-07426329D58D (Ready)
xrOS 1.0 (21N305) - 7FC5D98B-702A-4B63-ACB3-88C400AD4295 (Ready)

Total Disk Images: 5 (34.1G)

各imageにUUIDが振られているとわかる

xcrun simctl runtime delete -n A50B8FE4-D630-40F1-9E99-07426329D58D

Would delete D: A50B8FE4-D630-40F1-9E99-07426329D58D xrOS (1.0 - 21N5165g) (Ready)

--dry-run(-n) をかけて、予行演習できる。

xcrun simctl runtime delete A50B8FE4-D630-40F1-9E99-07426329D58D

消してみたので、確認してみる。

xcrun simctl runtime list

== Disk Images ==
-- iOS --
iOS 17.2 (21C62) - D6D0354A-CFBA-4ACA-8822-0D5E24C33E9F (Ready)
iOS 17.0.1 (21A342) - C8355079-AB6B-4B44-98D7-3574515C8646 (Ready)
iOS 17.0 (21A5268h) - 6BA83493-ADA5-4D2C-B09F-1A5B7BDE5505 (Ready)
-- xrOS --
xrOS 1.0 (21N305) - 7FC5D98B-702A-4B63-ACB3-88C400AD4295 (Ready)

Total Disk Images: 4 (27.2G)

消えた!

xcrun simctl list …… エラーなし!

pod spec lint …… エラーなし!

解決!

さぁ君も壊してみよう

  1. すでにインストール済みのランタイムを確認する
    • AppStore からインストールしたXcode 15.2 に付属する、xrOS 1.0 すなわち VisionOS 1.0 正式版がインストールされているものとする
  2. Apple Developer の Download ページから、 VisionOS 1.0 Beta 2 をダウンロードする
    • 2024-03-15 現在で手に入る古い VisionOS 1.0 の Beta版
  3. xcrun simctl runtime add '~/Downloads/visionOS_1_beta_2_Simulator_Runtime.dmg' を実行する
  4. 再現完了!

誰が原因だった?

  • VisionOS の Beta公開に飛びついた筆者自身?
  • iOS runtime の Beta では再現できなかったからやっぱり Apple が悪いよ
GitHubで編集を提案

Discussion