28.8 典型的な使用例
28.8.1 対話環境
対話環境を起動する最も簡単な方法は,引数なしで smlsharpコマンドを実行することである.
$ smlsharp
SML#の対話環境からあるCライブラリの関数を対話的に利用したい 場合,そのライブラリの名前を-lオプションで指定する. 例えば,対話環境からzlibライブラリを呼び出したいときは 以下のコマンドを実行する.
$ smlsharp -lz
C標準ライブラリやPOSIXスレッドライブラリなど, SML#コンパイラがデフォルトで リンクするライブラリは-lで指定しなくても利用できる.
28.8.2 プログラムのコンパイル
ファイルに書かれたSML#プログラムをコンパイルする場合, もしただひとつの.smlファイル(および対応する.smiファイル)のみ から成るプログラムならば,その.smlファイルをただ指定するだけで実行 形式ファイルを得ることができる.
$ smlsharp foo.sml
実行形式ファイルの名前をa.outから変えたいときは-oオプ ションを指定する.
$ smlsharp -o foo foo.sml
28.8.3 分割コンパイルとリンク
複数のファイルから成るSML#プログラムを手でコンパイルして リンクするときの標準的な手順は以下の通りである.
$ smlsharp -c -O2 foo.sml $ smlsharp -c -O2 bar.sml $ smlsharp -c -O2 baz.sml $ smlsharp foo.smi
まず,SML#プログラムを構成する各.smlファイルを -cを付けたsmlsharpコマンドでそれぞれ独立かつ順不同に コンパイルする. foo.smlのコンパイルに成功すると, オブジェクトファイルfoo.oが生成される. 全ての.smlファイルのコンパイルが完了した後, プログラム全体のエントリとなるコードを持つ.smlファイルのインターフェース ファイル(ここではfoo.smi)をsmlsharpコマンドに指定し, プログラム全体をリンクする. このときsmlsharpコマンドは,foo.smiから_require宣言 で辿れる.smiファイルを全て列挙し,拡張子を.oに変え,リンク対象の オブジェクトファイルのリストを得る.
ソースツリーの管理の都合などにより.smiファイルから.oファ イルへの対応を制御したい場合は,以下の例のように, ファイル名の対応表を持つファイルを作り-filemapオプションで指定する.
$ smlsharp -c -O2 -o obj/foo.o foo.sml $ smlsharp -c -O2 -o obj/bar.o bar.sml $ smlsharp -c -O2 -o obj/baz.o baz.sml $ smlsharp -filemap=objmap foo.smi
このとき,objmapの内容は以下の通りである.
= foo.o obj/foo.o = bar.o obj/bar.o = baz.o obj/baz.o
SML#プログラムは任意のC/C++プログラムやライブラリとリンクする ことができる. SML#プログラムをC/C++ライブラリとリンクする場合は, リンク時のsmlsharpコマンドラインにリンクするC/C++のオブジェクト ファイルやライブラリファイルを列挙する. 例えば,独自のCプログラムutil.cとOpenGLを利用するSML#プ ログラムfoo.smlをコンパイル・リンクする場合は以下のようにする.
$ smlsharp -c -O2 foo.sml $ cc -c -O2 util.c $ smlsharp foo.smi util.o -lgl -lglu
28.8.4 Makefileの生成
分割コンパイルを使いこなすには, コンパイルとリンクを自動化する“make”コマンドと組み合わせると良い. makeコマンドを使うためには,ファイル間の依存関係が書かれた Makefileを作る必要がある. smlsharp -Mmコマンドを使うことで, SML#プログラムをmakeでビルドするために必要な完全なMakefileを 自動的に作ることができる.
例えば,3つの.smiファイル foo.smi, bar.smi,および baz.smi(とそれらに対応する.smlファイル) からなるプロジェクトがあるとする. これらの間には以下の_require関係がある.
-
•
foo.smiはbar.smiを_requireしている.
-
•
bar.smiはbaz.smiを_requireしている.
このとき,
$ smlsharp -MMm foo.smi -o Makefile
は以下のMakefileを生成する.
SMLSHARP = smlsharp SMLFLAGS = -O2 LIBS = all: foo foo: foo.o bar.o baz.o foo.smi $(SMLSHARP) $(LDFLAGS) -o $@ foo.smi $(LIBS) foo.o: foo.sml foo.smi bar.smi baz.smi $(SMLSHARP) $(SMLFLAGS) -o $@ -c u.sml bar.o: bar.sml bar.smi baz.smi $(SMLSHARP) $(SMLFLAGS) -o $@ -c u.sml baz.o: baz.sml baz.smi $(SMLSHARP) $(SMLFLAGS) -o $@ -c u.sml
あとはただmakeを実行するだけでビルドが完了する.
% make smlsharp -o foo.o -c foo.sml smlsharp -o bar.o -c bar.sml smlsharp -o baz.o -c baz.sml smlsharp -o foo foo.smi
プログラムを変更して _require関係が変化したならば,その都度 smlsharp -MMmコマンドでMakefileを生成し直す必要がある.
もしあなたのプロジェクトにml-lexやml-yaccなどのソースファイルが 含まれているならば,smlsharp -MMmだけでは十分ではない. それらのツールを起動して.smlファイルを生成するルールを 追加する必要がある. 例えば,構文解析器parser.grmを含むならば, smlsharp -Mmが生成したMakefileに対して, 以下のような parser.grm.smlを生成するための規則を手で追加する必要がある.
parser.grm.sml parser.grm.sig: parser.grm ml-yacc parser.grm parser.grm.sig: parser.grm.sml
smlsharp -MMmが生成するMakefileと,これら追加のルールが 書かれたMakefileを分けておくと便利であろう. そのためのひとつの方法は, Makefileには追加のルールと自動生成ファイルのincludeを書くことである. 例えば,Makefileに以下のように書く.
# all all: # depend.mk: smlsharp -Mm foo.smi -o depend.mk include depend.mk # parser.grm.sml parser.grm.sig: parser.grm ml-yacc parser.grm parser.grm.sig: parser.grm.sml
もちろん,あなたのお気に入りのMakefileテクニックを駆使してもよい.