is there a simple way to create a command-line tool in Objective C?
I'd rather not use XCode, because XCode has targets and executables, and just complicated stuff.
I'd like to go classic way, just create a Makefile, compile something get an executable, play with it.
--
If this is not possible, is there any way to run the executable I get from regular XCode CL project? It creates a build and again - complicated stuff.
I just want to use my terminal instead of XCode's Console.
Yes. Just write your files as normal Objective-C files and compile with GCC or Clang, linking in the Foundation framework. It's hardly different from a normal C program.
Simple example:
chuck$ cat > main.m
#import <Foundation/Foundation.h>
int main() {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *words = [NSArray arrayWithObjects:#"Hello,", #"world!", #"Check", #"this", #"out!", nil];
NSLog(#"%#", [words componentsJoinedByString:#" "]);
[pool release];
return 0;
}
chuck$ cc -framework Foundation -o my-app main.m
chuck$ ./my-app
2010-10-26 22:32:04.652 my-app[5049:903] Hello, world! Check this out!
Related
Basically, I followed the instructions here: http://wiki.gnustep.org/index.php/GNUstep_under_Ubuntu_Linux
With the extra step of building the gui and back.
If I build and run a non-gui program, all works well. Only when I add something that uses the gui, like the following:
// Created by Tobias Lensing on 2/22/13.
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import <dispatch/dispatch.h>
int main(int argc, const char * argv[])
{
#autoreleasepool {
int multiplier = 7;
int (^myBlock)(int) = ^(int num) {
return num * multiplier;
};
NSLog(#"%d", myBlock(3));
dispatch_queue_t queue = dispatch_queue_create(NULL, NULL);
dispatch_sync(queue, ^{
printf("Hello, world from a dispatch queue!\n");
});
// dispatch_release(queue); // ARC takes care of this
}
#autoreleasepool {
[NSApplication sharedApplication];
NSRunAlertPanel(#"Test", #"Wow it works!", #"OK", nil, nil);
}
return 0;
}
I compile this with the following:
clang `gnustep-config --objc-flags` `gnustep-config --objc-libs` -fobjc-arc -fobjc-runtime=gnustep -fblocks -lobjc -ldispatch -lgnustep-gui test.m
It compiles and links with no errors.
When I run it, however, it spits out the following ugly-gram:
Hello, world from a dispatch queue!
Objective-C ABI Error: Loading modules from incompatible ABI's while loading .GSBackend.m
a.out: /home/lloyd/projects/ThirdParty/BuildGnuStep/libobjc2/loader.c:53: void __objc_exec_class(struct objc_module_abi_8 *): Assertion `objc_check_abi_verion(module)' failed.
Aborted (core dumped)
I have assured myself that there is no other version of libobjc (this is on a virtual machine so I can go back redo my steps).
Commenting out the following:
// [NSApplication sharedApplication];
// NSRunAlertPanel(#"Test", #"Wow it works!", #"OK", nil, nil);
and everything compiles and runs, aside from the GUI obviously.
How can I have two ABI's when I build everything from scratch? Do I need to configure the GUI differently? I've been puzzling over this for a couple of weeks.
Sorry, too long for a comment:
Well I am not sure of you exact problem but you have 3 ABI'a to consider rather than just the normal 2 (gnustep, fragile, not-fragile)... I am not an absolute expert on the area, but I believe you can run gnustep against the newer apple non-fragile ABI... so it is possible that isn't the ABI you have, but it is the one that gets selected with: gnustep-config --objc-libs, you could try omitting that...
I always used gnustep-make, but I haven't done much gnustep for a long time, and don't know if that is still preferred.
I did find an interesting thread: http://comments.gmane.org/gmane.comp.lib.gnustep.general/38698
Okay, after much messing around I discovered that, surprise, I was building everything wrong.
I would go into the long, deep, painful process, but this website actually has a nice set up, scripts, and everything.
Sadly I didn't find this website before asking my question. Now I have Objective C, ARC, blocks and GNUstep!
So, think the classic beginner C programming right of passage: hello world. But written in Objective-C.
For reasons I prefer not to get into, I don't want to use XCode but rather my new love, Sublime Text.
Can it be done?
Paste the following into Sublime and save the file as main.m
#import <Foundation/Foundation.h>
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(#"Hello, World!");
[pool drain];
return 0;
}
Then in the terminal navigate to the file with cd and type:
gcc -framework Foundation main.m -o NAME_OF_YOUR_APP
And run the app by typing:
./NAME_OF_YOUR_APP
I did a bit of digging and found this which lets me build and run entirely within Sublime Text which is what I need. Still testing: https://gist.github.com/chendo/4398077
Update: This was fixed in iOS 6.1 DP3 SDK.
I've tracked down a use-after-deallocated crash when building with ARC using the default release build configuration (debug seems to work fine). The problem occurs when creating an object inside an if-scope with a non-constant condition, assigning it to a variable from outside the scope and then only referencing the variable using Objective-C array or dictionary literals.
Here is the smallest reproducible case I've managed to find:
void test(BOOL arg)
{
id obj = nil;
if (arg) {
obj = [NSObject new];
}
// obj already deallocated here
#[obj];
// but using NSArray works
//[NSArray arrayWithObject:obj];
// #[obj] works if obj is referenced i.e. by NSLog print out
//NSLog(#"%#", obj);
}
int main(int argc, const char * argv[])
{
#autoreleasepool {
test(YES);
}
return 0;
}
When I build and run this with zombie objects enabled I get this error message:
-[NSObject retain]: message sent to deallocated instance 0x100109100
As I commented in the code it works fine if obj is referenced in some other way, like with NSLog or using NSArray instead. Have I misunderstood how objects are released with ARC and scopes or is this a optimization bug in LLVM or Clang?
I'm using Xcode 4.5.2 with clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn). I can reproduce it when building for x86 64 bit for iOS simulator and Mac OS X and I'm quite sure the same problem occurs when building for ARM as the issue was first found when running release build on an iPhone.
I have filed and bug report to Apple and created an open radar report.
What, if anything, am I missing?
Update, did some more experiments:
As Gabro pointed out the compiler translates #[] to a [NSArray arrayWithObjects:count:] statement so I did some tests:
// works
id a[] = {obj};
[NSArray arrayWithObjects:a count:1];
// does not work
const id *b = (id[]){obj};
[NSArray arrayWithObjects:b count:1];
// does not work
[NSArray arrayWithObjects:(id[]){obj} count:1];
So my guess is that this happens when combining ARC and anonymous C arrays.
You're not missing anything. It's a compiler bug.
I just tested the following code both building for OSX (x86 64) and iOS Simulator and I cannot reproduce the bug
void test(BOOL arg) {
id obj = nil;
if (arg) {
obj = [NSObject new];
}
#[obj];
NSLog(#"Hi there");
}
int main(int argc, const char * argv[]) {
#autoreleasepool {
test(YES);
}
return 0;
}
The above code simply prints Hi there in the console and returns.
My configuration is the same of yours: XCode 4.5.2 and Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn) as a compiler.
EDIT
I also tried to compile from command line (after adding #include <Foundation/Foundation.h>
at the beginning of the above example) using
clang -fobjc-arc -framework Foundation main.m
And the result was again
2012-12-03 12:47:45.647 a.out[39421:707] Hi there
EDIT 2
As pointed out in the comments it is possible to reproduce the bug increasing the optimization level over -O0. Summarizing:
clang -O0 -fobjc-arc -framework Foundation main.m
the program works as expected
clang -O1 -fobjc-arc -framework Foundation main.m
the bug presented in the question shows up. This is true with any optimization level over -O0
It's definitely a bug in the compiler.
ok i have this program here:
int main(int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSLog (#"Hello world!");
[pool drain];
return 0;
}
the problem is when i compile it with the command
"gcc -framework Foundation prog1.m -o prog1"
i get this:
"gcc: error trying to exec 'cclobj' : execvp: No such file or Directory"
do i need to install any packages??
"
Its not the only way but GNUStep worked for me. For a good writeup on setting it up look here.
Note: Your exact error is listed about halfway down that page. Your missing package seems to be 'gobjc'.
You need to install "gobjc"
Example
gcc -x objective-c -o
check this link Compiling Objective-C using the gcc
http://webcache.googleusercontent.com/search?q=cache:iIgkFc-JoRYJ:https://www.cs.indiana.edu/classes/c304/ObjCompile.html+http://www.it.uc3m.es/mibanez/lao/lab1/tutorial3/ObjCompile.html&cd=1&hl=en&ct=clnk&client=safari
I learning Objective-C in Linux(Ubuntu), but when i tryed to compile my application that needs the Foundation headers i got an error saying that the file cannot be found, but i have installed the GNUstep development package(gnustep-devel). Here is my code:
// Fraction.h
#import <Foundation/NSObject.h>
#interface Fraction: NSObject {
int numerator;
int denominator;
}
- (void) print;
- (void) setNumerator: (int) n;
- (void) setDenominator: (int) d;
- (void) numerator;
- (void) denominator;
#end
And here is the console log:
ubuntu#eeepc:~$ gcc main.m -o frac -lobjc
In file included from main.m:3:
Fraction.h:2:26: error: objc/NSObject.h: No such file or directory
In file included from main.m:3:
Fraction.h:4: error: cannot find interface declaration for ‘NSObject’, superclass of ‘Fraction’
ubuntu#eeepc:~$
What i need to do?
how are you compiling it? For me, I create a GNUMakefile makefile for my application (see here), and then I run source /usr/share/GNUstep/Makefiles/GNUstep.sh and then make.
GNUstep Installation Process For Windows
Visit The URL: http://ftpmain.gnustep.org/pub/gnustep/binaries/windows/
Download the exe file gnustep-system-0.19.2-setup.exe
Then Download gnustep-core-0.19.2-setup.exe
Remember one thing if you are downloading gnustep-system of any version you must have to download the same version for gnustep-core.
For example if you have downloaded gnustep-setup-0.22.1-setup.exe then you must have to download gustep-core-0.22.1-setup.exe otherwise your code will not run.
Install first the gnustep-system-0.19.2-setup.exe then install gnustep-core-0.19.2setup.exe. Don’t try to install in vice versa order.
Now you got the gnustep for windows then go to start>all program> GNUstep> shell
Now open the notepad editor and write the following code in notepad
#import
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc]
init];
NSLog (#"Anil Kumar Yadav has Run the First Objective C
program!");
[pool drain];
return 0;
}
save it as hello.m in your C:/GNUstep/home/foldername
Remember foldername is the name when you first time start the shell it create the envoirment and make a folder by the name of your computer name in C:/GNUstep/home folder. So don’t be panic.Okay
Go to your shell and type the following command gcc -o hello hello.m -I /GNUstep/System/Library/Headers -L /GNUstep/System/Library/Libraries -lobjc -lgnustep-base -constant-string-class=NSConstantString
This command will create a hello.exe file in your foldername folder.
Again in shell type the command ./hello.exe
Finally you will be able to see the output in the shell.
Conguratulation you wrote your first Objective C program successfully.
Need any clarification write me to : ayadav00009#gmail.com
I've searched at the repository and then i installed the foundation lib, now all is working.
Thanks.