HSDL with GHC 6.6.1

HaskellSDL binding である HSDLGHC 6.6.1 でコンパイルするための手順メモです。

1. 必要なものをダウンロードします。

HSDL のソースコードSDL のランタイムライブラリと開発ライブラリ (ヘッダとか) が必要です。

$ ls
HSDL-0.2.0.zip        SDL-devel-1.2.12-mingw32.tar.gz
SDL-1.2.12-win32.zip  haSDLis.zip

2. SDL の開発ライブラリを適当なところに展開します。

$ tar xzf SDL-devel-1.2.12-mingw32.tar.gz
$ mv SDL-1.2.12/ /usr/local/

ちなみに僕は cygwin を使ってます。/usr/local は C:\cygwin\usr\local です。好きなところに置けばいいと思います。

3. HSDL を展開します。

$ mkdir HSDL
$ cd HSDL
$ unzip ../HSDL-0.2.0.zip

4. HSDL.cabal を編集します。

ここがポイントです。

  • c-sources を消す。
  • include-dirs を C:\cygwin\usr\local\SDL-1.2.12\include\SDL にする。
  • ld-options を消す。
  • extra-lib-dirs を追加し、C:\cygwin\usr\local\SDL-1.2.12\lib にする。
$ cp HSDL.cabal HSDL.cabal.org
$ vi HSDL.cabal
$ diff HSDL.cabal.org HSDL.cabal
21,24d20
< c-sources:
<       Multimedia/SDL/Timer_stub.c,
<       Multimedia/SDL/Event_stub.c,
<       Multimedia/SDL/Audio_stub.c
28a25,26
> extra-lib-dirs:
>       C:\cygwin\usr\local\SDL-1.2.12\lib
30,32c28
<       /usr/local/include/SDL
< ld-options:
<       -L/usr/local/lib
---
>       C:\cygwin\usr\local\SDL-1.2.12\include\SDL

5. ビルドします。

README にある通り。

$ runghc Setup.hs configure
$ runghc Setup.hs build
$ runghc Setup.hs install

6. テトリスコンパイルして動作確認します。

$ cd ..
$ unzip SDL-1.2.12-win32.zip
$ mkdir haSDLis
$ cd haSDLis
$ unzip ../haSDLis.zip
$ ghc --make -o test main.hs
$ mv ../SDL.dll .
$ ./test.exe

SDL.dll を同じディレクトリ (か C:\WINDOWS\system32 あたり) に置くのを忘れないように。

その他

そのままコンパイルした場合、hsc2hs が libSDL.a を見つけられずにエラーになったり*1

$ runghc Setup.hs build
Preprocessing library hsdl-0.2.0...
C:\cygwin\usr\local\ghc-6.6.1\gcc-lib\ld.exe: cannot find -lSDL
collect2: ld returned 1 exit status
linking Multimedia\SDL\Audio_hsc_make.o failed
command was: C:\cygwin\usr\local\ghc-6.6.1\bin\ghc.exe -lSDL Multimedia\SDL\Audio_hsc_make.o -o Multimedia\SDL\Audio_hsc_make.exe
Setup.hs: got error code while preprocessing: Multimedia.SDL.Audio

リンク時にシンボルの重複でエラーになったりします*2

$ runghc Setup.hs build
Preprocessing library hsdl-0.2.0...
Building hsdl-0.2.0...
[ 1 of 10] Compiling Multimedia.SDL.Util ( Multimedia/SDL/Util.hs, dist\build/Multimedia/SDL/Util.o )
[ 2 of 10] Compiling Multimedia.SDL.Video ( Multimedia/SDL/Video.hs, dist\build/Multimedia/SDL/Video.o )
[ 3 of 10] Compiling Multimedia.SDL.Window ( Multimedia/SDL/Window.hs, dist\build/Multimedia/SDL/Window.o )
[ 4 of 10] Compiling Multimedia.SDL.Timer ( Multimedia/SDL/Timer.hs, dist\build/Multimedia/SDL/Timer.o )
[ 5 of 10] Compiling Multimedia.SDL.Keysym ( Multimedia/SDL/Keysym.hs, dist\build/Multimedia/SDL/Keysym.o )
[ 6 of 10] Compiling Multimedia.SDL.Joystick ( Multimedia/SDL/Joystick.hs, dist\build/Multimedia/SDL/Joystick.o )
[ 7 of 10] Compiling Multimedia.SDL.Init ( Multimedia/SDL/Init.hs, dist\build/Multimedia/SDL/Init.o )
[ 8 of 10] Compiling Multimedia.SDL.Event ( Multimedia/SDL/Event.hs, dist\build/Multimedia/SDL/Event.o )
[ 9 of 10] Compiling Multimedia.SDL.Audio ( Multimedia/SDL/Audio.hs, dist\build/Multimedia/SDL/Audio.o )
[10 of 10] Compiling Multimedia.SDL   ( Multimedia/SDL.hs, dist\build/Multimedia/SDL.o )
C:\cygwin\usr\local\ghc-6.6.1\bin\ar.exe: creating dist\build\libHShsdl-0.2.0.a
dist\build\Multimedia\SDL\Audio_stub.o(.text+0x0):Audio_stub.c: multiple definition of `MultimediaziSDLziAudio_dq6y'
dist\build\Multimedia\SDL\Audio_stub.o(.text+0x0):Audio_stub.c: first defined here
dist\build\Multimedia\SDL\Event_stub.o(.text+0x0):Event_stub.c: multiple definition of `MultimediaziSDLziEvent_dkOD'
dist\build\Multimedia\SDL\Event_stub.o(.text+0x0):Event_stub.c: first defined here
dist\build\Multimedia\SDL\Timer_stub.o(.text+0x0):Timer_stub.c: multiple definition of `MultimediaziSDLziTimer_ddwA'
dist\build\Multimedia\SDL\Timer_stub.o(.text+0x0):Timer_stub.c: first defined here
dist\build\Multimedia\SDL\Timer_stub.o(.text+0xb5):Timer_stub.c: multiple definition of `MultimediaziSDLziTimer_ddwd'
dist\build\Multimedia\SDL\Timer_stub.o(.text+0xb5):Timer_stub.c: first defined here


あと、HaskellSDL binding としては http://hackage.haskell.org/cgi-bin/hackage-scripts/package/SDL-0.5.0 もあるようです。こっちの方が公式っぽいですが、どっちの方がいいのかはわかりません。ぱっと見ですが、Audio に関しては HSDL の方が呼べる API が多いです*3。いずれにしても、あんまりメンテナンスされてないような気はしました。

*1:extra-lib-dirs が設定されていないため。

*2:hsc2hs が吐く C コードを c-sources で指定しているため、余分にリンクしようとするみたい。昔の GHC だと必要だったのかな?

*3:ただし README にあるようにバグ持ちですが。