Слабая ссылка на статическую библиотеку через -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" (неопределенный), как вы видите, когда вы слабо связываете фреймворк.

Но вы можете использовать обходной путь:

  1. Создайте новый проект Cocoa Touch Framework под названием MyWrapper.framework и добавьте в него libMyLibrary.a
  2. добавлять -ObjC на флаги компоновщика, чтобы убедиться, что все символы загружены (и -all_load если вам нужны не символы Obj-C)
  3. Добавьте заголовки вашей библиотеки в раздел Public Headers фреймворка в Этапы сборки
  4. Создайте эту платформу (вам нужно установить совокупную цель для всех архитектур, но это отдельная тема)
  5. Откройте свой проект MyFramework.framework и добавьте в него MyWrapper.framework, он слабо связан (т. Е. Используйте переключатель, чтобы установить его как " Необязательный", или, если вы предпочитаете, удалите его из фазы " Связать двоичные файлы с библиотеками" и добавьте его через -weak_framework на другие флаги компоновщика)
  6. Теперь создайте MyFramework.framework
  7. В вашем тестовом приложении удалите любую ссылку на libMyLibrary.a
  8. Вы должны иметь возможность запускать тестовое приложение без сбоев, и ваш код не должен обнаруживать присутствие символов из libMyLibrary.a
  9. Добавьте MyWrapper.framework в ваше тестовое приложение, и тогда вы увидите противоположный результат - символы из libMyLibrary.a будут найдены и пригодны для использования.
Другие вопросы по тегам