Перекомпиляция с изменениями битового кода 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)