| |||||
SML with GNU
autoconf macro package for SML-NJこのページで説明している各種のチェックをおこなうautoconfマクロを作成しました。 こちらで説明しています。 configure.in に記述するチェックはこれらのマクロを使用することで大幅に 省略できます。SMLの実行ファイル名の判定Unix上ではAC_CHECK_PROGでsmlコマンドが存在することを確認でき る。 しかし、Windows版ではsmlはバッチファイル (sml.bat/sml-cm.bat)としてインストールされ、 AC_CHECK_PROGがこれを認識してくれない。 仕方ないので、つぎのようにCygwin環境とそれ以外の場合とで判定方法を別に する。AC_CYGWIN : if test x"$CYGWIN" = x"yes";then dnl AC_CHECK_PROG can not find sml-cm.bat on cygwin, so set manually. smlcm=sml-cm.bat else AC_CHECK_PROG(smlcm, sml-cm, sml-cm, sml) fi AC_SUBST(smlcm)厳密には、CM.make();という式が実行できるかどうかをここで テストすべき。 exportFnで生成されるファイル名を判定するSMLofNJ.exportFn関数が生成するファイル名には、 hoge.sparc-solarisのようにマシンアーキテクチャとOSを指す文字列が含まれる。 これらの文字列はSMLNJのソースファイル中でべた書きでdefineされているも ので、unameなど何らかのコマンドから得られるものではない。smlで記述したプログラムをMakeコマンドで管理しようとするときに、 これが困る。 Makefileにマシンアーキテクチャ名とOS名をべた書きする以外の、より良い 方法を探る。
Autoconf,Automakeを使う場合、
以下のようにしてsmlで記述したプログラムを扱うことができる。
smlcmsuffix=` echo 'SMLofNJ.exportFn ("conftest",fn _=>OS.Process.success);' | ${smlcm} >/dev/null 2>&1
for f in conftest.*-*;do
echo $f | sed 's/^.*\.\(@<:@^.@:>@*\)$/\1/' ;rm $f;
done`
AC_SUBST(smlcmsuffix)
これは、exportFnによって生成されるヒープイメージファイル
名の拡張子をsmlcmsuffix変数に設定する。AC_SUBST(var)というマクロは、Makefile.am中に現れる @var@ という文字列をシェル変数varの値に置き換えることを指示する。 三行目のsedコマンドは、シェル変数fに格納されている ファイル名から拡張子を取り出している。 bashであれば、これは${f##*.}と記述できる。 しかし、configureはshによって実行されるので、このようなbash特有の機能 は使えず、sedを使って実現することになる。 ファイル名中の'.'以降の文字列を得たいので、つぎのようにすればよい。 sed 's/^.*\.\([^.]*\)$/\1/'しかし、autoconfが内部で使用しているマクロプロセッサm4が、 [,]を特別な意味を持つ文字として扱うので、 これをそのままconfigure.inに記述することはできない。 そこで、[,]の替りに @<:@,@:>@を使う。 これらのエスケープシーケンスは、 configure.inから生成されるconfigureファイル中で[,]に置き換えられる。 Makefile.amにはつぎのように記述する。 eslambdaはラッパースクリプト名で、 eslambda.@smlcmsuffix@がexportFnにより生成されるヒー プイメージファイル名となる。
sml_sources = hoge.sml ...
bin_SCRIPTS = eslambda
pkgdata_DATA = eslambda.@smlcmsuffix@
eslambda:
echo "@smlcm@ @SMLload=$(datadir)/$(PACKAGE)/eslambda.@smlcmsuffix@ \$$*" > eslambda
eslambda.@smlcmsuffix@: $(sml_sources)
echo 'CM.make();SMLofNJ.exportFn ("eslambda",EsLambda.main);' | @smlcm@
Cygwin上でのSMLプログラムのラッパー生成SMLNJでプログラムをコンパイルするとヒープイメージファイルが生成される。 このヒープイメージファイルをsmlへの引数として渡すと、プログラムが実行される。 いちいちヒープイメージファイルを指定してsmlを起動するのは面倒なので、 ラッパースクリプトを用意したい。 そこで、上記のMakefile.am中では、eslambda: echo "@smlcm@ @SMLload=$(datadir)/$(PACKAGE)/eslambda.@smlcmsuffix@ \$$*" > eslambdaとして、ヒープイメージファイルをsmlに渡す一行スクリプトを生成している。 Unix系の場合はこれでうまくいく。Unix版のsmlコマンドはそれ自体が smlの実行ファイル本体を呼び出すラッパースクリプトなのだが、 渡された引数を見て適切にヒープイメージファイルをsmlの実行ファイルに渡してくれる。 しかし、Windows版の場合、sml.batはたったの二行から構成されるバッチファイルで、 デフォルトのヒープイメージファイルと、コマンドラインで指定された引数を smlの実行ファイルに渡しているだけである。 コマンドライン引数でヒープイメージファイルを指定した場合でも デフォルトのヒープイメージファイルを常に最初の引数として渡しているために、 Unix版の場合に比べ、smlの実行ファイルに渡される引数がひとつ増えてしまう。 このため、ヒープイメージのエントリーポイント、すなわちSMLofNJ.exportFnに渡した関数 への引数もひとつ増えてしまう。 具体的には、コマンドラインから渡されたヒープイメージファイル名が、 エントリーポイントへの引数に渡されるリストの先頭要素となる。 そこで、つぎのようにして、デフォルトのヒープイメージファイルを渡さず、 コマンドラインから指定するヒープイメージファイルのみをsmlの実行ファイルに渡す ラッパースクリプトが生成されるようにする。
eslambda@script_suffix@ :
case @host@ in \
*cygwin*) heapwinpath=`cygpath -w $(datadir)/$(PACKAGE)/eslambda.@smlcmsuffix@ | sed 's;\\\\;\\\\\\\\;g'` ;\
cat `which @smlcm@` | sed "s;@SMLload=[^ ]*;@SMLload=$$heapwinpath;g" > eslambda@script_suffix@ ;; \
*) echo "@smlcm@ @SMLload=$(datadir)/$(PACKAGE)/eslambda.@smlcmsuffix@ \$$*" > eslambda@script_suffix@ ;; \
esac
Windows版のsmlの実行ファイルへの引数では、C:\path\to\fileのようなDOS形式で
指定しなければならない。
しかし、configureやmakeはcygwin環境で実行されることを前提にしており、
パスは/usr/local/...のようにUnixと同様の形式で扱われている。
そこで、Unix形式のパス名からDOS形式のパス名への変換が必要となる。
このため、つぎのようにcygwin付属のcygpathコマンドを使ってパス形式を変換する。
cygpath -w $(datadir)/$(PACKAGE)/eslambda.@smlcmsuffix@これにより、DOS形式のパス名が得られる。 しかし、これをそのままbatファイルに書き込んではいけない。 cygpathによって得られるパス名には('\')が含まれている。 batファイル中の'\'はエスケープ文字として扱われるので、smlコマンドへ渡される時点で '\'が引数の文字列から取り除かれてしまう。 したがって、batファイル中には、'\'を'\\'に変換したパス名を書き込まなければならない。 ここでsedコマンドを使う。 sed 's;\;\\;g'が、これはエラーとなる。 sedは'\'をエスケープ文字として扱う。 また、Makefile中のコマンドはshにより実行されるが、 shも'\'をエスケープ文字として扱う。 したがって、Makefile.amにはつぎのように二重に'\'をエスケープしたsedコマンドを記述する。 sed 's;\\\\;\\\\\\\\;g'こうして、ヒープイメージファイルのDOS形式のパス名が得られる。 つぎに、このパス名をsmlの実行ファイルに渡すスクリプトを記述する。 しかし、smlの実行ファイルのパス名はsml.bat内にべた書きされており、 whichコマンドなどでは探すことができない。 幸い、sml.batの中身はたったの二行なので、この中身を適当に置換して ラッパースクリプトを生成する。 cat `which @smlcm@` | sed "s;@SMLload=[^ ]*;@SMLload=$$heapwinpath;g" > eslambda@script_suffix@これは、sml.bat中でsmlの実行ファイルに渡されているデフォルトの ヒープイメージファイル名を、目的のヒープイメージファイル名で置き換えている。
|
| ||||||