如何在xcode 4.5中支持armv6和armv7s的发行版本

我知道这是不可能的,苹果计划这样强制用户升级他们的设备。 但我只想知道是否有一些解决方法或黑客能够做到这一点? 客户坚持认为我们仍然应该支持armv6,因为应用程序用户的比例仍然很高。

我知道一个名为lipo命令来合并静态库,我读了一些地方,我们也可以用它来合并ipa文件,但我不知道如何完成。 我已经在谷歌和这个网站上search了一些,但很难find具体的答案。

我已经能够成功地使用App Store中的应用程序。 它支持从4.2到6.0的armv6,armv7和armv7s以及iOS版本。 我已经validation,它通过iPhone 5一直运行在较旧的设备(iPhone 3G,iPod touch 2g)上。

这种方法需要同时安装Xcode 4.5和旧版本的Xcode。 我的老版本仍然在4.3.2上,但4.4版本也可以。

我有这个答案截图,但堆栈溢出不会让我发布,因为我是新的。 🙁

在Xcode 4.5中安装

  1. 为您的armv6版本添加一个新的版本configuration。 我复制Releaseconfiguration并将其命名为Release_armv6。

  2. 为您的构buildconfiguration设置架构和有效架构。 对于除Release_armv6之外的所有应用程序,请使用默认值。 对于Release_armv6,手动将其设置为armv6http://i.stack.imgur.com/h8Mpl.png

  3. 如果您使用的是Xcode 4.4及更低版本无法理解的iOS 6特性,则需要为armv6构build#ifdef这些特性。 在“其他C标志和其他C ++标志”下的“生成设置”中,我将-DARMV6_ONLY添加到了我的Release_armv6configuration中。 然后,无论代码使用新的iOS 6 API,我都会根据需要执行#ifndef ARMV6_ONLY / #endif。 http://i.stack.imgur.com/czF6J.png

  4. 添加一个新的scheme,并将其设置为在所有情况下都使用Release_armv6构buildconfiguration。

  5. 在“构build阶段”下,使用以下脚本添加“运行脚本构build阶段”(将Shell设置为/ bin / csh )。 这是魔术发生的地方。 编辑“configuration”部分:确定到Release_armv6版本的完整path,并将其replace为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" 

构build过程

准备好创build发布版本时,请按以下顺序进行:

  1. closuresXcode 4.5并打开Xcode 4.4或更低版本。 select你的armv6scheme,并build立它。

  2. closuresXcode 4.4或更低版本并打开Xcode 4.5。 select你的发行计划,并build立它。

这是非常多的。 检查构build输出以validation您是否拥有您想要的内容 – 包含三种体系结构的可执行文件。 运行脚本的最后一个输出应该告诉你这一点。

如果有人有想法来改善这一点,请随意。 我想你可能会喜欢,并从构build脚本中调用Xcode 4.4的“xcodebuild”命令,从而减轻了Xcode版本之间切换的需要。 但是这对我来说已经足够了。 ;)

注意事项:

  • 为了安全起见,您可能需要在旧版本的Xcode中编辑您的xib文件。 到目前为止,似乎4.5向后兼容,但你永远不知道。

  • 事实上,你可能会考虑在大多数的开发中,除了iOS 6特有的东西,在旧的Xcode。 取决于你最容易的事情。

还有另外一种方法,因为gcc-4.2仍然支持armv6,不需要你closuresXcode 4.5,打开以前的版本(用于编译,而不是用于在4.2设备上运行应用程序):

  • 将armv6添加到有效的拱形和拱形中:

Archs:$(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以下。

那么,如果你build立你的项目,你会看到警告:

警告:没有规则处理架构armv6的sourcecode.c.objctypes的文件“$(PROJECT_DIR)/App/AppDelegate.m”
警告:没有规则处理架构armv6的sourcecode.cctypes的文件“$(PROJECT_DIR)/App/SomeFile.c”
  • 为名称匹配的源文件添加一个Build Rule*.[mc]将使用LLVM GCC 4.2

它适用于静态库,但不适用于应用程序:

 ld:文件是通用的(4片),但不包含(n)armv6片:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk/usr/lib /crt1.3.1.o架构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/平台/ iPhoneOS.platform /开发商/软件开发工具包/ 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:具有3种体系结构的Mach-O通用二进制文件
 DerivedData / TestApp / Build / Products / Debug-iphoneos / TestApp.app / TestApp(用于架构armv6):Mach-O可执行部分
 DerivedData / TestApp / Build / Products / Debug-iphoneos / TestApp.app / TestApp(用于架构armv7):Mach-O可执行部分
 DerivedData / TestApp / Build / Products / Debug-iphoneos / TestApp.app / TestApp(用于体系结构cputype(12)cpusubtype(11)):Mach-O可执行部分

请注意,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:具有3种体系结构的Mach-O通用二进制文件
 DerivedData / TestApp / Build / Products / Debug-iphoneos / TestApp.app.dSYM / Contents / Resources / DWARF / TestApp(用于架构armv6):Mach-O dSYM配套文件arm
 DerivedData / TestApp / Build / Products / Debug-iphoneos / TestApp.app.dSYM / Contents / Resources / DWARF / TestApp(用于架构armv7):Mach-O dSYM配套文件arm
 DerivedData / TestApp / Build / Products / Debug-iphoneos / TestApp.app.dSYM / Contents / Resources / DWARF / TestApp(用于体系结构cputype(12)cpusubtype(11)):Mach-O dSYM伴随文件

我已经成功地在iOS 4.2 2gen iPod touch上安装并启动了应用程序,方法是打开xcode 4.4.1,然后单击Product – > Run without building

  • 当您存档您的产品时,您可能会再次遇到Apple Mach-O链接器错误,这次涉及其他文件,如libarclite_iphoneos.alibclang_rt.ios.a
 ld:文件是通用的(2个片段),但不包含(n)armv6片段:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/arc/libarclite_iphoneos.a用于架构armv6
 ld:文件是通用的(2片),但不包含(n)armv6片:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/4.1/libclang_rt.ios.a为build筑armv6

用于crt1.3.1.o的过程也适用于这些文件,并且将修复允许Xcode成功存档您的项目的错误:您可以使用ld打印的path来查找文件并用lipojoinarmv6切片; 请记住,Xcode的早期版本中的Xcode.app/[...]/usr/lib/clang/4.1并不位于Xcode.app/[...]/usr/lib/clang/4.1而是位于Xcode.app/[...]/usr/lib/clang/4.0

我已经成功地归档了这个文件,部署了一个ad-hoc分发configuration文件,并在iPhone 3G(4.2.1)和iPhone 3GS(6.0)上进行了testing。

  • 最后一个问题:我们无法启动应用程序。 在Organizer ,有一条消息: 这个版本的Xcode不支持“iPhone 3G”types的设备。

DeviceSupport中的ls显示:

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

从Xcode 4.4.1的4.2目录没有差异。

现在的问题是:Xcode如何检测设备是否被支持?

打开/Applications/Xcode.app/Contents/Developer//Platforms/iPhoneOS.platform/Developer//Library/PrivateFrameworks/DTDeviceKitBase.framework/DTDeviceKitBaseHex Fiend (或另一个hex编辑器),并replaceascii 4.3 4.2使错误消息消失,并且安装在设备上的应用程序被列出(但设备列表中的设备项目符号仍为红色)。

然后我们需要编辑/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/PrivateFrameworks//DTDeviceKit.framework/Versions/Current/DTDeviceKit并replace:

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

至 :

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

然后我们在组织者(Xcode 4.5.1)中有一个橙子弹:

 “iPhone”上的iOS版本太老,不适用于此版本的iOS SDK。 请将设备恢复到下面列出的操作系统版本。

操作系统安装在iPhone上
 4.2.1(8C148)

 Xcode支持的iOS版本
 6.0(10A403)
 5.1
 5
 4.3

现在的问题是:在哪里支持Xcode定义了哪些版本?

由于/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/ ,但不支持设备。

所以还没有find如何在Xcode 4.5中添加4.2设备支持。 有任何想法吗 ?

结论:在Xcode 4.5中编译armv6 / 7 / 7s是可能的。 但是不启动Xcode 4.4就无法在4.2 armv6设备上启动应用程序。

大更新:它适用于Xcode 4.5.2!

现在子弹在Xcode 4.5.2中是绿色的:-)设备出现在运行button旁边的下拉列表中。 但是,当试图运行该应用程序,得到的消息:

 Xcode无法使用选定的设备运行。
select一个支持体系结构的目的地,以便在此设备上运行。

只需将armv6添加到有效的体系结构:-)

其他注意:名称匹配的源文件的Build Rule*.[mc]可以使用LLVM GCC 4.2Apple LLVM compiler 4.1Default compiler

感谢这个有用的脚本!

我成功地结合了整个post的所有信息,结果完整的脚本如下。 这个脚本需要Xcode 4.5.x和先前支持armv6的Xcode版本(比如Xcode 4.4.1,安装在/ Applications / Xcode 4.4.1.app中)

该脚本不需要先在xcode 4.4.x中编译,只需启动最新的Xcode,selectReleaseconfiguration和构build。 (Release-armv6configuration应该像Mike在原文中提到的那样定义)。

它将产生与armv6 armv7和armv7s兼容的.app

感谢迈克的原始剧本!

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

感谢您的post。 我们有几个应用程序可以构build,所以我们使用xcodebuild自动化了armv6的构build。 这是我们的脚本(修改为我们使用bash)的一部分,可以将它添加到上面的脚本中。 这可以在“#debugging/健全性检查”

 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 

感谢迈克这个有用的教程和脚本。 正如Piotr在评论中提到的那样,如果您从Xcode运行归档命令,脚本将失败,因为它使用另一个生成目录进行归档。

下面是我对该脚本的修改,以使其能够用于正常版本构build和存档特定构build​​。

它假定armv6版本是根据Mike的原始指令运行的。 它使用bash语法,因为我更容易去除公共基础构build目录。 所以这意味着将原始脚本翻译为bash,这只是通过导出来replacesetenv并更改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" 

我想分享我的经验与肯尼的答案。 我认为这是最好的,也是最好的方法来构build一个通用的应用程序,运行在从iOS3.1到iOS7的armv6 / armv7 / armv7s上。

就像肯尼所说的一样。 您可以忽略关于归档产品的部分,主要是通过应用程序加载器(压缩)将应用程序发送给苹果。

几点build议:

当您为“分发”configuration构build时,xcode将validation产品,并且您将得到两个警告:

  • “架构armv6不支持…”
  • “不支持低于4.3的iOS部署目标…”。

当然,因为你实际上是为armv6构build的,你将部署目标设置为3.1或4.2,例如!

所以…只是忽略这些警告。

发送你的应用程序到iTunes连接后,你会收到来自苹果的警告电子邮件,说你的应用程序不是“位置独立的可执行文件”。 当然,这是因为你的目标低于4.3。 只要忽略这个警告。

在这个date(2013年7月3日),我已经用这个方法成功地将一个应用程序更新到了appstore,并且已经通过了validation。 应用程序部署目标是iOS 3.1.2,它支持armv6-armv7-armv7s。

我还想说的是:

  • 如果您制作一个全新的应用程序,只需将部署目标设置为iOS6或iOS5。 忽略旧的操作系统。
  • 如果你有一个自2010年以来销售的旧应用程序,拥有数十万用户,你可能会有更多的人在armv6上使用它,而不是像苹果平时说的那样。 我认为3年是一个太短的时间来放弃对这些旧设备的支持,主要是如果你的应用程序可以运行在他们身上。

苹果已经停止接受支持iOS5之前的设备并包含iPhone 5发布图像的构build。 这里是我提交的构build在Xcode 4.4.1上的最后一个构build的电子邮件

亲爱的开发者

我们已经发现了一个或多个与您近期交付“”的问题。 要处理您的交付,必须纠正以下问题:

无效的启动图像 – 您的应用程序包含启动图像,其大小修改器仅支持使用iOS 6.0 SDK或更高版本构build的应用程序。

一旦这些问题得到纠正,请转至“版本详细信息”页面,然后单击“准备好上传二进制文件”。 继续完成提交过程,直到应用状态为“等待上传”。 然后您可以交付更正的二进制文件。

问候,

App Store团队