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


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

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

7 53

7 ответов:

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

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

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

настройки в Xcode 4.5

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

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

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

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

  5. В разделе этапы сборки добавьте этап сборки сценария запуска со следующим сценарием (установите оболочку в / 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"

Построить Процесс

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

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

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

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

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

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

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

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

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

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

Archs: $(ARCHS_STANDARD_32_BIT) armv6

допустимые архитектуры: armv6 armv7 armv7s

  • Vim (или TextEdit) ваш проект.pbxproj файл для замены IPHONEOS_DEPLOYMENT_TARGET to 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, затем Product ->Run without building.

  • когда вы архиве ваш продукт, вы можете снова испытать ошибку компоновщика Apple Mach-O, на этот раз с участием других файлов, таких как 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 с Липо; просто имейте в виду, что libclang_rt.прошивкой.в предыдущем версии 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 detect is device поддерживается или нет ?

Открытие /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

тогда у нас есть оранжевая пуля в органайзере (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

теперь вопрос : где определяются версии iOS, поддерживаемые Xcode ?

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

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

так что не нашли, как добавить 4.2 поддержка устройств в 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

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

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

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

Он будет производить .приложение совместимо с armv6 armv7 и armv7s

спасибо майку за оригинальный сценарий !

#################
# 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"

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

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

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

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

предполагается, что сборка armv6 выполняется до того, как в соответствии с исходными инструкциями от Майка. Он использует синтаксис bash, потому что мне легче удалите общий базовый каталог сборки. Таким образом, это подразумевает перевод исходного сценария в 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"

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

просто делай так, как предлагает Кендзи. Вы можете игнорировать части об архивировании продукта, в основном, если вы отправляете свое приложение в apple через 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 года-это слишком короткий срок отказаться от поддержки старых устройств, преимущественно если ваше приложение может работать на них.

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

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

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

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

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

с уважением,

команда App Store