ロード可能バンドルについて
ロード可能バンドルはランタイムに読込み可能な、実行コードと関連リソースのパッケージです。 この柔軟性は、高度なモジュール性、カスタム性、そして拡張性を持つアプリケーションの設計を可能とします。 本ドキュメントを読み終えた後、あなたはロード可能バンドルの構築方法とそれらの使い時について理解するでしょう。
ロード可能バンドル入門
Mac OS Xはバンドルと呼ばれるディレクトリ構造を、実行コードと関連リソースを一纏めにするためにシステムの至る所で使用しています。 実体であるバンドルディレクトリは、個別のパッケージであるリソース群を1つの集合体に“バンドル”します。 リソースには、Interface Builderのnibファイル、画像、音声、ローカライズ用文字列といった物が含まれます。 実行コードと関連するリソースがファイルシステム上の1つの場所にあるため、インストールやアンインストール、あるいはその他のソフトウェア管理に関する手間がより簡単になります。
バンドルには、アプリケーション、フレームワーク、そしてロード可能バンドルといったように、いくつかの種類があります。 本ドキュメントは特に、ランタイムにロード可能なコードを含み、静的コンパイルのいくつかの制約からあなたを解放するロード可能バンドルについて扱います。 ロード可能バンドルに基づいたアプリケーション設計は、あなたにいくつかの利点をもたらします:
- 必要とされる時点までコードの読込みを遅らせる事が出来ます。また、いくつかのケースでは必要が無くなった時にコードの解放が出来ます。
- アプリケーションを、依存関係がなくコンパイル可能なコンポーネント単位に分割出来ます。このため、開発の分業とバージョン違いの各コンポーネントのテストがより簡単になります。
- プラグイン機構を設計することで、アプリケーションに拡張性を持たせる事が出来ます。これにより、あなた、もしくは第三者の開発者がアプリケーション全体の再コンパイルやソースコードに触れる事なく、新機能を容易に追加する事が出来ます。
ロードしたコードの解放は、Cocoaランタイム環境を使用していないアプリケーションのみに制限されています。 本稿執筆時点において、Objective-CランタイムはObjective-Cシンボルのアンロードに対応しておらず、その為、Cocoaバンドルも一度読込まれるとアンロードする事は出来ません。
Mac OS Xはロード可能バンドルの識別子として.bundle
拡張子を定義しています。
あなたは特定の種類のバンドルに対して、独自の拡張子(とアイコン)を定義する事も出来ます。
カーネル拡張は、システムのバンドルルーチンに認識され適切に扱われる、ロード可能バンドルの一種です(とは言え、その内部構造は他のロード可能バンドルとは異なります)。
これらのバンドルは.kext
拡張子を持ちます。
カーネルマネージャは、ドキュメントタイプがカーネル拡張であるバンドルを動的にカーネル環境へロードします。
本稿ではカーネル拡張についてこれ以上は扱いません。
より深く学ぶには、Darwin Documentationをご覧下さい。
バンドルについての更なる情報は、Bundle Programming Guideをご覧下さい。Mac OS Xにおけるコード読込み・実行機構に関する詳細はMac OS X ABI Mach-O File Format Referenceをご覧下さい。
ロード可能バンドルの使い時
基本的には、ロード可能バンドルはコードの読込みとシンボルの結合を、ランタイム時に行えるようにするものです。 実践的には、ロード可能バンドルは以下の3つのような事項が必要となった時に、あなたの助けとなります。
- 遅延リンクと遅延読込み(原文:Delayed (“lazy”) linking and loading)
- コードコンポーネントのモジュール化
- アプリケーションの拡張性
遅延リンクとロード
巨大で複雑なアプリケーションは様々な機能を持ちます。 しかしユーザーはたいてい、一時のアプリケーション使用においてその全ての機能を必要としている訳ではありません。 これは、アプリケーションコードの塊(所々に重要な部分が含まれます)がメモリに読込まれるものの、決して使用されない事を意味します。
アプリケーションを関係するロジックのコードから成るロード可能バンドルに区分けする事で、不必要なコード読込みを避ける事が出来ます。 また、これらコード片にアクセサ関数ないしメソッドを含める事で、そのコードが読込まれているかどうか直接確認する事なく、シームレスにオブジェクトを参照する事が出来ます。これらの確認はアクセサメソッド内で暗黙的に行われるのです。
遅延読込みは、巨大なアプリケーションの一部を頂上に据え、他の特定の機能を下位に置くといったような階層構造を取る事が出来ます。 特定の機能は、典型的には“アプリケーションの拡張性”で述べるプラグインの形態を採ります。
コードのモジュール化
アプリケーションを論理的に分かれたコードコンポーネントにモジュール化する方法は、幾つかあります。 コードをモジュール化する基本的な方法は、複数のソースファイルに分ける事です。取るに足らないアプリケーション以外はこの方法でビルドされます。 モジュール化レベルの次の段階はフレームワークです。これはディレクトリパッケージに、実行コード、ヘッダファイルを持ち、その他のリソースが含まれる事もあります。ちょっと手間の掛かる方法ですが、モジュールの単位としてロード可能バンドルを使う事も出来ます。
あらゆる状況でロード可能バンドルが相応しい訳ではありませんが、一手間掛ける事でより多くの利益を得る事が出来ます。 コードを複数のバンドルに分離すると、それぞれのバンドルはフレームワークと同等か、それ以上に独立した中で開発とテストを行う事が可能です。 バンドルは動的に読み込まれる実行可能コードを含むので、アプリケーションの他の部分は関数アドレスやオブジェクトのアドレス、そして参照するオブジェクトの所属先クラスにすら囚われません。クラスを利用するための情報さえ知っていれば十分なのです。 異なるコードコンポーネントの異なるバージョンのテストを、アプリケーションの再コンパイルなしに行う事が出来ます。Finderでアイコンをドラッグして、異なるコンポーネントをくっつけるだけでいいのです。
アプリケーションの拡張性
ロード可能バンドルの一番多い使われ方は、アプリケーションの拡張性ニーズに因るものです。 あなたのアプリケーションを、あなたの組織内部あるいは第三者の開発者に拡張して欲しいなら、あなたはプラグイン機構を定義する事が出来ます。 プラグイン機構は、プラグインと呼ばれる適切に構築されたロード可能バンドルが、機能の追加を行えるようにするインタフェースを定義します。 プラグインの例として、スクリーンセーバーモジュール、環境設定ペイン、Interface Builderパレット、Adobe Photoshopのグラフィックスフィルター、iTunesのミュージックビジュアライザーがあります。
留意点
CocoaならびにCore Foundationが豊富なAPIサポートを提供しているとはいえ、ロード可能バンドルの利用は“タダ”ではありません。 ロード可能バンドルを利用するかどうかを判断する場合、以下のコストが掛かることに留意して下さい:
- アプリケーションバンドルやフレームワークとは違い、ロード可能バンドルはランタイム時に明示的に読込まれなければなりません。コードの再利用性は必要なものの動的読み込みが不要な場合は、たいていフレームワークの方がより良い選択です。
- Cocoaにおいて、読込み可能バンドルが巨大なコードの欠片のためのメモリ管理スキームとして使われることはありません。Cocoaバンドルは解放が出来ない為です。
- プラグイン機構を定義するには、プラグインモジュールの妥当性を慎重に確認する必要があります。
- アプリケーションに外部プラグインコードを許可することは、安定性とセキュリティ問題を呼び寄せます。
しかしながら、アプリケーションが遅延読込みや、フレームワーク以上に動的なモジュール性、もしくは拡張性を必要とする場合に、ロード可能バンドルを利用します。
ロード可能バンドルの構造
バンドルディレクトリは、適切な場所に配置されるリソースと実行コードの階層構造を持ちます。 典型的なバンドルディレクトリ階層をリスト1に示します。
リスト1 典型的なロード可能バンドルのディレクトリ配置
- MyLoadableBundle Contents/ Info.plist MacOS/ MyLoadableBundle Resources/ Lizard.jpg MyLoadableBundle.icns English.lproj/ MyLoadableBundle.nib InfoPlist.strings Japanese.lproj/ MyLoadableBundle.nib InfoPlist.strings
全てのバンドルディレクトリは1つのアイテム、Contents
ディレクトリを持ちます。
全てのバンドルのContents
には2つのファイルInfo.plist
とPkgInfo、同様に
MacOSディレクトリを持ち、これには実行コード、そしてコード以外の全ての資源を持つ
Resourcesディレクトリが含まれます。
より複雑なバンドルでは、本格的なアプリケーションパッケージでサポートされるような
Frameworks、
PlugIns、
SharedFrameworks、
SharedSupportといった追加のディレクトリが含まれることもあります。
Info.plistまたは情報プロパティリストは、そのバンドルに関する情報のキー-値ペアを含むXMLプロパティリストです。
ランタイム時にシステムルーチンは、バンドルの実行可能コードにこれら属性の読み取りを許可します。
その他のアプリケーション定義データを情報プロパティリストに格納するのも自由です。
Xcodeは情報プロパティリスト編集用のインタフェースを提供し、そしてデフォルトで要求される全てのキーも含有します。
Resourcesディレクトリの言語ディレクトリ(
Japanese.lprojなど)に含まれる
InfoPlist.stringファイルに対応する項目を追加することで、情報プロパティリストのキーをローカライズすることが出来ます。
ロード可能バンドルの最も重要な情報プロパティリストのキーは、以下の通りです:
* CFBundleExecutable: 実行可能コードの名前。一般的に拡張子を除いたそのバンドルディレクトリ名と同名。
* CFBundleIdentifier: DNS名の逆順で表されるバンドルのグローバルで一意的な識別子(例:
com.apple.screensaver.Flurry)
* CFBundleName: 人間が識別に用いるバンドルの(ローカライズされるべき)短い名前。
* CFBundleDisplayName: ユーザーがリネームしない限りFinderでの表示に用いられる(ローカライズされるべき)バンドルの表示名。
Info.plistの標準的な全キーの完全な解説については、“Property List Key Reference”をご覧下さい。
MacOSディレクトはロード可能バンドルのMach-O実行可能コードを含みます。
このディレクト中の実行可能ファイルの名前は、一般的にそのバンドルディレクトリ名から拡張子を除いたものと等しく、また情報プロパティリストの
CFBundleExecutableキーの値とも一緒です。
バンドルの若干の種類によっては実行可能コードが無いこともあります。
しかしながら、ロード可能バンドル、アプリケーション、そして他の大部分の種類のバンドルは本質的に実行可能コードを必要とします。
Resourcesディレクトリは、音声、画像、Interface Builderのnibファイル、ローカライズ済み文字列といった、バンドルと連携する全てのリソースを持ちます。
ローカライズ済みリソースは言語名
.lprojディレクトリの中に含まれます。
Resources''にサブディレクトリを作成し、リソースの分類を行うことも出来ます。
情報プロパティリストの詳細な情報は“Information Property Lists”をご覧下さい。