Перекомпиляция с изменениями битового кода LC_ID_DYLIB

Я строю динамический фреймворк из исходного кода для iOS с включенным битовым кодом (используя cmake а также xcodebuild). я использую lipo а также install_name_tool сделать толстый бинарный файл и обновить LC_ID_DYLIB, для двоичного, чтобы быть загруженным правильно. Когда я архивирую приложение, фреймворк правильно подписывается и упаковывается вместе с приложением. Это вывод file:

MyFramework: Mach-O universal binary with 3 architectures: [arm_v7: Mach-O dynamically linked shared library arm_v7] [arm_v7s] [arm64]
MyFramework (for architecture armv7):   Mach-O dynamically linked shared library arm_v7
MyFramework (for architecture armv7s):  Mach-O dynamically linked shared library arm_v7s
MyFramework (for architecture arm64):   Mach-O 64-bit dynamically linked shared library arm64

Смотря на otool -l выход для LC_ID_DYLIB показывает это:

Load command 4
          cmd LC_ID_DYLIB
      cmdsize 64
         name @rpath/MyFramework.framework/MyFramework (offset 24)
   time stamp 1 Thu Jan  1 01:00:01 1970
      current version 1.0.0
compatibility version 1.0.0

Все кажется правильным. Если я загружаю этот архив в App Store, он загружается и обрабатывается правильно. После запуска из App Store происходит сбой сразу после запуска из-за загрузки динамических платформ. Известно, что приложения перекомпилируются из Биткода в App Store, поэтому я смоделировал это, выполнив экспорт как Ad-Hoc и оставив включенной опцию "Перестроить из Биткода", как предложено в Техническом примечании TN2432. Проверка.ipa (который также потерпел крах после запуска) и рассматриваемой платформы, это вывод otool -l:

Load command 3
          cmd LC_ID_DYLIB
      cmdsize 128
         name /Users/legoless/Downloads/ios/build/build-iphoneos/lib/Release/MyFramework_ios.framework/MyFramework_ios (offset 24)
   time stamp 1 Thu Jan  1 01:00:01 1970
      current version 1.0.0
compatibility version 1.0.0

Так очевидно, что LC_ID_DYLIB этой библиотеки неверен, и это абсолютный путь к месту, где изначально была создана платформа, до создания толстого двоичного файла. Это заменяется на этапе Rebuild from Bitcode, но я понятия не имею, почему и даже где этот путь хранится в существующем файле Mach-O. Я использовал оба otool а также objdump инструменты, чтобы попытаться найти ссылку в двоичном файле Mach-O, но не повезло.

На практике другой фреймворк зависит от этого, и это команда загрузки для целевой фреймворк:

Load command 14
          cmd LC_LOAD_DYLIB
      cmdsize 64
         name @rpath/MyFramework.framework/MyFramework (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 1.0.0
compatibility version 1.0.0

Опять после Rebuild with Bitcode, ссылка также изменяется здесь:

Load command 13
          cmd LC_LOAD_DYLIB
      cmdsize 128
         name /Users/legoless/Downloads/ios/build/build-iphoneos/lib/Release/MyFramework_ios.framework/MyFramework_ios (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 1.0.0
compatibility version 1.0.0

Это происходит только для рассматриваемой структуры, но не для других структур, где @rpath осталось как было.

Мой вопрос все еще остается:

Где хранится ссылка на абсолютный путь? И как его удалить, чтобы Rebuild from Bitcode больше не влиял на него?

Спасибо!

2 ответа

Решение

Проведение подробного исследования этой проблемы показало, что в архиве.xar, который содержит битовый код внутри файла Mach-O, хранится довольно много информации, включая флаги компоновщика. Эта информация хранится в оглавлении архива и используется для перекомпиляции / перекомпоновки библиотек при перекомпиляции битового кода.

В моем случае ясобирал фреймворк с помощью cmake, который добавил эту информацию в флаги компоновщика. Настройка INSTALL_NAME_DIR а также BUILD_WITH_INSTALL_RPATH и использование @rpath эффективно решило проблему, и install_name_tool больше не требовалось.

Я испытывал точно такую ​​же проблему. Принятый ответ сблизил меня, но установив INSTALL_NAME_DIR параметр сам по себе не исправил это, поскольку он не позволяет вам установить полное значение, передаваемое компоновщику, как имя_установки (только каталог, как вы могли ожидать).

Вместо этого я установил XCODE_ATTRIBUTE_LD_DYLIB_INSTALL_NAME который перезаписывает полное значение за один раз. Очевидно, это работает только на генераторе XCode в CMake, но это было хорошо для того, что я хотел. Подводя итог, мой файл CMake для этой платформы теперь содержит:

set_target_properties(${LIBRARY_NAME} PROPERTIES XCODE_ATTRIBUTE_LD_DYLIB_INSTALL_NAME "@rpath/${LIBRARY_NAME}.framework/${LIBRARY_NAME}")
set_target_properties(${LIBRARY_NAME} PROPERTIES BUILD_WITH_INSTALL_RPATH 1)
Другие вопросы по тегам