OMakeでOCamlのパッケージを作る

つい先週、2年振りに盆に帰省をしてきました。去年は一日だけ休んだら、結局秋田の地を踏むことなく青森に拉致されていったうえ、そのまま盛岡から東京に戻ったので、盆に規制したのは2年振りと相成りました。

しかしやっぱりというかなんというか、実家の方は涼しかったです。日中はさすがに暑いですが、夜はエアコンなんざいりませんでした。というかつけなくても寒かった・・・。東京に戻ってきて最初の言葉が「あちぃ」でしたしねぇ。

いつもは実家にいる間、なんだかんだとやることがあったりして開発とか進まない(当然PCは持っていく)のですが、今回は結構進めることができました。

さて、最近OCamlで細々としたプログラムを書いているのですが、その中で個人的なライブラリを作成したい、ということになりました。

OCamlで開発をするということは当然OMakeを使う、ということで、ライブラリを作成する場合、OMakeに標準である「OCamlLibrary」を使います。

ただ、私が作成しようとしたものをそのままopenするとえらいことになる & まだ増えるかもしれないことを考えて、次のような構成にすることにしました。

  • ライブラリ
    • Std
      • 色々ライブラリ

実際には、Stdに各種ライブラリをmoduleで入れておいてはいますが、Stdと同レベルにも格納されている、というような状態です。

さて、これをやるために(他にやり方がある気がしてならないですが)、一度ライブラリにする前に、Std以下を「ライブラリ」にパッケージとして作る必要がありました。

・・・ですが、標準で用意されている OCamlPackage には「ocamloptを使うとパッケージ作成時にエラーになる」という罠が潜んでいました。

ocamloptでパッケージを作成する際には、.mlをコンパイルする際に、-for-pack パッケージ名 というオプションを指定する必要があります。あるんですが、これを標準のOCaml.omが設定してくれてないので、ocamlopt -pack 時にエラーとなります。

OCAMLOPTFLAGとかを設定しても、コンパイル時とパッケージ作成時とで切り換えることはできませんでした。

なるほどこれが「ちょっと凝ったことをしようとすると結局自分で作らないとならない」というやつか・・・と思いつつ、まぁ仕方無いのでやることにしました。

と言っても、まるごと自分で作成するなんてことはしません。OMakeは完全なプログラミング言語のうえ、変数のスコープ概念が私には意味わからんレベルの難解なものですので、おとなしく必要最低限だけOCaml.omから拝借してきて、それを回収することにしました。

実際にどれくらい編集したかというと、それほど多くありません。まず、フラグとかを宣言しているところに、以下の変数を追加しました。

public.OCAML_PACKAGE_NAME =
public.PREFIXED_OCAML_PACKAGE_FLAG() =
    if $(and $(gt $(string-length $(OCAML_PACKAGE_NAME)), 0), $(NATIVE_ENABLED))
        return -for-pack $(OCAML_PACKAGE_NAME)
    else
        return $(EMPTY)

実際に利用する時に変数するのは、OCAML_PACKAGE_NAMEです。

次に、内部でコンパイルする時に利用される関数に、↑で定義した変数を追加で設定します。

public.OCamlOpt() =
    return $(OCAMLFIND) $(OCAMLOPT) $(LAZY_OCAMLFINDFLAGS) $(PREFIXED_OCAMLPACKS) $(OCAMLFLAGS)\
              $(OCAMLOPTFLAGS) $(OCAMLPPFLAGS) $(PREFIXED_OCAMLINCLUDES) $(PREFIXED_OCAML_PACKAGE_FLAG)

これでOKです。OCamlPackage内部で、パッケージのcmxが作成される際には、OCAMLOPTFLAGは指定されていますが、このOCamlOpt自体は使っていませんので、これだけでなんとかなります。利用する時は、OCamlPackageをする前にOCAML_PACKAGE_NAMEにパッケージ名を設定しておいてから、OCamlPackageを呼ぶようにします。

そして、OCamlLibraryの対象ファイルとして、OCamlPackageから返されたパッケージファイルを指定すれば、目出度くパッケージが作成されます。ちなみにこれをやるために3日くらいかかりました・・・。

OMakeは継続監視ビルドや並列ビルドなど、便利な機能があるのはとてもいいのですが、Makefileとの互換性をとったかのような変数の概念が非常に理解しづらいです。ぶっちゃけ理解しきってなどいませんが、利用するという点では問題ありません(何か起こると対処がめんどいですが)。

もうちょっと広まってくれると、こんな問題の解決法もさっくり見付かるんじゃないかなー、と思ったので、今回記事にしてみました。もう今の現場がグダグダすぎて現実逃避気味というのも多少は・・・。

ちなみに、emacs使いの人には、camlspotterさんが作成されている omake-mode.el が非常に便利です。実際使ってみましたが、非常にテンポよく開発ができます。

ではよいOMakeライフを。