Как мне скомпилировать статическую библиотеку (толстую) для armv6, armv7 и i386
Я знаю, что этот вопрос задавался несколько раз, но моя цель немного отличается от того, что я нашел при поиске в Интернете. В частности, я уже в состоянии собрать статическую библиотеку для iPhone, но окончательный толстый файл, который я могу создать, содержит только архитектуры arm и i386 (и я не уверен, что относится к arm: v6 или v7?). Я не могу скомпилировать специально для armv6 и armv7, и они объединяют обе архитектуры, используя lipo. Инструмент lipo жалуется, что в библиотеках armv6 и armv7 присутствует одна и та же архитектура (arm, а не armv6 или armv7).
Может кто-нибудь объяснить, как именно собрать для armv6 и armv7, и объединить эти библиотеки в толстый файл, используя lipo?
РЕДАКТИРОВАТЬ: мне нужно собрать не используя XCode, а компилировать непосредственно традиционную библиотеку Unix.
4 ответа
Просто используйте libtool, чтобы связать две версии arm6 и arm7 вместе - это то, что делает XCode. Однако у вас будут проблемы, если вы попытаетесь объединить эти статические библиотеки в новую супер-библиотеку. Если вам нужно сделать это, то прочитайте это.
Если вы уже делаете это, именно поэтому lipo жалуется, что ваша библиотека armv6 содержит и armv6, и armv7. В моем посте есть исправление, которое, вероятно, будет проще для вас, поскольку вы не используете XCode, но в основном вы используете lipo -extract, чтобы убедиться, что у вас есть тонкая библиотека armv6 и тонкая библиотека armv7, прежде чем идти дальше.
Вот хорошее решение, которое я нашел: Static Libs с поддержкой iOS 5 и Arm64
Отредактировано:
Решение состоит в том, чтобы создать разные архитектуры, а затем связать их, используя lipo, используя командную строку (или Rakefile).
Сначала соберите бинарный файл с помощью команды xcodebuild:
xcodebuild -project 'StaticLibDemo.xcodeproj' -configuration 'Release' -sdk 'iphoneos7.0' clean build ARCHS='armv7 armv7s' IPHONEOS_DEPLOYMENT_TARGET='5.0' TARGET_BUILD_DIR='./build-arm' BUILT_PRODUCTS_DIR='./build-arm'
Обратите внимание, что вы должны установить IPHONEOS_DEPLOYMENT_TARGET='5.0' и ARCHS='armv7 armv7s', рекомендуется установить каталоги сборки и продукта, чтобы сделать вещи более понятными, взгляните на Справочник настроек сборки для более подробной информации о том, что означает этот флаг.
Следующая сборка для arm64:
xcodebuild -project 'StaticLibDemo.xcodeproj' -configuration 'Release' -sdk 'iphoneos7.0' clean build ARCHS='arm64' IPHONEOS_DEPLOYMENT_TARGET='7.0' TARGET_BUILD_DIR='./build-arm64' BUILT_PRODUCTS_DIR='./build-arm64'
Обратите внимание на разницу в ARCHS и IPHONEOS_DEPLOYMENT_TARGET. Нам также нужно собрать симулятор, в этом случае нам нужно изменить sdk на iphonesimulator7.0 и собрать сначала два шага для i386:
xcodebuild -project 'StaticLibDemo.xcodeproj' -configuration 'Release' -sdk 'iphonesimulator7.0' clean build ARCHS='i386' IPHONEOS_DEPLOYMENT_TARGET='5.0' TARGET_BUILD_DIR='./build-i386' BUILT_PRODUCTS_DIR='./build-i386'
Теперь сложная часть! Если вы просто измените ARCHS на x86_86 в зависимости от настроек XCode, вы получите сообщение об ошибке типа "x86_64 не является допустимой аркой". Чтобы избежать этого, просто добавьте VALID_ARCHS='x86_64':
xcodebuild -project 'StaticLibDemo.xcodeproj' -configuration 'Release' -sdk 'iphonesimulator7.0' clean build ARCHS='x86_64' VALID_ARCHS='x86_64' IPHONEOS_DEPLOYMENT_TARGET='7.0' TARGET_BUILD_DIR='./build-x86_64' BUILT_PRODUCTS_DIR='./build-x86_64'
Наконец, нам просто нужно создать толстый двоичный файл со всеми 5 архитектурами:
lipo -create './build-arm/libStaticLibDemo.a' './build-arm64/libStaticLibDemo.a' './build-i386/libStaticLibDemo.a' './build-x86_64/libStaticLibDemo.a' -output 'libStaticLibDemo.a'
Автор создал рабочий пример этого, вы можете получить его: https://github.com/diogot/StaticLibDemo
Ссылка на пост: Static Libs с поддержкой iOS 5 и Arm64
Все кредиты идут к Диогу Тридапалли.
Похоже, больше нет необходимости извлекать из библиотеки жира перед тем, как снова присоединиться (как описано в ответе Джейми). Я использую последний 4.0 SDK от apple, который по умолчанию создает библиотеки fat armv6/armv7.
Ранее я указывал архитектуру для входной библиотеки следующим образом:
$DEVROOT/usr/bin/lipo -arch arm $PROJECT_DIR/buildlib/Release-iphoneos/lib.a -arch i386 $PROJECT_DIR/buildlib/Release-iphonesimulator/lib.a -create -output $PROJECT_DIR/buildlib/lib.a
Это терпит неудачу на более поздних SDK, но удаление архитектуры из (теперь толстой) библиотеки lib работает нормально:
$DEVROOT/usr/bin/lipo $PROJECT_DIR/buildlib/Release-iphoneos/lib.a -arch i386 $PROJECT_DIR/buildlib/Release-iphonesimulator/lib.a -create -output $PROJECT_DIR/buildlib/lib.a
Теперь Липо должен уметь обнаруживать архитектуры в толстых библиотеках.
Убедитесь, что ваши настройки сборки установлены на Valid Architectures: armv6 armv7
а также Architectures: Optimized (armv6 armv7)
, Это должно привести к бинарной оптимизации, оптимизированной как для v6, так и для v7. Если вы не уверены, что это сработало, просто установите Architectures: Standard (armv6)
и сравните размеры файлов. Оптимизированный должен давать вдвое больший размер (когда я правильно помню).
Вы также всегда можете использовать lipo -info
на вашем двоичном файле, чтобы увидеть все включенные архитектуры.
Запуск его в сборке дистрибутива моего приложения дает мне:
ullrich ~/Code/.../build/Distribution-iphoneos/My.app (streaming)$ lipo -info My
Architectures in the fat file: My are: armv6 armv7