ios - 将带有绑定(bind) Rust 二进制文件的 Flutter 应用程序发布到 AppStore 时出现问题

标签 ios flutter rust app-store ffi

语境
我们有一个 flutter 功能齐全且已发布到 PlayStore 和 AppStore 的应用程序。
我们正在尝试添加 Rust 二进制 到应用程序,以便我们可以使用一些用该语言编写的 SDK。
为了实现这一点,我们使用 Flutter 的 FFI 系统 我们可以使用它执行对已编译二进制文件的 native 调用并使用这些执行的结果。
在 Android 中我们没有遇到任何问题,它在开发模式和生产模式下都可以工作,二进制文件在编译时被添加到包中,并与应用程序一起发布到 PlayStore。
问题
问题 我们正在使用 iOS .当我们以开发模式在本地运行应用程序时,应用程序运行良好,它可以无缝编译,我们可以从 iOS 模拟器和物理设备执行对 Rust 的 native 调用。现在,当我们尝试为 编译应用程序时问题出现时部署到 AppStore .
编译过程分为 2个步骤 ,首先我们构建 Runner.app 包裹:

flutter build ios
这会生成 Runner.app,然后用作 的输入。 Xcode 生成存档 将上传到 AppStore:
Xcode Archive
我们面临的问题是,当我们 存档 Runner.app,二进制文件被编译器剥离,Rust 函数没有被打包。这意味着当应用程序到达 AppStore(TestFlight 和 Production)时,二进制文件不存在。
我们的设置
我们的应用程序是使用以下内容构建的:
  • Flutter 2.8.1-稳定版
  • rust 1.58.1

  • 我们尝试捆绑的二进制文件是编译后的静态库:library.a .此二进制文件是使用 cargo-lipo 构建的作为一个通用库。 (我们知道 cargo-lipo 处于维护状态,但我们也尝试过捆绑直接使用 cargo build 构建的二进制文件,结果是一样的)。
    这是我们的播客文件 :
    # Uncomment this line to define a global platform for your project
    
    platform :ios, '10.0'
    
    # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
    
    ENV['COCOAPODS_DISABLE_STATS'] = 'true'
    
    project 'Runner', {
    
      'Debug' => :debug,
    
      'Profile' => :release,
    
      'Release' => :release,
    
    }
    
    def flutter_root
    
      generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
    
      unless File.exist?(generated_xcode_build_settings_path)
    
        raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
    
      end
    
      File.foreach(generated_xcode_build_settings_path) do |line|
    
        matches = line.match(/FLUTTER_ROOT\=(.*)/)
    
        return matches[1].strip if matches
    
      end
    
      raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
    
    end
    
    require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
    
    flutter_ios_podfile_setup
    
    target 'Runner' do
    
      use_frameworks!
    
      use_modular_headers!
    
      flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
    
    end
    
    post_install do |installer|
    
      installer.pods_project.targets.each do |target|
    
        flutter_additional_ios_build_settings(target)
    
      end
    
    end
    
    这是 pods 规范 具有 Rust 二进制文件的 Dart 插件:
    #
    
    # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
    
    # Run `pod lib lint defiant_core.podspec` to validate before publishing.
    
    #
    
    Pod::Spec.new do |s|
    
      s.name             = 'defiant_core'
    
      s.version          = '0.0.1'
    
      s.summary          = 'A new flutter plugin project.'
    
      s.description      = <<-DESC
    
    A new flutter plugin project.
    
                           DESC
    
      s.homepage         = 'http://example.com'
    
      s.license          = { :file => '../LICENSE' }
    
      s.author           = { 'Your Company' => 'email@example.com' }
    
      s.source           = { :path => '.' }
    
      s.source_files = 'Classes/**/*'
    
      s.public_header_files = 'Classes**/*.h'
    
      s.vendored_libraries = "**/*.a"
    
      s.static_framework = true
    
      s.dependency 'Flutter'
    
      s.platform = :ios, '9.0'
    
      # Flutter.framework does not contain a i386 slice.
    
      s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
    
      s.pod_target_xcconfig = { "OTHER_LDFLAGS" => "-force_load $(PODS_TARGET_SRCROOT)/**/*.a" }
    
      s.swift_version = '5.0'
    
    end
    
    到目前为止我们已经尝试过并得到了相同的结果(或更糟)
  • 使用 cargo build 编译二进制文件而不是 cargo-lipo
  • 在 Podfile 和 podspec
  • 中使用 iOS 版本
  • 删除 use_frameworks!线
  • 根据不同的 Github 问题建议更改这 2 行:

  • # ...
      s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
      s.pod_target_xcconfig = { "OTHER_LDFLAGS" => "-force_load $(PODS_TARGET_SRCROOT)/**/*.a" }
    # ...
    
  • 删除此行 s.static_framework = true
  • 设置 .a 的准确位置s.vendored_libraries = "**/*.a" 行中的文件
  • 在 Xcode 的 Runner Target 中更改 Build Settings 中的代码 strip 化配置:

  • Xcode Runner Target Build Settings
  • 编译头文件( .h )并在 Xcode 的 Runner Target 的 Build Phase 中链接二进制文件( .a ):

  • Headers and Binary Build Phase
  • 在 Xcode 的 Runner Build Settings 中更改目标架构:

  • Changing architecture Runner Build Settings
    结论
    到目前为止,没有任何工作......我们的想法已经不多了,所以如果有人能指出我们正确的方向,我们将不胜感激。
    干杯!

    最佳答案

    我遇到了同样的问题,并通过以下方式修复:

  • https://github.com/fzyzcjy/flutter_rust_bridge/issues/496
  • http://cjycode.com/flutter_rust_bridge/integrate/ios_headers.html

  • 我认为原因是发布版本会去除未使用的符号,而 Rust 生成的符号直接被 Dart 使用,而不是 App。所以你需要直接在App中使用它们。

    关于ios - 将带有绑定(bind) Rust 二进制文件的 Flutter 应用程序发布到 AppStore 时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71133823/

    相关文章:

    iphone - 如何识别设备(唯一标识符、CFUUIDRef、设备 token ?)

    flutter - 如何在 Flutter 中为 Text Widget 添加自定义删除线

    ios - 无法生成位码包,因为

    types - 错误[E0308] : mismatched types expected `()` ,找到了 `bool`。如何清除此错误?

    objective-c - If-Else 语句不起作用

    ios - 解析 PFUser CurrentUser 返回 Null

    ios - UICollectionView 使用 SDWebImage 滚动

    android - Flutter - AppBar 底部小部件

    rust - 如何将泛型 T 的实例转换为 Rust 中的具体实例?

    iterator - 如何将盒装闭包传递给 `take_while` ?