解决关于Xcode16提交审核报错(Asset validation failed)

问题描述

正常通过Produre - Archive打包,并在XcodeWindow -Organizer - Distribute App提交App Store审核报错误。

提交报错

Bitcode 是一种中间表示形式,在 Xcode中打包提交到 App Store 审核时,如果出现包含 Bitcode 的报错,这通常意味着您的应用没有正确包含 BitcodeBitcode 是苹果的一项要求,它允许苹果在 App Store 中对您的应用进行进一步的优化。

当提交应用到 App Store 时出现与 Bitcode 相关的问题,您需要手动移除 framework 中的 Bitcode

解决方法

在 Xcode 中禁用 Bitcode:

  • 打开你的 Xcode 项目;
  • 选择你的项目在 Project Navigator 中;
  • 选择你的目标应用;
  • 选择“Build Settings”标签;
  • 搜索“Enable Bitcode”并将其设置为“No”;
  • 清理并重建你的项目(使用快捷键 Shift + Command + K 进行清理,然后使用 Command + B 进行重建)

由于 Xcode16 不再支持 Bitcode,所以我们无法在项目中找到这个设置。

使用Xcode 15打包构建上传

由于最近刚换了电脑,自己的 Intel 破笔记本上还是用的是Mac OS 13.7.2Xcode 15.2,而且 Apple 已经停止了对这个机型的更新。

公司一直有台Mac Mini (Apple M1 + 8GB + 256GB)着实丐中丐了,实在是提不起兴趣,但是确实没办法,自己的电脑面临着淘汰,最新的系统无法更新,Xcode可能需要最新的版本才能构建提交。

可以尝试使用旧版Xcode 15打包并构建,我这里并没有进行尝试,同事说这个错误在他的电脑上打包是一直都存在,通过我电脑打包构建的项目是没有问题的。

但还是建议通过各种方法做最新的兼容。

使用命令行工具,手动更改Bitcode

假设您有一个名为 NIMSDK.frameworkframework,并且它位于 /path/to/~/NIMSDK.framework路径,那么您可以按照以下方式处理:

  1. 通过 cd命令进入到 NIMSDK.framework 的路径。
    如果是通过 pod install 获取的 SDK,则进入 pods 文件夹。

  2. 执行以下命令检查 framework是否包含 bitcode,返回 0 即为不包含。

otool -l NIMSDK | grep __LLVM | wc -l
  1. 如果检测结果不是 0,则继续执行以下命令移除 NIMSDK.frameworkBitcode
xcrun bitcode_strip -r NIMSDK -o NIMSDK
framework路径

一定要注意是.framework路径下的同名文件
一定要注意是.framework路径下的同名文件
一定要注意是.framework路径下的同名文件
重要的事情说三遍。

使用shell脚本,批量处理

如果你的某一个路径下有很多需要移除的bitcode库,编写一个如下的脚本,下面使用网易云信的NERtcSDK举例。
代码示例如下:

#!/bin/sh

proj_path=$(pwd)

if [ -f NELivePlayerFramework.framework/NELivePlayerFramework ]; then
    echo "remove bitcode for NELivePlayerFramework.framework"
    xcrun bitcode_strip -r $proj_path/NELivePlayerFramework.framework/NELivePlayerFramework -o $proj_path/NELivePlayerFramework.framework/NELivePlayerFramework
    otool -l $proj_path/NELivePlayerFramework.framework/NELivePlayerFramework | grep __LLVM

fi

if [ -f NELPGslb.framework/NELPGslb ]; then
    echo "remove bitcode for NELPGslb.framework"
    xcrun bitcode_strip -r $proj_path/NELPGslb.framework/NELPGslb -o $proj_path/NELPGslb.framework/NELPGslb
    otool -l $proj_path/NELPGslb.framework/NELPGslb | grep __LLVM
fi

exit

最后保存为 remove_nertc_bitcode.sh

  1. 打开终端,通过 cd 命令进入到Pods/NERtcSDK/NERTC/NERtcSDK目录下;
  2. 拷贝 remove_nertc_bitcode.sh 脚本到 frameworks 所在路径;
  3. 执行以下命令:
sh remove_nertc_bitcode.sh

您可以下载 remove_nertc_bitcode.sh 脚本,批量去除引入了网易云信音视频产品 SDK 系列的 iOS 项目中的 Bitcode。或者参考它写出适用自己项目的脚本。

使用CocoaPodspost_install钩子

也是我正在使用的一种方式,相比较上面的方法来说,非常懒人,如果再次遇到报错的库,可以直接在podfile 文件中,添加 Framework 路径,然后重新pod install

post_install do |installer|
  bitcode_strip_path = 'xcrun --find bitcode_strip'.chop!
  def strip_bitcode_from_framework(bitcode_strip_path, framework_relative_path)
    framework_path = File.join(Dir.pwd, framework_relative_path)
    command = "#{bitcode_strip_path} #{framework_path} -r -o #{framework_path}"
    puts "Stripping bitcode: #{command}"
    system(command)
  end
  # 列出需要剥离BitCode的frameworks路径
  framework_paths = [
    "Pods/LibraryA/LibraryA/dynamic/LibraryA.xcframework/ios-arm64_armv7/LibraryA.framework/LibraryA",
    "Pods/LibraryB/LibraryB.xcframework/ios-arm64_armv7/LibraryB.framework/LibraryB"
  ]
  framework_paths.each do |framework_relative_path|
    strip_bitcode_from_framework(bitcode_strip_path, framework_relative_path)
  end
end

亦或者是添加config.build_settings['ENABLE_BITCODE'] = 'NO'来实现每次pod install都会去安装无bitcode的库,但是如果某一个的库中使用的是xcframework,则需要对xcframework中不同的架构路径下的framework进行移除bitcode操作。

下面是我基于上面的 post_install 代码做的调整,添加了对framework_paths 路径检查、bitcode检查。

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
      config.build_settings['ENABLE_BITCODE'] = 'NO'
    end
  end

  # 剥离pod库中的Bitcode
  bitcode_strip_path = `xcrun --find bitcode_strip`.chop!
  def strip_bitcode_from_framework(bitcode_strip_path, framework_relative_path)

    framework_path = File.join(Dir.pwd, framework_relative_path)

    command = "#{bitcode_strip_path} #{framework_path} -r -o #{framework_path}"
    puts "Stripping bitcode: #{command}\n\n"
    system(command)

  end

  # 检查是否存在bitcode
  def has_bitcode(framework_relative_path)
    framework_path = File.join(Dir.pwd, framework_relative_path)
    # 检查是否存在 bitcode
    command = "otool -l #{framework_path} | grep __LLVM | wc -l"
    result = `#{command}`.strip.to_i
    # 如果结果不为 0,则认为存在 bitcode
    result != 0
  end

  # 列出需要剥离Bitcode的xcframeworks路径
  framework_paths = [
    "Pods/LibraryA/LibraryA/dynamic/LibraryA.xcframework/ios-arm64_armv7/LibraryA.framework/LibraryA",
    "Pods/LibraryB/LibraryB.xcframework/ios-arm64_armv7/LibraryB.framework/LibraryB"
  ]

  framework_paths.each do |framework_relative_path|
    if File.exist?(framework_relative_path)
      if has_bitcode(framework_relative_path)
        strip_bitcode_from_framework(bitcode_strip_path, framework_relative_path)
      else
        filename = File.basename(framework_relative_path)
        puts "Framework #{filename} does not contain bitcode."
      end
    else
      puts "Framework path does not exist: #{framework_path}"
    end
  end

end

这两种方法可以实现互补,也可以找到全部的路径添加到framework_paths来全部实现,实际需要操作的framework可能会很多。

温馨提示

建议在重新pod install前,执行

pod cache clean --all

优化更新

  • 更新时间:2025 年 03 月 03 日

由于大部分的Bitcode都是通过remove_nertc_bitcode.sh 脚本处理了,这次更改为在framework_globs中实现,不再依赖于这个脚本执行。

# 自动发现需要处理的 framework 路径
  framework_globs = [
    # xcframework下的全部路径
    'Pods/LibraryA/*.xcframework/**/*.framework',
    # 可以指定xcframework路径下的指定路径
    'Pods/LibraryA/Library_Example_A.xcframework/**/Library_Example_A.framework',
    'Pods/LibraryB/Library_Example_B.xcframework/**/Library_Example_B.framework',
    # 全部路径下的
    'Pods/LibraryC/**/*.framework',
    # 亦可单独指定
    'Pods/LibraryD/**/LibraryD.framework',
  ]

  # 列出需要剥离Bitcode的framework和xcframeworks路径
  framework_paths = framework_globs.flat_map { |g| Dir.glob(g) }.map do |path|
    framework_name = File.basename(path, '.*')
    "#{path}/#{framework_name}"
  end
  • 将旧framework_paths替换为新framework_paths;
  • bitcode处理流程未改变,优化了可能需要手动添加的路径长度。

参考资料

融云干货丨由于 xcode16 不支持 framework 开启 bitcode,移除 framework 中的 bitcode
xcode16 提交审核报 bitcode 错错误-Asset validation failed (90482) Invalid Executable
App Store 审核应用时出现包含 bitcode 的报错
怎么删除 NERtc SDK Frameworks 的 Bitcode
Xcode 提交 App Store 审核时出现包含 bitcode 的报错
Xcode does not contain bitcode
Xcode14 正式版编译报错‘ does not contain bitcode.解决方案
[iOS] Upload Symbols Failed on Xcode 16 #46853

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容