ECLをLinux上でビルドするのは簡単だったが、Windowsではダメダメですな。

同根のINSTALLファイルによれば、Visual Studio 2008のコマンドプロンプトを使用して、

pushd < path \to\ecl- 15 .2.21>\msvc nmake nmake install

これで、最終的には \msvc\packageにビルド済みバイナリ一式が生成されるので、好きな場所に移動して使えばよいようだ。

しかし現実には全然ダメ。Visual Studio 2013を使っているからではないかとも思ったのだが、ネット上の情報を調査したところ、ECL 13.5.1をVisual Studio 2008でビルドできなかったという情報があった。当方で直面した問題のうち1つは、それと似たような現象だった。

最終的には、何とか成功したのだが……うーん、プロジェクトのリソース不足でメンテが滞っているのかなあ？

コンパイルエラーが発生する まず、以下のファイルにてコンパイルに失敗する。 src/c/arch/ffi_x86.d

src/c/arch/ffi_x86_64.d

src/c/numbers/number_equalp.d gotoのラベルに「INT」や「FLOAT」を使っているところがあるが、この2つはWindows APIでtypedefされているデータ型なので、コンフリクトが発生するようだ。 そこで適当な名前に変える。今回は、適切な名前を考えるのが面倒だったので、安直に「INT_XXX」と「FLOAT_XXX」に変更した。

ecl_minがクラッシュする（32bitビルド） ECLのビルドは、大雑把に2つの工程に分けられるようだ。 最小限の実行ファイル（ecl_min）をビルドする。 ecl_minを使用して、本物（？）の実行ファイル（ecl）をビルドする。 前項までのコンパイルエラーを解消すると、ecl_minのビルドまでは成功するようになるのだが、ecl_minを使って実際の実行ファイルをビルドする工程で、ecl_min自体がクラッシュしてしまう。 具体的には、この処理。 ecl_min < compile.lsp エラーコードは0xc00000fd。ググった限り、スタックオーバーフローを起こしているようだ。 そこで、一旦32bit版バイナリのビルドを諦めて、64bit版のバイナリをビルドしてみることにした。 64bit版ビルドの際には、Makefileの「ECL_WIN64」を有効化する必要がある。 あと、Visual C++用のMakefileでは、「nmake clean」や「nmake distclean」で削除されないオブジェクトファイル等があるので、ecl-15.2.21.tgzからソース一式を展開しなおしてビルドした方がよいだろう。

ecl_minが終わらない（64bitビルド） 32bitビルドにてクラッシュしていた、この処理： ecl_min < compile.lsp 64bitビルドでは、2コア（4スレッド）のCPUを25%（つまり1スレッド）占有したまま、1時間経っても終わらない……もしかして、無限ループ？

何が起きているのか？ printfデバッグで頑張ってみた。どうやら意図せず再帰呼び出しとなっている部分があるのが原因で、32bitビルドではスタックオーバーフローとなり、64bitビルドではスタックがなかなか尽きない or ループ状態になって延々と処理が終わらないようだ。 関数の呼び出しを追いかけたところ、こんな感じだった。 cinit.d::main(argc, args) \-main.d::cl_boot(argc, args) \-main.d::maybe_fix_console_strea(cl_core.standard_output) \-file.d::si_stream_external_format_set(stream, | external_format) \-file.d::set_stream_elt_type(stream, | stream->stream.byte_size, | stream->stream.flags, format) \-file.d::parse_external_format(stream, | external_format, | flags) \-cinit.d::si_make_encoding(format) \-internal.h::_ecl_funcall2(@'ext::make-encoding', mapping) eval.d::ecl_function_dispatch(ecl_process_env(), @'ext::make-encoding')(1, mapping) cinit.dのsi_make_encoding()の中でecl_function_dispatch()を呼び出し、ecl_function_dispatch()の戻り値の関数ポインタを実行しているのだが、どうも戻り値がsi_make_encoding()のようで、結果的にsi_make_encoding()の中でsi_make_encoding()を呼び出す再帰状態になるようだ。 ソースを追ってみてもよく分からなかったが、printfデバッグでそういう風に解釈するしかない出力が得られたので、深く考えず「そうなっているのだろう」と納得しておくことにした。正直、釈然としないのだが……。 ここに至るそもそもの原因だが、src/c/main.dのmaybe_fix_console_strea()の中でWindows APIのGetConsoleCP()の戻り値（コードページ）を文字列にマッピングしているのだが、その文字列の大半（"LATIN-1"以外）がparse_external_format()でチェックしているシンボル名に含まれていないのがマズイようだ。 なので、ここも修正。とりあえず強制的に"UTF-8"か"LATIN-1"にマッピングしてしまうことにした。

その他 Makefile中にマクロECL_SSEがあるが、これを有効にするとECLの実行ファイル本体（ecl2.exe）がビルドされないようだ。デフォルト（無効）のままにしておくこと。 その他の設定用マクロは、特にデフォルトから変更する必要はなさそうだ。 また、ecl-cc.batやecl-config.batといったバッチファイルが生成されるが、この中にてヘッダファイルやecl.libを参照している部分のパスが、ECLをビルドしたフォルダになってしまうようだ。ファイル一式を他の場所に移動して使用する場合には、そこを修正する必要がある。 （というか、ecl-cc.batとecl-config.batは微妙にバグっている気がする。具体的には引数なしで実行した場合の挙動とか）