Skip to content

Commit 474e2f8

Browse files
bkioshndt-iohk
andauthored
feat(rust): add flutter_rust_bridge (#347)
* feat(rust): add flutter_rust_bridge tool Signed-off-by: bkioshn <[email protected]> * fix(rust): flutter_rust_bridge tool package name Signed-off-by: bkioshn <[email protected]> * fix(rust): flutter_rust_bridge install Signed-off-by: bkioshn <[email protected]> * fix(rust): add builder for flutter_rust_bridge Signed-off-by: bkioshn <[email protected]> * fix(flutter): create install flutter function Signed-off-by: bkioshn <[email protected]> * fix(rust): create install rust function Signed-off-by: bkioshn <[email protected]> * fix: add word to dict Signed-off-by: bkioshn <[email protected]> * fix: add code gen web Signed-off-by: bkioshn <[email protected]> * fix: code gen web as a function Signed-off-by: bkioshn <[email protected]> * fix: remove save artifact Signed-off-by: bkioshn <[email protected]> * fix(rust): rust install Signed-off-by: bkioshn <[email protected]> * fix: flutter_rust_bridge builder Signed-off-by: bkioshn <[email protected]> * fix: typo Signed-off-by: bkioshn <[email protected]> * fix: add flutter_rust_bridge to existing flutter example Signed-off-by: bkioshn <[email protected]> * fix: doc and comment Signed-off-by: bkioshn <[email protected]> * fix: bash check Signed-off-by: bkioshn <[email protected]> * fix: flutter_rust_bridge Signed-off-by: bkioshn <[email protected]> * fix: auto gen file Signed-off-by: bkioshn <[email protected]> * fix: cp file command Signed-off-by: bkioshn <[email protected]> * fix: rm file command Signed-off-by: bkioshn <[email protected]> * fix: copy contents of pkg folder, not the folder itself --------- Signed-off-by: bkioshn <[email protected]> Co-authored-by: Dominik Toton <[email protected]>
1 parent f746f97 commit 474e2f8

Some content is hidden

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

70 files changed

+4929
-135
lines changed

.config/dictionaries/project.dic

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
aarch
22
bindgen
33
binstall
4+
bkioshn
45
buildkit
56
camelcase
67
canvaskit
@@ -46,6 +47,7 @@ gopls
4647
gosec
4748
graphviz
4849
idents
50+
JDBC
4951
jorm
5052
jormungandr
5153
junitreport
@@ -89,6 +91,7 @@ PYTHONDONTWRITEBYTECODE
8991
rankdir
9092
rivo
9193
runewidth
94+
rustc
9295
rustdoc
9396
rustdocflags
9497
rustflags
@@ -122,4 +125,3 @@ xerrors
122125
xvfb
123126
zstd
124127
zstdcat
125-
JDBC

docs/src/guides/languages/flutter.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,39 @@ please follow this [guide](./../../onboarding/index.md).
157157
It is pretty strait forward for this builder process,
158158
because as a part of `+build` target we already creating a docker image.
159159

160+
## Enhancing Flutter
161+
162+
### Integrating Flutter with Rust using `flutter_rust_bridge`
163+
164+
The `flutter_rust_bridge` allows you to integrate Rust with Flutter app, while maintaining the rest of the app in
165+
Dart.
166+
This can be useful for situations where you need to run complex algorithms, handle data
167+
processing, or interact with low-level system APIs, but still want to leverage the Flutter ecosystem
168+
for UI and app management.
169+
170+
Start by creating a new builder where all the necessary setup is done under the `flutter_rust_bridge+builder`,
171+
then copy the Flutter project that already have `flutter_rust_bridge` setup.
172+
Refer to <https://cjycode.com/flutter_rust_bridge/> for how to setup the project.
173+
174+
```Earthfile
175+
builder-frb:
176+
FROM flutter_rust_bridge+builder
177+
COPY . .
178+
```
179+
180+
Then generate a binding between Rust and Flutter
181+
182+
```Earthfile
183+
# Generated necessary files for running Flutter web locally and save it locally.
184+
code-generator-web:
185+
FROM +builder-frb
186+
DO flutter_rust_bridge+CODE_GENERATOR_WEB
187+
188+
SAVE ARTIFACT ./assets/js AS LOCAL ./assets/js
189+
SAVE ARTIFACT ./rust/src/frb_generated.rs AS LOCAL ./rust/src/frb_generated.rs
190+
SAVE ARTIFACT ./lib/src AS LOCAL ./lib/src
191+
```
192+
160193
## Conclusion
161194

162195
You can see the final `Earthfile`

earthly/flutter/Earthfile

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,47 @@ VERSION 0.8
44

55
IMPORT ./installer AS installer
66

7-
# flutter-src save Flutter source code as artifact.
8-
flutter-src:
9-
FROM busybox
7+
# TODO(bkioshn): https://github.com/input-output-hk/catalyst-ci/issues/322
8+
# Install flutter.
9+
INSTALL_FLUTTER:
10+
FUNCTION
1011
ARG version=3.24.1
1112
ARG TARGETARCH
1213

13-
RUN mkdir -p /flutter
14+
# Install Flutter
1415
IF [ "$TARGETARCH" = "amd64" ]
1516
RUN wget -qO - https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_$version-stable.tar.xz \
16-
| tar -xJ -C /flutter
17+
| tar -xJ -C /usr/local
18+
ELSE IF [ "$TARGETARCH" = "arm64" ]
19+
GIT CLONE --branch $version https://github.com/flutter/flutter.git /usr/local
1720
ELSE
18-
GIT CLONE --branch $version https://github.com/flutter/flutter.git /flutter
21+
RUN echo >&2 "unsupported architecture: ${TARGETARCH}"; exit 1
1922
END
20-
SAVE ARTIFACT /flutter flutter
2123

24+
RUN git config --global --add safe.directory /usr/local/flutter
25+
ENV PATH="/usr/local/flutter/bin:/usr/local/flutter/bin/cache/dart-sdk/bin:$HOME/.pub-cache/bin:${PATH}"
26+
27+
ENV CI="true"
28+
RUN flutter config --no-analytics
29+
RUN flutter --version
30+
RUN flutter doctor -v
31+
RUN flutter config --enable-web
32+
RUN dart pub global activate melos
33+
RUN dart pub global activate junitreport
34+
RUN dart pub global activate coverage
35+
RUN dart pub global activate combine_coverage
36+
RUN dart pub global activate license_checker
37+
2238
# flutter-base installs required tools and packages.
2339
flutter-base:
2440
FROM debian:bookworm-20240513-slim
2541

2642
ENV DEBIAN_FRONTEND=noninteractive
2743

2844
RUN apt-get update --fix-missing
29-
RUN apt-get install -y apt-utils git curl gzip unzip bzip2 bash jq gpg lcov
45+
RUN apt-get install -y apt-utils git curl gzip unzip bzip2 bash jq gpg lcov tar wget xz-utils
46+
47+
DO +INSTALL_FLUTTER
3048

3149
WORKDIR frontend
3250

@@ -37,21 +55,6 @@ flutter-base:
3755
ARG edge_package_release = 1
3856
DO installer+INSTALL_EDGE_LINUX64 --edge_version=$edge_version --edge_package_release=$edge_package_release
3957

40-
COPY +flutter-src/flutter /usr/local
41-
ENV PATH="/usr/local/flutter/bin:/usr/local/flutter/bin/cache/dart-sdk/bin:$HOME/.pub-cache/bin:${PATH}"
42-
# Flutter prints warnings when used by root user but omits them if has CI env flag found.
43-
# script: https://github.com/flutter/flutter/blob/master/bin/internal/shared.sh#L214
44-
ENV CI="true"
45-
RUN flutter config --no-analytics
46-
RUN flutter --version
47-
RUN flutter doctor -v
48-
RUN flutter config --enable-web
49-
RUN dart pub global activate melos
50-
RUN dart pub global activate junitreport
51-
RUN dart pub global activate coverage
52-
RUN dart pub global activate combine_coverage
53-
RUN dart pub global activate license_checker
54-
5558
# test-flutter-base-amd64 : installs required tools and packages for amd64.
5659
test-flutter-base-amd64:
5760
BUILD --platform=linux/amd64 +flutter-base
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
VERSION 0.8
2+
3+
IMPORT ../flutter AS flutter-ci
4+
IMPORT ../rust AS rust-ci
5+
6+
# This will be refactored in the future
7+
# TODO(bkioshn): https://github.com/input-output-hk/catalyst-ci/issues/322
8+
# builder: Setup necessary tools for `flutter_rust_bridge`
9+
builder:
10+
FROM debian:stable-slim
11+
12+
WORKDIR /work
13+
14+
RUN apt-get update \
15+
&& apt-get install -y \
16+
apt-utils \
17+
wget \
18+
tar \
19+
xz-utils \
20+
git \
21+
build-essential \
22+
curl \
23+
unzip
24+
25+
DO flutter-ci+INSTALL_FLUTTER
26+
DO rust-ci+INSTALL_RUST
27+
DO rust-ci+INSTALL_TOOLS
28+
29+
# Generated necessary files for running Flutter web.
30+
CODE_GENERATOR_WEB:
31+
FUNCTION
32+
33+
RUN flutter_rust_bridge_codegen generate --default-external-library-loader-web-prefix=/assets/packages/catalyst_key_derivation/assets/js/
34+
RUN flutter_rust_bridge_codegen build-web
35+
36+
RUN mkdir -p assets/js && cp -rf ./web/pkg/* assets/js/
37+
# Don't want this gitignore file.
38+
RUN rm -rf ./assets/js/.gitignore

earthly/rust/Earthfile

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ COPY_TOOL:
112112
FUNCTION
113113

114114
ARG --required tool
115-
COPY rust-tools+tool-$tool/$tool $CARGO_HOME/bin/$tool
115+
ARG bin = $tool
116+
COPY rust-tools+tool-$tool/$bin $CARGO_HOME/bin/$bin
116117

117118

118119
# rust-base-plus-tools : Add all tools we use for rust builds to the base builder image.
@@ -360,4 +361,91 @@ REMOVE_SOURCE_FINGERPRINTS:
360361
find . -maxdepth 1 -regex "\./$source_lib-[^-]+" -exec bash -c 'echo "deleting $(readlink -f {})"; rm -rf {}' \; ; \
361362
done \
362363
fi; \
363-
done;
364+
done;
365+
366+
# TODO(bkioshn): https://github.com/input-output-hk/catalyst-ci/issues/322
367+
# Installing Rust
368+
# Code reference from [rust1.81.0-slim-bookworm](https://github.com/rust-lang/docker-rust/blob/63f877a36f8ba9d9b4b35cd49df3327264510886/stable/bookworm/slim/Dockerfile)
369+
INSTALL_RUST:
370+
FUNCTION
371+
372+
ARG TARGETARCH
373+
374+
ENV RUSTUP_HOME=/usr/local/rustup
375+
ENV CARGO_HOME=/usr/local/cargo
376+
ENV PATH=/usr/local/cargo/bin:$PATH
377+
ENV RUST_VERSION=1.81.0
378+
379+
IF [ "$TARGETARCH" = "amd64" ]
380+
LET PLATFORM = "x86_64-unknown-linux-gnu"
381+
LET RUSTUP_SHA = "6aeece6993e902708983b209d04c0d1dbb14ebb405ddb87def578d41f920f56d"
382+
ELSE IF [ "$TARGETARCH" = "arm64" ]
383+
LET PLATFORM = "aarch64-unknown-linux-gnu"
384+
LET RUSTUP_SHA = "1cffbf51e63e634c746f741de50649bbbcbd9dbe1de363c9ecef64e278dba2b2"
385+
ELSE
386+
RUN echo >&2 "unsupported architecture: ${TARGETARCH}"; exit 1
387+
END
388+
389+
LET URL = "https://static.rust-lang.org/rustup/archive/1.27.1/${PLATFORM}/rustup-init"
390+
RUN wget $URL && echo "${RUSTUP_SHA} *rustup-init" | sha256sum -c - \
391+
&& chmod +x rustup-init \
392+
&& ./rustup-init -y --no-modify-path --profile minimal --default-toolchain $RUST_VERSION --default-host $PLATFORM \
393+
&& rm rustup-init \
394+
&& chmod -R a+w $RUSTUP_HOME $CARGO_HOME \
395+
&& rustup --version \
396+
&& cargo --version \
397+
&& rustc --version \
398+
&& rm -rf /var/lib/apt/lists/*
399+
400+
# Make sure we have cargo.
401+
RUN rustup component add cargo
402+
403+
# Make sure we have the clippy linter.
404+
RUN rustup component add clippy
405+
406+
# Needed to generate code coverage.
407+
RUN rustup component add llvm-tools-preview
408+
409+
# Install a nightly toolchain which matches.
410+
RUN rustup toolchain install nightly --component miri --component rust-src --component rustfmt --component clippy --component cargo
411+
412+
# Ensure we have all the necessary targets
413+
RUN rustup target add wasm32-unknown-unknown
414+
RUN rustup target add wasm32-wasip1
415+
# RUN rustup target add wasm32-wasip2 # wasm32-wasip2 not yet available in stable - Try again in 1.82
416+
RUN rustup target add x86_64-unknown-linux-gnu
417+
RUN rustup target add x86_64-apple-darwin
418+
RUN rustup target add x86_64-pc-windows-gnu
419+
RUN rustup target add aarch64-unknown-linux-gnu
420+
RUN rustup target add aarch64-apple-darwin
421+
422+
RUN rustup target add wasm32-unknown-unknown --toolchain nightly
423+
RUN rustup target add wasm32-wasip1 --toolchain nightly
424+
RUN rustup target add wasm32-wasip2 --toolchain nightly
425+
RUN rustup target add x86_64-unknown-linux-gnu --toolchain nightly
426+
RUN rustup target add x86_64-apple-darwin --toolchain nightly
427+
RUN rustup target add x86_64-pc-windows-gnu --toolchain nightly
428+
RUN rustup target add aarch64-unknown-linux-gnu --toolchain nightly
429+
RUN rustup target add aarch64-apple-darwin --toolchain nightly
430+
431+
# Install necessary tools for Rust.
432+
INSTALL_TOOLS:
433+
FUNCTION
434+
# Install cargo-binstall so we can speed up tool installation.
435+
DO rust-tools+CARGO_BINSTALL_INSTALL
436+
437+
DO +COPY_TOOL --tool="cargo-nextest"
438+
DO +COPY_TOOL --tool="cargo-machete"
439+
DO +COPY_TOOL --tool="refinery"
440+
DO +COPY_TOOL --tool="cargo-deny"
441+
DO +COPY_TOOL --tool="cargo-modules"
442+
DO +COPY_TOOL --tool="cargo-depgraph"
443+
DO +COPY_TOOL --tool="cargo-llvm-cov"
444+
DO +COPY_TOOL --tool="wasm-tools"
445+
DO +COPY_TOOL --tool="cargo-expand"
446+
DO +COPY_TOOL --tool="wit-bindgen"
447+
DO +COPY_TOOL --tool="cargo-sweep"
448+
DO +COPY_TOOL --tool="cargo-component"
449+
DO +COPY_TOOL --tool="wasm-pack"
450+
DO +COPY_TOOL --tool="flutter-rust-bridge-codegen" --bin="flutter_rust_bridge_codegen"
451+

earthly/rust/tools/Earthfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,6 @@ tool-cargo-component:
8282

8383
tool-wasm-pack:
8484
DO +CARGO_BINSTALL --package=wasm-pack --version=0.13.0
85+
86+
tool-flutter-rust-bridge-codegen:
87+
DO +CARGO_BINSTALL --package=flutter_rust_bridge_codegen --version=2.5.1 --executable="flutter_rust_bridge_codegen"

examples/flutter/example/Earthfile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
VERSION 0.8
22

33
IMPORT ../../../earthly/flutter AS flutter-ci
4+
IMPORT ../../../earthly/flutter_rust_bridge AS flutter_rust_bridge
45

56
# To see more available functions, navigate to earthly/flutter/Earthfile.
67

@@ -39,3 +40,18 @@ build-web:
3940
ARG --required SENTRY_DSN
4041

4142
DO flutter-ci+BUILD_WEB --WORKDIR=$WORKDIR --TARGET=$TARGET --SENTRY_DSN=$SENTRY_DSN
43+
44+
# -----------------flutter_rust_bridge-----------------
45+
46+
builder-frb:
47+
FROM flutter_rust_bridge+builder
48+
COPY . .
49+
50+
# Generated necessary files for running Flutter web locally and save it locally.
51+
code-generator-web:
52+
FROM +builder-frb
53+
DO flutter_rust_bridge+CODE_GENERATOR_WEB
54+
55+
SAVE ARTIFACT ./assets/js AS LOCAL ./assets/js
56+
SAVE ARTIFACT ./rust/src/frb_generated.rs AS LOCAL ./rust/src/frb_generated.rs
57+
SAVE ARTIFACT ./lib/src AS LOCAL ./lib/src
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
rust_input: crate::api
2+
rust_root: rust/
3+
dart_output: lib/src/rust
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:example/main.dart';
3+
import 'package:example/src/rust/frb_generated.dart';
4+
import 'package:integration_test/integration_test.dart';
5+
6+
void main() {
7+
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
8+
setUpAll(() async => await RustLib.init());
9+
testWidgets('Can call rust function', (WidgetTester tester) async {
10+
await tester.pumpWidget(const MyApp());
11+
expect(find.textContaining('Result: `Hello, Tom!`'), findsOneWidget);
12+
});
13+
}

0 commit comments

Comments
 (0)