Experimenting with Flutter on Torizon
Flutter™ is a UI toolkit from Google that aims to ease the development of graphical applications that runs on different platforms using a single codebase. It provides natively complied applications for mobile, web, desktop.
This experiment was driven by the announcement that Google and Ubuntu are collaborating to bring Flutter to Linux.
Why could Flutter be interesting on embedded devices?
It features a fast-growing ecosystem of developers. This is useful as specialized embedded developers are hard to find. Flutter allows one to run the same code on different targets, increasing the reuse of code. Flutter applications run natively to allow for good performance, even on hardware with limited resources. Another nice feature is the support of Visual Studio Code, which is an IDE many Toradex customers like, and Toradex provides integration for VS Code to simplify the development process.
Although Flutter is more mature on mobile platforms, its development for web and desktop targets is very active, which opens the possibility of running these applications on embedded devices. With that said, Flutter on desktop and particularly on embedded is very early and you can consider this alpha-quality.
This is a quick overview of how to use the flutter-pi Flutter Embedder to run Flutter applications on Torizon, the easy-to-use industrial Linux software platform from Toradex. Torizon is open source and built with the Yocto Project.
We'll get straight to the point and run a container that will bring the application up on a screen. If you have a touchscreen set up, that will work too.
On a standard Torizon installation, simply run
$ docker run --rm -it gustavsl/flutter-arm
Here's a video of how it should look running on a Toradex Colibri iMX6DL System on Module featuring an NXP i.MX6 DualLite SoC. For the carrier board, we used the Hensys H-Board carrier board featuring a 7" capacitive touch display:
Let's go through how this was done:
First, go through the installation steps for the Flutter environment on your host PC. You'll use it to build the application assets that will be run by the Flutter embedder on the target.
Once you got your environment running, let's build the Flutter Gallery example. On your host, clone the repo:
$ git clone https://github.com/flutter/gallery && cd gallery
Since Flutter Gallery uses some newer features that are on Flutter's `master` channel, so we'll switch to that:
$ flutter channel master $ flutter upgrade
Running `flutter doctor -v` should produce an output similar to:
$ flutter doctor -v [✓] Flutter (Channel master, 1.20.0-8.0.pre.57, on Linux, locale en_US.UTF-8) • Flutter version 1.20.0-8.0.pre.57 at /home/gustavo/Dev/flutter • Framework revision 8bd2e6585b (4 days ago), 2020-07-11 12:15:19 -0700 • Engine revision 9b3e3410f0 • Dart version 2.9.0 (build 2.9.0-21.0.dev 06cb010247) [...]
These are the current versions for Flutter's `master` channel. The embedder that runs on the target must also be based on this version. We'll get a little bit into that later. Now just build the assets bundle for the Flutter Gallery:
$ flutter build bundle
This will produce a `flutter_assets` directory under `build`.
Now let's take a look at the Dockerfile:
dockerfile FROM torizon/arm32v7-debian-wayland-base:buster COPY flutter_embedder.h /usr/include COPY libflutter_engine.so icudtl.dat /usr/lib/ COPY flutter_assets /root/flutter_assets RUN apt update && apt install -y --no-install-recommends git pkg-config \ libglvnd-dev libgl1-mesa-dev libgles2-mesa-dev \ libegl-mesa0 libdrm-dev libgbm-dev \ build-essential libgpiod-dev gpiod RUN git clone https://github.com/ardera/flutter-pi.git WORKDIR flutter-pi RUN make RUN mv out/flutter-pi /usr/bin/ CMD ["flutter-pi","/root/flutter_assets"]
Using one of Torizon's base debian images, the two essential dependencies were installed to the container root filesystem: the embedder (flutter_embedder.h) and the Flutter engine (libflutter_engine.so). Although the base image has "wayland" in its name, flutter-pi does not use Wayland. It actually requires no compositor to run and uses GLFW to generate the graphics.
Also, the resulting flutter_assets directory from our previous build was copied to the container.
Then all dependencies for making flutter-pi were installed, `make` was run and the resulting binary was moved to /usr/bin. The CMD of this Dockerfile simply runs the flutter-pi binary pointing to the assets of the Flutter Gallery application.
This post won't delve into the building the actual embedder and engine, but you can reuse those from the `gustavsl/flutter-arm` container (on revision 9b3e3410f0, Flutter 1.20.0-8.0.pre.57) or get them from the `engine_binaries` branch on the flutter-pi repository. Those were built on Flutter 1.17 stable.
Let us know what you think of this promising new technology via the comments section below!