Reproducible Flutter builds on macOS, iOS, Android, Linux, and Web with Nix.
This is a melos monorepo containing:
| Path | Description |
|---|---|
packages/nix |
Dart CLI package exposing the nix_dart executable |
apps/example |
Reference Flutter app demonstrating the toolkit |
dart pub global activate melos
melos bootstrapThe example app in apps/example/ is the smallest working example. It wraps
the same Makefile.inc that subtree users include in their host app.
cd apps/example
make setup-web
make build-web
make verify-webThe repo also includes a checked-in nix.yaml, so the example app works
through nix_dart as well:
dart run packages/nix/bin/nix_dart.dart doctorThe publishable package lives in packages/nix and exposes nix_dart.
dart pub global activate nix
# In a Flutter project:
nix_dart init linux android web
nix_dart setup
nix_dart shell linux
nix_dart build web
nix_dart pinnix_dart init --from-existing is the migration path for projects that
already have flutter_version.env, android_sdk_version.env, or a vendored
copy of this repo. After editing nix.yaml, run nix_dart sync to refresh
the .env files that the shell scripts consume.
If you want to start CLI-first and later hand a self-contained toolkit to CI or
to another repo, nix_dart eject materializes bootstrap.sh,
Makefile.inc, nix/, scripts/, and the .env files into the output
directory:
nix_dart eject --output-dir tooling/nix
bash tooling/nix/bootstrap.shPackage-specific docs live in packages/nix/README.md.
For new projects, prefer nix_dart init (see Dart CLI above) or
nix_dart eject (see Standalone Script Toolkit below). The subtree approach
is still supported for projects that want a vendored copy of the example
toolkit checked into their repo.
git subtree add --prefix=nix \
--squash https://github.com/ManyMath/nix.git main
bash nix/apps/example/bootstrap.sh
dart pub global activate nix
nix_dart init --from-existingThe host project's Makefile should point NIX_FLUTTER_DIR at the subtree's
example toolkit:
NIX_FLUTTER_DIR ?= nix/apps/example
include $(NIX_FLUTTER_DIR)/Makefile.incMakefile.inc auto-delegates to nix_dart only when both nix_dart and
nix.yaml are present in the host project. Until then it falls back to the
vendored shell scripts.
If you do not want a Dart CLI dependency in the host project, include
Makefile.inc and use the vendored scripts directly through make.
NIX_FLUTTER_DIR ?= nix/apps/example
include $(NIX_FLUTTER_DIR)/Makefile.incThen run:
make nix-bootstrap
make nix-setup-linux
make nix-shell-linux
make nix-build-linuxnix_dart eject is the bridge between the CLI workflow and the vendored
script workflow. It produces the same files that a subtree checkout would
contain, but without requiring git subtree history in the host project.
nix_dart init web
nix_dart setup web
nix_dart eject --output-dir .
./scripts/fetch-flutter-web.sh
PROJECT_ROOT="$PWD" ./scripts/build-web.shPinning happens at four layers:
nix/flake.lockfor Nix system dependencies.flutter_version.envfor the Flutter SDK version and archive checksums.android_sdk_version.envfor Android cmdline-tools, build-tools, and NDK.pubspec.lockfor Dart/Flutter packages.
make pin or nix_dart pin advances the checked-in flake.lock.
- Install Nix with flakes enabled:
experimental-features = nix-command flakes - macOS and iOS builds still require Xcode.
- Android on macOS needs a JDK on
PATHor Android Studio installed. - Android on Linux uses the Nix
androiddev shell to provide JDK 17. - Linux desktop builds rely on the
linuxdev shell innix/flake.nixfor GTK, clang, cmake, ninja, and related libraries.
- Nix packages:
make pinornix_dart pin - Flutter SDK: edit
flutter_version.envornix.yaml, then re-run setup - Android SDK versions: edit
android_sdk_version.envornix.yaml, then re-run setup - Dart packages:
flutter pub upgradeordart pub upgrade
MIT. See LICENSE.