提交到App Store的问题:不支持架构x86

所以我尝试使用Shopify API。当我存档并验证应用程序时,就没有问题了,但当我将其提交到应用程序商店时,它就会给我以下问题。

  1. 错误ITMS-90087:“不支持的体系结构。您的可执行文件包含不受支持的体系结构'[x86_64, i386]' "
  2. 错误ITMS-90209:“段对齐无效。在shapp . App /Frameworks/Buy.framework/Buy的应用程序二进制没有正确的段对齐。尝试使用最新的Xcode版本重新构建应用。”(我已经在使用最新版本了。)
  3. 错误ITMS-90125:二进制文件无效。LC_ENCRYPTION_INFO load命令中的加密信息缺失或无效,或者二进制文件已经加密。这个二进制文件似乎不是用苹果的Linker构建的。”
  4. 警告ITMS-90080:“可执行载荷/..../Buy.framework不是位置独立的可执行文件。请确保您的构建设置已配置为创建PIE可执行文件。”
98324 次浏览

问题是Buy框架包含模拟器(x86_64)和实际设备(ARM)的构建。

当然,你不允许向App Store提交不受支持的架构的二进制文件,所以解决方案是在提交之前“手动”从最终二进制文件中删除不需要的架构。

Daniel Kennett提出了一个很好的解决方案,并提供了这个脚本来添加到构建阶段:

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发布的修改后的脚本,因为这个脚本有一些小问题。

我通过从嵌入式二进制部分(Xcode target -> General选项卡)删除一个框架(优秀的SVProgressHUD)来解决ITMS-90080错误。

enter image description here

如果你正在使用迦太基,那么你可能会遇到这个问题,因为项目是:

  • 缺少carthage copy-frameworks构建阶段。
  • 或者构建阶段不包括所有的框架(不完整的列表)。

此操作将框架过滤为有效架构(代码)的列表。

设置复制框架构建阶段

迦太基建筑的iOS步骤:

在应用程序目标的“构建阶段”设置选项卡上,单击 “+”图标,选择“新建运行脚本阶段”。创建一个运行脚本 你指定你的shell(例如:bin/sh),添加以下内容 到shell下面的脚本区域:

/usr/local/bin/carthage copy-frameworks

并在“输入文件”下添加你想要使用的框架的路径,例如:

< p > $(SRCROOT)/Carthage/Build/iOS/Box.framework $(SRCROOT)/Carthage/Build/iOS/Result.framework $(SRCROOT)/Carthage/Build/iOS/ReactiveCocoa.framework < / p >

这个脚本围绕一个由universal触发的应用商店提交错误 二进制文件,并确保必要的位码相关文件和dsym

如果你正在使用Carthage,确保你的Embed Frameworks Build StepCarthage copy-frameworks之前


在一些不寻常的情况下(例如:Lottie-iOS框架):

  • 你可以像往常一样在“链接库”中找到它。

  • 但是你必须显式地将它添加到“嵌入框架”中(即使这看起来毫无意义,因为当你只在“嵌入框架”中有它时,它会完美地工作),

  • 把它放在复制框架

  • and确保copy-frameworks是after "Embed Frameworks"

pAkY88给出的回答工作,但我在https://stackoverflow.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 - iphonessimulator”)运行,这个脚本只是从胖二进制文件(如果它们存在的话)中删除i386和x86_64切片。

对不起,我不熟悉shell脚本,所以可能有人可以用更优雅的方式编写它。但它确实有效)

此错误(ITMS-90240)也可能由静态(.a)库引起。这里有一个脚本来剥离多余的架构。在Xcode中将此添加到目标> BuildPhases >单击+并选择运行脚本。然后将其粘贴到脚本框中。

该脚本搜索.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

我删除了i386架构;x64_86从构建设置-有效的架构-发布,一切都工作得很好。

enter image description here

现在唯一的问题是你不能为了测试目的在模拟器上运行释放构建。但是,如果你想的话,你可以很容易地把它们加回来。

您的框架包含ARMx86代码,这允许您在设备或模拟器中使用它。如果你打算将你的应用程序提交到应用程序商店,运行以下脚本从二进制文件中剥离非活动代码。

1.在Project Navigator中选择您的目标,并单击项目编辑器顶部的Build Phases。

2.从“编辑器”菜单中选择“添加构建阶段”,然后选择“添加运行脚本构建阶段”(或单击“构建阶段”编辑器左上角的“+”按钮)。

< p > 3。展开刚刚添加的新Run Script构建阶段旁边的披露三角形。在脚本编辑器中,粘贴如下内容: bash < / p >

$ {BUILT_PRODUCTS_DIR} / $ {FRAMEWORKS_FOLDER_PATH} / “YourframeworkName.framework” / strip-frameworks.sh

我也有同样的问题。 即使在添加给定的运行脚本后,它也不能工作。 这是与Xcode相关的问题。 我使用的是Xcode 9.0版本,但最新版本是9.2

所以我安装了最新的Xcode(9.2),它工作。

即使在添加脚本和更新框架几次之后,我也遇到了同样的问题。

确保在xCode中脚本被添加在嵌入之后的末尾。我想我不小心在嵌入框架之前移动了脚本。

enter image description here

注意:我有xCode 9.1

我将在这里补充我的2分(以一种不那么可怕的方式:-)。我遇到过很多来自供应商的胖库(出于某种原因),它们不能正常工作,不能将它们添加到Apple记录的Frameworks目录中。我们能够让它们工作的唯一方法是将.framekwork直接拉到项目目录中,并在Build Settings中手动链接Embedded FrameworksLink Binary with Libraries。这似乎没有任何问题,然而,就像任何脂肪库附带的无关模拟器架构i386 x86_64以及arm架构一样。

检查fat库上的架构的一个快速方法是

$ cd 'Project_dir/Project'
$ lipo -info 'YourLibrary.framework/YourLibExec`

哪个应该吐出这样的输出

Architectures in the fat file: YourLibrary.framework/YourLibExec are: i386 x86_64 armv7 arm64

这证实了你需要“修剪脂肪”。(即i386 &在iTunesConnect archive上传之前从你的框架x86_64),它不允许这些架构(因为它们不支持iOS)。

现在,这里所有的答案(或至少部分答案)都提供了这些出色的运行脚本,我确信它们工作得非常好,但前提是你的框架位于Frameworks目录下。现在,除非您是一个shell脚本爱好者,否则这些没有修改的脚本将不适用于我上面解释的场景。然而,有一个非常简单的方法来摆脱i386 &x86_64架构从框架。

  1. 打开项目目录中的终端。

  2. 直接将目录更改为.framekwork,如

    cd YourProjectDir/YourProject/YourLibrary.framework

  3. 执行如下命令- .执行如下命令

$ 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_64i386运行lipo -remove一次。上面的命令只是通过首先重命名可执行文件,然后最终删除所需的arch,然后清理剩下的文件来实现这一点。就这样,你现在应该看到一个绿色的复选标记在应用加载存档上传到iTunesConnect。

要记住的事情:上面的步骤应该只在产品构建时执行,因为.framework将从模拟器体系结构中剥离出来,在模拟器上的构建将停止工作(这是预期的)。在开发环境中,不需要从.framework文件中剥离架构,因为您希望能够在模拟器和物理设备上进行测试。如果你的脂肪库位于项目中的Frameworks文件夹中,那么请查看接受的答案。

通过稍微修改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

使用下面的步骤从框架中移除(x86_64, i386)(x86_64, i386)用于模拟器。

  1. 打开Terminal

  2. 打开你的项目拖动路径各自的框架到终端

    例如:cd /Users/MAC/Desktop/MyProject/Alamofire.framework

  3. 在下面的命令中设置你的框架名称并运行

lipo -remove i386 Alamofire -o Alamofire && lipo -remove x86_64 Alamofire -o Alamofire

  1. 现在再次打开你的项目,清洁,构建&运行并创建存档…

对我来说最简单的解决方法是

1-从嵌入式框架中移除框架。

2-添加框架作为链接框架

完成了!

感谢以上所有的答案。下面是一个使用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

更新为Xcode 10.1,以下解决方案为我工作:

你只需要从嵌入式二进制文件中删除框架,并将其添加到链接框架和库中。

参考下面的截图;

enter image description here

下面是我专门用来从可执行文件中删除一个框架架构的脚本。

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


将此脚本添加到项目目标的“构建阶段”中。请务必选中复选框:“仅在安装时运行脚本”

Preview of where to insert sample script .