В эти дни я возился со средой выполнения Objective-C, пытаясь выяснить, как некоторые вещи работают. В одном из своих «экспериментов» я сделал следующее: я получил следующий код, который находится в файле с именем 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;
}
и попытался скомпилировать его с помощью clang -fobjc-nonfragile-abi -fnext-runtime -o test test.m
. Как вы можете себе представить, компилятор сгенерирует сообщение об ошибке компоновки, потому что я компилирую файл Objective-C, но я не говорю компоновщику связать его с библиотекой времени выполнения Objective-C (например, с параметром -lobjc
). Но я сделал это специально, чтобы проверить, на какие символы библиотеки времени выполнения objc будут ссылаться и, следовательно, будут отсутствовать. И я получил следующее сообщение об ошибке:
$ 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)
Легко понять, почему некоторые из перечисленных символов не определены. objc_msgSend_fixup
, например, относится к функции библиотеки времени выполнения. _objc_empty_cache
и _objc_empty_vtable
являются структурами библиотеки времени выполнения, объявленными в http://opensource.apple.com/source/objc4/objc4-532/runtime/objc-abi.h. Однако OBJC_METACLASS_$_MySuperClass
и OBJC_CLASS_$_MySuperClass
представляют собой структуры, представляющие класс, объявленный в test.m
, поэтому в библиотеке времени выполнения Objective-C нет ссылок на эти символы. Они должны быть определены в teste.o
, но, похоже, это не так. Итак, почему это происходит?
И еще: нет битой ссылки ни на OBJC_METACLASS_$_MyClass
, ни на OBJC_CLASS_$_MyClass
. Следовательно, есть неработающие ссылки на Object
и MySuperClass
, и у них обоих есть подклассы в test.m
, но нет неработающих ссылок на MyClass
, у которого нет подкласса. Итак, почему компоновщик, кажется, ожидает, что в библиотеке времени выполнения будут ссылки на классы, у которых есть подклассы, но не на те, у которых их нет?