检查并移除IPA/Archive中不支持的体系结构[x86_64,i386]

60

问题:

在提交应用到App Store时,出现以下错误:

不支持的架构。 您的可执行文件包含不支持的架构 '[x86_64, i386]'

问题:

  1. 如何解决上述错误?

  2. 如何检查档案或IPA所使用的体系结构?

  3. 如何确保 Release 归档不包括模拟器架构 x86_64i386

    • 是否仅通过脚本才能实现,还是在 Build Settings 或其他设置中有设置?

2
转到构建设置->搜索“architecture”,您可以在那里检查“architectures”选项卡,通常默认情况下必须是armv7、arm64架构,请检查显示给您的哪一个。 - Mehul Thakkar
2
有时候上述错误是由于不正确的构建而显示的,请清理、构建、归档和上传(别忘了清理和构建)。让我们再试一次...也许你会以这种方式获得成功。 - Mehul Thakkar
我认为问题在于使用的一些框架包括了x86_64和i386体系结构。因此需要手动删除它。 - user1046037
https://dev59.com/MV0a5IYBdhLWcg3wPWpN#51324598 - MAhipal Singh
5个回答

138

苹果已开始在分发过程中抱怨应用是否包含模拟器架构。

如何解决上述错误?

解决方案:

将以下代码添加到项目目标的运行脚本中,在构建过程中从您的应用程序中删除模拟器架构(x86_64和i386):

Shell:

/bin/sh

代码:

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

解决方案:

还有一种解决方案,如果您只想执行一次操作。 但是请注意,在执行以下步骤后,您将无法在模拟器上运行应用程序。请在部署应用程序到Testflight/App-store之前执行此操作。

从终端进入您项目的ProjectFramework.framework文件夹。运行以下命令:

lipo -remove i386 ProjectFramework_SDK -o ProjectFramework_SDK 
lipo -remove x86_64 ProjectFramework_SDK -o ProjectFramework_SDK

检查框架的架构?

$ lipo -info PathToProject/ProjectName.framework/ProjectName

输出结果将为: → fat文件中的架构:ProjectName为: i386 x86_64 armv7 arm64

参考文献: http://ikennd.ac/blog/2015/02/stripping-unwanted-architectures-from-dynamic-libraries-in-xcode/


2
谢谢,注意到在https://dev59.com/MV0a5IYBdhLWcg3wPWpN中有相同的解决方案。 - user1046037
1
当然,你可以完整地回答它。如果代码是从其他地方引用的,提供参考链接会很好,这样他们就能得到认可。 - user1046037
@nikdange_me - 抱歉,我使用了第一个(构建脚本)。 - Vince
没什么好抱歉的,兄弟! :) @Vince 尝试移除脚本并运行。我们在分发时需要这个脚本,因为它会从应用中删除模拟器架构。 - nikdange_me
7
非常重要的一点是,运行脚本必须放置在嵌入框架步骤之后。 - garanda
显示剩余9条评论

12

针对自定义的动态框架

  1. 打开终端

  2. 打开您的项目,并将相应框架的路径拖到终端中

    例如,cd /Users/mahipal/Desktop/masterTest/Alamofire.framework

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

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


嗨,我移除了x86_64:"lipo -remove x86_64 WebRTC -o WebRTC" ---> 但现在我的项目出现了21个错误:(,不知道为什么,你能帮忙吗?我正在使用模拟器。 - famfamfam
显示所有消息 忽略文件 /Users/thehe/Documents/Work/XXX/WebRTC.framework/WebRTC,文件 /Users/thehe/Documents/Work/XXXX/WebRTC.framework/WebRTC 中缺少所需的架构 x86_64(2 个片段) 未定义符号:_RTCInitializeSSL - famfamfam
1
@famfamfam,实际上模拟器仅支持x86_64架构框架。因此,您需要编译和生成适用于模拟器的框架,但是当您尝试上传二进制文件到商店时,请删除该x86_64框架。 - MAhipal Singh
1
谢谢你,现在我有两个框架:一个用于模拟器,一个用于提交:D - famfamfam

6
在“构建阶段”下的“运行脚本”,添加以下步骤以删除x86_64和/或i386
cd "${ARTIFACTS_FOLDER}"/FrameworkName.framework

lipo -remove x86_64 FrameworkName -o FrameworkName
lipo -remove i386 FrameworkName -o FrameworkName

可以组合使用以移除多个架构,例如:
lipo -remove x86_64 FrameworkName -o FrameworkName && lipo -remove i386 FrameworkName -o FrameworkName

6
当我使用nikdange_me的脚本时,我收到以下信息:
error: exportArchive: ipatool failed with an exception: #<CmdSpec::NonZeroExcitException: ... >
error: Framework not found in dylib search path

所以我修改了它,使用lipo -remove代替lipo -extractlipo -create,这解决了我的问题:

# This script loops through the frameworks embedded in the application 
# and removes unused architectures.

find "${TARGET_BUILD_DIR}/${WRAPPER_NAME}" -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"
    for arch in $(lipo -archs $FRAMEWORK_EXECUTABLE_PATH); do
        if ! printf '%s\n' ${ARCHS[@]} | egrep -q "^$arch$"; then
            lipo -remove $arch "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH" 
        fi
    done
done

2
对于一个iOS项目,你有以下架构:arm64 armv7 armv7s i386 x86_64 x86_64i386用于模拟器。
你可能遇到的问题是,你使用的框架是为iOS构建的而不是为模拟器构建的。
要解决这个问题,你可以绕过构建框架并使用lipo命令行。 第一步: lipo -info [库文件.framework的位置] 示例用法 : lipo -info /Users/.../library.framework/LibrarySDK 示例输出 :
Architectures in the fat file: /Users/.../library.framework/LibrarySDK are: i386 x86_64 armv7 arm64 

您将获得该框架使用的体系结构列表。
第二步:我们需要从模拟器体系结构中剥离框架并制作两个版本的框架(一个用于iOS设备,另一个用于模拟器)。
使用命令:lipo -remove [architecture] [location] -o [output_location] 例如:lipo -remove i386 /Users/.../SDK -o /Users/.../SDK_Output_Directory 转到您选择的输出目录以获取新生成的不含已删除体系结构的SDK,以验证您可以使用与上述相同的lipo-info命令。
您可以在新创建的SDK上使用相同的lipo remove命令,但使用另一个体系结构lipo -remove x86_64 ...,这样您将获得仅适用于iOS设备的SDK。
第三步:将最终的SDK重命名为“SDK_Name_IOS”并使用它。
祝编码愉快!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接