アプリが使うFrameworkとかを置き換える方法

普段生活をしていると、たまに WebKit.framework とかを特定のリビジョンに置き換えたくなりますよね。

ほとんどの Mac OS X アプリケーションは /System/Library/Frameworks/WebKit.framework を利用しています。例えば、こんな感じで。

otool -L /Applications/Line.app/Contents/MacOS/Line|grep WebKit  /System/Library/Frameworks/WebKit.framework/Versions/A/WebKit (compatibility version 1.0.0, current version 533.16.0)

で、これを特定の WebKit.framework に差し替えたいと。単純に思いつくのが、 /System/Library/FrameworksWebKit.framework を差し替える方法ですが、まあけして良い結果にはならないでしょうね。

次に思いつくのが dyld でなんとかする方法。これはわりと簡単で、 man 1 dyld でもわかるように、 DYLD_FRAMEWORK_PATH を使えば良い。こんな感じ。

$ env DYLD_FRAMEWORK_PATH=/Volumes/WebKit/WebKit.app/Contents/Frameworks/10.7 \
    /Applications/Line.app/Contents/MacOS/Line

でも、毎回これで起動するの面倒ですよね、と。

そこで登場するのが @executable_path となります。Mac OS X の dyld は、ライブラリのパスのなかに @executable_path があるとそれを実行時のバイナリの場所に置き換える機能があります。だから、Nantoka.app/Contents/Frameworks に特定のバージョンのライブラリを置いてそれを使うってことができるんですね。 そこで、半恒久的に置き換える方法として次のような手段があります。

 $ install_name_tool -change \
    /System/Library/Frameworks/WebKit.framework/Versions/A/WebKit \
    @executable_path/../Frameworks/WebKit.framework/Versions/A/WebKit \
    /Applications/Line.app/Contents/MacOS/Line

install_name_tool を使うとバイナリが覚えてるライブラリのパスを書き換えることができます。そこで、この例の場合は /Applications/Line.app/Contents/Frameworks/WebKit.framework を置けばそれを使ってくれます。見つからない場合は /System/Library/Frameworks にフォールバックします。 また、実際に WebKit.framework を置き換える場合は、関連する WebCore.frameworkJavaScriptCore.framework のそれぞれのパスも書き換えて、セットで置き換える必要があります。

まあ、だから何ってことはないんですが、実際にとあるアプリケーションのとある機能が、現在の WebKit.framework でうまく使えない! みたいなことがあったので、こうやってなおしましたよっていう覚書みたいなものでした。

ちなみに、ここで例につかってる Line の WebKit を置き換えてなにか楽しいことがあるかどうかはわかりません。