提交到 App Store 问题:不支持的架构 x86
Posted
技术标签:
【中文标题】提交到 App Store 问题:不支持的架构 x86【英文标题】:Submit to App Store issues: Unsupported Architecture x86 【发布时间】:2015-05-30 14:21:42 【问题描述】:所以我正在尝试使用 Shopify API。当我存档应用程序并对其进行验证时,没有任何问题,但是当我将其提交到应用程序商店时,它给了我以下问题。
-
错误 ITMS-90087:“架构不受支持。您的可执行文件包含不受支持的架构 '[x86_64, i386]'。”
错误 ITMS-90209:“无效的段对齐。SJAPP.app/Frameworks/Buy.framework/Buy 中的应用程序二进制文件没有正确的段对齐。尝试使用最新的 Xcode 版本重建应用程序。” (我已经在使用最新版本了。)
错误 ITMS-90125:“二进制文件无效。LC_ENCRYPTION_INFO 加载命令中的加密信息丢失或无效,或者二进制文件已加密。此二进制文件似乎不是使用 Apple 的链接器构建的。”
警告 ITMS-90080:“可执行负载/..../Buy.framework 不是位置无关的可执行文件。请确保您的构建设置已配置为创建 PIE 可执行文件。”
【问题讨论】:
第一条消息听起来好像是模拟器版本。 当我为提交创建存档时,我在设备选项中选择 ios 设备然后创建一个存档,如果这就是你的要求 我同意@PhillipMills。专注于你的第一个错误。 为什么您的 iOS 应用中有 x86_64 二进制文件?要么你对构建设置做了一些奇怪的事情......要么你上传了一个模拟器构建。 @pAkY88。我无法做到。我最近在 Shopify API 论坛上发帖,正在等待回复。如果我遇到一个,肯定会发布一些东西 我在使用 Application Loader 3.5 上传时遇到了这种情况 【参考方案1】:问题在于 Buy 框架包含模拟器 (x86_64) 和实际设备 (ARM) 的构建。
当然,您不能向 App Store 提交不受支持架构的二进制文件,因此解决方案是在提交之前“手动”从最终二进制文件中删除不需要的架构。
Daniel Kennett 想出了a nice solution and provides this script 来添加到构建阶段:
APP_PATH="$TARGET_BUILD_DIR/$WRAPPER_NAME"
# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"
EXTRACTED_ARCHS=()
for ARCH in $ARCHS
do
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
done
echo "Merging extracted architectures: $ARCHS"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "$EXTRACTED_ARCHS[@]"
rm "$EXTRACTED_ARCHS[@]"
echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
done
我用过,效果很好。
编辑:请务必查看 Varrry 发布的修改后的脚本,因为该脚本存在一些小问题。
【讨论】:
@pAkY88 我在我的 Xcode 项目中使用这个脚本来修复上面提到的 App Store 问题,但是现在当我去构建时,我有很多致命错误 -> 致命错误:lipo : 当指定 -extract 选项时,输入文件 (/...Frameworks/Bolts.framework/Bolts) 必须是胖文件。任何想法如何解决这个问题? 我认为这很愚蠢:您必须结合 arm+x86 才能让您的应用在模拟器和设备上运行,并且必须剥离 x86 才能提交到应用商店。为什么只要检测到 x86,Apple 就不会在其末端进行剥离?他们可以帮助很多技术原因来捍卫这一点,但没有商业原因,因为它根本不方便用户。 @Skoua 选择相关目标,然后选择“Build Phases”并将其放在“Embed Frameworks”操作之后 上述脚本很有帮助,但没有提到在 Xcode 中运行脚本的步骤。要运行此脚本,请转到 TARGETS --> 选择 Build Phases,然后在 Xcode 中点击编辑器的上部标题 --> 添加构建阶段 --> 添加运行脚本构建阶段,您将在 TARGET 的构建阶段部分获得一列。在这里你可以复制粘贴上面的脚本并成功上传到Appstore。 无法在 Xcode 11.2 中工作 - 有人找到解决方案吗?【参考方案2】:Answer 由 pAkY88 提供,但我遇到了与https://***.com/a/35240555/5272316 中的 Mario A Guzman 相同的问题:一旦我们切断未使用的架构,我们就无法再运行脚本,因为它试图删除不存在的切片,因为xcode 不会每次都重新嵌入二进制文件。 想法是 - 在构建存档时只需删除 i386 和 x86_64 切片,所以我修改了脚本:
echo "Target architectures: $ARCHS"
APP_PATH="$TARGET_BUILD_DIR/$WRAPPER_NAME"
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"
echo $(lipo -info "$FRAMEWORK_EXECUTABLE_PATH")
FRAMEWORK_TMP_PATH="$FRAMEWORK_EXECUTABLE_PATH-tmp"
# remove simulator's archs if location is not simulator's directory
case "$TARGET_BUILD_DIR" in
*"iphonesimulator")
echo "No need to remove archs"
;;
*)
if $(lipo "$FRAMEWORK_EXECUTABLE_PATH" -verify_arch "i386") ; then
lipo -output "$FRAMEWORK_TMP_PATH" -remove "i386" "$FRAMEWORK_EXECUTABLE_PATH"
echo "i386 architecture removed"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_TMP_PATH" "$FRAMEWORK_EXECUTABLE_PATH"
fi
if $(lipo "$FRAMEWORK_EXECUTABLE_PATH" -verify_arch "x86_64") ; then
lipo -output "$FRAMEWORK_TMP_PATH" -remove "x86_64" "$FRAMEWORK_EXECUTABLE_PATH"
echo "x86_64 architecture removed"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_TMP_PATH" "$FRAMEWORK_EXECUTABLE_PATH"
fi
;;
esac
echo "Completed for executable $FRAMEWORK_EXECUTABLE_PATH"
echo $(lipo -info "$FRAMEWORK_EXECUTABLE_PATH")
done
如果不是为模拟器运行(这意味着目标文件夹不像“Debug-iphonesimulator”),此脚本只会从胖二进制文件(如果它们存在)中删除 i386 和 x86_64 切片。
对不起,我不熟悉 shell 脚本,所以可能有人可以用更优雅的方式编写它。但它有效)
【讨论】:
感谢您的想法。我只是在 while 循环case "$TARGET_BUILD_DIR" in *"iphonesimulator") echo "Skip simulator target"; continue ;; esac
中从接受的答案中添加了对代码的检查,它就像一个魅力。
我在TARGET -> Build Phases -> [CP] Embedded Pods Frameworks
中添加了这个脚本,但它不起作用,我仍然上传到 iTunesConnect 错误。如何运行这个脚本?
PiterPan,将其添加为单独的 RunScript 阶段
我刚刚检查了“仅在安装时运行脚本”选项,它被跳过,除了存档。
按照这里的建议做了一切,设法清除了迦太基错误;但需要在未经验证的情况下将其上传到 App Store 以获取有关失败原因的一些有用信息。设法解决这个问题并继续前进......【参考方案3】:
如果您使用的是Carthage,那么您可能会遇到此问题,因为该项目是:
缺少carthage copy-frameworks
构建阶段。
或者构建阶段不包括所有框架(不完整列表)。
此操作将框架过滤到有效架构列表(code)。
设置复制框架构建阶段
来自Carthage building for iOS steps:
在应用程序目标的“构建阶段”设置选项卡上,单击 “+”图标并选择“New Run Script Phase”。在中创建运行脚本 您指定您的外壳(例如:bin/sh),添加以下内容 到shell下面的脚本区域:
/usr/local/bin/carthage copy-frameworks
并在“输入文件”下添加要使用的框架的路径,例如:
$(SRCROOT)/Carthage/Build/iOS/Box.framework
$(SRCROOT)/Carthage/Build/iOS/Result.framework
$(SRCROOT)/Carthage/Build/iOS/ReactiveCocoa.framework
此脚本可解决由 Universal 触发的 App Store 提交错误 二进制文件并确保必要的位码相关文件和 dSYM 存档时被复制。
【讨论】:
作为补充说明,我最近遇到了这个问题,我从使用第三方框架的旧预编译版本切换到使用 Carthage 安装的同一框架的新版本。即使 Carthage 完全设置好,我仍然会收到此错误。对我来说,解决方法是从项目中完全删除框架并重新添加。如果您使用的是 Carthage 并且此答案无法为您解决问题,请尝试这样做。 确实,一个很棒的帖子。请注意,通常最好的选择是简单地删除所有框架,然后重新开始从 Carthage 添加所有框架。干杯 我正在使用 Carthage 和 Marshal 并添加$(SRCROOT)/Carthage/Build/iOS/Marshal.framework
完成了工作
在现代 iOS 中,99% 的时间都是问题所在——你只是忘记了复制框架。 (现在 100% 的项目使用 Carthage。)【参考方案4】:
我通过从 Embedded Binaries 部分(Xcode 目标 -> 常规选项卡)中删除框架(出色的 SVProgressHUD)解决了错误 ITMS-90080。
【讨论】:
这个答案应该有更多的赞成票。我怀疑这是许多人使用 Carthage 的根本原因。 如果您尝试嵌入动态框架,然后删除它会导致我收到以下错误消息:“原因:找不到图像” 这对我有用。您必须从嵌入式二进制文件中删除框架,然后将其添加到链接框架和库中。此外,您还必须执行其他操作,例如运行您在其他答案中找到的脚本。【参考方案5】:如果您使用的是Carthage
,请确保您的Embed Frameworks
Build Step
在Carthage
copy-frameworks
之前
在一些不寻常的情况下(例如:Lottie-iOS 框架):
您可以像往常一样在“链接库”中找到它。
但是您必须还明确地将其添加到“嵌入框架”中(即使这看起来毫无意义,因为它仅在“嵌入框架”),
并将其放入复制框架中
并且确保复制框架在“嵌入框架”之后
【讨论】:
这是我的问题。谢谢。【参考方案6】:使用以下步骤从框架中删除 [x86_64, i386]。 [x86_64, i386] 用于模拟器。
打开Terminal
打开你的项目拖拽路径到终端
示例:cd /Users/MAC/Desktop/MyProject/Alamofire.framework
在下面的命令中设置你的框架名称并运行
lipo -remove i386 Alamofire -o Alamofire && lipo -remove x86_64 Alamofire -o Alamofire
-
现在再次打开您的项目,清理、构建和运行并创建存档...
【讨论】:
@mahipal Singh .. 使用 lipo 命令删除后。应用程序无法在模拟器中运行。 iphone模拟器缺少x84_64之类的错误。但在真实设备上工作正常。 因为模拟器只支持调试框架【参考方案7】:我将在此处添加我的 2 美分(以一种不那么可怕的方式 :-)。我遇到了很多来自供应商的胖库(由于某种原因)通过将它们添加到 Apple 记录的Frameworks
目录中无法正常工作。我们能够使它们工作的唯一方法是将.framekwork
拉到项目目录中并在构建设置中手动链接Embedded Frameworks
和Link Binary with Libraries
。然而,这似乎没有任何问题,因为它们带有无关的模拟器架构 i386
和 x86_64
以及 arm
架构的任何胖库。
检查胖库架构的快速方法是
$ cd 'Project_dir/Project'
$ lipo -info 'YourLibrary.framework/YourLibExec`
应该输出类似这样的输出
Architectures in the fat file: YourLibrary.framework/YourLibExec are: i386 x86_64 armv7 arm64
这确认您需要在 iTunesConnect 存档上传之前从您的框架中“修剪胖”(即 i386
和 x86_64
),这不允许这些架构(因为它们不支持 iOS)。
现在,这里的所有答案(或至少一些答案)都提供了这些精彩的运行脚本,我确信它们确实运行良好,但前提是您的框架位于 Frameworks
目录中。现在,除非您是 shell 脚本迷,否则那些未经修改的脚本将不适用于我上面解释的场景。但是,有一种非常简单的方法可以从框架中移除 i386
和 x86_64
架构。
在项目目录中打开终端。
直接把目录改成.framekwork
,点赞
cd YourProjectDir/YourProject/YourLibrary.framework
运行如下所示的一系列命令-
$ mv YourLibrary YourLibrary_all_archs
$ lipo -remove x86_64 YourLibrary_all_archs -o YourLibrary_some_archs
$ lipo -remove i386 YourLibrary_some_archs -o YourLibrary
$ rm YourLibrary_all_archs YourLibrary_some_archs
这里有几点需要注意 - lipo -remove
必须为每个架构删除一次。 lipo
不会修改输入文件,它只会生成一个文件,因此您必须为x86_64
和i386
运行一次lipo -remove
。上面的命令只是通过首先重命名可执行文件然后最终删除所需的拱门,然后清理剩余的文件来做到这一点。就是这样,您现在应该在将应用程序加载器存档上传到 iTunesConnect 中看到一个绿色复选标记。
注意事项:上述步骤只能在生产构建时完成,因为 .framework
将从模拟器架构中剥离,模拟器上的构建将停止工作(这是预期的) )。在开发环境中,不需要从.framework
文件中剥离架构,因为您希望能够在模拟器和物理设备上进行测试。如果您的胖库位于项目的Frameworks
文件夹中,请查看接受的答案。
【讨论】:
对那些不想写脚本的人来说的简单解决方案。 只要运行上面的命令,拱形尺寸就减半了。希望有所作为。 尽管我已经部署了脚本以使一切正常工作,但这必须是关于如何解决问题的正确描述。 喜欢这个答案的本质。干净简洁【参考方案8】:感谢以上所有答案。这是一个使用 swift 4.2 和 5 的脚本。将 Your_Framework_Name 字符串替换为您的框架的原始名称。
APP_PATH="$TARGET_BUILD_DIR/$WRAPPER_NAME"
FRAMEWORK_NAME="Your_Framework_Name.framework"
# Check if Framework is present.
FRAMEWORK_LOCATION=$(find "$APP_PATH" -name "$FRAMEWORK_NAME" -type d)
if [ -z $FRAMEWORK_LOCATION ]; then
echo "Couldn't find Your_Framework_Name.framework in $APP_PATH. Make sure 'Embed Frameworks' build phase is listed before the 'Strip Unused Architectures' build phase."
exit 1
fi
# This script strips unused architectures
find "$APP_PATH" -name "$FRAMEWORK_NAME" -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"
EXTRACTED_ARCHS=()
for ARCH in $ARCHS
do
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
done
echo "Merging extracted architectures: $ARCHS"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "$EXTRACTED_ARCHS[@]"
rm "$EXTRACTED_ARCHS[@]"
echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
done
【讨论】:
谢谢!这对我有用,而接受的答案却没有。【参考方案9】:即使在添加脚本并更新框架几次后,我也遇到了同样的问题。
确保在 xCode 中将脚本添加到最后,嵌入之后。我想我不小心把脚本移到了嵌入式框架之前。
注意:我有 xCode 9.1
【讨论】:
这对我有用。近一年前我上次发布时,@pAkY88 的脚本就足够了。 我遇到了同样的问题,这对我有用。确保每次删除和添加框架时检查运行脚本的位置(仅在仅删除一个框架时才需要)。 你拯救了我的一天。只是在嵌入框架之后添加脚本。 感谢它对我有用,只需将此脚本添加到所有脚本的末尾【参考方案10】:为 Xcode 10.1 更新,以下解决方案对我有用:
您只需从嵌入式二进制文件中删除框架,然后将其添加到链接框架和库中即可。
参考下面的截图;
【讨论】:
我的工作解决方案(y) 它从链接的框架和库中删除了相同的内容【参考方案11】:通过稍微修改 pAky88 的答案中的运行脚本并在嵌入框架后执行,我解决了这个问题。还要确保取消选中“仅在安装时运行脚本”复选框。
/usr/local/bin/carthage copy-frameworks
#!/usr/bin/env bash
APP_PATH="$TARGET_BUILD_DIR/$WRAPPER_NAME"
# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
if [ ! -f "$FRAMEWORK_EXECUTABLE_PATH" ]; then
continue
fi
if xcrun lipo -info "$FRAMEWORK_EXECUTABLE_PATH" | grep --silent "Non-fat"; then
echo "Framework non-fat, skipping: $FRAMEWORK_EXECUTABLE_NAME"
continue
fi
echo "Thinning framework $FRAMEWORK_EXECUTABLE_NAME"
EXTRACTED_ARCHS=()
for ARCH in $ARCHS
do
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
xcrun lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
done
echo "Merging extracted architectures: $ARCHS"
xcrun lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "$EXTRACTED_ARCHS[@]"
rm "$EXTRACTED_ARCHS[@]"
echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
done
【讨论】:
【参考方案12】:我从 Build Settings - Valid Architectures - Release 中删除了 i386 和 x64_86 架构,一切正常。
现在唯一的问题是您无法在 SIMULATOR 上运行 RELEASE 构建以进行测试。但是,就像您移除拱门一样容易,您可以根据需要将它们重新添加。
【讨论】:
是的,那个解决方案。【参考方案13】:对我有用的简单解决方案是
1- 从嵌入式框架中删除框架。
2- 将框架添加为链接框架
完成!
【讨论】:
【参考方案14】:此错误 (ITMS-90240) 也可能由静态 (.a) 库引起。这是一个去除多余架构的脚本。在 Xcode 中将其添加到 Target > BuildPhases > 单击 + 并选择 Run Script。然后将其粘贴到脚本框中。
该脚本搜索 .a 文件,检查它是否包含有问题的架构,然后创建一个没有该架构的新 .a 文件。
对于 macOS:
APP_PATH="$TARGET_BUILD_DIR/$WRAPPER_NAME"
STRIPARCHS="armv7 armv7s arm64"
for t in $STRIPARCHS
do
if find "$APP_PATH" -name '*.a' -exec lipo -info \; | grep $t ; then
find "$APP_PATH" -name '*.a' -exec lipo -remove $t -output 2 \; -exec rm \; -exec mv 2 \; ;
fi
done
exit 0
对于 iOS:
APP_PATH="$TARGET_BUILD_DIR/$WRAPPER_NAME"
STRIPARCHS="x86_64 i386"
for t in $STRIPARCHS
do
if find "$APP_PATH" -name '*.a' -exec lipo -info \; | grep $t ; then
find "$APP_PATH" -name '*.a' -exec lipo -remove $t -output 2 \; -exec rm \; -exec mv 2 \; ;
fi
done
exit 0
【讨论】:
【参考方案15】:我有同样的问题。 即使在添加给定的运行脚本后它也不起作用。 这是与 Xcode 相关的问题。 我使用的是 Xcode 9.0 版,但最新版本是 9.2。
所以我安装了最新的 Xcode (9.2) 并且它工作正常。
【讨论】:
【参考方案16】:您的框架包含ARM
和x86
代码,允许您在设备或模拟器中使用它。如果您打算将应用提交到 App Store,请运行以下脚本以从二进制文件中删除非活动代码。
1.在 Project Navigator 中选择您的目标,然后单击项目编辑器顶部的 Build Phases。
2.从编辑器菜单中,选择添加构建阶段,然后选择添加运行脚本构建阶段(或单击构建阶段编辑器左上角的 + 按钮)。
3. 展开刚刚添加的新运行脚本构建阶段旁边的显示三角形。在脚本编辑器框中,粘贴以下内容: 重击
$BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH/"YourframeworkName.framework"/strip-frameworks.sh
【讨论】:
这假设 strip-frameworks.sh 脚本恰好在那里......【参考方案17】:这是我用来专门从可执行文件中删除一个框架的架构的脚本。
# Remove unused Framework architecture from "YourApp" framework.
FRAMEWORK_EXECUTABLE_PATH="$TARGET_BUILD_DIR/$WRAPPER_NAME/Frameworks/YourApp.framework/YourApp"
echo "$FRAMEWORK_EXECUTABLE_PATH"
cp "$FRAMEWORK_EXECUTABLE_PATH" "$FRAMEWORK_EXECUTABLE_PATH_X86_64"
echo "Executing following command to remove x86_64 arch from YourApp framework executable"
echo "lipo -remove x86_64 \"$FRAMEWORK_EXECUTABLE_PATH\" -o \"$FRAMEWORK_EXECUTABLE_PATH_X86_64\""
lipo -remove x86_64 "$FRAMEWORK_EXECUTABLE_PATH_X86_64" -o "$FRAMEWORK_EXECUTABLE_PATH"
rm "$FRAMEWORK_EXECUTABLE_PATH_X86_64"
将此脚本添加到项目目标的“构建阶段”中。请务必选中复选框:“仅在安装时运行脚本”
【讨论】:
以上是关于提交到 App Store 问题:不支持的架构 x86的主要内容,如果未能解决你的问题,请参考以下文章
Mac App Store 提交后二进制文件无效。可能架构不匹配
Ant Media Server 的 iOS 框架不被 App Store 接受?
提交到App Store的所有应用程序都必须支持仅IPv6网络
向 App Store 提交二进制文件 - 无效的代码签名权利