Compiling Objective-C without a GUI

I have very recently got a Mac Mini and obviously looked into Objective-C. I’m quite intrigued by the language and it’s quite useful to learn, yet I’m not a fan of the Mac, nor am I a fan of the GUI, so the first thing I wanted to know is how to compile Objective C without XCode and/or without a Mac. This is a beginner’s guide to compiling Objective-C (version 2.0) on Ubuntu and OSX.

Compiling Objective-C

OSX

To compile Objective-C on OSX the easy way you have to get XCode, which is free to obtain from the Application Store. Getting XCode will ensure you obtain the necessary frameworks (headers), like Foundation, Cocoa, etc. This will, however, not provide you with the necessary command line tools to compile Object-C from the command line. Open up XCode, go to Preference > Downloads > Components and Install Command Line Tools. This will install gcc, clang, make, etc.

Both gcc and clang compile Objective-C 2.0. Create a main.m file and write some irrelevant Objective-C code to test things out.

#import <Foundation/Foundation.h>

@interface Person : NSObject {
    @private char *name;
}
@property (readwrite, assign) char *name;
- (void)sayHello;
@end

@implementation Person
@synthesize name;

- (void)sayHello {
    printf("Hello, my name is %s!\n", [self name]);
}
@end

int main() {
    Person *brad = [Person new];
    brad.name = "Brad Cox";
    [brad sayHello];

    Person *tom = [Person new];
    tom.name = "Tom Love";
    [tom sayHello];
}

I won’t explain what the code does, but it’s quite simple. Here’s the Makefile:

CC=clang # or gcc

FRAMEWORKS:= -framework Foundation
LIBRARIES:= -lobjc

SOURCE=main.m

CFLAGS=-Wall -Werror -g -v $(SOURCE)
LDFLAGS=$(LIBRARIES) $(FRAMEWORKS)
OUT=-o main

all:
    $(CC) $(CFLAGS) $(LDFLAGS) $(OUT)

We have to link against the objc library for all the new Objective-C features, and supply the -frameworks used. Type make. Viola!

Ubuntu/Linux

First off make sure you have an Objective-C compiler. gcc or clang will do the job. You also need libobjc and libobjc-dev, although the latter is not really required to compile some Objective-C.

It is important to note that any Frameworks that you get under Mac are not available under Linux at all. To get these (Foundation, Core, etc.) you have to get gnustep. Setting up gnustep is outside of the scope of this article. Refer to this great writeup on doing so.

I’ll assume we didn’t go through the trouble of setting up GNUStep with all its bells and whistles, so all the NeXTStep objects are not available (NSObject, NSLog, etc.). There are, however, replacements for core utility objects and functions. You can get acquainted with the APIs by reading the header files.

Here’s how the example above would look in Linux:

#import <objc/Object.h>
#import <stdio.h>

@interface Person : Object {
    @private char *name;
}
@property (readwrite, assign) char *name;
- (void)sayHello;
@end

@implementation Person
@synthesize name;

- (void)sayHello {
    printf("Hello, my name is %s!\n", [self name]);
}
@end

int main() {
    Person *brad = [Person new];
    brad.name = "Brad Cox";
    [brad sayHello];

    Person *tom = [Person new];
    tom.name = "Tom Love";
    [tom sayHello];
}

I won’t explain what the code does, but it’s quite simple. Here’s the Makefile:

CC=clang # or gcc (tested with clang 3.2 and gcc 4.7.1)

LIBRARIES:= -lobjc
HEADERS:= -I/path/to/libobjc/headers

SOURCE=main.m

CFLAGS=-Wall -Werror -g -v $(HEADERS) $(SOURCE)
LDFLAGS=$(LIBRARIES)
OUT=-o main

all:
    $(CC) $(CFLAGS) $(LDFLAGS) $(OUT)

Some of the newer Objective-C 2.0 features are available only in recent versions of gcc, whereas the default software repositories on Ubuntu, for example, offer the 4.4 version which is old for features like @synthesizers. The libobjc headers can be acquired from the official repository along with libobjc.

It’s does get quite messy on Linux but overall quite simple to get started, so go learn yourself some good Objective-C now ;)