Haskell and freeglut at last!
It took for-freaking-evar, but I finally got freeglut and Haskell to play nice with each other.
Here’s how I got it working.
The Tools
I’m not giving step-by-step, but rather a general method plus some details where they’re important. It actually became relatively easy once I switched from Cygwin to MSYS for my build environment. So the first thing to do is to go set up MinGW and MSYS. Their documentation will tell you how to set that up better than I could, so I’ll refer you to that. We need some extra libraries, too, so grab the supplementary tools while you’re there. I got the ‘Current Release’ version of both MSYS and the supplementaries, not the technology previews.
The Source
Next, we need the source code for both freeglut and the Haskell glut binding. freeglut source can be found on their sourceforge page, freeglut.sourceforge.net. Version 2.4.0 has a bug that causes some programs, including every one I’ve written in Haskell, to fail with a “somesuch function was called before initialize” error or similar, so grab the nightly build. It looks like it was fixed in those. The Haskell GLUT binding can be gotten from the comfort of your command line with a command very much like
darcs get "http://darcs.haskell.org/libraries/GLUT/"
Assuming, of course, you have darcs installed, which you should. If you don’t, Google will help you out there.
Fire up MSYS, and get ready to rumble. We’ll tackle freeglut first.
freeglut
freeglut’s makefile for my setup seems, well, broken. I fiddled with it for hours and got nowhere. Have I mentioned I don’t like makefiles? Fortunately, the source layout is so simple, compiling by hand is relatively painless once you figure out the details. Even more fortunately, I’ve figured out enough of the details to get a working library. A word of warning, your mileage may vary and these probably aren’t the best compiler and linker flags to use. I really don’t know any better, and this at least works. From the MSYS shell, navigate to the src/ subdirectory in your freeglut source folder and enter:
gcc -O2 -c -DFREEGLUT_EXPORTS *.c
That should compile successfully. Now enter:
gcc -shared -o glut32.dll *.o -Wl,--enable-stdcall-fixup,--out-implib,libglut32.a -lopengl32 -lglu32 -lgdi32 -lwinmm -luser32
Note that I chose to replace my existing glut library with freeglut, so I named the DLL glut32.dll and the import library libglut32.a. You may want to name them differently, but this post assumes you are replacing the origninal glut. Now we need to move some files around. Copy libglut32.a to GHC’s gcc-lib directory. In my case it’s D:\ghc-6.8.2\gcc-lib\ I also replaced libglut.a in the same directory. I don’t know if that helps, but I did it anyway. Next, copy the headers from your freeglut’s \include\GL directory (freeglut.h, freeglut_ext.h, freeglut_std.s, glut.h) to GHC’s \include\mingw\GL directory. This will replace the original glut.h header. Put the DLL somewhere where you’re programs can find it, like in the windows\system32 directory, or just put copies next to your executables that need it.
That’s it for freeglut! Now we just need to get the Haskell glut binding to work with it.
The GLUT Binding
Open up MSYS and navigate to the GLUT directory you got from darcs. Enter:
autoreconf
If this doesn’t work, you probably missed some of the needed supplementary tools. Go get what’s missing and try again. Google will help you figure what missing files are found in which packages.
Next, enter:
runhaskell.exe Setup.hs configure
There are some flags for setting paths and the like, but I couldn’t get the thing to use the correct path variables with my thumbdrive based GHC installation. I’ll show you how to edit the package.conf file in a bit.
Now we have to edit some files if we want to avoid a nasty linker issue when using the interpreter. This is actually a known bug and the fix is slated for GHC version 6.10. Praise be to Ron Guida for his post here for figuring out what to edit. I’ll repeat the instructions here. Open up \Graphics\UI\GLUT\Extensions.hs, find the line
foreign import ccall unsafe "hs_GLUT_getProcAddress" hs_GLUT_getProcAddress :: CString -> IO (FunPtr a)
and change it to
foreign import stdcall unsafe "glutGetProcAddress" hs_GLUT_getProcAddress :: CString -> IO (FunPtr a)
Next, open \cbits\HsGLUT.c and remove the function hs_GLUT_getProcAddress. In my case, that meant removing lines 47-66. That’s all we need to edit. Compile from MSYS by entering:
runhaskell.exe Setup.hs build
Follow up with:
runhaskell.exe Setup.hs install
and you’re done!
Optional: Fix the Path
Optional unless install screws up the path setting, of course, like mine does. Oh well, pretty easy to fix. Make a note of where install dumped you’re files. Go copy those, and put them in GHC’s lib folder, with the rest of the libraries. Now, open up package.conf in your GHC folder, find the entry for GLUT, and make the paths point to the right place. When I edited my package.conf, all of the libraries used the $topdir variable in their paths except GLUT. A quick find-and-replace to rectify that, and I was all set.
You’re Done!
Celebrate by opening up an editor and making a spinning cube! Don’t forget to let me know how it turned out.
October 29th, 2008 at 5:22 pm
Hi Jeff. I’m following your instructions (thanks much!), and I ran into a missing symbol:
bash-3.1$ gcc -shared -o glut32.dll *.o -Wl,–enable-stdcall-fixup,–out-implib,libglut32.a -lopengl32 -lglu32 -lgdi32 -lwinmm
Creating library file: libglut32.a
freeglut_gamemode.o(.text+0×26b):freeglut_gamemode.c: undefined reference to `ChangeDisplaySettingsExA@20′
Did you hit this problem also? Any ideas?
October 29th, 2008 at 6:35 pm
Hi Conal,
I didn’t encounter that error, but I probably should have with the build command I used! ChangeDisplaySettings is in User32.dll, which my command doesn’t link against. I believe adding “-luser32″ (without quotes, of course) to the end of your build command will solve that.
I’ll update the article with the modified command. Let me know how it works out!
November 6th, 2008 at 2:11 pm
[...] Resources. The haskell-cafe mailing list is a good place to ask for help. Also this site has some information on getting freeglut+windows working with an older version of ghc. November [...]