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(公式マニュアル)