Log in

No account? Create an account
fragglet [userpic]

Chocolate Doom on OS X, and GNUstep

February 5th, 2010 (01:19 pm)

Chocolate Doom runs on Mac OS X and has done for several years; however, until now, getting it running has been overly complicated and required compiling the source code from scratch. Obviously this isn't really appropriate for a Mac; it certainly doesn't fit in with the Apple way of doing things. I recently set about trying to improve the situation.

I first investigated how things are installed on OS X. Generally speaking there are two ways that things are installed; the installer (.pkg files), and Application Bundles, typically contained inside a .dmg archive. The installer simply installs a bunch of files to your machine, while Application Bundles are a lot more fluid; to install, you simply drag an icon into the Applications folder.

Application Bundles seem obviously preferable, but there's the problem of how one should be structured. Chocolate Doom needs a Doom IWAD file that contains the data used by the game, so it's not sufficient to simply package the normal binary as a bundle. Then there's the setup tool as well - should that be in a separate bundle? Finally, people often like to load PWAD files containing extra levels and mods. How do you do that with a bundle?

In the end, I decided to write a minimalist launcher program. Everything is in a single bundle file which, when launched opens a launcher window. The launcher allows the locations of the IWAD files to be configured and extra command line parameters entered. There's also a button to open the setup tool.

The launcher also sets up file associations when installed, so that it is possible to double-click a WAD file in the Finder, and an appropriate command line is constructed to load it. The interface is not as fully-featured as other "launcher" programs are, but it's simple and I think fits with the philosophy of the project.

Developing with GNUstep

The interesting part is how I developed the launcher. I only have occasional use of a Mac, so I developed it on GNUstep. This is an earlier version of the launcher interface while it was under development:

GNUstep provides an implementation of the same Objective C API that OS X's Cocoa provides, albeit with a rather crufty-looking NeXTStep appearance. It also has Gorm, which works in a very similar way to OS X's Interface Builder application. Using GNUstep, I was able to mock up a working program relatively easy. Constructing interfaces is very straightforward: the controls are simply dragged-and-dropped onto a window. I was able to get the underlying code into a working state before porting to OS X.

Porting to OS X

Porting to OS X had some hassles. Firstly, Gorm/GNUstep uses its own native format for interface files, which are different to the .nibs used on OS X. Recent versions of Gorm can save .nibs, but I found that the program crashed when I tried to do this. I eventually just reconstructed the whole interface from scratch in Interface Builder. GNUstep can use .nibs, so I just threw the older Gorm interface away.

The other main annoyance was that the format for property lists is different on OS X. It seems that GNUstep uses the older NeXT format, which Apple have since replaced with a newer XML-based format. Finally, icon files on OS X are in a proprietary .icns format, while GNUstep simply uses PNGs.

Both OS X and GNUstep try to force you to use their build tools (Xcode, ProjectCenter) which seem to generate a whole load of junk. I wrote a Makefile instead. There are some conditional parts to handle the two systems - OS X and GNUstep application bundles have different internal structures, for example. On OS X, the Makefile will do the complete process of compiler code, constructing the application bundle and generating a .dmg archive.

One thing I did find interesting is how OS X handles libraries. The full paths to any .dylib libraries (which are like Linux .so files or Windows DLLs) are stored inside a program when it is compiled. In my case, my application bundle needs to include the SDL libraries that Chocolate Doom depends upon. There's a convenient program called install_name_tool that can be used to change these paths after the program has been compiled. A special macro called @executable_path can be used to mean "the path where this binary is". I wrote a script to copy a program along with any libraries it depends on, changing its library search paths appropriately.

As one last finishing touch, there's a "Command Line..." menu item that calls into Terminal.app to open a command line window, if you're of the type who prefers the command line. The window sets up the PATH to point to the directory within the package that contains the chocolate-doom binary, and also sets up DOOMWADPATH to point to all the IWAD files you've configured within the GUI.

Thoughts on GNUstep

GNUstep was certainly incredibly useful in this activity; the ability to develop the program on my usual (Linux) laptop was very convenient. From a technical perspective, GNUstep seems to be a very impressive project. There is great usefulness in having a Linux implementation of the OPENSTEP (ie. Cocoa) API, which is what GNUstep is. However, the NeXT-style interface clashes horribly with almost any desktop environment that you might want to run under Linux (Gnome/KDE/etc), which is a huge turn-off.

The main problems are (1) the mini-window icons (which represent the running application) and (2) the menus, which appear in a separate window to the other application windows. I expect these are things that I could get used to if I was running a full GNUstep desktop where everything was like this; however, I'm not and it wouldn't really be practical for me to do so. It is possible to theme GNUstep to look nicer than its default "ugly grey square" appearance, but these problem remain.

GNUstep is a frustrating project in this respect. I can't help wonder if the full potential of the project is limited by the short-sightedness of its developers. It seems like they're too hung up on their goal of recreating NeXTstep, when I doubt there are many people who would even want to use such a system nowadays. This entry from the developer FAQ gives a good example of what I'm talking about:
How about implementing parts of the Application Kit with GTK?
Yes and No - The GNUstep architecture provides a single, platform-independent, API for handling all aspects of GUI interaction (implemented in the gstep-gui library), with a backend architecture that permits you to have different display models (display postscript, X-windows, win32, berlin ...) while letting you use the same code for printing as for displaying. Use of GTK in the frontend gui library would remove some of those advantages without adding any.

"Without adding any [advantages]" - except, of course, the ability to give GNUstep applications an appearance that is consistent with 99% of Linux desktops! If it was possible to use GNUstep to make applications that looked like Gtk+ apps, I bet it would be a lot more attractive to developers. The practical advantages of such a decision are dismissed completely in the face of architectural/technical advantages that probably have little practical use.


Posted by: LionsPhil (lionsphil)
Posted at: February 5th, 2010 02:56 pm (UTC)

"For this tool to work when the install names or rpaths are larger the binary should be built with the ld(1) -headerpad_max_install_names option."

UGH. Hello dumb hex-edit-style overwriting of header fields. Why the hell is the default to store full paths?

Posted by: fragglet (fragglet)
Posted at: February 5th, 2010 03:30 pm (UTC)
Chocolate Doom

I suspect it's a side-effect of the OS X package system; it's not like in Unix where you can just search for libraries in a few common locations (/lib, /usr/lib, etc); a typical GUI app might be linked against a dozen or so library packages in /System/Library (see here for example).

I expect if you build with Xcode it takes care of it all automatically. I'm undecided whether it might actually be a better system than the Unix way; at least you can use @executable_path to make self-contained packages without having to mess around with shell scripts that set LD_LIBRARY_PATH (hello, eclipse).

Posted by: LionsPhil (lionsphil)
Posted at: February 5th, 2010 03:43 pm (UTC)
Re: packages

Yeah, but @executable_path is relative. Relative paths are sane enough if you're taking a "every binary must bundle all its dependencies" approach and are, after all, one of the ways Windows will locate DLLs.

Posted by: LionsPhil (lionsphil)
Posted at: February 7th, 2010 06:58 pm (UTC)


…a backend architecture that permits you to have different display models (display postscript, X-windows, win32, berlin ...) while letting you use the same code for printing as for displaying…
Hey! Just like GDK, or GGI, or Cairo! Some of which can use eachother for backends just because if there's one thing Linux weenies love, it's pointless stacks of abstraction layers that would theoretically let your program run on a better platform if only any developers actually worked on "supporting" that target properly.

Posted by: mewse (mewse)
Posted at: February 8th, 2010 08:10 pm (UTC)

Thanks for putting this post together. I suspect GNUstep is just going to get more and more irrelevant as time wears on.

Posted by: fragglet (fragglet)
Posted at: February 8th, 2010 08:54 pm (UTC)
Chocolate Doom

When, considering the popularity of OS X, it could be doing the exact opposite!

Posted by: http://www.google.com/profiles/116861846348590397461 (ext_325259)
Posted at: November 17th, 2010 09:30 pm (UTC)

There are many thigns one could add to this post - especially as a long time GNUstep and Mac developer.

Xcode forces you a build system and a new format with every release... ProjectCenter instead will just create a Makefile. This Makefile is designed to run with GNUstep-make to have some convenient methods and extensions, but it literally uses GNU make to execute. You could write the same file by hand.

This is how ProjectBuilder used to work on NeXT and OpenStep before Apple tore it apart by changing the development tool essentially at every major Macintosh release.

7 Read Comments