OCamlでCを利用したライブラリを作成するメモ

まだまだ残暑が厳しいです。もう9月半ば過ぎてるのにねぇ。それはともあれ、最近なぜかOCamlSDLバインディングを作りつつ、芋蔓式にOMakeを書くはめにもなっています。

まぁそもそもOCamlSDLバインディングが欲しいなら、ocamlsdlを使えばいいじゃん、というのももっともですが、どうせ勉強するなら車輪の再発明をしてもいいじゃん、ということでやっています。

この作業をやるうえでの基本方針としては、CをOCamlでラップしたものをライブラリとして提供する、という方針になります。当然のようですけど。

しかしこれがやってみると一筋縄では行きませんでした。特に、外部ライブラリ(今回はSDL)を含んだものについてや、このライブラリを利用して実行ファイルを作成する部分は手探り状態でやることになりました。

てこずった所としてはわりと初歩的な部分でしたが、探してもなかなか見つからなかった部分でもありましたので、ライブラリをコンパイルする際の手順をメモとして残しておくことにします。

まずはC部分をコンパイルするのですが、これは大体?次のようにしてコンパイルして、ライブラリ部分を作ります。

% ocamlc -c hoge.c  # hoge.oができます
% ocamlmklib -o hoge hoge.o # libhoge.so, libhoge.aとかができます

外部ライブラリ、今回の場合はSDLとのリンクが必要な場合、ocamlcにオプションを渡してコンパイルすればいけます。SDLには必要なオプションを作成してくれるsdl-configというコマンドがありますので、これを使います。

% ocamlc -ccopt "`sdl-config --cflags --libs`" -c hoge.c  # hoge.oができます
% ocamlmklib -o hoge hoge.o # libhoge.so, libhoge.aとかができます

OCamlコンパイルして実行ファイルを作ります。ここではocamloptでやります。

% ocamlopt -o huga hoge.ml -cclib "-L. -lhoge"

さっき作ったやつを、-cclib "-L. -lhoge"で渡しているのがポインツです。

さて、単純にCをOCamlから呼ぶだけならこれでなんとかできますが、「Cを呼んでいるOCamlのパッケージを利用した」実行ファイルを作る場合はちょっと面倒になります。

Cのコンパイルまでは一緒です。OCamlソースをコンパイルする際に、ライブラリとしてコンパイルします。ここではhogeというライブラリとしてみます。

% ocamlopt -c huga.ml
% ocamlopt -a hoge.cmxa huga.cmx -cclib "-L. -lhoge"

さて、こうしてやるとhoge.cmxaができて、こいつをopenとかできるようになりますが、できあがったhoge.cmxaのサイズを見ると妙に小さいです。これはocamloptの-aオプションの説明から抜粋しますが、

コマンドラインに与えられたオブジェクトファイル (.cmx/.o) をとり、ライブラリ (.cmxa/.a) を作成します。実行ファイルは生成されません。ライブラリの名前は -o オプションで指定できます。デフォルトでは library.cmxa です。

コマンドラインに -cclib や -ccopt オプションが渡されたら、これらのオプションは出力される .cmxa ライブラリに保存され、このライブラリをリンクするときに自動的に -cclib や -ccopt が追加されます (ただしリンク時に -noautolink が指定されない場合) 。

というわけで、ocamloptで作成したライブラリに渡された外部ライブラリについては情報のみが含まれ、このライブラリを利用してコンパイルする際に、勝手に-cclibとか-ccoptとかを付けてやってくれるということのようです。

実際にこれを利用する場合、

% ocamlopt -o hige hige.ml -lhoge

のようにすると、実際には-cclib "-L. -lhoge"が渡されます。ですので同じディレクトリにlibhoge.aかlibhoge.soが無いと多分リンクエラーになります。

ライブラリを作るところまでは解説しているところが多く(というほど多いわけでも・・・)ありましたが、それを利用して実際に実行ファイルを作るところでどうなるか、というのがあまりなかったので書いてみました。

実際に開発の中ではOMakeを使って上の流れを自動でやるようにしています。OMakeは凝ったことをしなければ使いやすいと思います。普通のMakefileよりも見やすい(気がする)ですし。

まぁ先人が言う通り、なんかやろうとすると色々面倒ですが・・・。上では書きませんでしたが、ocamlopt -packを利用しようとすると、これがOMake標準のOCaml.omではやってくれなかったので、参考にして自前で用意するハメになったりしました。でも継続ビルドはサイコーです。

なお、OCamlでのCバインディングは個人的に書きやすいです。あまり考えなくても書けるからでしょうか(でもリークとかしてそう・・・)。このあたりもまとまった日本語情報があるにはあるのですが、どうも古いようで現状に合っていない部分が何ヵ所かありました。この辺の暇があれば書いていきたいと思います。