Reputation: 2991
These days, I've been messing around with the Objective-C runtime, trying to find out how some things work. In one of my "experiments", I did the following: I got the following code which is in a file called test.m
:
#import <objc/Object.h>
@interface MySuperClass: Object {
}
-(int) myMessage1;
@end
@interface MyClass: MySuperClass {
int myIvar;
}
-(void) myMessage2;
@end
@implementation MyClass
-(void) myMessage2 {
myIvar++;
}
@end
int main() {
MyClass *myObject;
myObject = [[MyClass alloc] init];
[myObject myMessage2];
return 0;
}
and tried to compile it with clang -fobjc-nonfragile-abi -fnext-runtime -o test test.m
. As you can imagine, the compiler will generate a linking error message because I'm compiling an Objective-C file, but I'm not telling the linker to link it against an Objective-C runtime library (with the -lobjc
option, for example). But I did that on purpose, to check out which objc runtime library symbols would be referenced and, thus, would be missing. And I got the following error message:
$ clang -fobjc-nonfragile-abi -fnext-runtime -o test test.m
/tmp/test-jEfgSA.o:(__DATA, __objc_data+0x0): undefined reference to `OBJC_METACLASS_$_Object'
/tmp/test-jEfgSA.o:(__DATA, __objc_data+0x8): undefined reference to `OBJC_METACLASS_$_MySuperClass'
/tmp/test-jEfgSA.o:(__DATA, __objc_data+0x10): undefined reference to `_objc_empty_cache'
/tmp/test-jEfgSA.o:(__DATA, __objc_data+0x18): undefined reference to `_objc_empty_vtable'
/tmp/test-jEfgSA.o:(__DATA, __objc_data+0x30): undefined reference to `OBJC_CLASS_$_MySuperClass'
/tmp/test-jEfgSA.o:(__DATA, __objc_data+0x38): undefined reference to `_objc_empty_cache'
/tmp/test-jEfgSA.o:(__DATA, __objc_data+0x40): undefined reference to `_objc_empty_vtable'
/tmp/test-jEfgSA.o:(__DATA, __objc_msgrefs, coalesced+0x0): undefined reference to `objc_msgSend_fixup'
/tmp/test-jEfgSA.o:(__DATA, __objc_msgrefs, coalesced+0x10): undefined reference to `objc_msgSend_fixup'
/tmp/test-jEfgSA.o:(__DATA, __objc_msgrefs, coalesced+0x20): undefined reference to `objc_msgSend_fixup'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
It's easy to understand why some of the listed symbols are undefined. objc_msgSend_fixup
, for example, refers to a runtime library function. _objc_empty_cache
and _objc_empty_vtable
are both runtime library structs declared in http://opensource.apple.com/source/objc4/objc4-532/runtime/objc-abi.h. However, OBJC_METACLASS_$_MySuperClass
and OBJC_CLASS_$_MySuperClass
are structs that represent a class that has been declared in test.m
, so that there is no reference in the Objective-C runtime library to these symbols. They should be defined in teste.o
, but it seems they're not. So, why does this happen?
And one more thing: there is no broken reference to neither OBJC_METACLASS_$_MyClass
nor OBJC_CLASS_$_MyClass
. Therefore, there are broken references to Object
and MySuperClass
and both of them have subclasses in test.m
, but there is no broken reference to MyClass
, which has no subclass. So, why the linker seems to expect there to be references, in the runtime library, to the classes that have subclasses, but not to those that haven't any?
Upvotes: 1
Views: 999
Reputation: 2991
I found out that the OBJC_METACLASS_$_<my class name>
symbols are defined in the object file only if there is an @implementation <my class name>
statement. So, if I add, for example, the snippet:
@implementation MySuperClass
-(int) myMessage1 {
return 0;
}
@end
to test.m
, the linker would generate the error message:
$ clang -fobjc-nonfragile-abi -fnext-runtime -o class_teste class_teste.m
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x0): undefined reference to `OBJC_METACLASS_$_Object'
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x8): undefined reference to `OBJC_METACLASS_$_Object'
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x10): undefined reference to `_objc_empty_cache'
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x18): undefined reference to `_objc_empty_vtable'
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x30): undefined reference to `OBJC_CLASS_$_Object'
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x38): undefined reference to `_objc_empty_cache'
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x40): undefined reference to `_objc_empty_vtable'
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x50): undefined reference to `OBJC_METACLASS_$_Object'
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x60): undefined reference to `_objc_empty_cache'
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x68): undefined reference to `_objc_empty_vtable'
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x88): undefined reference to `_objc_empty_cache'
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_data+0x90): undefined reference to `_objc_empty_vtable'
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_msgrefs, coalesced+0x0): undefined reference to `objc_msgSend_fixup'
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_msgrefs, coalesced+0x10): undefined reference to `objc_msgSend_fixup'
/tmp/class_teste-gDWfF6.o:(__DATA, __objc_msgrefs, coalesced+0x20): undefined reference to `objc_msgSend_fixup'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
which is pretty acceptable, since all these undefined symbols are part of the Objective-C runtime library. Since my first version of test.m
was for testing purpose, I hadn't added an implementation to the MySuperClass
class as I thought it wouldn't affect the object file's symbols table. So, the problem has nothing to do with subclassing.
Upvotes: 2
Reputation: 3833
Good to experiment with these sorts of things. It will be helpful later when you get similar errors and need to debug.
A few points that stick out:
Upvotes: 2