build SML/NJ 110.76 on Cygwin 1.7
いつの間にかcygwin上で SML/NJ がビルド出来なくなっていた。(いつからだろう?
具体的には base/runtime/mach-dep/cygwin-fault.c で参照されているヘッダ
現時点での最新版を含む SML/NJ 110.7{6,5,4} と cygwin 1.7 で同様のエラーになることを確認しています。
build & install
SML/NJのビルド方法は少し変わっていて、用意されているスクリプトを実行するとソースのダウンロードからビルドまでがいきなり完了します(^^;;
こんな感じ。
$ curl -O http://smlnj.cs.uchicago.edu/dist/working/110.76/config.tgz $ tar -xf config.tgz $ export SMLNJ_CYGWIN_RUNTIME=1 # cygwinでビルドする場合必要 $ vim config/target # ビルドしたい周辺ソフトの指定を必要に応じて編集 $ ./config/install.sh $ bin/sml Standard ML of New Jersey v110.76 [built: Sun Aug 18 08:46:02 2013] -
うまく行った場合はカレントディレクトリから bin/sml の位置に実行ファイル(のラッパー)が出来ています。
Cygwin上で実行する時は常に SMLNJ_CYGWIN_RUNTIME=1 が環境変数に定義されている必要があるのでWindowsの環境変数に設定すると手間が無くてよいです。
compilation error
今回の環境ではコンパイルに失敗します(よね?)。
..(略).. In file included from ../mach-dep/unix-fault.c:10:0: ../mach-dep/cygwin-fault.c:21:43: fatal error: exceptions.h: No such file or directory #include <exceptions.h> /* Cygwin stuff */ ^ compilation terminated. makefile:242: recipe for target 'unix-fault.o' failed make[1]: *** [unix-fault.o] Error 1 make[1]: Leaving directory '/cygdrive/c/usr/sml110.76/base/runtime/objs' mk.x86-cygwin:22: recipe for target 'all' failed make: *** [all] Error 2 ./config/install.sh: !!! Run-time system build failed for some reason.
patch
で、このエラーを修正するため exceptions.h をでっち上げるパッチ(?)を書きました。cygwin-fault.h に改名してますが。
(以下で言及している base/ は config/install.sh が自動でタウンロードしてくれるので、エラーが起きると分かっていても1度実行しておくとパッチを当てるのが楽です)
以下のようになりました。 Gistにも貼ってあります> https://gist.github.com/eldesh/9317060
$ diff -U 3 base/runtime/mach-dep/cygwin-fault.c.old base/runtime/mach-dep/cygwin-fault.c --- base/runtime/mach-dep/cygwin-fault.c.old 2014-03-03 23:25:41.882968800 +0900 +++ base/runtime/mach-dep/cygwin-fault.c 2014-03-03 23:25:55.698398500 +0900 @@ -17,8 +17,7 @@ #include "ml-state.h" #include "ml-globals.h" -#include <windows.h> -#include <exceptions.h> /* Cygwin stuff */ +#include "cygwin-fault.h" /* Cygwin stuff */ #define SELF_VPROC (VProc[0])
/* base/runtime/include/cygwin-fault.h */ #if !defined CYGWIN_FAULT_INCLUDED #define CYGWIN_FAULT_INCLUDED #include <windows.h> typedef int (exn_handler_fn)(EXCEPTION_RECORD *, void *, CONTEXT *, void *); typedef struct exception_list { struct exception_list * prev; exn_handler_fn * handler; } exception_list; #endif /* CYGWIN_FAULT_INCLUDED */
このようにして再度 config/install.sh を実行するとビルドに成功します。
修正内容
今回定義した exception_list は structured exception handling という、windowsが持っているエラー通知の仕組みにアクセスするための型です。
各スレッドの特定のレジスタに常に載っているので、そのアドレスの型を定義しただけでコンパイルは出来ました。