语境
我们有一个 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)时,二进制文件不存在。
我们的设置
我们的应用程序是使用以下内容构建的:
我们尝试捆绑的二进制文件是编译后的静态库:
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
use_frameworks!
线# ...
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
.h
)并在 Xcode 的 Runner Target 的 Build Phase 中链接二进制文件( .a
):Headers and Binary Build Phase
Changing architecture Runner Build Settings
结论
到目前为止,没有任何工作......我们的想法已经不多了,所以如果有人能指出我们正确的方向,我们将不胜感激。
干杯!
最佳答案
我遇到了同样的问题,并通过以下方式修复:
我认为原因是发布版本会去除未使用的符号,而 Rust 生成的符号直接被 Dart 使用,而不是 App。所以你需要直接在App中使用它们。
关于ios - 将带有绑定(bind) Rust 二进制文件的 Flutter 应用程序发布到 AppStore 时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71133823/