
2025/12/07 21:31
The Anatomy of a macOS App
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
改訂サマリー
この記事は、Classic Mac OS のリソース・フォーク方式(UI アセットが別のフォークに存在した)から NeXTSTEP のバンドルアーキテクチャへ進化した macOS の歴史を追っています。NeXTSTEP ではコード、リソース、およびメタデータをひとつのフォルダーに統合するバンドル構造が採用されました。各アプリケーションバンドル(
*.app)には、以下のようなサブフォルダを含む Contents ディレクトリがあります。
- MacOS – 実行可能バイナリ
- Resources – アイコン、GUI アセットなど
- Frameworks – バンドルされた動的ライブラリ
- XPCServices, Plugins, Extensions – オプションのサービスコンポーネント
バンドルには必須の
Info.plist が含まれ、実行ファイル名・アイコン・最小 macOS バージョン・ドキュメントタイプなどを指定します。さらに型/作成者情報を持つ PkgInfo ファイルがあればそれも格納できます。起動は二通りの経路があります:コマンドラインツールは launchd を使用し、アプリケーションは LaunchServices(および RunningBoard)によって plist のデータを元に起動されます。
OS X 10.5 以降、Apple は
_CodeSignature/CodeResources にコード署名(CDHashes)を追加し、整合性の検証を行っています。App‑Store アプリはさらに _MASReceipt ディレクトリに購入領収書を含み、2018 年以降は notarization が CodeResources 内にチケットを埋め込みます。ユニバーサルバイナリは同一ファイル内に Intel と Apple‑silicon の Mach‑O スライスを両方埋め込み、それぞれが独自の署名を持ちます。
すべてのコンポーネントをバンドル内に集中させることで、インストール・更新・削除が簡素化され、リソース不足によるエラーが減少し、署名・notarization・領収書検証によってセキュリティが強化されます。開発者はクロスアーキテクチャバイナリをサポートする標準化されたパッケージモデルの恩恵を受け、ユーザーはより滑らかなインストールと少ないリソース問題を享受できます。この傾向は、バンドル整合性への継続的な重視と階層内での拡張機能やサービスのさらなる統合を示唆しています。
本文
ウィンドウ環境で動作するプログラム―従来のコマンドラインから実行されるアプリケーションよりも複雑な要件を持つ―は、必要とするリソース(ウィンドウやメニューなど)をすべて1ファイルに埋め込む代わりに、Mac OS はそれらをアプリの「リソースフォーク」に格納し、新しい手法を確立しました。
以下は、2000年頃に登場した QuarkXPress 4.11 の例です。ResEdit(リソースエディタ)で表示されるリソースを確認すると、実行コードも
CODE リソースとして格納されており、各ファイルには Finder が作り出す「見せかけ」をサポートするタイプとクリエイター情報が付与されています。
Mac OS X
Mac OS X の設計時に NeXTSTEP から継承したバンドル構造へ移行しました。従来の多数のリソースを一元化せず、実行コードとそれ以前は Mac OS がサポートしていたリソースが格納されたディレクトリ階層でアプリを構成します。このバンドルは以下の標準形態に従います。
- 拡張子
のバンドル名を持ち、1つだけ.app
ディレクトリがあります。Contents
に実行コードが置かれます。ここには GUI アプリのメイン実行ファイルと、必要に応じて同梱されたコマンドラインツールが含まれます。Contents/MacOS- 別ディレクトリ
はアプリ専用アイコンや GUI コンポーネントを保持します。Resources
一部のアプリではさらに
ディレクトリに dylib(ライブラリ)を置くことがあります。Frameworks
- 重要ファイル 2 つ が存在します:
とInfo.plist
。PkgInfo
は Classic Mac OS から継承されたタイプとクリエイター情報を保持し、必須ではないようですがほぼ普遍的です。PkgInfo
(インフォプロパティリスト)は必須であり、実行ファイル名・アイコンファイル名(Info.plist
内)、必要最低 macOS バージョン、アプリのドキュメントタイプ宣言、バージョン番号などを指定します。Resources
macOS でコマンドツールを起動すると、その Mach‑O 実行ファイルは
launchd によって実行されます。アプリを起動する場合も同様に launchd が実行ファイルを起動しますが、事前に LaunchServices と RunningBoard を経由して起動プロセスが開始され、Info.plist などから取得した情報を用いて処理が進められます。
macOS(継続)
この構造は 2007 年の Mac OS X 10.5 Leopard でコード署名が導入されるまで安定していました。署名に対応するため、
_CodeSignature ディレクトリを追加し、その中に CodeResources ファイル(CDHashes を含む)を置きます。これによりアプリバンドルの整合性チェックが可能になります。
App Store で配布されるアプリはさらに
_MASReceipt ディレクトリにストア領収書を格納します。2018 年以降、Apple が notarization(ノタリゼーション)を導入すると、Apple が発行する「ticket」を CodeResources ファイルとしてバンドルに「スタップル」できます。
過去には Library/Application Support フォルダなどにインストールされていた追加アイテムも、現在はアプリバンドル内に含まれるようになりました。代表的なディレクトリは次の通りです:
(以前はユーザー Home またはメイン Library に設置されていたLibrary
・LaunchDaemons
を保持)LoginItems
(アプリが提供する特定サービス用実行コードを格納)XPCServices
(Appex 等の拡張機能)Plugins
(アプリ意図など他種の拡張機能)Extensions
Apple のアプリには
version.plist など、その他多様なコンポーネントが存在することもあります。
メリット
バンドル内に全てを集約することで、以下の利点があります:
- 自己完結型:インストール・更新・削除が容易で、残留ファイルのリスクが低減。
- 欠落しにくい:コンポーネントがバンドル内にあるため、外部から消失することはほぼありません。
- セキュリティ強化:アプリ署名とノタリゼーションで保護されるため、不正改ざんの検出が容易。
図解(概要)
- 淡黄色:必須または基本的に全アプリ共通のコンポーネント。
- 緑色:App Store 経由で配布されるアプリに見られるコンポーネント。
- 青色:ノタリゼーション票(スタップル)がある場合。
(任意)
また、Automator ワークフローやスクリプトなど追加フォルダも含まれます。
Intel と Arm アーキテクチャの共通性
現在 Intel および Arm 用にビルドされたアプリは構造上差異がありません。
Contents/MacOS(および Frameworks、XPCServices、Plugins など)のバイナリは単一 Mach‑O 実行ファイル内にプラットフォーム固有コードを持ちます。Universal アプリの場合、1つの「fat」コードファイルに両アーキテクチャ用のコードが含まれ、共通ファイル内に別々の署名も保持されます。