Почему флаг компоновщика -ObjC необходим для связывания категорий в статических библиотеках? (LLVM)

Regarding this technical Q&A from Apple: http://developer.apple.com/library/mac/#qa/qa1490/_index.html

Я думаю, что компилятор может пометить вызовы методов, определенных в категориях, во время компиляции (он знает, что они были определены в категории, а не в основном классе, потому что прототип был в@interface Class (Category) раздел), чтобы можно было построить таблицу в объектных файлах «методов внешней категории». Затем компоновщик после выполнения обычной компоновки должен иметь возможность объединять / объединять и обрабатывать «методы внешней категории». таблиц из всех объектов и ищите совпадающие символы в соответствующих категориях классов из всех связанных структур / библиотек / объектов, затем он может получить те, которые не были уже в & a; цель.

Должно быть что-то, чего мне не хватает, но что это? Почему это невозможно?

Ответы на вопрос(1)

ю случайных частей, из которых он будет рисовать отдельные части для выполнения любых запросов символов от остальной части блока ссылок.

То есть если основная программа вызывает_foo а также_foo появляется только в статической библиотеке, затем_foo, вместе с любыми зависимыми символами, будет перетащен в.

Однако, когда вы вызываете метод в категории, нет конкретной ссылки на символ из-за динамичности Objective-C.

-ObjC flag сообщает компоновщику, что из-за этого ему следует захватить все категории из статической библиотеки и поместить их в основной двоичный файл.

Это немного сбивает с толку, и предполагается, что компилятор должен быть умнее в этом (и, конечно, он должен оказывать помощь на уровне инструментов разработки). Важно помнить несколько вещей:

Anything declared in a header file is pretty much lost by the time the linker rolls around. Symbols are created by compilation units, not by header files. Header files pretty much generate a promise that a symbol will be concretely created later or fulfilled by the link, but cannot create a symbol in and of themselves (or else everyone compilation unit -- every .o -- would end up with a copy of the symbol and hilarity would ensue at link time).

Objective-C is fully dynamic. When you say [(id)foo bar];, the only requirement is that bar is defined somewhere prior. Doesn't matter if it is actually implemented at all (until runtime anyway).

Categories don't have to have corresponding @implementations; a category can be used to declare that methods might exist and, in fact, prior to adding @optional to @protocol, it was common to use a category on NSObject (ewwwwww) with no @implementation to say "Hey, this optional method might exist at runtime".

Compilation and linking are completely separate processes. Compilation is all about expanding the code and turning it into libraries of executable bytes. Linking is all about taking those libraries and putting them together into something that can actually be run, including resolving all the dependencies between libraries. The compiler doesn't really know about how something might be linked and the linker doesn't have any information about where things (that didn't yield hard symbols) might have been defined.

Конечный результат?

Линкер не имеет достаточной информации для разрешения зависимостей.

 31 окт. 2013 г., 19:05
@ Роберту-компоновщику нужно увидеть символ, который решается жесткой связью с библиотекой. Если это символ, разрешенный динамически во время выполнения, он не будет учитываться (например, IB). Это не обязательно должен быть вызов метода, но это самый простой механизм для использования. То есть[MyClass class];, например.
 31 окт. 2013 г., 18:59
Отличный ответ - один вопрос. Этого достаточно, чтобы компилятор связывал символ из статической библиотеки. Просто#import или просто определение переменнойMyClass c;или вам нужно вызвать метод в вашем классе[c myMethod]? А что, если на класс только что ссылаются в конструкторе интерфейсов?
 jhabbott19 июн. 2012 г., 01:06
Но компилятор знает, что он видел вызов метода, который был определен в категории, поэтому онcould создать ссылку на конкретный символ, которая будет использоваться во время соединения - вот о чем мой вопрос. Я хочу понять это немного глубже, чем то, что уже описано в Техническом вопросе, который я связал.

Ваш ответ на вопрос