Слабая ссылка на статическую библиотеку через -weak_library
Вопрос:
Можно ли слабо связать статическую библиотеку (Obj-C)?
Краткие сведения
Я хочу, чтобы моя пользовательская статическая структура (MyFramework.framework) слабо связывала мою другую пользовательскую статическую библиотеку (libMyLibrary.a).
Функциональность libMyLibrary.a является необязательной и может быть опущена, если нет никакого libMyLibrary.a, связанного каким-либо сторонним приложением, которое использует MyFramework.framework.
я использую -weak_library
, Мое тестовое приложение жалуется, что статический компоновщик не может найти символ MyLibrary MyClass
в рамках MyFramework ABCTracker.o
условное обозначение:
Undefined symbols for architecture arm64:
"_OBJC_CLASS_$_MyClass", referenced from:
objc-class-ref in MyFramework(ABCTracker.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Как правильно настроить слабое связывание?
Полная информация
Настроить
- Проект Xcode создает статический двоичный файл Mach-O и объединяет его в статическую структуру. Результатом является пакет MyFramework.framework.
- Другой проект создает статический двоичный файл Mach-O, и в результате получается статический файл lib libMyLibrary.a с заголовком MyLib.h
- libMyLibrary.a удален из этапов сборки цели MyFramework.framework > связать двоичные файлы с библиотеками ( как предлагается здесь). Только MyLib.h доступен для использования API библиотеки из классов фреймворка.
- Бит-код NO не используется ни в фреймворке, ни в библиотеке
- MyFramework.framework, libMyLibrary.a и пользовательское приложение написаны на Objective-C
- MyLib.h определяет только один класс Objective C
MyClass
- MyFramework.framework использует
MyClass
из своего собственного классаABCTracker
условная проверка доступности символов во время выполнения, напримерNSClassFromString(@"MyClass") == NULL
Из настроек сборки цели MyFramework, которые я установил
Other Librarian Flags
а такжеOther Linker Flags
к тому же значению-weak_library MyLibrary
:OTHER_LDFLAGS = ( "-weak_library", MyLibrary, ); OTHER_LIBTOOLFLAGS = "-weak_library MyLibrary";
Результат
- MyFramework.framework строит ОК
После сборки я проверил символы в полученном двоичном файле, и вывод был пустым (никакие символы из статической библиотеки не были встроены в двоичный статический каркас):
$ otool -L MyFramework.framework/MyFramework | grep MyClass
Несмотря на это, мое тестовое приложение, которое не связано с MyLibrary, создается с
ld
ошибка:Undefined symbols for architecture arm64: "_OBJC_CLASS_$_MyClass", referenced from: objc-class-ref in MyFramework(ABCTracker.o) ld: symbol(s) not found for architecture arm64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
Что я здесь не так делаю?
Другие наблюдения
В цели MyFramework я установил Other Librarian Flags
а также Other Linker Flags
из того же значения:
-lMyLibrary
, Результат:otool
показывает, что символы библиотеки встроены в структуру (ожидается).-weak-lMyLibrary
, Результат такой же, как и дляlMyLibrary
(это ожидается?)
В моей цели приложения я установил Other Linker Flags
в -force_load MyLibrary
, Результат: ошибка компоновщика немного меняется:
ld: file not found: MyClass
clang: error: linker command failed with exit code 1 (use -v to see invocation)
1 ответ
Мне также не удалось заставить XCode правильно связать статическую библиотеку со слабой связью, хотя у меня есть проблема, противоположная вашей - для меня nm
показал все символы из статической библиотеки, а не с символом типа "U" (неопределенный), как вы видите, когда вы слабо связываете фреймворк.
Но вы можете использовать обходной путь:
- Создайте новый проект Cocoa Touch Framework под названием MyWrapper.framework и добавьте в него libMyLibrary.a
- добавлять
-ObjC
на флаги компоновщика, чтобы убедиться, что все символы загружены (и-all_load
если вам нужны не символы Obj-C) - Добавьте заголовки вашей библиотеки в раздел Public Headers фреймворка в Этапы сборки
- Создайте эту платформу (вам нужно установить совокупную цель для всех архитектур, но это отдельная тема)
- Откройте свой проект MyFramework.framework и добавьте в него MyWrapper.framework, он слабо связан (т. Е. Используйте переключатель, чтобы установить его как " Необязательный", или, если вы предпочитаете, удалите его из фазы " Связать двоичные файлы с библиотеками" и добавьте его через
-weak_framework
на другие флаги компоновщика) - Теперь создайте MyFramework.framework
- В вашем тестовом приложении удалите любую ссылку на libMyLibrary.a
- Вы должны иметь возможность запускать тестовое приложение без сбоев, и ваш код не должен обнаруживать присутствие символов из libMyLibrary.a
- Добавьте MyWrapper.framework в ваше тестовое приложение, и тогда вы увидите противоположный результат - символы из libMyLibrary.a будут найдены и пригодны для использования.