OCaml

Oasis で楽に OCaml プロジェクトを作る

これは ML Advent Calendar 2017 の 6日目の記事です.

ご案内: Jbuilder (Dune) でもっと楽に OCaml プロジェクトを作る もご覧ください。

Oasis は OCaml のビルドツールの一つです. 最低限必要な設定ファイルを作れば,ありがちな依存解析を全て自動的にやってくれて便利です. いわゆる ./configure && make && make install 式のインストーラをうまいこと自動生成してくれます. さらに OCamlfind (Findlib) 周りもよしなにしてくれるので,他の OCamlfind パッケージを使ったり,自前のパッケージの開発も簡単にできます.

しかし,Oasis の日本語の解説記事はこれといって見当たりません.そこで,この記事では私が Oasis をどのように使っているかを書きます. こまかいことは Oasis のマニュアル を読んでください. 具体例としては,大きいものだと Tyxml があり,他には "_oasis" で github をググる などの方法もあります.

Oasis と OCaml のビルドシステム

Oasis は,他のビルドシステム (OCamlbulid か Omake) を呼び出してプロジェクトをビルドします.Oasis が各ツールのビルドスクリプトを自動生成してくれるのです.

実際,既存のビルドシステムにはそれぞれ一長一短があるように思います:

  • make. OCamlマニュアルには,典型的な Makefile の例 が掲載されていますが,よほど小さなプロジェクト以外には使えないでしょう. シリアスに Makefile で生きていくなら,よく使う定義をまとめた OCamlMakefile を使うのが良いかもしれませんが,試したことはない.
  • OCamlbuild は OCaml コンパイラについてくるので可搬性が高いですが,ビルド規則を OCaml のソースコード (myocamlbuild.ml) に書くのがいかにも複雑な感じです.
  • Omake は, OCamlプロジェクトに限らず使える柔軟性と汎用性が強みであり,広く使われていますが,私には OMakefile の敷居が高かったです (ヘタレ.一応,使おうとした形跡 はあります).
  • Jbuilder は Jane Street Capital 発で,今後のデファクトになっていきそうな感じがしますが,S式を書きたくないのと,よく知らないので今回はパスです.

Oasis なら, _oasis という設定ファイルに最低限のことを書くだけで良いです.

使い方

  1. _oasis ファイルを作る (下記).
    • Library (または Executable) セクションを作る
    • Modules フィールドに最低1つのモジュールを書いておく.
  2. oasis setup
    • Makefile./configure, setup.ml などのスクリプト一式が生成される.
  3. make (&& make install)

簡単ですね.また,./configure (ocaml setup.ml -configure) は, 初回に make を叩いた時に自動で呼ばれます.

注意:

  • プロジェクトにモジュールを追加した時は,_oasis を編集して oasis setup を呼ぶ
  • 何故かビルドが上手くいかなくなったら make distclean か, git clean -fdX で要らないファイルを削除して oasis setup を再実行する.このため .gitignore も載せておきます.

_oasis ファイル

OCamlfind で使える典型的なパッケージを作る場合は次のような _oasis を作ります.実行ファイルを作るときは LibraryExecutable に変えるだけです.複数のライブラリや実行ファイルも書けます.

OASISFormat: 0.4
Plugins:     META (0.4), DevFiles (0.4)
BuildTools:  ocamlbuild

Name:        ocamlsample
Version:     0.1
Homepage:    https://github.com/keigoi/ocamlsample
Synopsis:    A sample library
Authors:     Keigo Imai
License:     Apache

Library samplelib
  Path: lib
  Findlibname: samplelib
  BuildDepends: threads, str
  Modules: Sample

Oasis プラグイン:

  • METAプラグイン は OCamlfind の META ファイルを生成
  • DevFiles プラグイン は(setup.ml を呼ぶだけの)スクリプト configure や Makefile を生成

Library セクションについて.

  • Path は,ソースコードを置くディレクトリです.他の Library や Executable とは重複できないようです.
  • Findlibname は,このライブラリを使う時に ocamlfind -package パッケージ名 で指定する時のパッケージ名になります.
  • BuildDepends には依存する OCamlfind のパッケージ名を書きます.
  • Modules は,ライブラリに含めるモジュールのリスト.ファイル名ではなく,モジュール名(sample.ml なら Sample のように).
  • OCamlfind 向けのオプション: FindlibParent (親パッケージ), XMETAType (ppx を作る場合には syntax などと書く),XMETARequires (他の依存パッケージ), XMETAExtraLines (META に追加する行. ppx の実行ファイル等を指定) など

テスト (Test) やドキュメント生成 (Document), リポジトリ情報 (SourceRepository) のためのセクションもあります.マニュアルを見よ

インストール

make install で適当な位置にライブラリをインストールしてくれます. Executables はデフォルトでは /usr/local/bin に入るはず. インストール位置は全て, ./configure に与えるオプションで変えられます.

$ make install
ocaml setup.ml -install 
Installed /Users/keigoi/.opam/4.05.0+flambda/lib/samplelib/sample.ml
Installed /Users/keigoi/.opam/4.05.0+flambda/lib/samplelib/samplelib.cma
Installed /Users/keigoi/.opam/4.05.0+flambda/lib/samplelib/samplelib.cmxa
Installed /Users/keigoi/.opam/4.05.0+flambda/lib/samplelib/samplelib.a
Installed /Users/keigoi/.opam/4.05.0+flambda/lib/samplelib/samplelib.cmxs
Installed /Users/keigoi/.opam/4.05.0+flambda/lib/samplelib/sample.cmi
Installed /Users/keigoi/.opam/4.05.0+flambda/lib/samplelib/sample.cmt
Installed /Users/keigoi/.opam/4.05.0+flambda/lib/samplelib/sample.annot
Installed /Users/keigoi/.opam/4.05.0+flambda/lib/samplelib/sample.cmx
Installed /Users/keigoi/.opam/4.05.0+flambda/lib/samplelib/META

やったね!

OMake を使う場合

ビルドシステムとして OMake を使う場合は,BuildTools: ocamlbuild の代わりに,以下のように書けばよいようです.

OCamlVersion: >= 4.01
BuildType: OMake (0.4)
BuildTools:  omake

配布時に必要なファイル

私は,最低限 ./configure && make && make install をできるようにしておきたいので,以下のファイルはリポジトリにコミットしています.

Makefile
configure
myocamlbuild.ml (OCamlbuild の場合)
setup.ml

**/META
**/*.mldylib
**/*.mllib

.gitignore

これを書いておいて,何か変なことになったら git clean -fdX しています.

*.annot
*.cmo
*.cma
*.cmi
*.a
*.o
*.cmx
*.cmxs
*.cmxa
*.cmt

# ocamlbuild working directory
_build/

# ocamlbuild targets
*.byte
*.native

# oasis generated files
setup.data
setup.log

# omake files
*.omc
*.om
.omakedb
.omakedb.lock

PPX を伴うライブラリを作る

PPX を提供するライブラリを作るときは次のようにします.

  1. Executable でプリプロセッサの実行形式を作る (仮に ppx_example とする)
  2. 提供するライブラリの Library に XMETAExtraLines: ppx = "ppx_example" を追加する

同じプロジェクトの他のソースコード(テストコード等)で PPX を使いたい場合は、_tags ファイルに

# OASIS_START
# OASIS_STOP

<test/*.ml>: ppx_example

と書いておいて, myocamlbulid.ml でなんとかするしかないようです.

気になること

  • make する度に ocaml setup.ml -build が走るが,このときに 1秒くらい固まる気がする.もっとサクサク動かない?
  • 偶に make が失敗し oasis setup してもビルドできない状態に陥る.私は何も考えず git clean -fdX しているが….

まとめ

Oasis は, _oasis から OCamlbuild の myocamlbuild.ml や OMake の OMakefile, OMakeroot を生成してくれる便利ツールで, OCaml のツールチェインに慣れていない人でも使えるのではないかと思います. Oasis で happy OCaml life を!