きりかノート 3冊め

おあそびプログラミング

packagemakerコマンドでインストーラをつくる

この記事は Mac Dev JP Advent Calendar の参加記事(17日目)です。

今日は私が開発に参加しているRubyCocoaをモデルに、packagemakerコマンドでインストーラパッケージを作成する手順を紹介します。

PackageMakerとは

PackageMakerは「インストーラ」アプリケーションでインストールするときに使う、.pkgや.mpkgといったパッケージを作成するソフトウェアです。

通常のアプリケーションはインストーラでなく、ディスクイメージなどの中に.appファイルを入れておき、ユーザが自由に配置できるようにしておくのが一般的です。インストーラを使用したインストールが適しているのは、「決められた位置にファイルをインストールする」ことが求められる場合です。たとえば、

  • 環境設定パネル(.prefPane) - Library/PreferencePanes/
  • かな漢字変換などのインプットメソッド(.app) - Library/Input Methods/
  • サービス(.app, .service) - Library/Services/
  • 汎用のフレームワーク(.framework) - Library/Frameworks/
  • 多数のファイルをそれぞれ配置する(Xcode, MacPortsなど)

などです。これらを配布するときは、ユーザに適切な場所にコピーするよう依頼するよりも、インストーラで自動的に決められた場所に配置されるようになっているほうが親切ってもんです。

GUIでなくコマンドを使う理由

PackageMakerにはここで紹介するコマンドの他に、GUIのアプリケーションがあります。というかそちらが本家です。

一般論ではありますが、コマンドのほうが自動化や繰り返しのオペレーションに適しています。これはPackageMakerにもあてはまり、RubyCocoaでは2006年ごろからリリース用のインストーラの作成は以下のコマンド一発になっています。

 % ruby install.rb package # または rake package

packagemakerコマンドの使い方

なにはともあれmanです。packagemaker(1)。最後にあるEXAMPLESを見ると感じがつかめるのではないかと思います。

  • packagemaker -root: 新しい書き方(10.5-)
  • packagemaker -build: 古い書き方(-10.4) manの下のほう

どちらでもインストーラを同様に作成できますが、10.5以降の1ファイル(バンドルでなくフラット)のインストーラは新しい書き方でしか作成できません。新スタイルのほうは.pkgが単一のファイルとなるため、配布に.dmgや.zipで固めなくてもよい、署名できるというメリットがあります。

フラットな.pkg

 % ls -l InstallXcodeLion.pkg
 -rw-r--r--  1 kimuraw  staff  3189834552 Jul 19 12:08 /Volumes/Install Xcode/InstallXcodeLion.pkg
 % xar -t -f InstallXcodeLion.pkg
 Distribution
 InstallXcodeLion.pkg
 InstallXcodeLion.pkg/Bom
 InstallXcodeLion.pkg/PackageInfo
 InstallXcodeLion.pkg/Payload
 Resources
 Resources/English.lproj
 Resources/English.lproj/License.rtf
 Resources/English.lproj/Localizable.strings

バンドル形式の.pkg

 % ls -la RubyCocoa-1.0.2-OSX10.7.pkg
 total 0
 drwxr-xr-x  3 kimuraw  staff  102 Dec 17 14:29 ./
 drwxr-xr-x  6 kimuraw  staff  204 Dec 17 14:29 ../
 drwxr-xr-x  7 kimuraw  staff  238 Dec 17 14:29 Contents/

RubyCocoaでは古い書き方のころにパッケージスクリプトを作成して、そのまま問題も起きてないということで、そのままになっています。

実際の使用

  • インストールするファイル
  • ReadMe, Licenseなどのインストーラに表示する内容
  • Info.plist
  • Description.plist

これらを用意して、packagemakerコマンドで.pkgファイルを作成します。

Info.plist

Info.plistではバージョンや識別子のほかに、インストールに必要な要件を指定することができます。たとえば、RubyCocoaではインストールできるシステムのバージョンを制限しています。


 <key>IFRequirementDicts</key>
 <array>
   <dict>
       <key>SpecArgument</key>
       <string>/System/Library/CoreServices/SystemVersion.plist</string>
       <key>SpecProperty</key>
       <string>ProductVersion</string>
       <key>SpecType</key>
       <string>plist</string>
       <key>TestObject</key>
       <string>10.7</string>
       <key>TestOperator</key>
       <string>&gt;=</string>
   </dict>
   <dict>
       <key>SpecArgument</key>
       <string>/System/Library/CoreServices/SystemVersion.plist</string>
       <key>SpecProperty</key>
       <string>ProductVersion</string>
       <key>SpecType</key>
       <string>plist</string>
       <key>TestObject</key>
       <string>10.8</string>
       <key>TestOperator</key>
       <string>&lt;</string>
   </dict>
 </array>

残念ながら現在のAppleのドキュメントにはこれらの詳細は記載されていません。TigerLeopardごろのドキュメントにはあったと思います。

コマンド実行

それぞれ用意したらあとはコマンドの実行です。

 % packagemaker -build \
       -p work/RubyCocoa-1.0.2-OSX10.7/RubyCocoa-1.0.2-OSX10.7.pkg \
       -f work/files \
       -r work/resources \
       -i work/Info.plist \
       -d work/Description.plist

終わりに

こんかいこの記事を書くにあたって、新しい-rootオプションを使用したコマンドも試してみたのですが、ReadMeやLicenseを表示させる手順がわかりませんでした(-resourcesに指定した場所に置いてもダメ)。ご存知の方は教えてください!

新しいpkgbuildコマンドについても知りたいです!