Cogs and Levers A blog full of technical stuff

Getting Started with GNUstep

Introduction

GNUstep is a development framework for writing GUI applications. It aims to follow Apple’s Cocoa API but allows you to write applications for more platforms than just OSX.

In today’s article we’ll setup a local environment for writing GNUstep programs, and we’ll also write and compile a simple “Hello, world” application to make sure everything is setup.

Brief History

GNUstep is an open-source implementation of the OpenStep specification, which originated from NeXT, a company founded by Steve Jobs after he left Apple in 1985. NeXT developed the NeXTSTEP operating system, which introduced an advanced object-oriented framework for software development. In 1993, NeXT partnered with Sun Microsystems to create the OpenStep standard, which aimed to make NeXT’s frameworks available on other platforms.

When Apple acquired NeXT in 1996, the technology from NeXTSTEP and OpenStep formed the foundation of Apple’s new operating system, Mac OS X. Apple’s Cocoa framework, a core part of macOS, is directly derived from OpenStep. GNUstep, initiated in the early 1990s, aims to provide a free and portable version of the OpenStep API, allowing developers to create cross-platform applications with a foundation rooted in the same principles that underpin macOS development.

So, this still leaves us with GNUstep to get up and running.

Developer environment

First up, we need to install all of the dependencies in our developer environment. I’m using Debian so all of my package management will be specific to that distribution. All of these packages will be available on all distributions though.

sudo apt-get install build-essential gnustep gnustep-devel

Once this is installed, we can move on to writing some code.

“Hello World” alert

The following program is very basic. It’ll show an alert to screen, and then exit after the user has dismissed the alert.

// hello.m

#include <AppKit/AppKit.h>

@interface AppDelegate : NSObject<NSApplicationDelegate>

@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)notification {
  NSAlert *alert = [[[NSAlert alloc] init] autorelease];
  [alert setMessageText:@"Hello, World!"];
  [alert runModal];
  [NSApp terminate:nil];
}

@end

int main(int argc, char *argv[]) {
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  NSApplication *app = [NSApplication sharedApplication];

  AppDelegate *appDelegate = [[[AppDelegate alloc] init] autorelease];
  [app setDelegate:appDelegate];

  [app run];
  [pool drain];

  return 0;
}

Walkthrough

First of all, we include AppKit/AppKit.h so that we get access to the programming API. We then define our own AppDelegate so we capture the applicationDidFinishLaunching slot:

#include <AppKit/AppKit.h>

@interface AppDelegate : NSObject<NSApplicationDelegate>

@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)notification {
  NSAlert *alert = [[[NSAlert alloc] init] autorelease];
  [alert setMessageText:@"Hello, World!"];
  [alert runModal];
  [NSApp terminate:nil];
}

@end

The handler sets up the alert to show to screen, runs this modal as “the program” with runModal, and then we finish with `terminate’.

Next is the main program itself.

We start with an NSAutoreleasePool to give our program some automatic memory management. This is cleaned up at the end with a call to [pool drain].

The app variable is setup as an NSApplication which allows us to instantiate and attach our AppDelegate via the [app setDelegate:appDelegate]; call.

int main(int argc, char *argv[]) {
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  NSApplication *app = [NSApplication sharedApplication];

  AppDelegate *appDelegate = [[[AppDelegate alloc] init] autorelease];
  [app setDelegate:appDelegate];

  [app run];
  [pool drain];

  return 0;
}

Building

Now that we have our code written into hello.m, we can compile and link. There are some compile and link time libraries required to get this running. For this, we’ll use gnustep-config to do all of the heavy lifting for us.

gcc `gnustep-config --objc-flags` -o hello hello.m `gnustep-config --gui-libs`

If everything has gone to plan, you should be left with an executable called hello.

GNUstep Hello World

Happy GNUstep’ing!