Rant: Flutter install and build utterly entangled

Midjourney prompt: Walking while looking at phone with all attention stumbles into a sign standing in the middle of the sidewalk.

I’ve been looking into creating a phone app using Flutter. Like any good developer, I looked for a reproducible environment, and Docker seemed like a reasonable place to find inspiration.

It proved to be harder than expected.

Disclaimer: I don’t have any experience with Flutter or mobile development, not in the slightest. So that might be where the REAL problem is buried.

I’m usually good at these things. But either I’m falling behind, or the Flutter SDK just doesn’t make it easy (or even possible) to implement in an elegant way.

My vision was:

It was possible to “redirect” the cache for the Dart package system and Gradle. But regardless, Flutter insists on “checking in” on every command, and updating a timestamp, e.g. in engine.stamp. I could provide a third cache via a bind mount for Flutter (flutter/bin/cache/), but an empty cache triggered Flutter to check (and reinstall) things in flutter/packages/flutter_tools/. It started to feel like a dependency circle with no way to tie down a foundation without breaking something else.

I tried to replace upgrade with get in $DART pub get --suppress-analytics to avoid Flutter updating parts of itself (reproducible builds and all that).

I even looked into disabling pub_upgrade_with_retry found in flutter/bin/internal/shared.sh and ignoring the lockfile outside the cache in flutter/packages/flutter_tools/pubspec.lock - yes, I was desperate.

… and I did get flutter test working for a “Hello World” app, but everything started falling apart when building the APK file, and I didn’t dare imagine what else would break once I moved beyond the “Hello World” stage.

On top, Flutter seems to insist on being able to write in the directory with the code. My naive brain had expected that Flutter would only need read access to my code and then produce its build artifact(s) in a directory of my choice.

In short, you can only use Flutter if:

I was disappointed, neither should be required, in my opinion 😮‍💨

I compromised by building gmeligio/flutter-docker-image where the uid and gid for the flutter user were replaced with my uid and gid on the host system in the file android.Dockerfile.

I have traded elegance for pragmatism. Maintaining the Docker image is suddenly a lot easier. I just hope having write access all over will not bite me.

Enjoyed reading this post?

Here are some others that you might like — or scroll down to leave a comment.