提交到App Store问题:不支持的体系结构x86

问题描述 投票:214回答:16

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

  1. 错误ITMS-90087:“不支持的体系结构。您的可执行文件包含不受支持的体系结构'[x86_64,i386]'。”
  2. ERROR ITMS-90209:“无效的段对齐.SJAPP.app/Frameworks/Buy.framework/Buy上的应用程序二进制文件没有正确的段对齐。尝试使用最新的xcode版本重建应用程序。” (我已经在使用最新版本了。)
  3. 错误ITMS-90125:“二进制文件无效.LC_ENCRYPTION_INFO加载命令中的加密信息丢失或无效,或者二进制文件已加密。此二进制文件似乎不是使用Apple的链接器构建的。”
  4. 警告ITMS-90080:“可执行的有效负载/ $ / Buy.framework不是位置无关的可执行文件。请确保将您的构建设置配置为创建PIE可执行文件。”
ios xcode
16个回答
362
投票

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

当然,您不允许向App Store提交不支持的体系结构的二进制文件,因此解决方案是在提交之前“手动”从最终二进制文件中删除不需要的体系结构。

丹尼尔肯尼特提出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发布的修改过的脚本,因为这个有一些小问题。


4
投票

针对Xcode 10.1进行了更新,以下解决方案适用于我:

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

请参阅下面的截图

enter image description here


3
投票

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

enter image description here

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


2
投票

对我有用的简单解决方案是

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

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

完成了!


1
投票

此错误(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

1
投票

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

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


1
投票

感谢以上所有答案。这是使用swift 4.2的脚本

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

0
投票

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

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

2.从Editor菜单中,选择Add Build Phase,然后选择Add Run Script Build Phase(或单击Build Phases编辑器左上角的+按钮)。

3.展开刚刚添加的新Run Script构建阶段旁边的显示三角形。在脚本编辑器框中,粘贴以下内容:bash

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


0
投票

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

# 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


141
投票

由pAkY88给出的Answer有效,但我在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-iphonesimulator”),这个脚本只是从胖二进制文件(如果存在)中删除i386和x86_64片。

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


86
投票

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

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

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

Setting up the copy-frameworks build phase

来自Carthage building for iOS steps

在应用程序目标的“构建阶段”设置选项卡上,单击“+”图标并选择“新建运行脚本阶段”。创建一个运行脚本,在其中指定shell(例如: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

此脚本解决由通用二进制文件触发的App Store提交错误,并确保在归档时复制必要的bitcode相关文件和dSYM。


38
投票

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

enter image description here


30
投票

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


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

  • 你会照常在“链接库”中使用它。
  • 但是你必须在“嵌入框架”中明确地添加它(即使这看起来毫无意义,因为只有在“嵌入框架”中它才能完美地工作),
  • 并将其放在复制框架中
  • 并确保复制框架在“嵌入框架”之后

10
投票

我会在这里加上我的2美分(以不太可怕的方式:-)。我遇到了很多来自供应商的胖库(由于某些原因)不能正常工作,只需将它们添加到Apple记录的Frameworks目录中。我们能够使它们工作的唯一方法是将.framekwork直接拉入项目目录并在Build Settings中手动链接Embedded FrameworksLink Binary with Libraries。这似乎没有任何问题,但是,与任何脂肪库一样,它们带有无关的模拟器架构i386x86_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 Archival上传之前从你的框架中“削减脂肪”(即i386x86_64),这不允许这些体系结构(因为它们不支持iOS)。

现在,这里的所有答案(或至少一些答案)提供了这些精彩的运行脚本,我确信它们运行得非常好,但前提是您的Framework位于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 -removex86_64运行i386一次。上面的命令只是通过首先重命名可执行文件然后最终删除所需的arch,然后清理左边的文件来完成。就是这样,您现在应该看到Application Loader Archival上传到iTunesConnect的绿色复选标记。

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


9
投票

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

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

enter image description here

注意:我有xCode 9.1


9
投票

使用以下步骤从框架中删除[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. 现在再次打开您的项目,清理,构建和运行以及创建存档...

4
投票

通过从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
© www.soinside.com 2019 - 2024. All rights reserved.