Gecko SDK 9でXPIDLのコンパイルがpythonスクリプトになった

Firefox(XULアプリ)アドオンでバイナリコンポーネント(ネイティブ実装)を含んでいる場合、アプリケーションがメジャーバージョンアップするとそれに対応したGecko SDKでビルドしなおさないと行けないという不毛な作業がある。

https://developer.mozilla.org/En/Developer_Guide/Interface_Compatibility

Beginning with Mozilla 2 (Firefox 4), this will no longer be supported: all @status markings have been removed, and extensions that use binary components will need to recompile for each major version they wish to support.

残念ながら高速リリースが始まってからこれは仕様として必須の作業なのである。

とはいえやることはGeckoSDKを差し替えてビルドしなおすだけで、今回も何も考えずにその通りやったらxpidlからタイプライブラリ(xpt)が作成できなかった。

調べたら今回から pyxpidl というXPCOMのidlをコンパイルするツールがpythonのスクリプトに変わっていた。

これまでこのツールはバイナリで提供されていたので当然このツール自体もクロスプラットフォーム対応になっていた。おそらくMozilla側もそのクロスプラットフォーム対応のためのコストを削減したかったのだと思う。そこでクロスプラットフォームで動かせるインタプリタ言語に白羽の矢が立ったと。

ただ、こっちとしては、いきなりそんな事言われてもどうしていいのかわからなかったのでWindowsでpyxpidlに置き換えたことについて書く。

xpidl から pyxpidl の置き換えでやったこと

まずどのバージョンのPythonを使うべきか書いてない。スクリプトを見てもよくわからない。とりあえず何も言わないってことは2.7で動くんだろうと判断してhttp://python.org/から2.7.2をインストールした。結果動いた。

次に置き換えであるが、どうやらパラメータ指定などは互換があるのであまりいじらなくて済んだ。Windows用のバッチだが変更前と変更後を並べると以下のようになる。

rem https://developer.mozilla.org/en/XPIDL/xpidl
%GECKO_SDK_PATH%\sdk\bin\xpidl.exe -o include\%BASENAME% -m header -I%GECKO_SDK_PATH%\idl %1
%GECKO_SDK_PATH%\sdk\bin\xpidl.exe -o %3\%BASENAME% -m typelib -I%GECKO_SDK_PATH%\idl %1

rem https://developer.mozilla.org/en/XPIDL/pyxpidl
mkdir cache
%PY% %GECKO_SDK_PATH%\sdk\bin\header.py --cachedir=cache -o include\%BASENAME%.h -I%GECKO_SDK_PATH%\idl %1
%PY% %GECKO_SDK_PATH%\sdk\bin\typelib.py --cachedir=cache -o %3\%BASENAME% -I%GECKO_SDK_PATH%\idl %1
Gecko9の際につくったバッチを使ってGecko10で実行したら以下の様なエラーになった。どうやらドキュメントを確認したら–cachedirオプションが追加されていてこれがないとエラーになる模様。

Traceback (most recent call last):
File “C:\xulrunner-sdk\sdk\bin\header.py”, line 497, in
p = xpidl.IDLParser(outputdir=options.cachedir)
File “C:\xulrunner-sdk\sdk\bin\xpidl.py”, line 1453, in __init__
optimize=1)
File “C:\xulrunner-sdk\sdk\bin\ply\lex.py”, line 1004, in lex
lexobj.writetab(lextab,outputdir)
File “C:\xulrunner-sdk\sdk\bin\ply\lex.py”, line 175, in writetab
filename = os.path.join(outputdir,basetabfilename)+”.py”
File “C:\Python27\lib\ntpath.py”, line 96, in join
assert len(path) > 0
TypeError: object of type ‘NoneType’ has no len()
Traceback (most recent call last):
File “C:\xulrunner-sdk\sdk\bin\typelib.py”, line 313, in
p = xpidl.IDLParser(outputdir=options.cachedir)
File “C:\xulrunner-sdk\sdk\bin\xpidl.py”, line 1453, in __init__
optimize=1)
File “C:\xulrunner-sdk\sdk\bin\ply\lex.py”, line 1004, in lex
lexobj.writetab(lextab,outputdir)
File “C:\xulrunner-sdk\sdk\bin\ply\lex.py”, line 175, in writetab
filename = os.path.join(outputdir,basetabfilename)+”.py”
File “C:\Python27\lib\ntpath.py”, line 96, in join
assert len(path) > 0
TypeError: object of type ‘NoneType’ has no len()

まずヘッダファイルとタイプライブラリの出力で別々のスクリプトが用意された。これによって -m xxxx の指定は不要になった。

次にヘッダファイルの出力では拡張子を自動補完はしてくれなかったので明示的に.hをつける必要があった。タイプライブラリは補完してくれた。

以上により、変更点は

  • xpidlの代わりにヘッダの場合はheader.py、タイプライブラリの場合はtypelib.pyを使う
  • -m指定は削除する
  • ヘッダの場合に出力ファイルに拡張子.hを明示的に追加する
  • –cachedirオプションでキャッシュディレクトリを指定する(Gecko SDK 10より)

といったところ。いい加減 Gecko SDKの取得から自動ビルドで事を済ませたいのだが・・・