SML/NJで実行ファイルを作る
タイトルはやや詐欺なのだけど。
SML/NJで実行ファイル、というか、型検査とコンパイル*1が終わった状態のファイルが欲しいことがある。
ソフトウェアをバイナリ配布するとか。あるいはベンチマークを取りたい(=パースや型検査の時間を入れたくない)場合が考えられる。
stack-over-flowにもあるんだけど日本語ですぐ出てこないので書いておく。
exportFnを使う
replから SMLofNJ.expportFn を使う。
val SMLofNJ.expportFn : string * (string * string list -> OS.Process.status) -> unit
- fun main (name, args) = (print (String.concatWith "," (name::args@["\n"])); OS.Process.success); val main = fn : string * string list -> OS.Process.status - SMLofNJ.exportFn("test",main); $ ls test.x86-linux
ml-build
上の方法ではいちいちreplを立ち上げる必要があって回りくどい。そのためこの機能を呼び出すラッパースクリプトが ml-build として用意されている。
.cmファイル、実行を開始するmain関数、書き出すファイル名(の一部)を指定する。
$ ml-build source.cm Main.main test
$ ls
source.cm test.x86-linux
以下のように通常の makefile に自然に記述することも出来るようになる。
all: test.x86-linux %.x86-linux: source.cm ml-build $< Main.main test
ただしトップレベルに書いた関数は .cm から公開出来ないため、ml-build による方法では .cm からmain(相当)の関数を提供する structure を公開している必要がある。
実行
以上で得られたヒープイメージを smlコマンド に渡して実行する。サフィックスは付けなくても動く。
$ sml @SMLload=test foo bar bazz /path/to/bin/sml,foo,bar,bazz,
*1:NJはネイティブコード吐いてるらしい