26 January 2008

Compile Objective-C Programs Using gcc

Probably 99% of all Objective-C programmers out there are compiling their programs with XCode very happily. However that doesn't stop the other 1%, who are brave enough or simply don't have choice, from compiling Objective-C programs using gcc under command line.

Being one of that 1%, I had hard time trying compiling my program. I finally had my first program compiled after days of struggling due to lack of information and experience. I'd like to share the lesson I learned so that maybe someone sees this and save a little effort. The process of compiling a very simple objective-c program on several platforms are explained below.

Here is the objective-c program file I used - hello.m (download).

/******************* hello.m ***********************/
#import <Foundation/Foundation.h>

@interface HelloWorld : NSObject
- (void) hello;
@end

@implementation HelloWorld
- (void) hello {
NSLog(@"hello world!");
}
@end

int main(void) {
HelloWorld *hw = [[HelloWorld alloc] init];
[hw hello];
[hw release];
}
/******************* end ***********************/

1. To Compile Objective-C Programs on Mac OS X

Compiling on Mac OS X is the simplest, just cd to the directory where hello.m resides and type in the following command.
$ gcc -o hello hello.m \
-L /System/Library/Frameworks/Foundation.framework/Foundation

The compile goes happily and produces an executable file "hello".
$ ./hello
2008-01-26 23:10:32.983 hello[381:10b] hello world!


2. To Compile Objective-C Programs on Linux
Well, to compile Objective-C programs, GNUstep needs to be installed. Please visit www.gnustep.org to find out how to install GNUstep on your Linux version; or use "apt-get" or "synaptic" if you are running Debian-based distributions (Ubuntu for example).
Once GNUstep is installed, assuming its installation directory is /usr/lib/GNUstep, the following command compiles hello.m.
$ gcc -o hello hello.m -I /usr/lib/GNUstep/System/Library/Headers \
-L /usr/lib/GNUstep/System/Library/Libraries/ -lgnustep-base \
-fconstant-string-class=NSConstantString

$ ./hello
2008-01-27 00:02:17.321 hello[7067] hello world!

The compiler may complain about NXConstantString not declared if the last switch "-fconstant-string-class=NSConstantString" is not included.
This process was tested on Ubuntu 7.10 and should work for other linux distributions as well.

UPDATE:
I just tested on Ubuntu 8.10 and find the latest GNUstep package have slightly different installation directory. Please use the following command instead.

$ gcc -o hello hello.m -I /usr/include/GNUstep/ -L /usr/lib/GNUstep/ \
-lgnustep-base -fconstant-string-class=NSConstantString

$ ./hello


For other distributions please do check the correct Header and Library installation directory and place them after the -I and -L flag respectively.


3. To Compile Objective-C Programs on Windows
This is the most tricky one. In order to compile, GNUstep for Windows needs to be installed first. Point your browser to http://www.gnustep.org/experience/Windows.html and download the two necessary packages: GNUstep System and GNUstep Core. Install them in the order as they were mentioned.

Once everything is setup, use the following command to compile your hello.m program. The compiler emits some linking information and that means compilation is successful.
$ gcc -o hello hello.m -I /GNUstep/System/Library/Headers \
-L /GNUstep/System/Library/Libraries -lobjc -lgnustep-base
Info: resolving ___objc_class_name_NXConstantString by linking to __imp____objc_class_name_NXConstantString (auto-import)
Info: resolving ___objc_class_name_NSObject by linking to __imp____objc_class_name_NSObject (auto-import)

$ ./hello
2008-01-27 00:27:14.630 hello[3724] hello world!


Be very careful about the -lobjc and -lgnustep-base switch, they must appear after file name "hello.m", otherwise linking will fail.
I tried to compile with the following command, and very weird linking errors came up:
$ gcc -o hello -I /GNUstep/System/Library/Headers \
-L /GNUstep/System/Library/Libraries -lobjc -lgnustep-base hello.m
C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ccAFbaaa.o:hello.m:(.text+0xe): undefined reference to `NSLog'
C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ccAFbaaa.o:hello.m:(.text+0x47): undefined reference to `objc_get_class'
C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ccAFbaaa.o:hello.m:(.text+0x59): undefined reference to `objc_msg_lookup'
C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ccAFbaaa.o:hello.m:(.text+0x78): undefined reference to `objc_msg_lookup'
C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ccAFbaaa.o:hello.m:(.text+0x9b): undefined reference to `objc_msg_lookup'
C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ccAFbaaa.o:hello.m:(.text+0xbb): undefined reference to `objc_msg_lookup'
C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ccAFbaaa.o:hello.m:(.text+0xdf): undefined reference to `__objc_exec_class'
C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ccAFbaaa.o:hello.m:(.data+0xfc): undefined reference to `__objc_class_name_NXConstantString'
C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/ccAFbaaa.o:hello.m:(.data+0x104): undefined reference to `__objc_class_name_NSObject'
collect2: ld returned 1 exit status
make: *** [build] Error 1

It took me a few days to realized that the switches need to be following hello.m. I'm still not able to understand the reason behind, though. If anybody knows, please be generous enough to put down a comment.

Now, happy compiling your first Objective-C program on whichever environment you are in.

44 comments:

MisterCaustic said...

I'm using GNUstep on Ubuntu too. I have a tip: use makefiles! To compile your commandline app, just include a simple textfile called GNUmakefile with the following contents:

include $(GNUSTEP_MAKEFILES)/common.make
TOOL_NAME = HelloHello
HelloHello_OBJC_FILES = hello.m
include $(GNUSTEP_MAKEFILES)/tool.make

Then just type `make` at the command line. More info is at this guide: Writing GNUstep Makefiles.

LYx said...

that's a great tip. I will sure use that next time I compile :-D Thanks a lot!
However including everything in a command shows a better picture on how the file is compiled, specially under windows. Just to clear some doubts.

marcio said...

where is the hello.m file saved to?

LYx said...

The content of 'hello.m' can be found at the beginning of the article. A download link is also provided. It should be saved to your working folder, save '~/hello/'. And you need to do 'cd ~/hello' before start working. cheers.

For U Only said...

I want to compile Objective-C program on windows that should run on Mac OS. How can I do that?
thanks

lyxite said...

I'm afraid that is not possible, at least to my knowledge.

Serge said...

Thanks! I'm waiting for mid-June Mac Mini line refresh, so that I can buy a used Intel Mac Mini for a reasonable price. Thanks to you I'm not wasting the time. I'm learning objective C on my Windows box.

lyxite said...

You are most welcome. I'm glad that I helped.

d11wtq said...

Just a quick note, on OS X you can compile with an even shorted command:

gcc -o hello hello.m -framework Foundation

(i.e drop the -L /path/to/Foundation and just use -framework Foundation)

lyxite said...

thx for the tip!
:-)

nekin said...

gr8 job .. really help full thanks a lot :)

ഷണ്ഡന്‍ said...

Hi lyx,

i used your directions to run objective-c on my xp machine.

but the result i got was

Owner@MAX11 ~/hello
$ gcc -o hello hello.m -I /GNUstep/System/Library/Headers -L /GNUstep/System/Library/Libraries -lobjc -lgnustep-base
hello.m: In function `-[HelloWorld hello]':
hello.m:10: error: cannot find interface declaration for `NXConstantString'

what could be the probable cause ?

thanks
sunil

lyxite said...

Since this is a compilation error, you probably want to start trouble shooting by looking at if your header file is properly included. Check whether GNUStep is properly installed to the directory I assume in my blog post.
Make sure the command typed in your command line is exactly the same as the one I provided and see if the same error comes up.

ഷണ്ഡന്‍ said...

hi lyxite,

As you can see (from the commandline-log i pasted in the last post), i tested with the same commands as you mentioned. Also, the include files are there in the specified include path. I am using your hello.m file for testing.

thanks

bala said...

$ gcc -o hello hello.m -I/GNUstep/System/Library/Headers\
> -L/GNUstep/System/Library/Libraries -lobjc -lgnustep-base Info:resolving ___objc_class_name_N
XconstantString by linking to __imp___objc_class_name_NXConstantString (auto-import) Info:resol
ving ___objc_class_name_NSObject by linking to __imp___objc_class_name_NSObject (auto-import)

i used in the above code in my MINGW32 editor but it give the error as

sh: syntax error near unexpected token `(a'

i need help .pls

teo said...

for GNUStep on Windows, you need to include `gnustep-config --objc-flags` in the command line:

gcc `gnustep-config --objc-flags` -o hello2 hello2.m -L /GNUstep/System/Library/Libraries -lobjc -lgnustep-base

Hemen said...

I'm using GNUstep on Windows and i have also followed all the step of installation and run the file
from Command :::
$ gcc -o main main.m -I /GNUstep/System/Library/Headers \
-L /GNUstep/System/Library/Libraries/ -lobjc -lgnustep-base

But it generates the error :::
gcc.exe: -L: No such file or directory

So please help me for this

Dan said...

Hi Hemen,

Remove that backslash between your '-I /GNUstep/System/Library/Headers' and '-L /GNUstep/System/Library/Libraries' and then it should work. I think it was a typo.

lyxite - thanks so much for this post, I've been trying for days to compile, and had no idea about including these four switches.

lyxite said...

the back slash is used to separate command into different lines. if you type the entire command in the same line, they are not needed.

Marius said...

Hi LYx,
I have followed your instructions in order to compile your program on my XP machine.
Still, I am receiving the following error:
hello.m:10: error: cannot find interface declaration for `NXConstantString'
All I can say is that after installing the GNUstep I ended up with two nested GNUstep folders.
I have choosen the defautl instalation and for both packages (system and core) I have accepted the default installation path, which is: c:\GNUstep.
Do you have any ideea of what could be wrong?
Thank you very much in advance,
Marius

lyxite said...

you may try this switch for luck.
-fconstant-string-class=NSConstantString

LVS said...

that works perfectly! many thanks!
however, is there some way i can avoid doing it everytime i compile a program?

lyxite said...

'make' is the way.

Arok said...

Hi lyx,

i used your directions to run objective-c on my ubuntu 8.10.

but the result i got was

gcc -o source source.m -I /usr/lib/GNUstep/System/Library/Headers \-L /usr/lib/GNUstep/System/Library/Libraries/ -lgnustep-base \-fconstant-string-class=NSConstantString
source.m:2:34: error: Foundation/Foundation.h: No such file or directory
source.m:5: error: cannot find interface declaration for ‘NSObject’, superclass of ‘HelloWorld’
source.m: In function ‘-[HelloWorld hello]’:
source.m:10: error: cannot find interface declaration for ‘NSConstantString’
source.m: In function ‘main’:
source.m:15: warning: ‘HelloWorld’ may not respond to ‘+alloc’
source.m:15: warning: (Messages without a matching method signature
source.m:15: warning: will be assumed to return ‘id’ and accept
source.m:15: warning: ‘...’ as arguments.)

what could be the probable cause ?

thanks
tegez

lyxite said...

check out the update in the original post, highlighted in red.

Arok said...

that works perfectly! many thanks! my brother...:D

best regardsss

tegez

MikeL said...

Great post on an obscure topic. I had to go by what teo showed above:

gcc `gnustep-config --objc-flags` -o hello2 hello2.m -L /GNUstep/System/Library/Libraries -lobjc -lgnustep-base

This works for me on Windows XP. Make sure that you have the right directories for the library as was also stated. For me I ultimately used:

gcc `gnustep-config --objc-flags` -o hello hello.m -L C:/GNUstep/GNUstep/System/Library/Libraries -lobjc -lgnustep-base

and it worked.

Cesar said...

works smoothly thanks. used the -fsconstant you recommended. i'm looking forward to getting started :)

Unati said...

Thanks a ton! I had been trying to compile my program on Windows XP for so long and was getting linking errors... Your tips solved the problem immediately!

T.J. said...

This command worked for me:
gcc -o hello hello.m -I /GNUstep/System/Library/Headers -L /GNUstep/System/Library/Libraries -lobjc -lgnustep-base -fconstant-string-class=NSConstantString

Kiran Vemula said...

I am getting below while compiling an example

$ gcc -o MyDelegate MyDelegate.m -I C:/GNUstep/GNUstep/System/Library/Headers -
L C:/GNUstep/GNUstep/System/Library/Libraries -lobjc -lgnustep-base
Info: resolving ___objc_class_name_NSObject by linking to __imp____objc_class_na
me_NSObject (auto-import)
c:\gnustep\mingw\bin\..\lib\gcc\mingw32\3.4.5\..\..\..\..\mingw32\bin\ld.exe: wa
rning: auto-importing has been activated without --enable-auto-import specified
on the command line.
This should work unless it involves constant data structures referencing symbols
from auto-imported DLLs.C:/DOCUME~1/user/LOCALS~1/Temp/ccJzWOHC.o:MyDelegate.m:
(.data+0x414): undefined reference to `___objc_class_name_NSApplication'
collect2: ld returned 1 exit status

hyderali said...

I am trying to build a make file GNUStep for windows every time I run this gives Foundation: no such file or directory found.
Can any one help...!

lyxite said...

make sure you have windows version of gnustep properly installed. see more details here
http://www.gnustep.org/experience/Windows.html

EQ said...

Fantastic blog, thanks a lot, I was really getting desperate, unable to compile a relatively simple program under WinXP. In the end this command worked for me:

gcc `gnustep-config --objc-flags` -o prog prog.m -I /GNUstep/System/Library/Headers -L /GNUstep/System/Library/Libraries -lobjc -lgnustep-base

EQ said...

Better yet for WinXP, because there are no resolve messages and compile warnings:

gcc `gnustep-config --objc-flags` -o prog prog.m -I /GNUstep/System/Library/Headers -L /GNUstep/System/Library/Libraries -lobjc -lgnustep-base -enable-auto-import

Dave said...

Thanks SO much.

Sakhawat said...

Pretty useful post. That saved me a lot... Thanks!

tasnia said...

Hi,
I am using GNUSTEP on windows XP.
I followed the copilation instructions. But I faced some problem.
Here is the code:

#import
#import
@interface SumClass:NSObject{
int firstNumber;
int secondNumber;
int result;
}
-(void)sumNumber:(int)x:(int)y;
-(int)getSum;
-(void)printResult;
@end

#import"SumClass.h"
#import
@implementation SumClass
-(void)sumNumber:(int)x:(int)y
{
firstNumber = x;
secondNumber = y;
result = firstNumber + secondNumber;
}
-(int)getSum
{
return result;
}
-(void)printResult
{
printf("%i",result);
}
@end

#import
#import"SumClass.h"
int main(int argc, const char *argv[])
{
SumClass *sumobj = [[SumClass alloc] init];

//set the values
[sumobj sumNumber:1:2];
[sumobj getsum];
[sumobj printResult];
[sumobj release];
return 0;
}


There are 3 errors:

error1: Foundation.h: No such file or directory
error2: NSObject: No such file or directory
error3: cannot find interface declaration for `NSObject', superclass of `Hello'

Can anyone give me the solution plz???

lyxite said...

Looks like u did have the -I argument properly set.
Try find where the header files (for Foundation) are and then place that folder path after -I

sindhushiva said...

very useful post. thanks

Piyush said...

C:/DOCUME~1/hb52/LOCALS~1 Temp/ccqNwxZc.o:main.m:(.data+0x74):undefined reference to `___objc_class_name_Fraction'

C:/DOCUME~1/hb52/LOCALS~1 Temp/ccRktthc.o:FractionB.m:.data+0xc4): undefined reference to `___objc_class_name_Fraction'collect2: ld returned 1 exit status

Ansgar Kröger said...

Thank you very much for this article. Helped a lot!!!

Samar Mahajan said...

I'm using GNUstep on Windows and i have also followed all the step of installation and run the file
from Command :::
$ gcc -o main main.m -I /GNUstep/System/Library/Headers -L /GNUstep/System/Library/Libraries/ -lobjc -lgnustep-base

But it generates the warning :::
gcc.exe: -L: No such file or directory

and my Libraries contains gnustep-base but not objc

So please help me for this

lyxite said...

new versions of GNUStep might take difference directories as default installation destination. Please try to manually locate those files and put that directory after -L accordingly.