MacPorts で package を作る

ふだんの開発環境は MacPorts を使ってるのだけれど、自分の書いたプログラムをバイナリ配布するにはライブラリも配布しなきゃいけないわけだ。で、MacPorts には、個々の port を package にする機能に加えて依存関係をぜんぶまとめた meta package を作る機能もついている。

しかし、port mpkg gtk2 としたら、Xft2 のところで「もう一度インストールしてください」みたいなメッセージを出して停まってしまった。で、Xft2 の .pkg の下をチェックしたら、Contents/ の下に Archive.pax.gz と Archive.bom というファイルがなくて、他にもいくつかそういう package が存在するみたいだ。pax は tar みたいなもので、FreeBSD なんかにも付いている模様。bom はつまり、bill of materials で、要するにファイル一覧を入れておくものみたいだ。

そんなわけで、こんな script 書いてみた。

#!/bin/csh
setenv PKGDIR ${PWD}
cd /
pax -w `port contents $1 | awk '{i++; if(i!=1) print "."$1}'` > ${PKGDIR}/Archive.pax
cd ${PKGDIR}
mkdir tmp
cd tmp
cat ../Archive.pax | pax -r
mkbom . ../Archive.bom
cd ..
gzip -9 Archive.pax
rm -rf tmp

これで、

cd PACKAGE-VERSION.pkg/Contents
csh mkpackage.csh PACKAGE

とかすれば OK なはず。

あと、meta package の Contents/Info.plist に載ってる subpackage name と、Contents/Resources 以下の subpackage name が食い違っていることがある模様。要注意。

launchd HOWTO

MacOS X 10.5 has autofs, but 10.4 doesn’t. Alternative solution is am-utils, available in MacPorts. However, MacPorts doesn’t provide any way to launch amd at startup.

In MacOS X, there’s no scripts like /etc/rc, but there’s launchd. I spent about a half day to launch amd by launchd and learned:

  • Write the policy to launch in /System/Library/LaunchDaemons/foobar.plist
  • The process spawned by foobar.plist must NOT go background, but must stay in foreground (see launchd.plist(5)!).

However, my sweet amd goes background… So, launchd misunderstands: “Oh, amd is dead. I must start a new one!” and there will be so many amd processes.

As the solution, I wrote a simple wrapper script (amd_start) like:

#!/bin/sh
/opt/local/sbin/amd -F /opt/local/etc/amd.conf
while [ true ]; do
sleep 360000
done

And my amd.plist is this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>amd</string>
<key>OnDemand</key>
<false/>
<key>ProgramArguments</key>
<array>
<string>/System/Library/amd_start</string>
</array>
<key>ServiceIPC</key>
<false/>
</dict>
</plist>

Put this in /System/Library/LaunchDaemons/amd.plist, then:

% sudo launchctl load /System/Library/LaunchDaemons/amd.plist

This will launch amd.

launchd is fun… It works as /etc/rc, crond and inetd. Wow.