Following "Programming in Objective-C (6th Edition) shows this Hello World
#import <Foundation/Foundation.h>
int main(void)
{
#autoreleasepool
{
NSLog(#"Programming is fun!");
}
return 0;
}
When I try to compile the program using a GNUStep makefile
include $(GNUSTEP_MAKEFILES)/common.make
TOOL_NAME = Hello
Hello_OBJC_FILES = hello.m
include $(GNUSTEP_MAKEFILES)/tool.make
I get errors such as
hello.m: In function 'main':
hello.m:5:2: error: stray '#' in program
hello.m:5:3: error: 'autoreleasepool' undeclared (first use in this function)
hello.m:5:3: note: each undeclared identifier is reported only once for each function it appears in
hello.m:5:19: error: expected ';' before '{' token
hello.m:9:1: warning: control reaches end of non-void function [-Wreturn-type]
make[3]: *** [obj/Hello.obj/hello.m.o] Error 1
make[2]: *** [internal-tool-all_] Error 2
make[1]: *** [Hello.all.tool.variables] Error 2
make: *** [internal-all] Error 2
Am I doing something wrong? I can't see any bugs in the program and I'm not sure why the makefile wouldn't work.
I should add I am running on Windows 10
I found the problem after reading this (http://gnustep.8.n7.nabble.com/getting-error-autoreleasepool-undeclared-first-use-in-this-function-td32251.html)
Turns out using #autoreleasepool {} is syntactic sugar for
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// do your stuff
[pool drain];
This old method is the only one supported by GCC, you will have to switch to clang to use Objective-C 2.0.
Related
I installed GNUStep on Ubuntu 12.10, and some tools for Objective-C development. I then tried to compile the following code.
#import <Foundation/Foundation.h>
int main(int *argc, const char *argv[]) {
NSAutorelease *pool = [[NSAutorelease alloc] init];
NSLog(#"hello world");
[pool drain];
return 0;
}
When I compile it with gcc -o hello hello.m -Wall -lobjc, I get the following error.
Foundation/Foundation.h: No such file or directory; compilation terminated.
I find the Foundation library and other libraries in /usr/include/GNUstep/Foundation. Why am I getting that error message?
I have been messing around with GNUStep, and I have a simple main.m, which compiles fine. I wanted to see if objective-c libraries (meant for ios/mac) work with GNUStep, so i downloaded JSONKit and tried to compile that, but I keep getting this error:
mark#Emperor:~/objc-test2$ make
This is gnustep-make 2.6.2. Type 'make print-gnustep-make-help' for help.
Making all for tool Test...
Compiling file JSONKit.m ...
In file included from JSONKit.m:110:0:
JSONKit.h:63:21: warning: "/*" within comment [-Wcomment]
In file included from /usr/include/GNUstep/Foundation/NSAttributedString.h:143:0,
from /usr/include/GNUstep/Foundation/Foundation.h:42,
from JSONKit.h:72,
from JSONKit.m:110:
/usr/include/GNUstep/GNUstepBase/NSAttributedString+GNUstepBase.h:44:1: error: cannot find interface declaration for ‘NSAttributedString’
make[3]: *** [obj/Test.obj/JSONKit.m.o] Error 1
make[2]: *** [internal-tool-all_] Error 2
make[1]: *** [Test.all.tool.variables] Error 2
make: *** [internal-all] Error 2
mark#Emperor:~/objc-test2$
my main.m is this:
mark#Emperor:~/objc-test2$ cat main.m
#import <stdio.h>
#include <Foundation/Foundation.h>
#import "Fraction.h"
#import "JSONKit.h"
int main( int argc, const char *argv[] ) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// create a new instance
Fraction *frac = [[Fraction alloc] init];
// set the values
[frac setNumerator: 1];
[frac setDenominator: 3];
// print it
NSLog(# "The fraction is: %#", [frac print]);
// free memory
[frac release];
NSMutableArray *testArr = [[NSMutableArray alloc] initWithCapacity:0];
[testArr addObject:[NSNumber numberWithInt:2]];
[testArr addObject:#"Hey"];
NSLog([testArr JSONString]);
[pool drain];
return 0;
}
mark#Emperor:~/objc-test2$
I've googled around and I have made sure that i have the GNUStep env variables set, and i'm using a make file (taken from examples online)
mark#Emperor:~/objc-test2$ cat GNUmakefile
include $(GNUSTEP_MAKEFILES)/common.make
TOOL_NAME = Test
Test_OBJC_FILES = main.m Fraction.m JSONKit.m
Test_CPPFLAGS = $(RUNTIME_DEFINE)
# Include in the rules for making Objective-C programs
include $(GNUSTEP_MAKEFILES)/tool.make
mark#Emperor:~/objc-test2$
I really don't get this as /Foundation/NSAttributedString.h clearly contains the interface declaration for NSAttributedString, and NSAttributedString+GNUStepBase.h imports , so any idea on what is going wrong?
i trying to use libxml2 in GNUsetup in windows using objective-C
compiling with clang.
it keeps giving me the error:
$ make CC=clang
This is gnustep-make 2.6.2. Type 'make print-gnustep-make-help' for help.
Making all for tool sample_app...
Compiling file HtmlParser.m ...
In file included from HtmlParser.m:1:
./HtmlParser.h:2:9: fatal error: 'libxml/tree.h' file not found
#import <libxml/tree.h>
^
1 error generated.
make[3]: *** [obj/sample_app.obj/HtmlParser.m.o] Error 1
make[2]: *** [internal-tool-all_] Error 2
make[1]: *** [sample_app.all.tool.variables] Error 2
make: *** [internal-all] Error 2
the files do existe in :c:\GNUstep\include\libxml2\libxml\
this is my GNUsetup file which compiles the files
include $(GNUSTEP_MAKEFILES)/common.make
TOOL_NAME = sample_app
sample_app_HEADERS = HttpManager.h UT.h HtmlParser.h
sample_app_OBJC_FILES = main.m HttpManager.m UT.m HtmlParser.m
sample_app_RESOURCE_FILES =
include $(GNUSTEP_MAKEFILES)/tool.make
and this is my file that include the libxml2 headers
#import <Foundation/Foundation.h>
#import <libxml/tree.h>
#import <libxml/parser.h>
#import <libxml/HTMLparser.h>
#import <libxml/xpath.h>
#import <libxml/xpathInternals.h>
#interface HtmlParser
{
NSString* encoding;
}
-(id)init
{
self = [super init];
if(self) {
encoding = #"UTF-8";
}
return self;
}
-(void)ExtractInnerSiteLinks:(NSString*) PageHtml:(NSString*) url;
#end
You can try to add more flags into GNUmakefile eg.
ADDITIONAL_INCLUDE_DIRS += c:\GNUstep\include\libxml2\ .. well I don't really know how to specify a path in a makefile on Windows..
may be you will have linking problem, play with
ADDITIONAL_LIB_DIRS += -L*your dll path..*
ADDITIONAL_OBJC_LIBS += -lxml2
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.
I'm trying to compile a trivial command-line tool with XCode:
#import <Cocoa/Cocoa.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
//NSSpeechSynthesizer *speeker = [[NSSpeechSynthesizer alloc] initWithVoice: nil];
NSLog(#"%#", [NSSpeechSynthesizer availableVoices]);
NSLog(#"Hello, World!");
[pool drain];
return 0;
}
and even thought I'm importing Cocoa.h, I'm getting a link error:
Undefined symbols:
"_OBJC_CLASS_$_NSSpeechSynthesizer",
referenced from:
objc-class-ref-to-NSSpeechSynthesizer
in byc.o ld: symbol(s) not found
collect2: ld returned 1 exit status
Anybody knows what's going on???
You imported the header, so compilation worked, but linking failed because you didn't link against a framework that provides NSSpeechSynthesizer. You need to link against either the Application Kit framework (in addition to Foundation) or the Cocoa umbrella framework (instead of Foundation).
Whichever framework you choose, add it to your Linked Frameworks group in your project's group tree (by right-clicking on the group and choosing “Add Existing Framework”), and make sure you also add it to your target.