This article was originally published in Linux Magazine France n47, Feb. 2003
Authors : Nicolas Roard and Fabien Vallon, translation : Gerold Rupprecht

Introduction to the GNUstep project

`` My view of Microsoft is that they had two goals in the last 10 years: to copy the Macintosh and to copy Lotus' success in the application business. And they accomplished those goals. Now, they're kind of lost. I've told Bill [Gates] that I think it's in Microsoft's best interest if NeXT becomes successful because we'll give them something to copy for the rest of this decade ''

-- Steve Jobs

NeXT failed, but certain features are still present - with Mac OS X - but also , which is of more interest to us, in the GNUstep project.

Historical background : From NeXTSTEP to OpenStep

Before talking about GNUstep, a brief historical summary is necessary.It all started in 1985, when Steve Jobs, who had just quit Apple, decided to start a new computer company: NeXT Inc. (1). With NeXT, his goal was to build a machine that was twenty years ahead of its time.

Surrounded by a team of brilliant engineers (Avie Tevanian, Jean-Marie Hullot, etc.) NeXT launched in 1988 a revolutionary machine: the NeXT Cube. It was equiped with a Unix operating system (BSD personality on top of a mach kernel), with high resolution PostScript, complete with a graphical environment, entirely object oriented (using Objective-C, an object oriented super-set of ANSI C, inspired by SMALLTALK).

The entire world was amazed by the machine... and yet almost no one bought it: bad marketing, difficult relations with developers, machines considered too expensive... The following incarnations of the OS or the machines did not change that. NeXT remained only a developer's fantasy.

NeXT Computer finally became NeXT Software, having abandoned the building machines, reorienting itself towards selling software, in particular their NeXTSTEP system, which evolved into OPENSTEP.

NeXT was finally bought by Apple in 1996, and in a form of irony, Steve Jobs (re)became the CEO of Apple (2). The particularity of OPENSTEP was that it was an implementation of an open standard (OpenStep), made in collaboration with Sun, which was an evolution of the NeXTSTEP framework. OPENSTEP existed op SUN, HP, Intel and even on top of Windows NT. At this timeMac OSX is just an evolution of OPENSTEP, with display PDF instead of PostScript, and basically, a compatibility mode with the old Mac software in additon to the OPENSTEP tools.

GNUstep

Following the publication of the OPENSTEP API, a Free Sofware Foundation project was started to reimplement it> GNUstep. It was destined to be the default environment of the GNU system.

But the project advanced very slowly over the years, because few developers were working on it. Contrary to other projects, there was an enormous entire system to reimplement from scratch(problem of display PostScript for example); it was therefore difficult to get something interesting during this implementation... thus a clear problem of visibility.

Nevertheless, since some time, the system has become usable by developers: the implementation is sufficiently complete to allow the development of programs using the GNUstep environment. And effectively, since about one year , the applications are gently beginning to arrive...

The GNUstep advantage

GNUstep is thus a reimplementation of the known and documented API: OPENSTEP.

In this manner, what had been a disadvantage (of little interest to work on while the ensemble had not reached a sufficient stage, thus difficult to interest programmers) is thus an advantage, because we do not have profound changes of the framework, such as did happen over the different versions of KDE or GNOME. The OPENSTEP framework itself is particularly well polished and coherent, and has not needed any particular modifications since its publication ... in 1994!

MacOS X nevertheless adds several new widgets to those available (which GNUstep implements from time to time), but being an OPENSTEP implementation, the portability between a GNUstep and a MacOS X application is high. A GNUstep program could be recompiled almost unchanged under Mac (3).The final objective of GNUstep is to deliver a true multi-platform portability. The applications for example are distributed in the form of a directory (wrapper) containing several versions (one for x86, one for PPC, etc.) GNUstep of course supports localization, with the added advantage to be able to rework, without touching the code, the graphical interface for each language if needed.

GNUstep does not stop with only managing a GUI, but also offers tools for the non graphic parts (threads, data structures... or different functionalities such as a powerful clipboard, an intelligent assisted cooperation between programs (services) etc.

GNUstep also offers a framework (GDL2/EOF) allowing the mapping of objects onto a classic relational database, thus offering at the same time the comfort of object orientation for managing data and an abstraction with respect to the relational database management system used.

Finally, the most evident advantage for the developer is the availability of tools such as GORM (Gnu Object Relational Modeler), a graphical interface modeller, which greatly accelerates software development.

GNUstep platform overview

The following figure shows us the architecture used by GNUstep. A graphical application thus is supported by two frameworks, Foundation and AppKit.

base (Foundation Kit)

The Foundation Kit is a non graphic framework allowing the abstraction of the operating system. Other than the classic manipulations of strings, arrays, the Foundation Kit offers resource management (Bundles), threads, object persistance, Unicode... The Foundation Kit is an essential component guaranteeing the portability of the GNUstep platform.

gui (Application Kit)

The Application Kit contains the graphical part of classes (graphical objects such as windows, buttons, panels, event management...), but also a Desktop orientation with the management of peripherals, services, application launching or the Pasteboard.

backend

GNUstep, contrary to MacOS X, also offers an abstraction of the display system. It currently supports X11 for traditional Unixes, Windows, or Display PostScript (display PDF on Apple), A DirectFB backend is also being considered....Being implemented as a bundle (read plug-in, for the moment), it is even possible to move from one to another, even several others at the same time...

Other frameworks: (EOF/GNUstepWeb/ Pantomime...)

Besides Foundation and the AppKit, GNUstep offers numerous extensions:

Other frameworks are available such as Pantomime (an Objective-C implementation of JavaMail), MusicKit or the SoundKit.

Installation of GNUstep

A small exercise to be prepared for next month: installation of the GNUstep platform. The reference platforms here will be GNUstep / Linux (Debian Woody) and GNUstep / BSD (FreeBSD-4.7).

You can easily transpose it on to your favorite OS, it will not normally be any problem on any type of *nix; the installation of GNUstep / MS-Windows or GNUstep / BeOS being a little more complex and less complete.

First of all, the compiler. Even if GNUstep works under gcc-2.9x it is recommended to us a gcc-3.x compiler. On Debian, a simple:

apt-get install gcc-3.0 gobjc-3.0

On FreeBSD (gcc-33 is available via CVSup), is just as simple:

cd /usr/ports/lang/gcc33/ && make install clean

you will install the compiler (you could delete the Java part if you want to gain some compilation time :) The Debian packages, as many of the BSD ports, are a bit old (even on sid), therefore it is recommended to take the packages from CVS:

cvs -z3-d:pserver:anoncvs@subversions.gnu.org:/cvsroot/gnustep login

--Press on Enter

We will only take a small part...

cvs -z3 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/gnustep co core

Let us set up our default compiler settings:

export CC=gcc-3.0 -fno-strict-aliasing
Now, let us go into core/make:
./configure
(./configure -disable-openssl)
make
(gmake for FreeBSD)
make install
(gmake install for FreeBSD)

You may want to change to root for the make install. You can add the option -prefix= yourpath to choose an installation directory other than the default. If we take a tour around where we have installed GNUstep, you will find a directory tree that MacOS X or OPENSTEP users know well :) In a pure *step system, this tree is found at the root (and for WindowMaker users your ~/GNUstep will actually be your home directory). OK. We now must set the GNUstep environment variables. For this, I recommend putting source /whereGNUstepWasInstalled/System/Makefiles/GNUstep.sh (or GNUstep.csh if you are using the C-shell) in your shell profiles.

Let us return to our CVS repository, an more precisely go to core/base. The base is what *Steppers call Foundation. It is recommended to install the development libraries openssl, libxml2 and iconv, namely libssl-dev, libxml2-dev for Debian, iconv normally being in the libc and iconv-2.0_3, libxml2-2.4.24, for FreeBSD.

If your GNUstep variables are set correctly, a simple

./configure

makefiles (gmake for FreeBSD)

make install (gmake install for FreeBSD)

should suffice (if you have installed as root do not forget to source the GNUstep.sh file). For AppKit, referred her as gui (in core/gui), you must have the tiff development library. Installation is in the same manner as for base.

Let us finish with the backend. Under X11 there are actually several backends (using eith the xlib, or libart libraries). We will choose libart by default, which even if it is slightly more difficult to install, has a better font rendering and a better graphic engine (antialiasing of vectorial rays, better imagery support -alpha channel, for example). You will need libart-2 and freetype2; it is also recommended to have libwraster2-dev.

Lets go back to core/back:

./configure -enable-graphics=art
make (gmake for FreeBSD)
make install
(gmake for FreeBSD)

You now need to place the fonts into ~/GNUstep/Library/Fonts/ .

A minimal set of fonts can be downloaded from http://developer.linuxstep.org/downloads/ , one can also use NeXT fonts: ftp://ftp.peak.org/next-ftp/next/fonts/index.html.

We are now ready. We will set our personal environment variables beginning with the time zone:

defaults write NSGlobalDomain "Local Time Zone" Europe/Paris

then the language: defaults write NSGlobalDomain NSLanguages "English"

All we need to do now is to start the daemons for distributed objects (gdomap), notifications server (gdnc) and the pasteboard server (gpbs). Personnally, I start these via init scripts: /etc/init.d/GNUstep.sh for Debian and /usr/local/etc/rc.d/GNUstep.sh for FreeBSD. See the example scripts for your system.

Now that your GNUstep system is installed, we can start to develop some applications which we will see next month. We will first of all present Objective-C...

Objective-C: a powerful object oriented language

Objective-C is the language used by GNUstep, and is part of the GNU GCC compiler.

It is a superset of ANSI C, with a few additions, providing a SmallTalk inspired syntax. It is considered the most dynamic C inspired object oriented language.

Brad J. Cox developed the original version of the language by adding SmallTalk-80 like extensions to the C language. Dennis Gladding wrote the first GNU version in 1992, rapidly followed by Richard Stallman's second implementation.

In 1993, another version appeared, written by Kresten Thorup, which was to be used by NeXT (now Apple). The following versions have been maintained by Ovidiu Predescu, and currently by Stan Shebs, of Apple.

Objective-C uses a runtime, which allows message sending between objects in a dynamic manner, at execution time. This gives a lot of flexibility, and allows a very elegant form or programming.

Even though it is possible to develop under GNUstep with other languages (Python, Ruby, Java...) Objective-C remains the favorite developers language., because it offers a good synthesis between the simplicity of C and the powerfulness brought by objects. The following presentation about Objective-C supposes you have some notions of object oriented programming and the C language.

Syntax

Objective-C adds a few keywords to ANSI C, and one syntactic addition: the use of square brackets ( [ ] ). to send a message to an object. The object myObject thus receives the message aMessage :

[myObject aMessage];

A message can have a parameter:

[myObject aMessageWithParameter: aParameter];

...or several:

[myObject aMessageWithAParameter: aParameter andAnother: parameter];

Objective-C allows the labelling of the different parameters, which are written in the middle of the message and not at the end (suchas as with C, C++, Java function calls). The method prototype responds to the message (from the compiler point of view) thus the following:

aMessageWithAParameter:andAnother:

does not end as one might first think after aMessageWithAParameter:

The C++ /Java equivalent would be to write in this fashion:

myObject.aMessageWithAParameterandAnother (aParameter, parameter);

his way of writing is surprising at first, but allows the creation of very readible code (because the messages are written like phrases, which finally appears the most logical.

The blocks can be embedded:

[[myObject message1] message2];

For this example, myObject first receives message1 and the return of this action then receives message2 (it would be best for us if message1 returns an object;)

The naming convention for methods is the following:

Defining an object

Three key words are used to define an object, @interface, @implementation and @end.

Here is an example:

@interface anObject: NSObject
{
	//object data members
	int number;
	NSString* name;
}
+ (void) aMessage;
- (int) aMessageWithAParameter: (int) aParameter;
- (NSString*) aMessageWithAParameter: (int) aParameter 
	andAnother: (NSString*) parameter;
@end

The key word @interface is followed by the name of the object, followed by a colon and the name of the object that one is subclassing (that one is deriving). Here, it is NSObject, which is the root object of the GNUstep class hierarchy (almost all objects used within GNUstep are derived from NSObject).

We then find two curly brackets (mandatory), which contains the member data of the object, here an integer (int) and an NSString object (Unicode character string).

The object's method declarations follow. The first character at the start of a prototype is either a + or a -; the plus indicates a method used on the class object, the minus indicating methods used on object instances. We then have the return value of the method. Each parameter is also preceded by its type, shown between parentheses

Object implementation

The following example shows the implementation of the class anObject. We repeat the method declarations and add their implementation between curly brackets.

@implementation anObject
+ (void) aMessage 
{
	NSLog (@"Hello world");
}

- (int) aMessageWithAParameter: (int) aParameter
{
	return aParameter;
}

- (NSString*) aMessageWithAParameter: (int) aParameter 
	andAnother: (NSString*) parameter 
{
	return [NSString stringWithFormat: "@%@ : %d", 
		parameter, aParameter];
}
@end

The method aMessage displays Hello world. The arobase (@) before the character string is a short cut to indicate a NSString (a Unicode string) instead of a simple char array as in C or C++.

The method aMessageWithAParameter: aParameter andAnother: returns a character string (a NSString object); this object is constructed from a NSString class method callable without an instance ( remember the + a moment ago), is in effect a NSString constructor.

Protocols

We can define protocols (equivalent to Java interfaces) to which the object responds.

@protocol NameOfProtocol
	// list of protocol methods
@end

The declaration of an object conforming to a protocol will be as follows:

@interface MyObject : NSObject <NameOfProtocol>

An object can conform to serveral protocols, we separate these with a comma in the declaration:

@interface MyObject : NSObject <NameOfProtocol1, NameOfProtocol2>

You can even ask an object at runtime if it responds to a given protocol.

Categories

Who never wanted to add an indispensible function for example to a C++ class, without being able to (the class did not belong to the program, the sources were not available, etc.)?

Then the only solution was to create a new class, derived from the first, implement this function, which introduces other kinds of problems (coherence, mixing the two classes, etc.)

This is one of the Objective-C advantages and the use of a runtime... You can add to a class object new methods, without needing the sources of the original class or to recompile.

These new methods are accessible (only for the current program), as if they had always been part of the class.

Here is an example of the syntax used:

@interface MyObject (MyCategory)
	// list of methods added to the category
@end

@implementation MyObject (myCategory)
	//implementation of category methods
@end

Object Usage

There is a generic type of object: id . It is actually a pointer to an object. id contains no information about the object, other than it is an object. We thus work with dynamic typing.

The object can benefit from introspection, and can thus ask what type it is, if it can respond to a message or a given protocol, etc. Note that in the code extract examples 1 and 2, the objects (here NSString) are declared using a class name, and as pointers (NSString*). The difference from the id type, the compiler can verify that the object is of the given type. This allows static typing, which helps in debugging.

Allocation and initialisation

An object is allocated by the alloc class method. We can then follow up by sending an initialisation message:

MyClass* toto =[[MyClasss alloc] init];

The method responsible for the initialisation can have any name, take parameters, and from the moment it returns, it too returns the initialised object!

- (id) init 
{
	self = [super init];
	return self;
}

By the way, note the two key words self and super, which respectively make reference to the current object and its parent.

Memory management

GNUstep offers two forms of memory management:

We only want to speak about reference counting here, the most commonly used method. The principle is very simple: when allocating an object, the reference counter is set to one. If we send a release message to the object, this will decrement the counter, and if we send a retain message to the object, this will increment the counter. A counter set to zero deallocates the object.

An object which receives as a parameter another object will send it a retain message if it wants to keep and use it; in this way, even if it receives a release message (from its initial setting), it will not be deallocated, the counter still being positive thanks to the second retain message.

The rule is to only deallocate the objects that one has directly created or to those that one has sent a retain message.

There are some cases where one may want to deallocate in advance an object, but where we cannot because another object could be using it (typically, a method creating an object on the fly which it returns but does not want to keep, but cannot deallocate).

One can thus send an autorelease message to the object, which will automatically deallocate at the end of the event loop of the program, leaving enough time for (example) the calling method to use the object.

Conclusion

There, our tour of the GNUstep project horizon is finished.

We hope that you appreciated this article , and we will normally will see you again next month to attack this time programming a GNUstep application:)

Until then, we recommend looking at some URLs as shown below... and for those curious you are welcome to join the irc #gnustep (irc.debian.org) !

Nicolas Roard, nicolas@roard.com

Fabien Vallon, fabien@tuxfamily.org

Thanks to Vincent Ricard for reviewing this article.
Big thanks to Gerold Rupprecht for the traduction !

Links

(1) For the resume, the other company that Jobs founded at the moment is called Pixar, the creator (amongst others) of Toy Story.
(2) The critics say that NeXT succeeded in a reverse takeover of Apple and got paid for it:)
(3) The best example is GNUMail