Подтвердить что ты не робот

Как поддерживать как armv6, так и armv7s для создания сборки в xcode 4.5

Я знаю, что это невозможно, и Apple планировала его таким образом, чтобы заставить пользователей обновлять свои устройства. Но я просто хочу знать, есть ли способ обхода или хаки, способный это сделать? Клиент настаивает на том, что мы все равно должны поддерживать armv6 из-за еще "большого" процента пользователей приложения.

Я знаю команду под названием lipo для объединения статических библиотек, и я где-то читал, что мы также можем использовать ее для слияния файлов ipa, но я не уверен, как это точно сделано. Я уже несколько раз искал в Google и на этом сайте, но трудно найти конкретный ответ.

4b9b3361

Ответ 1

Я смог сделать это с моим приложением в App Store. Он поддерживает версии armv6, armv7 и armv7s и iOS с 4.2 до 6.0. Я проверял, что он работает на более старых устройствах (iPhone 3G, iPod touch 2g) на всем протяжении iPhone 5.

Этот метод требует одновременного использования как Xcode 4.5, так и старой версии Xcode. Я все еще на 4.3.2 для своей старой версии, но 4.4 тоже должен работать.

У меня были скриншоты для этого ответа, но Qaru не позволяет мне публиковать их, потому что я новичок.: (

Настройка в Xcode 4.5

  • Добавьте новую конфигурацию сборки для сборки armv6. Я продублировал конфигурацию Release и назвал ее Release_armv6.

  • Установите Архитектуры и Действительные Архитектуры для своих конфигураций сборки. Для всех, кроме Release_armv6, используйте значение по умолчанию. Для Release_armv6 вручную установите значение armv6. http://i.stack.imgur.com/h8Mpl.png

  • Если вы используете функции iOS 6, которые Xcode 4.4 и ниже не поймут, вам нужно будет #ifdef их для вашей сборки armv6. В настройках сборки под другими флагами C и другими флагами С++ я добавил -DARMV6_ONLY в мою конфигурацию Release_armv6. Затем везде, где код использует новый API iOS 6, я делаю что-то вроде #ifndef ARMV6_ONLY/#endif, если это необходимо. http://i.stack.imgur.com/czF6J.png

  • Добавить новую схему и установить ее для использования конфигурации сборки Release_armv6 во всех случаях.

  • В разделе "Сборка фаз" добавьте этап "Запуск Script" со следующим Script (установите для командной консоли значение /bin/csh). Здесь происходит волшебство. Отредактируйте раздел Конфигурация: Определите свой полный путь к сборке Release_armv6 и замените его на ARMV6_EXECUTABLE_PATH. Также установите MINIMUM_OS.



    #
    # Script to add armv6 architecture to iOS executable built with Xcode 4.5
    #

    #################
    # Configuration #
    #################
    # Change this to the full path where Xcode 4.4 (or below) puts your armv6 output
    setenv ARMV6_EXECUTABLE_PATH "$BUILD_ROOT/Release_armv6-iphoneos/$EXECUTABLE_PATH"

    # Your "real" minimum OS version since Xcode 4.5 wants to make it iOS 4.3
    # Must be 4.2 or below if you are supporting armv6...
    setenv MINIMUM_OS 4.2
    #####################
    # End configuration #
    #####################


    # For debugging
    echo CURRENT_ARCH = $CURRENT_ARCH
    echo CONFIGURATION = $CONFIGURATION

    # Don't need to do this for armv6 (built in older Xcode), simulator (i386), or debug build
    if ("$CURRENT_ARCH" == "armv6") exit 0
    if ("$CURRENT_ARCH" == "i386") exit 0
    if ("$CONFIGURATION" != "Release" && "$CONFIGURATION" != "Beta Test") exit 0

    # Paths
    setenv LIPO_PATH "$CODESIGNING_FOLDER_PATH/${EXECUTABLE_NAME}.lipo"
    setenv FINAL_PATH "$CODESIGNING_FOLDER_PATH/$EXECUTABLE_NAME"
    setenv FULL_INFO_PLIST_PATH "$CONFIGURATION_BUILD_DIR/$INFOPLIST_PATH"

    # Debug / sanity check
    lipo -info "$FINAL_PATH"
    ls -l "$ARMV6_EXECUTABLE_PATH"

    # Make sure something exists at $LIPO_PATH even if the next command fails
    cp -pv "$FINAL_PATH" "$LIPO_PATH"

    # If rebuilding without cleaning first, old armv6 might already be there so remove it
    # If not, lipo won't output anything (thus the cp command just above)
    lipo -remove armv6 -output "$LIPO_PATH" "$FINAL_PATH"

    # Add armv6 to the fat binary, show that it worked for debugging, then remove temp file
    lipo -create -output "$FINAL_PATH" "$ARMV6_EXECUTABLE_PATH" "$LIPO_PATH"
    lipo -info "$FINAL_PATH"
    rm -f "$LIPO_PATH"

    # Change Info.plist to set minimum OS version to 4.2 (instead of 4.3 which Xcode 4.5 wants)
    /usr/libexec/PlistBuddy -c "Set :MinimumOSVersion $MINIMUM_OS" "$FULL_INFO_PLIST_PATH"
    plutil -convert binary1 "$FULL_INFO_PLIST_PATH"

Процесс сборки

Когда вы будете готовы создать сборку релизов, сделайте это в следующем порядке:

  • Закройте Xcode 4.5 и откройте Xcode 4.4 или ниже. Выберите свою схему armv6 и постройте ее.

  • Закройте Xcode 4.4 или ниже и откройте Xcode 4.5. Выберите схему выпуска и постройте ее.

Это в значительной степени. Проверьте вывод сборки, чтобы убедиться, что вы получили то, что хотите, - исполняемый файл с тремя архитектурами в нем. Последний вывод из запуска Script должен сказать вам это.

Если у кого есть идеи, чтобы улучшить это, пожалуйста, не стесняйтесь. Я предполагаю, что вы можете получить фантазию и вызвать команду Xcode 4.4 "xcodebuild" из сборки script, что облегчает необходимость переключения между версиями Xcode. Но это работает достаточно хорошо для меня.;)

Предостережения:

  • Чтобы быть в безопасности, вы можете отредактировать свои xib файлы в старой версии Xcode. До сих пор кажется, что 4.5 обратно совместим, но вы никогда не знаете.

  • На самом деле, вы можете подумать о том, чтобы просто выполнить большую часть своей разработки, за исключением iOS 6, в старшем Xcode. Зависит от самого легкого для вас.

Ответ 2

Есть другой способ, поскольку gcc-4.2 все еще поддерживает armv6, который не требует, чтобы вы закрыли Xcode 4.5, чтобы открыть предыдущую версию (для компиляции, но не для запуска приложения на устройстве 4.2):

  • Добавьте armv6 к действительным аркам и аркам:

Арки: $(ARCHS_STANDARD_32_BIT) armv6

Действительные архитектуры: armv6 armv7 armv7s

  • Vim (или TextEdit) ваш файл project.pbxproj для замены IPHONEOS_DEPLOYMENT_TARGET на 4.0 - 4.1 - 4.2 по мере необходимости, Xcode 4.5 не позволит вам получить ниже 4.3.

Затем, если вы создадите проект, вы увидите предупреждения:

warning: no rule to process file '$(PROJECT_DIR)/App/AppDelegate.m' of type sourcecode.c.objc for architecture armv6
warning: no rule to process file '$(PROJECT_DIR)/App/SomeFile.c' of type sourcecode.c.c for architecture armv6
  • Добавьте Build Rule для исходных файлов с именами, соответствующими: *.[mc], которые будут использовать LLVM GCC 4.2

Он работает для статических библиотек, но не для приложений:

ld: file is universal (4 slices) but does not contain a(n) armv6 slice: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib/crt1.3.1.o for architecture armv6
  • Чтобы сделать это для приложений, нам нужно добавить срез armv6 в этот объектный файл (который поставляется с 5.1 SDK):
lipo /path/to-4.4/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/usr/lib/crt1.3.1.o -extract armv6 -output /tmp/crt1.3.1-armv6.o
lipo /Applications/Xcode.app/Contents//Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib/crt1.3.1.o /tmp/crt1.3.1-armv6.o -create -output /tmp/crt1.3.1-armv677s.o
mv /Applications/Xcode.app/Contents//Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib/crt1.3.1.o /Applications/Xcode.app/Contents//Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib/crt1.3.1.o.bkp
mv /tmp/crt1.3.1-armv677s.o /Applications/Xcode.app/Contents//Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib/crt1.3.1.o

Скомпилируйте свой проект и убедитесь, что ваше приложение содержит все арки:

$ file DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app/TestApp 
DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app/TestApp: Mach-O universal binary with 3 architectures
DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app/TestApp (for architecture armv6): Mach-O executable arm
DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app/TestApp (for architecture armv7): Mach-O executable arm
DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app/TestApp (for architecture cputype (12) cpusubtype (11)):  Mach-O executable arm

Обратите внимание, что файл dSYM также содержит все арки (полезно для символа отчета о сбое):

$ file DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app.dSYM/Contents/Resources/DWARF/TestApp 
DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app.dSYM/Contents/Resources/DWARF/TestApp: Mach-O universal binary with 3 architectures
DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app.dSYM/Contents/Resources/DWARF/TestApp (for architecture armv6):   Mach-O dSYM companion file arm
DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app.dSYM/Contents/Resources/DWARF/TestApp (for architecture armv7):   Mach-O dSYM companion file arm
DerivedData/TestApp/Build/Products/Debug-iphoneos/TestApp.app.dSYM/Contents/Resources/DWARF/TestApp (for architecture cputype (12) cpusubtype (11)):    Mach-O dSYM companion file arm

Я успешно установил и запустил приложение на iOS 4.2 2gen iPod touch, открыв xcode 4.4.1, затем ProductRun without building.

  • Когда вы Архивируете ваш продукт, вы можете снова столкнуться с ошибкой Apple Mach-O Linker, на этот раз с другими файлами, такими как libarclite_iphoneos.a или libclang_rt.ios.a:
ld: file is universal (2 slices) but does not contain a(n) armv6 slice: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphoneos.a for architecture armv6
ld: file is universal (2 slices) but does not contain a(n) armv6 slice: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/4.1/libclang_rt.ios.a for architecture armv6

Процедура, используемая для crt1.3.1.o, также применяется к этим файлам и исправляет ошибку, позволяющую Xcode успешно архивировать ваш проект: вы можете использовать путь, напечатанный ld, чтобы найти файл и присоединиться к куску armv6 с помощью lipo; просто имейте в виду, что libclang_rt.ios.a в предыдущих версиях Xcode не находится в Xcode.app/[...]/usr/lib/clang/4.1, а в Xcode.app/[...]/usr/lib/clang/4.0.

Я успешно архивировал файл, разворачивал его с помощью специального профиля распространения и тестировал на iPhone 3G (4.2.1) и iPhone 3GS (6.0).

  • Последняя проблема: мы не можем запускать приложение. В Organizer есть сообщение: Устройства типа "iPhone 3G" не поддерживаются этой версией Xcode.

Но ls в DeviceSupport показывает:

 ls /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/ 
4.2          4.3          5.0          5.1          6.0 (10A403)

Без различий в каталоге 4.2 из Xcode 4.4.1.

Вопрос в том, как поддерживается Xcode-устройство или нет?

Открытие /Applications/Xcode.app/Contents/Developer//Platforms/iPhoneOS.platform/Developer//Library/PrivateFrameworks/DTDeviceKitBase.framework/DTDeviceKitBase с помощью Hex Fiend (или другого шестнадцатеричного редактора) и замена ascii 4.3 на 4.2 приведет к исчезновению сообщения об ошибке и приложению, установленному на устройстве, (но маркер устройства в списке устройств все еще красный).

Затем нам нужно отредактировать /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks//DTDeviceKit.framework/Versions/Current/DTDeviceKit и заменить:

Expired.deviceArchitecture.iPhone1,1.iPhone1,2.iPod1,1.iPod2,1.iPod2,2.armv6

to:

Expired.deviceArchitecture.iPhone0,1.iPhone0,2.iPod0,1.iPod0,1.iPod0,2.armv5

Затем у нас есть оранжевая пуля в Organizer (Xcode 4.5.1):

The version of iOS on "iPhone" is too old for use with this version of the iOS SDK. Please restore the device to a version of the OS listed below.

OS Installed on iPhone
4.2.1 (8C148)

Xcode Supported iOS Versions
6.0 (10A403)
5.1
5.0
4.3

Вопрос теперь: где Xcode Поддерживаемые версии iOS определены?

Поскольку в /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/ есть каталог 4.2, он уже должен быть поддержан...

Попробовал скопировать iPhoneOS4.2.sdk из Xcode 4.4.1 в /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/, но он не поддерживает устройство.

Так что не удалось найти, как добавить поддержку 4-го устройства в Xcode 4.5. Любые идеи?

Заключение: возможно компиляция для armv6/7/7s в Xcode 4.5. Но не запускать приложение на устройстве 4,2 armv6 без запуска Xcode 4.4.

Большое обновление: оно работает с Xcode 4.5.2!

Теперь пуля зеленая в Xcode 4.5.2:-) Устройство появится в выпадающем списке рядом с кнопкой "Выполнить". Но при попытке запустить приложение получил сообщение:

Xcode cannot run using the selected device.
Choose a destination with a supported architecture in order to run on this device.

Просто добавьте armv6 к допустимым архитектурам: -)

Другое примечание: Build Rule для исходных файлов с именами, соответствующими: *.[mc] может использовать LLVM GCC 4.2 или Apple LLVM compiler 4.1, или Default compiler

Ответ 3

Спасибо за этот полезный script!

Я успешно скомбинировал всю информацию из всего этого сообщения, итоговая полная script приведена ниже. Этот script требует наличия как Xcode 4.5.x, так и предыдущей версии Xcode, поддерживающей armv6 (например, Xcode 4.4.1, установленный в /Applications/Xcode 4.4.1.app)

script НЕ требует компиляции сначала в xcode 4.4.x, вам просто нужно запустить свой последний Xcode, выбрать конфигурацию и сборку Release. (конфигурация Release-armv6 должна была быть определена, как указано в оригинальной записи от Майка).

Он будет создавать .app, совместимый с armv6 armv7 и armv7s

Спасибо Майку за оригинальный script!

#################
# Configuration #
#################
# Change this to the full path where Xcode 4.4 (or below) puts your armv6 output
setenv ARMV6_OUTPUT_PATH     "$BUILD_ROOT/Release-armv6-iphoneos/"
setenv ARMV6_EXECUTABLE_PATH "$ARMV6_OUTPUT_PATH$EXECUTABLE_PATH"

# Your "real" minimum OS version since Xcode 4.5 wants to make it iOS 4.3
# Must be 4.2 or below if you are supporting armv6...
setenv MINIMUM_OS 4.2
#####################
# End configuration #
#####################

# For debugging
echo CURRENT_ARCH = $CURRENT_ARCH
echo CONFIGURATION = $CONFIGURATION

# Don't need to do this for armv6 (built in older Xcode), simulator (i386), or debug build
#if ("$CURRENT_ARCH" == "armv6") exit 0
if ("$CURRENT_ARCH" == "i386") exit 0
if ("$CONFIGURATION" != "Release" && "$CONFIGURATION" != "Beta Test") exit 0

# Paths
setenv LIPO_PATH "$CODESIGNING_FOLDER_PATH/${EXECUTABLE_NAME}.lipo"
setenv FINAL_PATH "$CODESIGNING_FOLDER_PATH/$EXECUTABLE_NAME"
setenv FULL_INFO_PLIST_PATH "$CONFIGURATION_BUILD_DIR/$INFOPLIST_PATH"

#log file for armv6 build
echo "------------------------- BUILDING ARMV6 NOW -------------------------"
setenv LOGFILE "$BUILD_ROOT/buildarmv6.txt"
setenv CONFIGURATION_ARMV6 "${CONFIGURATION}-armv6"
#build armv6 version
echo "Building $FULL_PRODUCT_NAME armv6         CONFIG=$CONFIGURATION-armv6            target=$TARGETNAME"
"/Applications/Xcode 4.4.1.app/Contents/Developer/usr/bin/xcodebuild" -project         "${PROJECT_FILE_PATH}" -target "${TARGETNAME}" -sdk "${PLATFORM_NAME}" -configuration "$CONFIGURATION-armv6" CONFIGURATION_BUILD_DIR="$ARMV6_OUTPUT_PATH" >> "$LOGFILE"
echo "---------------------------- ARMV6 BUILT  -------------------------"
# to check for armv6 build errors
open "$LOGFILE"

# Debug / sanity check
lipo -info "$FINAL_PATH"
ls -l "$ARMV6_EXECUTABLE_PATH"

# Make sure something exists at $LIPO_PATH even if the next command fails
cp -pv "$FINAL_PATH" "$LIPO_PATH"

# If rebuilding without cleaning first, old armv6 might already be there so remove it
# If not, lipo won't output anything (thus the cp command just above)
lipo -remove armv6 -output "$LIPO_PATH" "$FINAL_PATH"

# Add armv6 to the fat binary, show that it worked for debugging, then remove temp file
lipo -create -output "$FINAL_PATH" "$ARMV6_EXECUTABLE_PATH" "$LIPO_PATH"
echo "------------------------- CHECK ARMV6 ARMV7 ARMV7S ARE MENTIONED BELOW -------------------------"
lipo -info "$FINAL_PATH"
echo "------------------------------------------------------------------------------------------------"
rm -f "$LIPO_PATH"

# Change Info.plist to set minimum OS version to 4.2 (instead of 4.3 which Xcode 4.5 wants)
/usr/libexec/PlistBuddy -c "Set :MinimumOSVersion $MINIMUM_OS" "$FULL_INFO_PLIST_PATH"
plutil -convert binary1 "$FULL_INFO_PLIST_PATH"

Ответ 4

Спасибо за сообщение. У нас есть несколько приложений для сборки, поэтому мы автоматизировали сборку armv6 с помощью xcodebuild, как вы предложили. Это часть нашего script (измененная, поскольку мы используем bash), которая делает это, что может быть добавлено в ваш script выше. Это можно добавить до "# Отладка/проверка работоспособности"

setenv LOGFILE "/Users/xyz/Desktop/buildarmv6.txt"

setenv CONFIGURATION_ARMV6 "${CONFIGURATION}_armv6"
echo "Building $FULL_PRODUCT_NAME armv6         CONFIG=$CONFIGURATION_ARMV6         target=$TARGETNAME"

"/Applications/Xcode 4.4.1.app/Contents/Developer/usr/bin/xcodebuild" -project "${PROJECT_FILE_PATH}" -target "${TARGETNAME}" -sdk "${PLATFORM_NAME}" -configuration "$CONFIGURATION_ARMV6" >> "$LOGFILE"

echo "Built armv6"
open "$LOGFILE" # to check for armv6 build errors

Ответ 5

Спасибо Майку за этот полезный учебник и script. Как упоминалось в комментариях Piotr, script терпит неудачу, если вы запустите команду архива из Xcode, так как она использует другой каталог сборки для архивирования.

Ниже приведена моя модификация script, чтобы включить ее как для стандартной сборки релиза, так и для архивной конкретной сборки.

Предполагается, что сборка armv6 запускается раньше в соответствии с оригинальными инструкциями от Майка. Он использует синтаксис bash, потому что мне легче разделить общий каталог базы данных. Таким образом, это подразумевает перевод исходного script в bash, который является лишь заменой setenv на экспорт и изменением синтаксиса if.

# Find the common base directory for both build
XCODE_BUILD=${BUILD_ROOT%%/Build*}
# Change this to the full path where Xcode 4.4 (or below) puts your armv6 output, using the previously derived base
export ARMV6_EXECUTABLE_PATH="$XCODE_BUILD/Build/Products/Release_armv6-iphoneos/$EXECUTABLE_PATH"

Ответ 6

Я хотел бы поделиться своим опытом с ответом кенджи. Я считаю, что это лучший и лучший способ создать универсальное приложение, которое работает на armv6/armv7/armv7s, от iOS3.1 до iOS7.

Просто делай то, что предлагает кендзи. Вы можете игнорировать части, касающиеся архивирования продукта, в основном, если вы отправляете приложение в яблоко через Application Loader (zipped).

Несколько советов:

Когда вы создаете для конфигурации "распределение", xcode будет проверять продукт, и вы получите два предупреждения:

  • "архитектура armv6 не поддерживается..."
  • "Цели развертывания iOS ниже 4.3 не поддерживаются...".

Конечно, потому что вы действительно создаете для armv6 и, например, устанавливаете цель развертывания в 3.1 или 4.2!

Итак... просто игнорируйте эти предупреждения.

После отправки вашего приложения в itunes connect вы получите предупреждающее письмо от Apple, в котором говорится, что ваше приложение не является "независимым от должности". Конечно, опять же, потому что ваша цель ниже 4.3. Просто игнорируйте это предупреждение.

На этой дате (2013 jul 03) я успешно обновил приложение в appstore с помощью этого метода и прошел проверку. Целью развертывания приложения является iOS 3.1.2, и он поддерживает armv6-armv7-armv7s.

Я хотел бы также сказать, что:

  • Если вы создаете совершенно новое приложение, просто установите цель развертывания для iOS6 или iOS5. Игнорировать старую ОС.
  • Если у вас есть старое приложение, проданное с 2010 года, с десятками тысяч пользователей, на самом деле у вас может быть гораздо больше людей, которые используют его на armv6, чем обычно говорит Apple. Я думаю, что 3 года - слишком короткий период, чтобы отказаться от поддержки этих старых устройств, в основном, если ваше приложение будет работать на них.

Ответ 7

Apple прекратила принимать сборки, поддерживающие устройства pre iOS5, и содержит изображение запуска iPhone 5. Вот письмо для последней сборки, которую я представил, которая была построена на Xcode 4.4.1

Уважаемый разработчик,

Мы обнаружили одну или несколько проблем с вашей недавней доставкой для ". Для обработки вашей доставки необходимо устранить следующие проблемы:

Недопустимое изображение запуска - ваше приложение содержит изображение запуска с модификатором размера, который поддерживается только для приложений, созданных с помощью SDK iOS 6.0 или более поздней версии.

После устранения этих проблем перейдите на страницу" Сведения о версии "и нажмите" Готово для загрузки двоичных файлов ". Продолжайте процесс подачи, пока не появится статус приложения" Ожидание загрузки". Затем вы можете доставить исправленный двоичный файл.

Привет,

Команда App Store