Home > other >  Creating Flutter Rust FFI Plugin with an XCFramework for macOS/iOS
Creating Flutter Rust FFI Plugin with an XCFramework for macOS/iOS

Time:11-19

Overview

I am trying to:

  • Create an FFI plugin for Flutter with flutter_rust_bridge
  • For iOS/macOS, use an XCFramework (seems to be the better option right now over universal libraries)

In short, I am having a really hard time getting my example project (using my flutter ffi plugin) to build.

What I've Done

  1. Created one XCFramework from the generated rust static libraries (includes macOS, iOS, and iOS simulator static libraries). This alone was quite the headache.
  2. Created the following flutter_mimir.podspec file in my ios and macos folders:
Pod::Spec.new do |spec|
  spec.name          = 'flutter_mimir'
  spec.version       = '0.0.1'
  spec.license       = { :file => '../LICENSE' }
  spec.homepage      = 'https://github.com/GregoryConrad/mimir'
  spec.authors       = { 'Gregory Conrad' => '[email protected]' }
  spec.summary       = 'Embedded instance of milli'

  spec.ios.deployment_target = '9.0'
  spec.osx.deployment_target = '10.11'

  spec.source = { :path => '.' }
  spec.preserve_paths = 'EmbeddedMilli.xcframework/**/*'
  spec.vendored_frameworks = 'EmbeddedMilli.xcframework'
  spec.xcconfig = { 'OTHER_LDFLAGS' => '-framework EmbeddedMilli' }

  # TODO clean up following (not sure if these are actually needed here?)
  # Flutter.framework does not contain a i386 slice.
  spec.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
  spec.static_framework = true
end
  1. Moved my created EmbeddedMilli.xcframework into the ios and macos directories.
  2. pod install runs fine.

The Problem

When building for macOS:

Launching lib/main.dart on macOS in debug mode...
lib/main.dart:1
--- xcodebuild: WARNING: Using the first of multiple matching destinations:
{ platform:macOS, arch:arm64, id:00006000-0004695C0C06801E }
{ platform:macOS, arch:x86_64, id:00006000-0004695C0C06801E }
ld: framework not found EmbeddedMilli
clang: error: linker command failed with exit code 1 (use -v to see invocation)

How can I modify my library's podspec/project build settings to allow the example project to build?

Related

CodePudding user response:

The answer to my question arose from this GitHub thread. Here's a copy of my comment:

In case anyone else stumbles into this, I got FFI working with my cross-platform XCFramework using ffiPlugin: true (thanks to @leisim's great example with Isar!). I can't believe I didn't realize this, but my XCFramework was getting tree-shaken. Here's how I fixed it (same exact code for macOS and iOS, but cannot be symbolically linked unfortunately):

  • my_package.podspec
Pod::Spec.new do |spec|
  spec.name          = 'my_package'
  spec.version       = '0.0.1'
  spec.license       = { :file => '../LICENSE' }
  spec.homepage      = ''
  spec.authors       = { 'Your Name' => '[email protected]' }
  spec.summary       = 'Some summary'

  spec.source              = { :path => '.' }
  spec.source_files        = 'Classes/**/*'
  spec.public_header_files = 'Classes/**/*.h'
  spec.vendored_frameworks = 'Frameworks/MyPackage.xcframework'

  spec.ios.deployment_target = '11.0'
  spec.osx.deployment_target = '10.11'
end
  • Classes/binding.h
void enforce_binding();
  • Classes/EnforceBinding.swift
public func dummyMethodToEnforceBundling() {
    enforce_binding() // disable tree shaking
}
  • Frameworks/MyPackage.xcframework needs to have a void enforce_binding() {} function. I did this in Rust with:
/// Enforce the binding for this library (to prevent tree-shaking)
#[no_mangle]
pub extern "C" fn enforce_binding() {}
  • Related