初代Rosettaをリアルタイムで経験した身としては、正直Rosetta 2のパフォーマンスは狐につままれたような気分だが、iOSアプリがそのまま動くというのもまた不思議な話だ。同じARMアーキテクチャだから(バイナリに互換性がある)、iOSはmacOS派生で使用するフレームワークも共通なものが多いからということは理解できるが、ここまであっさり動くとは。拍子抜け、という言葉が腑に落ちる。
とはいえ、macOSネイティブのアプリとの相違点は必ずあるはずで、特別な仕様や制約があるかもしれない。今回は、M1 MacにおけるiOSアプリのあれやこれやを調べてみよう。
iOSアプリのフォルダ構造
Mac App StoreでiOSアプリをダウンロードすると、ファイル一式はmacOSのセオリーに従いアプリケーションフォルダ(/Applications)にインストールされる。一見単一のファイルだが実際はフォルダというバンドル構造、拡張子に「.app」が付くが非表示というスタイルはmacOSと同じ、というよりiOS/iPad OS(のホーム画面を管轄するSpringBoard)ではユーザに見せなかっただけに過ぎない。
バンドルの内容物は、一般的なmacOSアプリ同様、FinderでControlキーを押しながらアプリアイコンをクリックし、現れた「パッケージの内容を表示」を選択すればOK。ただし、macOSアプリとは構造が異なり、最初に姿を見せるフォルダは「Contents」ではなく「WrappedBundle」というエイリアスと、「Wrapper」というフォルダだ。
そのWrapperフォルダを開くと、最初に表示されたものと同一(○○○.app)の名称を持つiOSアプリの実体部分が現れる。アイコンには進入禁止の斜線が引かれておりダブルクリックしても起動できないが、これに対し「パッケージの内容を表示」を実行すると、iOSアプリを構成する一切合切がFinder上に出現する。
アプリにもよるが、そこには膨大な数のファイルがある。一切隠ぺいされることなく表示されるため、UIを構成するボタン類(PNG画像)はもちろんのこと、テキストベースのリソースファイル(*.jsonや*.tsvなど)、StoryBoardファイルまで閲覧できてしまうし、コピーも可能だ。この点、アプリ開発者は意識を高める...というか対策を講じなくてはならないだろう。
依存するライブラリは
iOSアプリの内部を覗いたついでに、メモリの状況や依存するライブラリ/フレームワークについて調べてみた。利用するツールは「vmmap」と「otool」、どちらも開発者ツールに収録されている定番のコマンドだから敢えて説明するまでもないだろう。
起動したiOSアプリのプロセスIDを調べ、それをもとにvmmapコマンドを実行したところ、Platform欄が「iOS」なこと、OS Versionが「Mac OS X 10.16 (20A2411)」なことを除けば、特筆するほどの情報はなし。OS Versionについては、macOSアプリが「macOS 11.0 (20A2411)」とビルド番号は一致しているため、単なる表記ミスと思われるが、とにかくシステムにiOSアプリと認識されていることは確かだ。
otoolコマンドで調べた依存ライブラリの情報も、ごく当たり前のもの。CoreGraphicsやCoreImageなどシステム標準のフレームワークは、macOSアプリと同じ/System/Library/Frameworks以下を指しているし、macOSとiOSのブリッジ的な役割と思しき名前のフレームワークは見当たらない。強いて言えば、「CoreTelephony」や「AdSupport」など、macOSアプリではあまり見かけないフレームワークが使われているなあ、と思う程度だ。
IPAファイルも動く!
過去にiTunesでバックアップしたアプリ(*.ipa)の動作も確かめてみた。最近iOSアプリの管理はクラウドに移行していたため、約3年前のものしか見つからなかったが、動作確認程度はできるだろう。
驚いたことに、IPAファイルはダブルクリックするだけでインストールできる。アプリケーションフォルダに一式を展開したあと、ご丁寧にも「○○○が正常にインストールされました。インストーラパッケージをゴミ箱に入れますか?」と確認する念の入りようで、Mac App Store経由でインストールするより手間がかからないほどだ。
手元にあったiOSアプリは起動直後にバージョンチェックを行い、古い場合はアップデートしないと先へ進めないしくみのため、残念ながらしっかりとした動作確認はできなかったが、起動自体は問題ないことがわかった。念のためバイナリを調べて見ると32bit(armv7)と64bit(arm64)のユニバーサルバイナリ、ここ数年公開されたアプリであればすんなり動くと推定される。
さらに念を入れ、lipoコマンドを使いiOSアプリの実行ファイルを32bitオンリー(armv7のシングルバイナリ)に改変して実行したところ、期待どおり(?)起動できなくなった。当然といえば当然だが、M1 Macで動作するiOSアプリを絞り込むうえでは参考になる情報かと思う。