This repo is currently about build automation for Tip of the Tree Clang, Binutils, and Flutter Engine artifacts. The useage target is for an embedded system.
See if Embedded Flutter is a compeling alternative to Chromium ContentShell+JS+CSS, and QT.
Areas of interest are memory footprint, stack latency, and where does it fit in the UI Framework landscape.
I can build a ContentShell browser that with the smallest of pages, only has a 15MB system heap footprint. As the HTML5 application complexity increases, the memory usage ballons. We're looking for controlled predictability.
In regards to latency, one test case will be CAN bus signal from an Automotive ODBC-II connector, rendering a gauge.
The default build configuration (provided a properly configured sysroot), will generate bits that execute on a Raspberry Pi.
Planned Work Items
1. Memory Profiling and optimization. With Debug engine running a simple app on the PI, it's allocating around 150MB, with 12 threads.
2. Platform Channel handler. This will allow Dart to call C/C++ code. Think CAN bus, I2C, SPI, RS-232, RS-485, MIDI, Audio, Espresso Machine I/O, etc.
3. Support all 4 machine architectures to build on Linux. Currently only ARM has been tested.
4. Depending on demand and use cases, add support for building on Mac and Windows (although it may already work)...
Planned Targets in no particular order (I can be persuaded with money to support specific targets)
Raspberry Pi - Standalone
DragonBoard 410c - Standalone/Yocto meta layer
Ultra96 - Standalone/Yocto meta layer
SabreLite - Standalone/Yocto meta layer
Intel Target - TBD
-
CMake 3.11 or greater
-
Setup depot_tools and add to path. This provides gclient, ninja, autoninja, etc.
-
Confirm you can build the engine repo standalone
https://github.com/flutter/flutter/wiki/Setting-up-the-Engine-development-environment
https://github.com/flutter/flutter/wiki/Compiling-the-engine
Install build dependencies with this shell script:
install-build-deps.sh
-
Raspberry Pi prior to generating sysroot
sudo apt-get install libx11-dev
git clone https://github.com/jwinarske/flutter_embedded
cd flutter_embedded
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -GNinja
autoninja
Note: Your build folder can be wherever you want...
To use the override variables, pass them in with the cmake command. One example
cmake -DTOOLCHAIN_DIR=~/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64 -DTARGET_SYSROOT=~/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/sysroot -DTARGET_TRIPLE=arm-linux-androideabi-clang -DENGINE_REPO=https://github.com/jwinarske/engine -GNinja -DCMAKE_BUILD_TYPE=Debug
This is the directory of the installed toolchain. The default value used is "${CMAKE_SOURCE_DIR}/sdk/toolchain". When the toolchain is built, it's installed to this directory. If TOOLCHAIN_DIR is not set, it will build the toolchain.
This is the location of the target sysroot. The default value is "${CMAKE_SOURCE_DIR}/sdk/sysroot". One approach would be to download target image such as a Raspberry Pi image, and mount it. Setting TARGET_SYSROOT to the rootfs directory.
This is the triple of your toolchain. The default value used is "arm-linux-gnueabihf"
This is the target architecture of your build. It must match your toolchain, and that which the flutter engine build supports.
This is the repo of the flutter engine. The default value is https://github.com/flutter/engine.git. If you want to use your own fork, set this variable to point to your fork's url.
List of Targets LLVM should be built with. Relavant to Flutter the options are: "AArch64;ARM;X86". Host architecture (x86_64) is implicit, as that is the expected build host. If crosscompiling compiler-rt, libcxxabi, and libcxx the current scheme expects only a single value for LLVM_TARGETS_TO_BUILD.
Checks out and builds compiler-rt for host and target. Default value is ON, and valid only when TOOLCHAIN_DIR is not set.
Checks out and builds libcxxabi for host and target. Default value is ON, and valid only when TOOLCHAIN_DIR is not set.
Checks out and builds libcxx. Default value is ON, and valid only when TOOLCHAIN_DIR is not set.
Checks out and builds lld. Default value is OFF, and valid only when TOOLCHAIN_DIR is not set. This option enables the use of "-fuse-ld=lld".
Unoptimized flag, defaults to OFF
If ENGINE_RUNTIME_MODE is not set to debug, profile, or release, it will default to debug.
Enable Dynamic, defaults to off.
Enable simulator, defaults to OFF
Enable interpreter, defaults to OFF
Enable dart-debug, defaults to OFF
Enable clang, defaults to ON
Enable goma, defaults to OFF
Enable link-time optimization, defaults to ON
Embedder for Target, defaults to ON
Enable Vulcan, defaults to OFF
Example building Android engine. The flutter engine uses it's own NDK copy. So passing in the toolchain file is for project builds (your own executables and libraries).
cmake .. -GNinja -DCMAKE_TOOLCHAIN_FILE=~/Android/Sdk/ndk-bundle/build/cmake/android.toolchain.cmake -DANDROID_ABI=armeabi-v7a -DANDROID_PLATFORM=17
autoninja
cmake .. -GNinja -DCMAKE_TOOLCHAIN_FILE=~/Android/Sdk/ndk-bundle/build/cmake/android.toolchain.cmake -DENGINE_ENABLE_VULCAN=on -DANDROID_ABI=x86_64
autoninja
cmake .. -GNinja -DCMAKE_TOOLCHAIN_FILE=~/Android/Sdk/ndk-bundle/build/cmake/android.toolchain.cmake -DENGINE_ENABLE_VULCAN=off -DANDROID_ABI=armeabi-v7a
autoninja
To generate target binaries for a Raspberry Pi, you need a valid sysroot, prior to building
I dynamically create the target sysroot from this rootfs archive:
https://downloads.raspberrypi.org/raspbian/archive/2018-11-15-21:02/root.tar.xz
The resultant build artifacts are compatible with any 2018-11-15 Raspbian image. If you need a different rootfs version, you will need to update the wget command in flutter_embedded/cmake/rpi.sysroot.cmake.
Download Raspbian Lite image from Raspbian Image Download Page
https://downloads.raspberrypi.org/raspbian_lite_latest
Extract the archive, which will give you a .img file. If on Ubuntu Bionic, double click the img file. It will auto-mount the partitions present. You're interested in the rootfs partition. From terminal or nautilus, copy the /lib, /opt, and /usr directories from the rootfs mount. Copy these to the default sysroot folder
cd /media/$USER/rootfs
cp -r lib {flutter_embedded git clone root}/sdk/sysroot
cp -r opt {flutter_embedded git clone root}/sdk/sysroot
cp -r usr {flutter_embedded git clone root}/sdk/sysroot
The sdk folder will look like this after the toolchain has built properly
./sdk
|-- sysroot
| |-- lib
| |-- opt
| `-- usr
`-- toolchain
|-- arm-linux-gnueabihf
|-- bin
|-- include
|-- lib
|-- libexec
`-- share
Arial.ttf
Check your target using
fc-match Arial
It should return
Arial.ttf: "Arial" "Normal"
If the Arial font is not present, you get this fatal error when attemping to launch Flutter
LOG: /home/joel/git/flutter_embedded/build/rpi_flutter-prefix/src/rpi_flutter/flutter/main.cc:66: Display Size: 800 x 480
flutter: Observatory listening on http://127.0.0.1:34949/
[ERROR:flutter/third_party/txt/src/minikin/FontFamily.cpp(184)] Could not get cmap table size!
sudo apt-get install ttf-mscorefonts-installer
sudo fc-cache
scp -r {build folder}/target/* pi@raspberrypi.local:/home/pi
cd <flutter git root (not this repo)>
git apply <flutter_embedded repo>/cmake/flutter_platform.patch
Note that that Flutter repo does not have TargetPlatform.linux as part of Material design. You have to add it by hand, or override debugDefaultTargetPlatformOverride and set it to a supported one... There are a couple of cases that need a unique implementation for Linux. Vibrate, etc.
Apply this changelist, if not present. https://github.com/flutter/flutter/pull/24932/files
When adding in Linux support to the Dart code, start by adding "case TargetPlatform.linux:" to all switch cases found via
cd {flutter repo}
grep -r "case TargetPlatform.android:"
cd {flutter app project folder}
flutter build bundle
Note: You either need to override debugDefaultTargetPlatformOverride, or "Enable Linux as a Platform in your Flutter Repo"
Tested apps post Flutter Dart "linux" platfrom add
flutter/examples/catalog * Generates rendered text: "Instead run", "flutter run lib/xxx.dart"
flutter/examples/flutter_gallery * key test case for platform
flutter/examples/flutter_view
flutter/examples/hello_world
flutter/examples/layers * Generates rendered text: "Instead run", "flutter run lib/xxx.dart"
flutter/examples/platform_channel *requires MessageCallback impl for 100%
flutter/examples/platform_view * Android view not impl.. no-op btn
flutter/examples/stocks
flutter-desktop-embedding/example/flutter_app
Depending on the app, be preapred for Dart runtime exceptions. Refer to https://github.com/flutter/flutter/issues
scp -r {flutter app root }/build/* pi@raspberrypi.local:/home/pi
Presuming you built your Flutter app, and pushed the build folder to your target, you can run it with this
TSLIB_CONFFILE=/etc/ts.conf TSLIB_PLUGINDIR=/home/pi/lib/ts TSLIB_CALIBFILE=/etc/pointercal LD_LIBRARY_PATH=./lib ./bin/flutter ./build/flutter_assets/
If your touch screen is not auto-detected correctly, specify the /dev/input/event[n] using the environmental variable TSLIB_TSDEVICE
This can be run from a SSH session, or directly on the device. You should see output like this, prior to the app being rendered
LOG: /home/joel/git/flutter_embedded/build/rpi_flutter-prefix/src/rpi_flutter/flutter/main.cc:66: Display Size: 800 x 480
flutter: Observatory listening on http://127.0.0.1:34949/
Note: If you get unknown platform exception, you either need to override debugDefaultTargetPlatformOverride, or "Enable Linux as a Platform in your Flutter Repo"
Verify your touch display is working correctly on your Raspberry Pi using evtest
sudo apt-get install evtest
Running it, you should see something like
$ evtest
No device specified, trying to scan all of /dev/input/event*
Not running as root, no devices may be available.
Available devices:
/dev/input/event0: HID 0c45:7403
/dev/input/event1: HID 0c45:7403
/dev/input/event2: FT5406 memory based driver
Select the device event number [0-2]:
The touch device in this case, is /dev/input/event2. Selecting 2 will enable touch data to print to the console.
sudo LD_LIBRARY_PATH=./lib TSLIB_CONFFILE=/etc/ts.conf TSLIB_PLUGINDIR=/home/pi/lib/ts TSLIB_CALIBFILE=/etc/pointercal ./bin/ts_calibrate
sudo LD_LIBRARY_PATH=./lib TSLIB_CONFFILE=/etc/ts.conf TSLIB_PLUGINDIR=/home/pi/lib/ts TSLIB_CALIBFILE=/etc/pointercal ./bin/ts_test
sudo LD_LIBRARY_PATH=./lib TSLIB_CONFFILE=/etc/ts.conf TSLIB_PLUGINDIR=/home/pi/lib/ts TSLIB_CALIBFILE=/etc/pointercal ./bin/ts_print
I am successfully able to single step the Flutter Embedder using Host Side gdb-multiarch, and latest Eclipse release. Target side requires gdbserver installed. LLDB will be at a later date.
sudo apt-get install gdbserver
Change build flags in this file
{build folder}/engine-prefix/src/engine/src/build/config/compiler/BUILD.gn
To include
if (is_linux) {
if (current_cpu != "x86") {
cflags_cc += [
"-ggdb",
"-ggdb3",
Rebuild Engine
Copy Artifact
scp {absolute build folder}/engine-prefix/src/engine/src/out/linux_debug_arm/so.unstripped/libflutter_engine.so pi@raspberrypi.local:/home/pi/lib
Inside Eclipse - Import C/C++ Executable, and select the Flutter binary.
Configuration - via Debugger Dialog
Main / C/C++ Application: flutter
Main / Connection: Remote Host
Main / Remote Absolute File Path for C/C++ Application: /home/pi/bin/flutter
Main / Commands to execute before application
export LD_LIBRARY_PATH=/home/pi/lib
Main / Skip download to target path [TRUE]
Arguments: /home/pi/build/flutter_assets/
Debugger / Main / GDB Debugger
gdb-multiarch
Debugger / Shared Libraries
{absolute build folder}/engine-prefix/src/engine/src/out/linux_debug_arm/so.unstripped
{absolute sdk folder}/sysroot/lib
{absolute sdk folder}/toolchain/lib
Debugger / Shared Libraries / Load shared library symbols automatically [TRUE]
Set breakpoint at FlutterEngineRun().
Run the debugger, once breakpoint hits, change to the Debugger Console window, and issue
set step-mode on
Step into FlutterEngineRun()
Building is currently supported using a Yocto project SDK
-
Follow steps in repo README to generate target image. This repo is used for the DragonBoard 410c
-
Build SDK
bitbake <image> -c populate_sdk
-
Install SDK. Default install path is /usr/local/rpb-wayland-x86_64
Note: the required .o files are installed in the wrong place. You have to copy or move them to the gcc folder.
Bug Filed: 96boards/oe-rpb-manifest#106
-
Build Flutter stack using SDK for DragonBoard 410c
cd {flutter_embedded git clone root} mkdir build64 && cd build64 cmake .. -DCMAKE_BUILD_TYPE=MinSizeRel -DTARGET_ARCH=arm64 -DTARGET_SYSROOT=/usr/local/rpb-wayland-x86_64/sysroots/aarch64-linaro-linux -DTOOLCHAIN_DIR=/usr/local/rpb-wayland-x86_64/sysroots/x86_64-oesdk-linux/usr -DTARGET_TRIPLE=aarch64-linaro-linux -DBUILD_RPI_FLUTTER=OFF -DBUILD_WAYLAND_FLUTTER=ON -DENGINE_RUNTIME_MODE=release
https://github.com/flutter/flutter/wiki/Compiling-the-engine
https://github.com/flutter/flutter/wiki/Setting-up-the-Engine-development-environment
https://clang.llvm.org/get_started.html
https://libcxx.llvm.org/docs/BuildingLibcxx.html
https://medium.com/@zw3rk/making-a-raspbian-cross-compilation-sdk-830fe56d75ba
https://medium.com/@au42/the-useful-raspberrypi-cross-compile-guide-ea56054de187
https://www.raspberrypi.org/downloads/raspbian/
https://medium.com/flutter-io/flutter-on-raspberry-pi-mostly-from-scratch-2824c5e7dcb1
https://android.googlesource.com/platform/ndk/+/master/docs/BuildSystemMaintainers.md#libc
https://github.com/kergoth/tslib
http://geomodule.com/sw-eng-notes/2017/03/25/raspberry-pi-debugging-with-gdb-command-line/