Introduction

Objective-C is a dynamically bound object-oriented extension to ANSI C popularized first by NeXT and then by Apple in MacOS X. The additions that Objective-C makes to ANSI C are few and simple so it is easy to learn. Because Objective-C is a true superset of C, developers can leverage existing C infrastructure and interleave objected-oriented and procedural programming techniques as they see fit.

The simplicity and flexibility of Objective-C make it an attractive choice for developing software, or at least I think so. But I found learning and using Objective-C on GNU/Linux confusing at first. For example, the stock GNU Objective-C class library is sparse on features, sparse on documentation and rumor has it that it's not actively maintained. While the alternatives (gnustep-base and libFoundation) are more complete, provide a good degree of OpenStep/MacOS X compatibility and are better documented (e.g., you can often read Apple's documentation because the APIs are the same), both are tied into specialized file system hierarchies that I personally found baroque.

Fortunately that did not deter me. After some vacillation, experimentation, googling and IRC chatting, I decided to press forward with gnustep-base, which seems to be the class library with the most momentum. I wrote my first Objective-C program, built it (using the gnustep-make system), installed it, tweaked it, built it, installed it and then I sat down to document my experience; which is when I started to learn a few things.

My First Objective-C Program

The Goal

I needed to program something simple enough that I could finish, but complicated enough that I could be satisfied that I had learned to do more than grunt, "Hello, World." I decided to write part of a library class for accessing freedb CD information. I had already written the complete, equivalent library in Perl so the problem space was familiar, and it gave me the opportunity to write a brief demonstration program in addition to the library itself. Furthermore, I could program the library to completion in digestable chunks as I continued to familiarize myself with the Objective-C landscape.

A Little Confusion

Despite the fact that this was merely a programming exercise, I also wanted to be able to install the library and application in sensible locations. In other words, I wanted to implement a distributable tool in miniature.

But it turned out that GNUstep and I had different opinions about what constitutes a sensible location. For example, gnustep-make installs applications and libraries in the GNUSTEP_ROOT (e.g., /usr/lib/GNUstep) and GNUSTEP_LOCAL_ROOT (e.g., /usr/local/lib/GNUstep) hierarchies. In order to run such an application, you have to use the openapp wrapper script:

openapp tbx-discid

This is what I meant when I said baroque. The openapp script apparently waves a dead chicken over the proper bits before invoking tbx-discid.

Don't Worry, I Can Fix It...

All it took was a little bit of digging, a little experimentation and five relatively simple lines in my makefile:

GNUSTEP_INSTALLATION_DIR = "/"
GNUSTEP_HEADERS = "/usr/local/include"
GNUSTEP_LIBRARIES = "/usr/local/lib"

...

GNUSTEP_INSTALLATION_DIR = "/"
GNUSTEP_TOOLS = "/usr/local/bin"

Et voila, sensible locations. Right? Right.

But...

It turns out that the reason GNUstep is structured the way it is is this: The OpenStep specification that GNUstep implements is "an operating system independent, object-oriented application layer, based on NeXT's advanced object technology." Now, we've all heard of that other operating system independent, object-oriented application layer:

java -server -cp /usr/src/org/armedbear/j/src:
/usr/local/share/j/j.jar:
/usr/share/java:
/usr/share/java/xerces.jar:
/usr/share/java/JimiProClasses.zip:
/usr/java/j2sdk1.4.2/lib/tools.jar Main

And we know from eye-witness testimony that Java owes a lot to Objective-C, OpenStep and ex-NeXT developers in Sun's employ.

If you've ever worked with Java, you'll appreciate that in order to be operating system independent, the application layer has to carry at least some of the operating system along with with it: libraries, helper apps, fonts, locale descriptions and so on. But if you look closely at the basic GNUstep hierarchy, you will see that it is mostly skeletal. The bulk of its meager 13M disk space is dedicated to libraries, documentation, headers and makefiles – in that order. It's not so baroque after all.

Clearly if you circumvent the GNUstep infrastructure as I did, you will lose some of the portability it provides. That's not necessarily a good thing, and the potential benefits of doing so do not look as promising in retrospect.

Conclusion

There are many ways to make an application feel like it is part of the local system even while it participates in a system independent layer such as GNUstep. Distributors of Java applications, for example, only infrequently require people to invoke their applications directly through a java command like the one shown above. In fact, I use the above command all the time; but the version I usually use looks like this:

j

Which, of course, is just a wrapper that hides all of the gory details of launching Armed Bear J (with some optional extension libraries). GNUstep even provides makefile hooks (e.g., after-install) that promote the construction of wrapper scripts and installation packages (c.f., rpm.make) based on the build properties (including the GNUstep install locations) of libraries and executables.

Now that I better understand GNUstep's ambition, I'm more likely to play by its rules. My next task is to learn how to use gnustep-make to construct a wrapper script. Then I will complete the freedb library. In the meantime, here is my first program, with my so-called sensible installation locations intact:

TBXFreedb.tar.gz