Skip to content

Commit 8c0ee81

Browse files
committed
feat: new generated flutter plugin
1 parent fb4958b commit 8c0ee81

File tree

102 files changed

+212
-1297
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+212
-1297
lines changed

frb_codegen/assets/integration_template/plugin/example/integration_test/simple_test.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
import 'package:integration_test/integration_test.dart';
12
import 'package:flutter_test/flutter_test.dart';
23
import 'package:REPLACE_ME_DART_PACKAGE_NAME/REPLACE_ME_DART_PACKAGE_NAME.dart';
3-
import 'package:integration_test/integration_test.dart';
44

55
void main() {
66
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

frb_codegen/assets/integration_template/plugin/pubspec.yaml

-38
This file was deleted.

frb_codegen/src/library/commands/flutter.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ pub fn flutter_create(name: &str, org: &Option<String>, template: Template) -> a
1515
Template::App => args.extend(["--template", "app"]),
1616
Template::Plugin => args.extend([
1717
"--template",
18-
"plugin",
18+
"plugin_ffi",
1919
"--platforms",
20-
"android,ios,linux,macos,windows,web",
20+
"android,ios,linux,macos,windows",
2121
]),
2222
}
2323
info!(

frb_codegen/src/library/integration/creator.rs

+29-14
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,8 @@ pub fn create(config: CreateConfig) -> anyhow::Result<()> {
5757
fn remove_unnecessary_app_files(dart_root: &Path) -> anyhow::Result<()> {
5858
// frb-coverage:ignore-end
5959
let lib_dir = dart_root.join("lib");
60-
let test_dir = dart_root.join("test");
61-
6260
remove_files_in_dir(&lib_dir)?;
61+
let test_dir = dart_root.join("test");
6362
remove_files_in_dir(&test_dir)?;
6463

6564
Ok(())
@@ -70,23 +69,39 @@ fn remove_unnecessary_app_files(dart_root: &Path) -> anyhow::Result<()> {
7069
fn remove_unnecessary_plugin_files(dart_root: &Path) -> anyhow::Result<()> {
7170
// frb-coverage:ignore-end
7271
let lib_dir = dart_root.join("lib");
73-
let test_dir = dart_root.join("test");
74-
let example_lib_dir = dart_root.join("example").join("lib");
75-
let example_integration_test_dir = dart_root.join("example").join("integration_test");
76-
let android_dir = dart_root.join("android");
77-
let ios_dir = dart_root.join("ios");
78-
let linux_dir = dart_root.join("linux");
79-
let macos_dir = dart_root.join("macos");
80-
let windows_dir = dart_root.join("windows");
81-
8272
remove_files_in_dir(&lib_dir)?;
83-
remove_files_in_dir(&test_dir)?;
73+
let src_dir = dart_root.join("src");
74+
remove_files_in_dir(&src_dir)?;
75+
let ffi_gen_file = dart_root.join("ffigen.yaml");
76+
fs::remove_file(ffi_gen_file)?;
77+
fs::remove_dir(src_dir)?;
78+
let example_lib_dir = dart_root.join("example").join("lib");
8479
remove_files_in_dir(&example_lib_dir)?;
85-
remove_files_in_dir(&example_integration_test_dir)?;
80+
81+
let android_dir = dart_root.join("android");
82+
let android_src_dir = &android_dir.join("src");
83+
let android_src_main_dir = &android_src_dir.join("main");
84+
remove_files_in_dir(&android_src_main_dir)?;
85+
fs::remove_dir(&android_src_main_dir)?;
86+
fs::remove_dir(&android_src_dir)?;
8687
remove_files_in_dir(&android_dir)?;
88+
89+
let ios_dir = dart_root.join("ios");
90+
let ios_classes_dir = &ios_dir.join("Classes");
91+
remove_files_in_dir(&ios_classes_dir)?;
92+
fs::remove_dir(&ios_classes_dir)?;
8793
remove_files_in_dir(&ios_dir)?;
94+
95+
let linux_dir = dart_root.join("linux");
8896
remove_files_in_dir(&linux_dir)?;
97+
98+
let macos_dir = dart_root.join("macos");
99+
let macos_classes_dir = &macos_dir.join("Classes");
100+
remove_files_in_dir(&macos_classes_dir)?;
101+
fs::remove_dir(&macos_classes_dir)?;
89102
remove_files_in_dir(&macos_dir)?;
103+
104+
let windows_dir = dart_root.join("windows");
90105
remove_files_in_dir(&windows_dir)?;
91106

92107
Ok(())
@@ -99,7 +114,7 @@ fn remove_files_in_dir(dir: &Path) -> anyhow::Result<()> {
99114
if path.is_file() {
100115
fs::remove_file(&path)?;
101116
} else if path.is_dir() {
102-
bail!("An unexpected directory was encountered: {:?}", path);
117+
bail!("Directory '{:?}' was expected to contain only files but directory '{:?}' was encountered", dir.display(), path.display());
103118
}
104119
}
105120
Ok(())

frb_codegen/src/library/integration/integrator.rs

+23-13
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,18 @@ pub fn integrate(config: IntegrateConfig) -> Result<()> {
6060
}
6161

6262
info!("Modify file permissions");
63-
modify_permissions(&dart_root)?;
63+
modify_permissions(&dart_root, &config.template)?;
6464

6565
info!("Add pub dependencies");
6666
pub_add_dependencies(
6767
config.enable_integration_test,
6868
config.enable_local_dependency,
6969
&rust_crate_name,
70+
&config.template,
7071
)?;
7172

7273
info!("Setup cargokit dependencies");
73-
setup_cargokit_dependencies(&dart_root)?;
74+
setup_cargokit_dependencies(&dart_root, &config.template)?;
7475

7576
info!("Format Dart code");
7677
format_dart(&[dart_root.clone()], &dart_root, 80, &[])?;
@@ -133,9 +134,12 @@ fn compute_replacements(
133134
replacements
134135
}
135136

136-
fn modify_permissions(dart_root: &Path) -> Result<()> {
137+
fn modify_permissions(dart_root: &Path, template: &Template) -> Result<()> {
137138
#[allow(unused_variables)] // unused when in windows
138-
let dir_cargokit = dart_root.join("rust_builder").join("cargokit");
139+
let dir_cargokit = match template {
140+
Template::App => dart_root.join("rust_builder").join("cargokit"),
141+
Template::Plugin => dart_root.join("cargokit"),
142+
};
139143

140144
#[cfg(unix)]
141145
{
@@ -147,11 +151,14 @@ fn modify_permissions(dart_root: &Path) -> Result<()> {
147151
Ok(())
148152
}
149153

150-
fn setup_cargokit_dependencies(dart_root: &Path) -> Result<()> {
151-
let build_tool_dir = dart_root
152-
.join("rust_builder")
153-
.join("cargokit")
154-
.join("build_tool");
154+
fn setup_cargokit_dependencies(dart_root: &Path, template: &Template) -> Result<()> {
155+
let build_tool_dir = match template {
156+
Template::App => dart_root
157+
.join("rust_builder")
158+
.join("cargokit")
159+
.join("build_tool"),
160+
Template::Plugin => dart_root.join("cargokit").join("build_tool"),
161+
};
155162

156163
flutter_pub_get(&build_tool_dir)
157164
}
@@ -292,12 +299,15 @@ fn pub_add_dependencies(
292299
enable_integration_test: bool,
293300
enable_local_dependency: bool,
294301
rust_crate_name: &str,
302+
template: &Template,
295303
) -> Result<()> {
296304
// frb-coverage:ignore-end
297-
flutter_pub_add(
298-
&[rust_crate_name.into(), "--path=rust_builder".into()],
299-
None,
300-
)?;
305+
if template == &Template::App {
306+
flutter_pub_add(
307+
&[rust_crate_name.into(), "--path=rust_builder".into()],
308+
None,
309+
)?;
310+
}
301311

302312
pub_add_dependency_frb(enable_local_dependency, None)?;
303313

frb_example/flutter_package/.metadata

+1-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ version:
77
revision: "5dcb86f68f239346676ceb1ed1ea385bd215fba1"
88
channel: "stable"
99

10-
project_type: plugin
10+
project_type: plugin_ffi
1111

1212
# Tracks metadata for the flutter migrate command
1313
migration:
@@ -27,9 +27,6 @@ migration:
2727
- platform: macos
2828
create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
2929
base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
30-
- platform: web
31-
create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
32-
base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
3330
- platform: windows
3431
create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1
3532
base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1

frb_example/flutter_package/README.md

+82-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,92 @@
11
# flutter_package
22

3-
A new Flutter plugin project.
3+
A new Flutter FFI plugin project.
44

55
## Getting Started
66

77
This project is a starting point for a Flutter
8-
[plug-in package](https://flutter.dev/developing-packages/),
9-
a specialized package that includes platform-specific implementation code for
10-
Android and/or iOS.
8+
[FFI plugin](https://docs.flutter.dev/development/platform-integration/c-interop),
9+
a specialized package that includes native code directly invoked with Dart FFI.
1110

12-
For help getting started with Flutter development, view the
11+
## Project structure
12+
13+
This template uses the following structure:
14+
15+
* `src`: Contains the native source code, and a CmakeFile.txt file for building
16+
that source code into a dynamic library.
17+
18+
* `lib`: Contains the Dart code that defines the API of the plugin, and which
19+
calls into the native code using `dart:ffi`.
20+
21+
* platform folders (`android`, `ios`, `windows`, etc.): Contains the build files
22+
for building and bundling the native code library with the platform application.
23+
24+
## Building and bundling native code
25+
26+
The `pubspec.yaml` specifies FFI plugins as follows:
27+
28+
```yaml
29+
plugin:
30+
platforms:
31+
some_platform:
32+
ffiPlugin: true
33+
```
34+
35+
This configuration invokes the native build for the various target platforms
36+
and bundles the binaries in Flutter applications using these FFI plugins.
37+
38+
This can be combined with dartPluginClass, such as when FFI is used for the
39+
implementation of one platform in a federated plugin:
40+
41+
```yaml
42+
plugin:
43+
implements: some_other_plugin
44+
platforms:
45+
some_platform:
46+
dartPluginClass: SomeClass
47+
ffiPlugin: true
48+
```
49+
50+
A plugin can have both FFI and method channels:
51+
52+
```yaml
53+
plugin:
54+
platforms:
55+
some_platform:
56+
pluginClass: SomeName
57+
ffiPlugin: true
58+
```
59+
60+
The native build systems that are invoked by FFI (and method channel) plugins are:
61+
62+
* For Android: Gradle, which invokes the Android NDK for native builds.
63+
* See the documentation in android/build.gradle.
64+
* For iOS and MacOS: Xcode, via CocoaPods.
65+
* See the documentation in ios/flutter_package.podspec.
66+
* See the documentation in macos/flutter_package.podspec.
67+
* For Linux and Windows: CMake.
68+
* See the documentation in linux/CMakeLists.txt.
69+
* See the documentation in windows/CMakeLists.txt.
70+
71+
## Binding to native code
72+
73+
To use the native code, bindings in Dart are needed.
74+
To avoid writing these by hand, they are generated from the header file
75+
(`src/flutter_package.h`) by `package:ffigen`.
76+
Regenerate the bindings by running `dart run ffigen --config ffigen.yaml`.
77+
78+
## Invoking native code
79+
80+
Very short-running native functions can be directly invoked from any isolate.
81+
For example, see `sum` in `lib/flutter_package.dart`.
82+
83+
Longer-running functions should be invoked on a helper isolate to avoid
84+
dropping frames in Flutter applications.
85+
For example, see `sumAsync` in `lib/flutter_package.dart`.
86+
87+
## Flutter help
88+
89+
For help getting started with Flutter, view our
1390
[online documentation](https://flutter.dev/docs), which offers tutorials,
1491
samples, guidance on mobile development, and a full API reference.
1592

0 commit comments

Comments
 (0)