Building Flutter apps with newest Engine & newest Dart

Modify the Flutter tools

Clone https://github.com/flutter/flutter. This repo contains the flutter command line tool used to build Flutter apps. For building web apps it's using the dart compile wasm command from the Dart SDK. We ensure it uses the Dart SDK we built by patching the usages of the dart binary:

<flutter> % git diff
diff --git a/packages/flutter_tools/lib/src/artifacts.dart b/packages/flutter_tools/lib/src/artifacts.dart
index ba3703b86e..e0fb968fab 100644
--- a/packages/flutter_tools/lib/src/artifacts.dart
+++ b/packages/flutter_tools/lib/src/artifacts.dart
@@ -1174,6 +1174,7 @@ class CachedLocalEngineArtifacts implements Artifacts {
   }

   String _getDartSdkPath() {
+    return _dartSdkPath();
     final String builtPath = _fileSystem.path.join(_hostEngineOutPath, 'dart-sdk');
     if (_fileSystem.isDirectorySync(_fileSystem.path.join(builtPath, 'bin'))) {
       return builtPath;
@@ -1404,6 +1405,7 @@ class CachedLocalWebSdkArtifacts implements Artifacts {
   }

   String _getDartSdkPath() {
+    return _dartSdkPath();
     // If we couldn't find a built dart sdk, let's look for a prebuilt one.
     final String prebuiltPath = _fileSystem.path.join(_getFlutterPrebuiltsPath(), _getPrebuiltTarget(), 'dart-sdk');
     if (_fileSystem.isDirectorySync(prebuiltPath)) {
@@ -1522,8 +1524,9 @@ class OverrideArtifacts implements Artifacts {
 }

 /// Locate the Dart SDK.
 String _dartSdkPath(Cache cache) {
-  return cache.getRoot().childDirectory('dart-sdk').path;
+  return '<path-to-dart-sdk-checkout>/out/ReleaseX64/dart-sdk';
 }

 class _TestArtifacts implements Artifacts {

We then ensure the Flutter tool is re-built via

<flutter> % rm bin/cache/flutter_tools.snapshot

=> Next time one runs flutter it will re-build the Flutter command line tool.

Modify the Flutter engine

Building Flutter apps requires not only the dart2wasm compiler but also the platform file. As there may be dependencies (e.g. adding a member in core libraries that the compiler has an intrinsic for) we also need to ensure the core libraries are compiled with the same Dart version (resulting in a correct dart2wasm_platform.dill file that also includes the dart:ui Flutter library).

Build it

Create an engine checkout with:

% mkdir engine
% cd engine
<engine> % fetch flutter

Edit .gclient to add the download_emsdk custom variable:

solutions = [
  {
    "custom_deps": {},
    "deps_file": "DEPS",
    "managed": False,
    "name": "src/flutter",
    "safesync_url": "",
    "url": "https://github.com/flutter/engine.git",
    "custom_vars" : {
      "download_emsdk": True,
    },
  },
]

Sync dependencies and download emsdk:

<src> % gclient sync -D

Then checkout the Dart version we want. If the commit is available in the Dart checkout from <src>/flutter/third_party/dart then one may

<src> % vim flutter/DEPS

<...update Dart revision hash...>

<src> % gclient sync -D

but for local development one may just

<src> % cd flutter/third_party/dart
<src>/flutter/third_party/dart % git checkout ...

Now we have to make some modification to ensure that the build of the platform file doesn't use the downloaded prebuilt SDK but the one in <src>/flutter/third_party/dart, we do that by applying the following patch:

<src>/flutter % git diff
diff --git a/web_sdk/BUILD.gn b/web_sdk/BUILD.gn
index f1383ae321..caa8aac8f1 100644
--- a/web_sdk/BUILD.gn
+++ b/web_sdk/BUILD.gn
@@ -266,17 +266,21 @@ template("_compile_platform") {
       "--source",
       "dart:_web_locale_keymap",
     ]
-    if (flutter_prebuilt_dart_sdk) {
-      args += [
-        "--multi-root",
-        "file:///" + rebase_path("$host_prebuilt_dart_sdk/.."),
-      ]
-    } else {
-      args += [
-        "--multi-root",
-        "file:///" + rebase_path("$root_out_dir"),
-      ]
-    }
+    args += [
+      "--multi-root",
+      "file:///<path-to-your-dart-sdk>/out/ReleaseX64",
+    ]
   }
 }

Then build the release web engine via

<src> % flutter/lib/web_ui/dev/felt build

NOTE: If you modify the Dart sources, the incremental build may not work correctly. You man want to rm -rf <src>/out/wasm_release/flutter_web_sdk or rm -rf <src>/out.

Build the Dart SDK

Build the normal Dart SDK in the same version as used in Flutter engine via tools/build.py -mrelease create_sdk

NOTE: You can (after syncing dependencies with gclient sync -D) make <src>/flutter/third_party/dart a symlink to the normal Dart SDK you work on. That avoids the need to keep the two in sync.

Building a Flutter app (e.g. Wonderous)

<path-to-flutter-app> % flutter                                  \
        --local-engine-src-path=<path-to-flutter-engine-src>     \
        --local-web-sdk=wasm_release                             \
        build web --wasm

=> This will now use the flutter tools with our custom dart compile wasm with a custom dart2wasm_platform.dill file.