CompileManager(SML用make)の使い方

CompileManager(以下CM)はSML/NJに付いてくるmakeシステムです.
ある程度分かってきたのでメモしておきます.


cmファイル(ライブラリファイル)は特定のソースファイルセットから, 指定した structure/signature/functor/funsig のみを公開してライブラリにすることが出来ます.
(普通は).cmという拡張子を持ったファイルに記述します.

ライブラリファイル(makeファイル)の書き方

たとえば

(* monad.cm *)
Library
  structure Monad  (* 公開するstructure *)
  signature MONAD  (* 公開するsignature *)
  (* functorとfunsigもあればここに書く *)
is
  $/basis.cm     (* 標準ライブラリをインポート *)
  monad-impl.cm  (* 別のライブラリのcmファイルをインポート *)
  monad.sml      (* 必要なソースファイル *)
  monad.sig      (* を列挙               *)

とか書きます.
必要なファイルと公開するインターフェースを定義するだけです. 簡単ですね.
また外部ライブラリをインポートすることも簡単です. 当該の.cmファイルを書くだけです.(ここではmonad-impl.cm)

標準ライブラリの読み込み

上のmonad.cmでは

  $/basis.cm

このように標準ライブラリを読み込んでいます.
ファイル中の''$''はCMにあらかじめ登録してあるpathを探しに行くように指定する記述です.
(sml-extをインストールしたときも使いました)

あらかじめ $SMLNJ_HOME/lib/pathconfig に書いてある場所を探してくれます.

記述の一意性

上で紹介した方法では, 読み込む''ソースファイル全体''で,
それぞれのファイルのトップレベルで定義されている structure/signature/functor/funsig の名前が一意で無いといけません.
同名の定義が二つ以上あるとコンパイルエラーになります.
(たとえ字面が全く同じ定義が複数有る場合でもエラーになります.)

ただし.cmからexportされている名前は何度読み込まれても大丈夫です.

また, .cmからexportされている名前とソースファイル中での名前が被った場合は
ソースファイル側の名前が優先されます.*1

ライブラリファイルの使い方

使う時は CM.make : string -> bool 関数を使います.

- CM.make "monad.cm";
[library $smlnj/cm/cm.cm is stable]
[library $smlnj/internal/cm-sig-lib.cm is stable]
[library $/pgraph.cm is stable]
[library $smlnj/internal/srcpath-lib.cm is stable]
[library $SMLNJ-BASIS/basis.cm is stable]

(中略)

[New bindings added.]
val it = true : bool
- Monad.return;
val it = fn : 'a -> 'a option (* makeしてロードした関数が使えている *)
- 

CM.makeを呼び出せば自動的にコンパイルしてロードしてくれます.
結果はモジュール毎にキャッシュしてくれるので, でかい依存関係を持つモジュールでも気軽にCM.makeできます. *2

既に同名の名前がrepl上で定義されている場合にも, それに影響されずに新しくモジュールを読み直してくれるので, ''取りあえずCM.make''で動作します.

ファイルを読み込める関数にはこの他に use : string -> unit 関数がありますが, これはファイルの内容をreplにそのまま打ち込んだように動作するので, 評価した時のreplの文脈によって結果が変わります.
これは簡単なスクリプトやinfixオペレータの読み込みくらいにしておくのが無難です.

参考

Matthias Blume. "The SML/NJ Compilation Manager (CM)."
http://www.smlnj.org/doc/CM/new.pdf(公式マニュアル)

*1:実際にはもうすこし入り組んだ例外規則がある

*2:キャッシュしなくても十分速いんだけど…. NJのがんばるべきトコはそこじゃない!