fzyzcjy / flutter_rust_bridge

Flutter/Dart <-> Rust binding generator, feature-rich, but seamless and simple.
https://fzyzcjy.github.io/flutter_rust_bridge/
MIT License
4.12k stars 283 forks source link

Write documentation on integration with Flutter's new FFI plugin structure #531

Closed Desdaemon closed 1 year ago

Desdaemon commented 2 years ago

Reference: https://docs.flutter.dev/development/packages-and-plugins/developing-packages#plugin-ffi

Currently, flutter create -t plugin_ffi generates a C library directly consumable by Flutter on all non-Web platforms. It might be interesting to see how we can update our book to replace the included C library with Rust and streamline the setup process.

Andrflor commented 2 years ago

One issue with the plugin_ffi template is that it builds the lib when you run flutter run. But since you will never change the lib on the consumer side building it is not a good option.

Any consumer of your lib then must have the proper rust toolchain to build the lib... The consumer will rebuild the lib on every flutter clean. This will also increase ci time and complexify ci config for nothing.

Starting with that idea in mind here is a proposal:

Starting from that template we could remove src and replace it with our native folder containing rust code. Then we could create a folder named "libs" in each platform folder containing the compiled libs.

We could modify ffigen.yaml to fit our needs or just remove it.

Then we can link the library. For example for linux and windows by replacing content of CMakeLists.txt

Linux:

set(CRATE_NAME "myLibName")

add_library(${CRATE_NAME} STATIC IMPORTED GLOBAL)
set_property(TARGET ${CRATE_NAME} PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/libs/lib${CRATE_NAME}.so")

set(extractor_bundled_libraries
  $<TARGET_FILE:${CRATE_NAME}>
  PARENT_SCOPE
)

Windows:

set(CRATE_NAME "myLibName")

add_library(${CRATE_NAME} SHARED IMPORTED GLOBAL)
set_property(TARGET ${CRATE_NAME} PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/${CRATE_NAME}.dll")

set(extractor_bundled_libraries
  $<TARGET_FILE:${CRATE_NAME}>
  PARENT_SCOPE
)

For android we could diff build.gradle

-    // Invoke the shared CMake build with the Android Gradle Plugin.
-    externalNativeBuild {
-        cmake {
-            path "../native/CMakeLists.txt"
-
-            // The default CMake version for the Android Gradle Plugin is 3.10.2.
-            // https://developer.android.com/studio/projects/install-ndk#vanilla_cmake
-            //
-            // The Flutter tooling requires that developers have CMake 3.10 or later
-            // installed. You should not increase this version, as doing so will cause
-            // the plugin to fail to compile for some customers of the plugin.
-            // version "3.10.2"
-        }
-    }

+    // Bundle the jniLibs in the libs folder
+    sourceSets {
+        main {
+            jniLibs.srcDirs = ['libs']
+        }
+    }

For ios we need to replace the content of the Classes folder and put the bridge_generated.h inside it. To be able to get it loaded and not striped we need to use flutter register of the plugin and use the dummy method in the init.

Classes/MyLibNamePlugin.h

#import <Flutter/Flutter.h>

@interface MyLibNamePlugin : NSObject<FlutterPlugin>
@end

Classes/MyLibNamePlugin.m

#import "MyLibNamePlugin.h"
#import "bridge_generated.h"

@implementation MyLibNamePlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
  ((void*)dummy_method_to_enforce_bundling);
}
@end

And add the proper generated libs to the podspec

-  s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }

+  s.pod_target_xcconfig = {
+    'DEFINES_MODULE' => 'YES',
+    'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386',
+    'OTHER_LDFLAGS[sdk=iphoneos*]' => '-force_load $(PODS_TARGET_SRCROOT)/libs/aarch64-apple-ios/libmylibname.a',
+    'OTHER_LDFLAGS[sdk=iphonesimulator*]' => '-force_load $(PODS_TARGET_SRCROOT)/libs/aarch64-apple-ios-sim/libmylibname.a'
+  }

I still need to investiagate mac, but I may not get the time to do so...

The main issue is that there is no automation process for building the libs, but is that a real problem? Or may we make a script to build and copy on the right locations? Even if it's just one command per platform?

What do you think about that idea?

Desdaemon commented 2 years ago

Or may we make a script to build and copy on the right locations? Even if it's just one command per platform?

Nice idea, this works better for plugin authors who would like to have a different build file for development and for pulling precompiled binaries.

stale[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Desdaemon commented 1 year ago

Related:

stale[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

github-actions[bot] commented 1 year ago

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new issue.