pForthをMinGWでビルドする

スタック指向のプログラミング言語を何か勉強したいと考えていて、処理系を探している。

言語の候補としては、

  • Forth
  • PostScript
  • Mind

こんなところだと思う。

で、まずはForthの処理系を探している。要求事項はこんな感じ。

色々物色していた所pForthという処理系を見つけた。Windows用のバイナリは見つからなかったがソースがpublic domainで公開されていた。

ソース一式にはVisual Studio 2005のプロジェクトファイルが付属している。Windows用のバイナリをビルドする場合はこれを使えばよいらしい。

が、しかし、だ。個人的にはMinGWでビルドできると非常に嬉しい。Visual Studioは便利といえば便利だけど、Express Editionといえどもインストールが手間だし、IDEを使うとそれなりにリソースを消費する。

pForthをUnixマシンでビルドする為のMakefileが付属しているので、それを流用してMinGWでビルドしてみた。

用意するもの

必要なもの 今回使用したもの 備考
pForthのソース pforth_v27_20101121.zip
MinGW + msys TDM-GCC 4.5.1 MinGW猫科研究所パックのassemble008を使用
Windowsマシン Windows XP Pro SP3 32bit環境

pForthの最新のソースはGoogle Codeにあるので、そこからダウンロードしてくる*1

MinGWGCC用にMakefileを修正する

元のMakefileではコンパイラとして定義済みマクロの CC を使用しているが、デフォルトでは cc に展開されてしまう。MinGWを使う場合は CC が gcc に展開されるように修正する必要がある。

また警告用のフラグに「-c89」が含まれているが、MinGWgccにはないオプションだ*2。ひとまず似たようなオプションだと思われる「-std=c89」に変えておく。

最小限の修正でビルドする場合

この段階ではまだビルドできない。ソースファイル pf_io_posix.c でインクルードしている termios.h がMinGWに含まれていないからだ。

pf_io_posix.c は環境依存部のソースコードのようだ。Unix系OSのようなPosix準拠度が高めな環境用らしい。標準Cライブラリを使用した pf_io_stdio.c というソースがあるので、そちらに差し替えることにする。

また fseeko や ftello が存在しないことが原因でリンクに失敗する。これは pf_io.h で定義しているマクロ sdSeekFile と sdTellFile がこれらの関数に置換されることが原因だ。

このマクロは条件コンパイルによって値が変わるので、とりあえず fseek や ftell に置換されるようにしておく。

以上の変更は、全てMakefileの修正で事足りる。ソースファイルに手を入れる必要はない。

元のMakefileとの差分は次の通り。

--- Makefile	2010-08-27 10:50:08.000000000 +0900
+++ Makefile_stdio_mingw_tdm_4.5.1	2010-12-04 21:46:04.078125000 +0900
@@ -23,8 +23,9 @@
 # This is needed to get pForth to build on Snow Leopard and other 64 bit platforms.
 WIDTHOPT=
 
+CC = gcc
 FULL_WARNINGS =  \
-        -c89 \
+        -std=c89 \
         -fsigned-char \
         -fno-builtin \
         -fno-unroll-loops \
@@ -39,10 +40,10 @@
         -Wmissing-declarations
 
 DEBUGOPTS = -g
-CCOPTS = $(WIDTHOPT) -x c -DPF_SUPPORT_FP -O2 $(FULL_WARNINGS) $(EXTRA_CCOPTS) $(DEBUGOPTS)
+CCOPTS = $(WIDTHOPT) -x c -DPF_SUPPORT_FP -O2 $(FULL_WARNINGS) $(EXTRA_CCOPTS) $(DEBUGOPTS) -D__NT__
 
-IO_SOURCE = pf_io_posix.c
-#IO_SOURCE = pf_io_stdio.c
+#IO_SOURCE = pf_io_posix.c
+IO_SOURCE = pf_io_stdio.c
 
 EMBCCOPTS = -DPF_STATIC_DIC
 

変更したMakefileで「make all」と実行すると pforth.exe と pforth_standalone.exe の2つの実行ファイルが生成される。

pforth.exe は最小限のディクショナリが含まれているらしい。ビルド時に一緒に生成される pforth.dic というディクショナリのファイルと組み合わせて使うのだろうか。

pforth_standalone.exe には pforth.dic の中身が全て埋め込まれているようだ。

Windows用の環境依存部を使ってみる

pf_io_stdio.c は標準Cライブラリを使って書かれているので、比較的広範囲のプラットフォームで使用できる。Windows上でも問題なく使用できるはずだ。

とはいえ、自分のプラットフォーム向けに環境依存部のソースが用意されているのなら、そちらを使いたくなるのが人情だ。

Windows用のソースはなぜか2種類もあるが、Visual Studioのプロジェクトファイルの中身を見ると pf_io_win32_console.c を使用しているようだ。そこで pf_io_stdio.c から pf_io_win32_console.c に差し替えることにする。

これに伴う変更として、まず警告オプションのうち「-std=c89」を取り除く。C++スタイルのコメントを有効にする為だ。

また pf_inner.c にてMinGWにはない crtdbg.h をインクルードしようとして失敗するが、これはMakefileと同じディレクトリに crtdbg.h という名前の空のファイルを用意しておけばよい*3

今回もMakefileの修正だけで済む。差分は以下の通り。

--- Makefile	2010-08-27 10:50:08.000000000 +0900
+++ Makefile_win32_console_mingw_tdm_4.5.1	2010-12-04 22:19:14.343750000 +0900
@@ -23,8 +23,8 @@
 # This is needed to get pForth to build on Snow Leopard and other 64 bit platforms.
 WIDTHOPT=
 
+CC = gcc
 FULL_WARNINGS =  \
-        -c89 \
         -fsigned-char \
         -fno-builtin \
         -fno-unroll-loops \
@@ -39,9 +39,10 @@
         -Wmissing-declarations
 
 DEBUGOPTS = -g
-CCOPTS = $(WIDTHOPT) -x c -DPF_SUPPORT_FP -O2 $(FULL_WARNINGS) $(EXTRA_CCOPTS) $(DEBUGOPTS)
+CCOPTS = $(WIDTHOPT) -x c -DPF_SUPPORT_FP -O2 $(FULL_WARNINGS) $(EXTRA_CCOPTS) $(DEBUGOPTS) -DWIN32 -D__NT__
 
-IO_SOURCE = pf_io_posix.c
+IO_SOURCE = pf_io_win32_console.c
+#IO_SOURCE = pf_io_posix.c
 #IO_SOURCE = pf_io_stdio.c
 
 EMBCCOPTS = -DPF_STATIC_DIC
@@ -56,8 +57,8 @@
 	pf_text.c pf_words.c pfcompil.c pfcustom.c
 PFSOURCE = $(PFBASESOURCE) $(IO_SOURCE)
 
-VPATH = .:../../csrc:../../csrc/posix:../../csrc/stdio
-VPATH = .:$(SRCDIR)/csrc:$(SRCDIR)/csrc/posix:$(SRCDIR)/csrc/stdio
+VPATH = .:../../csrc:../../csrc/win32_console:../../csrc/posix:../../csrc/stdio
+VPATH = .:$(SRCDIR)/csrc:$(SRCDIR)/csrc/win32_console:$(SRCDIR)/csrc/posix:$(SRCDIR)/csrc/stdio
 
 XCFLAGS = $(CCOPTS)
 XCPPFLAGS = $(CDEFS) -I.

先ほどと同様に「make all」でビルドする。生成される pforth.exe と pforth_standalone.exe は、pf_io_stdio.c を使った場合よりもファイルサイズが小さくなるようだ。

実行ファイル名 pf_io_stdio.c版 pf_io_win32_console.c版
pforth.exe 227,213 byte 198,213 byte
pforth_standalone.exe 288,714 byte 259,202 byte

問題点、課題

実は「make clean」した時に pf_io_stdio.c ないし pf_io_win32_console.c から生成されるオブジェクトファイルが消えずに残ってしまうのだが、些細な問題なので放置している。

*1:こちらのソースはMITライセンスとなっている

*2:少なくともgcc 4.5.1には存在しない。多分gcc 3.4.2あたりにも無いと思う。

*3:多分 _CrtCheckMemory() を使うためにインクルードしていると思われるが、当該部分は #if 0 でコメントアウトされている。なのでダミーの crtdbg.h で十分。