Skip to content

解决 Xcode 上传应用时“hermes.framework 包含 bitcode”错误

问题描述
在使用 Xcode 16 构建并上传应用到 TestFlight 时,遇到以下验证错误:
Asset validation failed, NSLocalizedRecoverySuggestion=Invalid Executable. The executable 'hermes.framework/hermes' contains bitcode
尽管构建和归档过程成功完成,但上传失败导致无法分发到 TestFlight。

问题根源

此问题通常发生在以下环境:

  • Xcode 16 或更高版本
  • iOS 18 开发环境
  • 项目使用了 Hermes JavaScript 引擎(React Native 项目常见)

主要原因是某些框架(特别是 hermes.framework) 包含 bitcode,但 Xcode 16+ 对 bitcode 处理更为严格。

bash
# 典型错误日志
<IDEDistributionContext: 0x7f9ef32a6d50; ...>
2024-09-25 10:05:15 +0000 [MT] Upload for archive had issues:
(
    "Asset validation failed", 
    "Invalid Executable. The executable 'hermes.framework/hermes' contains bitcode"
)

解决方案

✅ 推荐方案:在 Podfile 中添加自动 strip 脚本

  1. 修改 Podfile 文件
    在文件末尾 end 之前添加以下函数(若无 post_install 块则需创建):
ruby
post_install do |installer|
  # 自动检测并移除 bitcode 的函数
  def strip_bitcode_from_frameworks
    puts "Checking frameworks for Bitcode..."

    # 搜索 Pods 中所有 .framework 文件
    frameworks = Dir.glob("Pods/**/*.framework")

    frameworks.each do |framework|
      binary = File.join(framework, File.basename(framework, ".framework"))

      if File.exist?(binary)
        # 检测是否包含 bitcode
        contains_bitcode = `otool -l "#{binary}" | grep __LLVM`
        next unless contains_bitcode &amp;&amp; !contains_bitcode.empty?

        puts "#{binary} 包含 bitcode,正在移除..."
        stripped = "#{binary}_stripped"

        # 执行 bitcode 移除
        success = system("xcrun bitcode_strip \"#{binary}\" -r -o \"#{stripped}\"")
        
        # 替换原始文件
        if success && File.exist?(stripped)
          FileUtils.mv(stripped, binary, force: true)
          puts "✅ 成功移除 #{binary} 中的 bitcode"
        else
          puts "❌ 移除 #{binary} 的 bitcode 失败"
        end
      end
    end
    puts "🧹 Bitcode 清除完成"
  end

  # 调用函数
  strip_bitcode_from_frameworks
end
  1. 执行后续操作
bash
# 1. 更新依赖
pod install

# 2. 清理构建缓存
rm -rf ~/Library/Developer/Xcode/DerivedData

# 3. 重新编译归档
xcodebuild clean archive -workspace YourProject.xcworkspace -scheme YourScheme
  1. 验证修复效果
    重新上传到 App Store Connect,确认错误已消失。

⚙️ 替代方案:手动指定框架路径

如果只需处理已知框架(如 Hermes):

ruby
post_install do |installer|
  bitcode_strip_path = `xcrun --find bitcode_strip`.chomp

  # 定义处理函数
  def strip_bitcode(bitcode_strip_path, path)
    full_path = File.join(Dir.pwd, path)
    if File.exist?(full_path)
      system("#{bitcode_strip_path} #{full_path} -r -o #{full_path}")
      puts "已处理: #{full_path}"
    end
  end

  # 指定需要处理的路径
  [
    "Pods/hermes-engine/destroot/Library/Frameworks/macosx/hermes.framework/hermes",
    "Pods/hermes-engine/destroot/Library/Frameworks/universal/hermes.xcframework/ios-arm64/hermes.framework/hermes",
    # 添加其他路径(如有需要)
  ].each { |path| strip_bitcode(bitcode_strip_path, path) }
end

注意事项

  1. RN 版本兼容性
    • React Native < 0.72 可能需要额外配置
    • 确保 hermes_enabled 正确设置:
ruby
use_react_native!(
  :hermes_enabled => true, # 检查此处配置
  ...
)
  1. 权限问题 首次运行脚本可能需授权:
bash
sudo chmod +x your_script.sh
  1. Bitcode 设置 在 Xcode 中确认项目设置:
    • Target → Build Settings → Enable Bitcode → NO

⚠️ 重要提示
此解决方案适用于 Xcode 16+ 和 macOS Sonoma/Ventura。
升级 React Native 到兼容版本 0.73+ 可预防此问题再次发生。


验证步骤

  1. 检查二进制是否仍含 bitcode
bash
otool -l YOUR_APP.app/Frameworks/hermes.framework/hermes | grep __LLVM
  1. 若无输出则表示 bitcode 已成功移除

遵循以上步骤,即可解决 TestFlight 上传时的 bitcode 验证错误。