提交到 App Store 问题:Unsupported Architecture x86

Submit to App Store issues: Unsupported Architecture x86

所以我正在尝试使用 Shopify API。当我存档应用程序并对其进行验证时,没有任何问题,但是当我将其提交到应用程序商店时,它给了我以下问题。

  1. 错误 ITMS-90087:"Unsupported Architecture. Your executable contains unsupported architecture '[x86_64, i386]'."
  2. 错误 ITMS-90209:"Invalid segment Alignment. The App Binary at SJAPP.app/Frameworks/Buy.framework/Buy does not have proper segment alignment. Try rebuilding the app with the latest Xcode version."(我已经在使用最新版本。)
  3. 错误 ITMS-90125:"The Binary is invalid. The encryption info in the LC_ENCRYPTION_INFO load command is either missing or invalid, or the binary is already encrypted. This binary does not seem to have been built with Apple's Linker."
  4. 警告 ITMS-90080:"The Executable Payload/..../Buy.framework is not a Position Independent Executable. Please ensure that ur build settings are configured to create PIE executables."

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

当然,您不能向 App Store 提交不支持架构的二进制文件,因此解决方案是 "manually" 在提交之前从最终二进制文件中删除不需要的架构。

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

我通过从嵌入式二进制文件部分(Xcode 目标 -> 常规选项卡)删除一个框架(出色的 SVProgressHUD)解决了错误 ITMS-90080。

如果您使用的是 Carthage,那么您可能会遇到此问题,因为项目是:

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

此操作将框架过滤为有效架构列表 (code)

设置复制框架构建阶段

来自Carthage building for iOS steps

On your application targets’ “Build Phases” settings tab, click the “+” icon and choose “New Run Script Phase”. Create a Run Script in which you specify your shell (ex: bin/sh), add the following contents to the script area below the shell:

/usr/local/bin/carthage copy-frameworks

and add the paths to the frameworks you want to use under “Input Files”, e.g.:

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

This script works around an App Store submission bug triggered by universal binaries and ensures that necessary bitcode-related files and dSYMs are copied when archiving.

如果您使用 Carthage,请确保您的 Embed Frameworks Build StepCarthage copy-frameworks

之前

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

  • 你会像往常一样在 "Link Library" 中得到它。

  • 但是你必须明确地将它添加到"Embed Frameworks"中(即使这看起来毫无意义, 因为只有在 "Embed Frameworks"),

  • and 放在copy-frameworks

  • 确保复制框架是 after "Embed Frameworks"

given by pAkY88 works, but I faced the same problem as Mario A Guzman in :一旦我们切断未使用的架构,我们就不能再运行编写脚本,因为它会尝试删除不存在的切片,因为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"),此脚本只是从 fat 二进制文件(如果存在)中删除 i386 和 x86_64 切片.

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

此错误 (ITMS-90240) 也可能由静态 (.a) 库引起。这是一个去除多余架构的脚本。在 Xcode 中将其添加到 Target > BuildPhases > 单击 + 和 select 运行 脚本。然后将其粘贴到脚本框中。

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

我从 Build Settings - Valid Architectures - Release 中删除了架构 i386 & x64_86,一切正常。

现在唯一的问题是您不能 运行 在 SIMULATOR 上进行 RELEASE 构建以进行测试.但是,就像移除拱门一样容易,如果需要,您可以将它们重新添加。

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

1.Select 您在项目导航器中的目标,然后单击项目编辑器顶部的构建阶段。

2.From编辑器菜单,select添加构建阶段,然后添加运行脚本构建阶段(或点击构建阶段编辑器左上角的+按钮).

3.Expand 刚刚添加的新 运行 脚本构建阶段旁边的披露三角形。在脚本编辑器框中,粘贴以下内容: bash

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

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

所以我安装了最新的 Xcode (9.2) 并且有效。

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

确保在 xCode 中将脚本添加到最后,在嵌入 之后。我想我不小心把脚本移到了嵌入式框架之前。

注:我有xCode9.1

我会在这里加上我的 2 美分(以一种不那么可怕的方式:-)。我遇到过很多来自供应商的胖库(由于某种原因)无法通过将它们添加到 Apple 记录的 Frameworks 目录来正常工作。我们能够使它们工作的唯一方法是将 .framekwork 直接拉入项目目录并在构建设置中手动链接 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

这确认您需要在 iTunesConnect 存档上传之前从您的框架中“trim fat”(即 i386x86_64),这不允许这些体系结构(因为 iOS 不支持它们)。

现在,这里的所有答案(或至少一些答案)都提供了这些很棒的 运行 脚本,我确信它们确实工作得很好,但前提是您的框架位于 Frameworks 目录中.现在,除非您是 shell 脚本迷,否则那些未经修改的脚本将不适用于我上面解释的场景。但是,有一种非常简单的方法可以从框架中删除 i386x86_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 不会修改输入文件,它只会生成一个文件,因此您必须 运行 lipo -remove 一次 x86_64i386。上面的命令只是通过首先重命名可执行文件然后最终删除所需的拱门,然后清理剩余的文件来做到这一点。就是这样,您现在应该在 Application Loader Archival upload to iTunesConnect 中看到一个绿色复选标记。

注意事项:以上步骤只能在生产构建时完成,因为 .framework 将从模拟器架构中剥离,构建在模拟器上将停止工作(这是预期的)。在开发环境中,不需要从 .framework 文件中剥离架构,因为您希望能够在模拟器和物理设备上进行测试。如果您的胖库位于项目的 Frameworks 文件夹中,那么请查看已接受的答案。

我通过稍微修改 pAky88 的答案中的 运行 脚本并在嵌入框架后执行来解决这个问题。还要确保取消选中 "Run Script only when installing".

的框
/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- remove the framework from embedded frameworks.

2- add the framework as a linked framework

完成!

感谢以上所有回答。这是一个使用 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

Updated for Xcode 10.1, Below solution worked for me :

只需从嵌入式二进制文件中删除框架,然后将其添加到链接框架和库即可。

参考下面的截图;

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

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

将此脚本添加到项目目标的项目 "Build Phases" 中。请务必选中此框:"Run script only when installing"