2006-10-28

近況

先月は日記を書きすぎた. 今月は反省してちまちまコードを書いている. 今つくっているのは C++ で書かれたアプリケーション. ふだんは Mac で動かしつつ Windows でも動かしたい下心がある. なので適当に可搬なかんじで書いている. コードを win32/darwin 間で可搬にするのはそれなりに簡単なんだけれど, 依存するライブラリの扱いがとても面倒で参った.

ポータブルなビルドへの道 (アドホック編)

まず, 最初は Mac の port (macport) に依存して作っていた. port に依存するのは楽でいい. apt-get みたいなもんだからね.

次に Windows 環境でビルドしようと準備を始めた. ここから少しずつ面倒になってくる. Windows には port も apt もないから, 自分でサードパーティのコードを管理する必要がある. コード管理のベストプラクティスに従うなら, そのコードは自分のツリーの一部としてチェックインすべきだろう.

これはおおよそ正しい方針なのだが, 依存先が大物の場合は悩ましい. たとえば boost. コードサイズがでかいので, チェックアウトに時間がかかる. そのうち web で配布などと思ったときに, boost の 20MB を配るのは気がひける. 加えてビルド時間もながい. たぶん 1 時間くらいかかる. 私はたまにクリーンなツリーを取り直してチェックイン漏れがないのを確認するんだけれど, それだけのために一時間も待ちたくない.

仕事なら迷わず全部チェックインして, 作業ミスはデイリービルドで確認するのが筋だと思う. でも趣味はあまり大袈裟にしたくない. 友達と相談した結果, 小物のライブラリ(zlib とか)はチェックインして, 大物は自分の環境にインストールしておくことにした. dll は色々面倒が多そうなので, ライブラリはすべて静的にビルド, リンクした. 小物のうちいくつかは付属の Makefile がつかえなかった. それらは IDE からプロジェクトを作って適当にコードを登録, ビルドした.

かくして Windows のために小物のライブラリをチェックインした. さて, どうせなら Mac でも (port ではなく) チェックインしたコードを使うようにしよう. そう思って更に作業をすすめることにしたのが運のつき. やや大変だった.

基本的な方針は Windows と変わらない. 大物は外, 小物は中. あとは静的ライブラリを作ってリンクするだけ...と思ったら, Mac の gcc は -static が使えないらしい. 仕方なく .dylib を使うことにしたのだが, ライブラリ付属の Makefile を使うと /usr/local などへのインストールを前提に .dylib が作られてしまう. うーんと悩んだ末, 諦めて Makefile を書き換えた.

更に面倒は続く. 当初 boost などの大物は port を参照するつもりでいたけれど, 検索パスの都合から port の大物を参照するとついでに小物までみつかってしまう. その結果, ツリー内のライブラリでなく port のライブラリが使われてしまう. うーん...と再び悩んだ末, boost を port とは別のディレクトリにインストールして逃れた. この時点で Makefile は私の環境でしかビルドできなくなってしまった. かえって複雑さを増しそうなので, 依存を環境変数に抜きだすのは保留した. がっくし. 実害はないからいいけど...

このあと更に Mac のバンドルへライブラリを追加する方法がわからず悩んだりもしたけど そのへんは省略.

教訓

ポータブルなコードを書く時, 依存するライブラリはぜんぶツリーに入れるか, ぜんぶシステムのレポジトリを参照しよう. 中途半端はよくない. Windows に port のようなレポジトリが存在しない以上, 実際にはぜんぶ入れるしかなさそう. C/C++ の趣味プログラミングは大変だ...

Windows にも port が欲しい

ビルドに苦しんでいるとき, 以前 可搬なビルドプロセスが欲しい といったのを思いだした. よく考えると, 欲しいのはビルドプロセスより port や apt みたいなライブラリのレポジトリな気がする. 閉じたビルドプロセスだと不十分. 依存関係を追跡して必要なものをダウンロードするなど, もっとよろしくやって欲しい.

世間のレポジトリ

そう思って世の中を見回すと, コードのレポジトリは色々ある. 思いつく範囲で並べてみよう...とその前に Wikipedia を見てみるか. "Package management systems".

Wikipedia では Linux や BSD のシステムを中心に紹介している. たしかに依存関係のメタ情報を持たせる "パッケージ管理" は RPM を始めとして色々ある. 一方で, コードを集中的に管理する "レポジトリ" は CPAN の方が歴史が古そう. CPAN は今年で 10 周年. 1996 からあるわけか. APT 誕生は 1998 らしい...大差なかった. どちらも古くからあるんだね.

プログラミング言語向けのレポジトリは, 他にも ruby の ruby gems や Java の maven, 最近だと JavaScript の JSAN などがある. 言語処理系が一定以上普及すると, 誰かが CPAN respect で作るのかもしれない.

Windows のレポジトリ

Linux や Perl をはじめとするオープンソースの世界では一般的なレポジトリの仕組みが, なぜ Windows にはないんだろう. こんなに需要があるのに. (ここに!)

ソースがクローズドだからというのは理由の一つだろうけれど, それだけではない気もする. rpm や dep のパッケージは主にバイナリで配布されているし, 実際 Redhat など商用 distro のレポジトリにはオープンソースでないパッケージもある. 逆に Windows にもオープンソースのライブラリはある.

その他の理由を考えてみた:

- 標準のコンパイラがなかった - 利害関係が複雑だった - みんな COM を使っていた

こんなところかしら.

理由 1: 標準のコンパイラがなかった

ライブラリは, 特に C++ の場合ビルドしたコンパイラが違うと互換性がない. Linux(UNIX) は標準でコンパイラが用意されているため, 特別な事情がない限りそれを使えばコンパイラは統一される. だから互換性の問題が起きにくかった. 一方の Windows には標準のコンパイラというのがない. そのためライブラリの配布が難しかったのかもしれない. バイナリを配ると互換性がなく, コードを配るにもビルド方法がわからないからね.

一方で dll を配布している人はけっこういるから, 標準コンパイラの不在を十分条件と考えるのは苦しそう.

理由 2: 利害関係が複雑だった

Windows 用ライブラリのホスト役は Microsoft が一番だと思うけれど, なんとなく独禁法にひっかかりそうな気がする.

その点, 今おもうと Vector や窓の杜はホスト役をできる位置にいた気がする. 彼らが頑張ってパッケージマネージャを作り配布していたら, Windows の趣味プログラミングの世界はもう少し実り豊かなものになったかもしれない. 以前から VB のランタイムなどライブラリに関係する問題は多かったのだから, 商機はあった. 結果論だけどね.

理由 3: みんな COM を使っていた

これが一番の理由かな.

COM はバイナリ配布のためのコンポーネント技術として, とてもよくできている. だからコンパイラに標準がなくサーバ側にレポジトリがない状況でも UNIX の世界ほど不自由することはなかった. 異なるバージョンが共存できて, レジトリで集中的に管理されている. バイナリだけでヘッダがなくても typelib などを使って開発をすることができる.

実際, ベクターの プログラミング カテゴリでは "各種OCX ActiveX" の数が一番多い.

やっぱり Windows に port が欲しい

COM はよくできているけれど Windows 専用だ. だから世の中のオープンソースのライブラリはふつう COM で書かれていない. 私が使いたいのはオープンソースのコードなので, これだと嬉しくない. それに COM は依存するライブラリをサーバから持ってきてもくれない. port が欲しい.

視点を変えると Windows 上で動くレポジトリもある. CPAN と gems. 言語処理系に付随するレポジトリは環境を問わない. Windows でも動く. インタプリタ上のコードは可搬性が高い. コンパイルが絡むがないのはいい.

cygwin は一見よさそうに見えるけれど大袈裟すぎる. それにアプリケーションが Windows らしくならないのは困る. ファイルのパス表記からして違う. ただそれを期待するのも筋違いではあるだろう. cygwin はパッケージマネージャではなく環境だからね.

それにしても, ほんとに既存のパッケージマネージャはないの? 探し方が悪いのかなあ. 私は別に UNIX 用のコードをなんでも動かしたいわけじゃない. いかにも UNIX なライブラリも要らないし, アプリケーションも必要ない. こういうのこそ cygwin を使えばいい. ただ APR, zlib, SpiderMonkey, Qt, wxWidgets expat といった, もともと環境非依存のライブラリを簡単に使いたいだけ. もう xxxx-win32-bin.zip を拾ってきて使ってみたら デバッグビルドでしか動かないみたいなトラブルはうんざりだ. なんとかしてくれー誰かー...

...Windows と OSS を愛する暇な学生は未踏ネタにどうですか?