about summary refs log tree commit diff
diff options
context:
space:
mode:
authortomberek <tomberek@users.noreply.github.com>2024-06-15 18:53:38 -0400
committerGitHub <noreply@github.com>2024-06-15 18:53:38 -0400
commitf7aae7b083c99e5d7d88d56dfd2e1866662cb4e5 (patch)
tree7e85050fb5ae89c804aeca78b99b2742a44c5438
parenta0ec5ff8e39df27a731bfb7e20d128e9c47025f1 (diff)
parent4a59129384d0d0187c4f20f1a0a62b8da9bf5f43 (diff)
Merge pull request #212328 from ExpidusOS/flutter-engine/init
flutter.engine: init
-rw-r--r--pkgs/build-support/flutter/default.nix26
-rw-r--r--pkgs/development/compilers/flutter/default.nix9
-rw-r--r--pkgs/development/compilers/flutter/engine/constants.nix41
-rw-r--r--pkgs/development/compilers/flutter/engine/default.nix74
-rw-r--r--pkgs/development/compilers/flutter/engine/package.nix311
-rw-r--r--pkgs/development/compilers/flutter/engine/pkg-config.py247
-rw-r--r--pkgs/development/compilers/flutter/engine/source.nix78
-rw-r--r--pkgs/development/compilers/flutter/engine/tools.nix62
-rw-r--r--pkgs/development/compilers/flutter/flutter.nix23
-rw-r--r--pkgs/development/compilers/flutter/update/get-engine-hashes.nix.in23
-rwxr-xr-xpkgs/development/compilers/flutter/update/update.py45
-rw-r--r--pkgs/development/compilers/flutter/versions/3_13/data.json3
-rw-r--r--pkgs/development/compilers/flutter/versions/3_16/data.json3
-rw-r--r--pkgs/development/compilers/flutter/versions/3_19/data.json5
-rw-r--r--pkgs/development/compilers/flutter/versions/3_19/engine/patches/flutter-140969.patch41
-rw-r--r--pkgs/development/compilers/flutter/versions/3_22/data.json4
-rw-r--r--pkgs/development/compilers/flutter/versions/3_23/data.json3
-rw-r--r--pkgs/development/compilers/flutter/wrapper.nix5
-rw-r--r--pkgs/top-level/all-packages.nix4
19 files changed, 991 insertions, 16 deletions
diff --git a/pkgs/build-support/flutter/default.nix b/pkgs/build-support/flutter/default.nix
index dd4341c675dca..ff6c6b31006f7 100644
--- a/pkgs/build-support/flutter/default.nix
+++ b/pkgs/build-support/flutter/default.nix
@@ -14,16 +14,28 @@
 
 # absolutely no mac support for now
 
-{ pubGetScript ? "flutter pub get"
+{ pubGetScript ? null
 , flutterBuildFlags ? [ ]
 , targetFlutterPlatform ? "linux"
 , extraWrapProgramArgs ? ""
+, flutterMode ? null
 , ...
 }@args:
 
 let
+  hasEngine = flutter ? engine && flutter.engine != null && flutter.engine.meta.available;
+  flutterMode = args.flutterMode or (if hasEngine then flutter.engine.runtimeMode else "release");
+
+  flutterFlags = lib.optional hasEngine "--local-engine host_${flutterMode}${lib.optionalString (!flutter.engine.isOptimized) "_unopt"}";
+
+  flutterBuildFlags = [
+    "--${flutterMode}"
+  ] ++ (args.flutterBuildFlags or []) ++ flutterFlags;
+
   builderArgs = rec {
     universal = args // {
+      inherit flutterMode flutterFlags flutterBuildFlags;
+
       sdkSetupScript = ''
         # Pub needs SSL certificates. Dart normally looks in a hardcoded path.
         # https://github.com/dart-lang/sdk/blob/3.1.0/runtime/bin/security_context_linux.cc#L48
@@ -46,11 +58,11 @@ let
         ''}/bin/dart"
 
         export HOME="$NIX_BUILD_TOP"
-        flutter config --no-analytics &>/dev/null # mute first-run
-        flutter config --enable-linux-desktop >/dev/null
+        flutter config $flutterFlags --no-analytics &>/dev/null # mute first-run
+        flutter config $flutterFlags --enable-linux-desktop >/dev/null
       '';
 
-      inherit pubGetScript;
+      pubGetScript = args.pubGetScript or "flutter${lib.optionalString hasEngine " --local-engine $flutterMode"} pub get";
 
       sdkSourceBuilders = {
         # https://github.com/dart-lang/pub/blob/68dc2f547d0a264955c1fa551fa0a0e158046494/lib/src/sdk/flutter.dart#L81
@@ -122,7 +134,7 @@ let
 
         mkdir -p build/flutter_assets/fonts
 
-        flutter build linux -v --release --split-debug-info="$debug" ${builtins.concatStringsSep " " (map (flag: "\"${flag}\"") flutterBuildFlags)}
+        flutter build linux -v --split-debug-info="$debug" $flutterBuildFlags
 
         runHook postBuild
       '';
@@ -131,7 +143,7 @@ let
       installPhase = universal.installPhase or ''
         runHook preInstall
 
-        built=build/linux/*/release/bundle
+        built=build/linux/*/$flutterMode/bundle
 
         mkdir -p $out/bin
         mv $built $out/app
@@ -173,7 +185,7 @@ let
 
         mkdir -p build/flutter_assets/fonts
 
-        flutter build web -v --release ${builtins.concatStringsSep " " (map (flag: "\"${flag}\"") flutterBuildFlags)}
+        flutter build web -v $flutterBuildFlags
 
         runHook postBuild
       '';
diff --git a/pkgs/development/compilers/flutter/default.nix b/pkgs/development/compilers/flutter/default.nix
index fd18f9500288b..3f2bb2e5cec83 100644
--- a/pkgs/development/compilers/flutter/default.nix
+++ b/pkgs/development/compilers/flutter/default.nix
@@ -1,4 +1,4 @@
-{ callPackage, fetchzip, fetchFromGitHub, dart, lib, stdenv }:
+{ useNixpkgsEngine ? false, callPackage, fetchzip, fetchFromGitHub, dart, lib, stdenv }@args:
 let
   mkCustomFlutter = args: callPackage ./flutter.nix args;
   wrapFlutter = flutter: callPackage ./wrapper.nix { inherit flutter; };
@@ -8,6 +8,8 @@ let
   mkFlutter =
     { version
     , engineVersion
+    , engineHashes
+    , enginePatches
     , dartVersion
     , flutterHash
     , dartHash
@@ -15,10 +17,10 @@ let
     , pubspecLock
     , artifactHashes
     , channel
-    }:
+    }@fargs:
     let
       args = {
-        inherit version engineVersion patches pubspecLock artifactHashes channel;
+        inherit version engineVersion engineHashes enginePatches patches pubspecLock artifactHashes useNixpkgsEngine channel;
 
         dart = dart.override {
           version = dartVersion;
@@ -64,6 +66,7 @@ let
       in
       lib.nameValuePair "v${version}" (wrapFlutter (mkFlutter ({
         patches = (getPatches ./patches) ++ (getPatches (versionDir + "/patches"));
+        enginePatches = (getPatches ./engine/patches) ++ (getPatches (versionDir + "/engine/patches"));
       } // data))))
     (builtins.readDir ./versions);
 
diff --git a/pkgs/development/compilers/flutter/engine/constants.nix b/pkgs/development/compilers/flutter/engine/constants.nix
new file mode 100644
index 0000000000000..9b7907fc337f7
--- /dev/null
+++ b/pkgs/development/compilers/flutter/engine/constants.nix
@@ -0,0 +1,41 @@
+{ lib, targetPlatform }:
+rec {
+  os =
+    if targetPlatform.isLinux then
+      "linux"
+    else if targetPlatform.isDarwin then
+      "macos"
+    else if targetPlatform.isWindows then
+      "windows"
+    else
+      throw "Unsupported OS \"${targetPlatform.parsed.kernel.name}\"";
+
+  arch =
+    if targetPlatform.isx86_64 then
+      "amd64"
+    else if targetPlatform.isx86 && targetPlatform.is32bit then
+      "386"
+    else if targetPlatform.isAarch64 then
+      "arm64"
+    else if targetPlatform.isMips && targetPlatform.parsed.cpu.significantByte == "littleEndian" then
+      "mipsle"
+    else if targetPlatform.isMips64 then
+      "mips64${lib.optionalString (targetPlatform.parsed.cpu.significantByte == "littleEndian") "le"}"
+    else if targetPlatform.isPower64 then
+      "ppc64${lib.optionalString (targetPlatform.parsed.cpu.significantByte == "littleEndian") "le"}"
+    else if targetPlatform.isS390x then
+      "s390x"
+    else
+      throw "Unsupported CPU \"${targetPlatform.parsed.cpu.name}\"";
+
+  alt-arch =
+    if targetPlatform.isx86_64 then
+      "x64"
+    else if targetPlatform.isAarch64 then
+      "arm64"
+    else
+      targetPlatform.parsed.cpu.name;
+
+  platform = "${os}-${arch}";
+  alt-platform = "${os}-${alt-arch}";
+}
diff --git a/pkgs/development/compilers/flutter/engine/default.nix b/pkgs/development/compilers/flutter/engine/default.nix
new file mode 100644
index 0000000000000..cea41933e4343
--- /dev/null
+++ b/pkgs/development/compilers/flutter/engine/default.nix
@@ -0,0 +1,74 @@
+{
+  callPackage,
+  dartSdkVersion,
+  flutterVersion,
+  version,
+  hashes,
+  url,
+  patches,
+  runtimeModes,
+  isOptimized ? true,
+  lib,
+  stdenv,
+}:
+let
+  mainRuntimeMode = builtins.elemAt runtimeModes 0;
+  altRuntimeMode = builtins.elemAt runtimeModes 1;
+
+  runtimeModesBuilds = lib.genAttrs runtimeModes (
+    runtimeMode:
+    callPackage ./package.nix {
+      inherit
+        dartSdkVersion
+        flutterVersion
+        version
+        hashes
+        url
+        patches
+        runtimeMode
+        isOptimized
+        ;
+    }
+  );
+in
+stdenv.mkDerivation (
+  {
+    pname = "flutter-engine";
+    inherit url runtimeModes;
+    inherit (runtimeModesBuilds.${mainRuntimeMode})
+      meta
+      src
+      version
+      dartSdkVersion
+      isOptimized
+      runtimeMode
+      ;
+    inherit altRuntimeMode;
+
+    dontUnpack = true;
+    dontBuild = true;
+
+    installPhase =
+      ''
+        mkdir -p $out/out
+
+        for dir in $(find $src/src -mindepth 1 -maxdepth 1); do
+          ln -sf $dir $out/$(basename $dir)
+        done
+
+      ''
+      + lib.concatMapStrings (
+        runtimeMode:
+        let
+          runtimeModeBuild = runtimeModesBuilds.${runtimeMode};
+          runtimeModeOut = "host_${runtimeMode}${
+            lib.optionalString (!runtimeModeBuild.isOptimized) "_unopt"
+          }";
+        in
+        ''
+          ln -sf ${runtimeModeBuild}/out/${runtimeModeOut} $out/out/${runtimeModeOut}
+        ''
+      ) runtimeModes;
+  }
+  // runtimeModesBuilds
+)
diff --git a/pkgs/development/compilers/flutter/engine/package.nix b/pkgs/development/compilers/flutter/engine/package.nix
new file mode 100644
index 0000000000000..6f87b28f19098
--- /dev/null
+++ b/pkgs/development/compilers/flutter/engine/package.nix
@@ -0,0 +1,311 @@
+{
+  lib,
+  callPackage,
+  writeText,
+  symlinkJoin,
+  targetPlatform,
+  hostPlatform,
+  darwin,
+  clang,
+  llvm,
+  tools ? callPackage ./tools.nix { inherit hostPlatform; },
+  stdenv,
+  stdenvNoCC,
+  runCommand,
+  patchelf,
+  xorg,
+  libglvnd,
+  libepoxy,
+  wayland,
+  freetype,
+  pango,
+  glib,
+  harfbuzz,
+  cairo,
+  gdk-pixbuf,
+  at-spi2-atk,
+  zlib,
+  gtk3,
+  pkg-config,
+  ninja,
+  python3,
+  git,
+  version,
+  flutterVersion,
+  dartSdkVersion,
+  hashes,
+  patches,
+  url,
+  runtimeMode ? "release",
+  isOptimized ? true,
+}:
+with lib;
+let
+  expandSingleDep =
+    dep: lib.optionals (lib.isDerivation dep) ([ dep ] ++ map (output: dep.${output}) dep.outputs);
+
+  expandDeps = deps: flatten (map expandSingleDep deps);
+
+  constants = callPackage ./constants.nix { inherit targetPlatform; };
+
+  src = callPackage ./source.nix {
+    inherit
+      tools
+      version
+      hashes
+      url
+      ;
+  };
+in
+stdenv.mkDerivation {
+  pname = "flutter-engine-${runtimeMode}${lib.optionalString (!isOptimized) "-unopt"}";
+  inherit
+    version
+    runtimeMode
+    patches
+    isOptimized
+    dartSdkVersion
+    src;
+
+  toolchain = symlinkJoin {
+    name = "flutter-engine-toolchain-${version}";
+
+    paths =
+      expandDeps (
+        optionals (stdenv.isLinux) [
+          gtk3
+          wayland
+          libepoxy
+          libglvnd
+          freetype
+          at-spi2-atk
+          glib
+          gdk-pixbuf
+          harfbuzz
+          pango
+          cairo
+          xorg.libxcb
+          xorg.libX11
+          xorg.libXcursor
+          xorg.libXrandr
+          xorg.libXrender
+          xorg.libXinerama
+          xorg.libXi
+          xorg.libXext
+          xorg.libXfixes
+          xorg.libXxf86vm
+          xorg.xorgproto
+          zlib
+        ]
+        ++ optionals (stdenv.isDarwin) [
+          clang
+          llvm
+        ]
+      )
+      ++ [
+        stdenv.cc.libc_dev
+        stdenv.cc.libc_lib
+      ];
+
+    postBuild = ''
+      ln -s /nix $out/nix
+    '';
+  };
+
+  nativeBuildInputs =
+    [
+      python3
+      (tools.vpython python3)
+      git
+      pkg-config
+      ninja
+    ]
+    ++ lib.optionals (stdenv.isLinux) [ patchelf ]
+    ++ optionals (stdenv.isDarwin) [
+      darwin.system_cmds
+      darwin.xcode
+      tools.xcode-select
+    ]
+    ++ lib.optionals (stdenv.cc.libc ? bin) [ stdenv.cc.libc.bin ];
+
+  buildInputs = [ gtk3 ];
+
+  patchtools =
+    let
+      buildtoolsPath =
+        if lib.versionAtLeast flutterVersion "3.21" then "flutter/buildtools" else "buildtools";
+    in
+    [
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/clang-apply-replacements"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/clang-doc"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/clang-format"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/clang-include-fixer"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/clang-refactor"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/clang-scan-deps"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/clang-tidy"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/clangd"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/dsymutil"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/find-all-symbols"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/lld"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-ar"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-bolt"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-cov"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-cxxfilt"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-debuginfod-find"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-dwarfdump"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-dwp"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-gsymutil"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-ifs"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-libtool-darwin"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-lipo"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-ml"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-mt"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-nm"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-objcopy"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-objdump"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-pdbutil"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-profdata"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-rc"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-readobj"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-size"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-symbolizer"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-undname"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm-xray"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/llvm"
+      "${buildtoolsPath}/${constants.alt-platform}/clang/bin/sancov"
+      "flutter/prebuilts/${constants.alt-platform}/dart-sdk/bin/dartaotruntime"
+      "flutter/prebuilts/${constants.alt-platform}/dart-sdk/bin/dart"
+      "flutter/third_party/gn/gn"
+      "third_party/dart/tools/sdks/dart-sdk/bin/dart"
+    ];
+
+  dontPatch = true;
+
+  patchgit = [
+    "third_party/dart"
+    "flutter"
+    "."
+  ] ++ lib.optional (lib.versionAtLeast flutterVersion "3.21") "flutter/third_party/skia";
+
+  postUnpack = ''
+    pushd ${src.name}
+    ${lib.optionalString (stdenv.isLinux) ''
+      for patchtool in ''${patchtools[@]}; do
+        patchelf src/$patchtool --set-interpreter $(cat $NIX_CC/nix-support/dynamic-linker)
+      done
+    ''}
+
+    for dir in ''${patchgit[@]}; do
+      pushd src/$dir
+      rev=$(cat .git/HEAD)
+      rm -rf .git
+      git init
+      git add .
+      git config user.name "nobody"
+      git config user.email "nobody@local.host"
+      git commit -a -m "$rev"
+      popd
+    done
+
+    src/flutter/prebuilts/${constants.alt-platform}/dart-sdk/bin/dart src/third_party/dart/tools/generate_package_config.dart
+    cp ${./pkg-config.py} src/build/config/linux/pkg-config.py
+    echo "${dartSdkVersion}" >src/third_party/dart/sdk/version
+
+    rm -rf src/third_party/angle/.git
+    python3 src/flutter/tools/pub_get_offline.py
+
+    pushd src/flutter
+
+    for p in ''${patches[@]}; do
+      patch -p1 -i $p
+    done
+
+    popd
+    popd
+  '';
+
+  configureFlags =
+    [
+      "--no-prebuilt-dart-sdk"
+      "--embedder-for-target"
+      "--no-goma"
+    ]
+    ++ optionals (targetPlatform.isx86_64 == false) [
+      "--linux"
+      "--linux-cpu ${constants.alt-arch}"
+    ];
+
+  # NOTE: Once https://github.com/flutter/flutter/issues/127606 is fixed, use "--no-prebuilt-dart-sdk"
+  configurePhase =
+    ''
+      runHook preConfigure
+
+      export PYTHONPATH=$src/src/build
+    ''
+    + lib.optionalString stdenv.isDarwin ''
+      export PATH=${darwin.xcode}/Contents/Developer/usr/bin/:$PATH
+    ''
+    + ''
+      python3 ./src/flutter/tools/gn $configureFlags \
+        --runtime-mode $runtimeMode \
+        --out-dir $out \
+        --target-sysroot $toolchain \
+        --target-dir host_$runtimeMode${lib.optionalString (!isOptimized) "_unopt --unoptimized"} \
+        --verbose
+
+      runHook postConfigure
+    '';
+
+  buildPhase = ''
+    runHook preBuild
+
+    export TERM=dumb
+    for tool in flatc scenec gen_snapshot dart impellerc shader_archiver gen_snapshot_product; do
+      ninja -C $out/out/host_$runtimeMode${
+        lib.optionalString (!isOptimized) "_unopt"
+      } -j$NIX_BUILD_CORES $tool
+      ${lib.optionalString (stdenv.isLinux) ''
+        patchelf $out/out/host_$runtimeMode${
+          lib.optionalString (!isOptimized) "_unopt"
+        }/$tool --set-interpreter $(cat $NIX_CC/nix-support/dynamic-linker)
+      ''}
+    done
+
+    ninja -C $out/out/host_$runtimeMode${lib.optionalString (!isOptimized) "_unopt"} -j$NIX_BUILD_CORES
+
+    ${lib.optionalString (stdenv.isLinux) ''
+      patchelf $out/out/host_$runtimeMode${
+        lib.optionalString (!isOptimized) "_unopt"
+      }/dart-sdk/bin/dartaotruntime \
+        --set-interpreter $(cat $NIX_CC/nix-support/dynamic-linker)
+    ''}
+
+    runHook postBuild
+  '';
+
+  # Link sources so we can set $FLUTTER_ENGINE to this derivation
+  installPhase = ''
+    runHook preInstall
+
+    for dir in $(find $src/src -mindepth 1 -maxdepth 1); do
+      ln -sf $dir $out/$(basename $dir)
+    done
+
+    runHook postInstall
+  '';
+
+  meta = {
+    # Very broken on Darwin
+    broken = stdenv.isDarwin;
+    description = "The Flutter engine";
+    homepage = "https://flutter.dev";
+    maintainers = with maintainers; [ RossComputerGuy ];
+    license = licenses.bsd3;
+    platforms = [
+      "x86_64-linux"
+      "aarch64-linux"
+      "x86_64-darwin"
+      "aarch64-darwin"
+    ];
+  };
+}
diff --git a/pkgs/development/compilers/flutter/engine/pkg-config.py b/pkgs/development/compilers/flutter/engine/pkg-config.py
new file mode 100644
index 0000000000000..1df08211e570d
--- /dev/null
+++ b/pkgs/development/compilers/flutter/engine/pkg-config.py
@@ -0,0 +1,247 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+
+import json
+import os
+import subprocess
+import sys
+import re
+from optparse import OptionParser
+
+# This script runs pkg-config, optionally filtering out some results, and
+# returns the result.
+#
+# The result will be [ <includes>, <cflags>, <libs>, <lib_dirs>, <ldflags> ]
+# where each member is itself a list of strings.
+#
+# You can filter out matches using "-v <regexp>" where all results from
+# pkgconfig matching the given regular expression will be ignored. You can
+# specify more than one regular expression my specifying "-v" more than once.
+#
+# You can specify a sysroot using "-s <sysroot>" where sysroot is the absolute
+# system path to the sysroot used for compiling. This script will attempt to
+# generate correct paths for the sysroot.
+#
+# When using a sysroot, you must also specify the architecture via
+# "-a <arch>" where arch is either "x86" or "x64".
+#
+# CrOS systemroots place pkgconfig files at <systemroot>/usr/share/pkgconfig
+# and one of <systemroot>/usr/lib/pkgconfig or <systemroot>/usr/lib64/pkgconfig
+# depending on whether the systemroot is for a 32 or 64 bit architecture. They
+# specify the 'lib' or 'lib64' of the pkgconfig path by defining the
+# 'system_libdir' variable in the args.gn file. pkg_config.gni communicates this
+# variable to this script with the "--system_libdir <system_libdir>" flag. If no
+# flag is provided, then pkgconfig files are assumed to come from
+# <systemroot>/usr/lib/pkgconfig.
+#
+# Additionally, you can specify the option --atleast-version. This will skip
+# the normal outputting of a dictionary and instead print true or false,
+# depending on the return value of pkg-config for the given package.
+
+
+def SetConfigPath(options):
+  """Set the PKG_CONFIG_LIBDIR environment variable.
+
+  This takes into account any sysroot and architecture specification from the
+  options on the given command line.
+  """
+
+  sysroot = options.sysroot
+  assert sysroot
+
+  # Compute the library path name based on the architecture.
+  arch = options.arch
+  if sysroot and not arch:
+    print("You must specify an architecture via -a if using a sysroot.")
+    sys.exit(1)
+
+  libdir = sysroot + '/' + options.system_libdir + '/pkgconfig'
+  libdir += ':' + sysroot + '/share/pkgconfig'
+  os.environ['PKG_CONFIG_LIBDIR'] = libdir
+  return libdir
+
+
+def GetPkgConfigPrefixToStrip(options, args):
+  """Returns the prefix from pkg-config where packages are installed.
+
+  This returned prefix is the one that should be stripped from the beginning of
+  directory names to take into account sysroots.
+  """
+  # Some sysroots, like the Chromium OS ones, may generate paths that are not
+  # relative to the sysroot. For example,
+  # /path/to/chroot/build/x86-generic/usr/lib/pkgconfig/pkg.pc may have all
+  # paths relative to /path/to/chroot (i.e. prefix=/build/x86-generic/usr)
+  # instead of relative to /path/to/chroot/build/x86-generic (i.e prefix=/usr).
+  # To support this correctly, it's necessary to extract the prefix to strip
+  # from pkg-config's |prefix| variable.
+  prefix = subprocess.check_output([options.pkg_config,
+      "--variable=prefix"] + args, env=os.environ).decode('utf-8')
+  return prefix
+
+
+def MatchesAnyRegexp(flag, list_of_regexps):
+  """Returns true if the first argument matches any regular expression in the
+  given list."""
+  for regexp in list_of_regexps:
+    if regexp.search(flag) != None:
+      return True
+  return False
+
+
+def RewritePath(path, strip_prefix, sysroot):
+  """Rewrites a path by stripping the prefix and prepending the sysroot."""
+  if os.path.isabs(path) and not path.startswith(sysroot):
+    if path.startswith(strip_prefix):
+      path = path[len(strip_prefix):]
+    path = path.lstrip('/')
+    return os.path.join(sysroot, path)
+  else:
+    return path
+
+
+def main():
+  # If this is run on non-Linux platforms, just return nothing and indicate
+  # success. This allows us to "kind of emulate" a Linux build from other
+  # platforms.
+  if "linux" not in sys.platform:
+    print("[[],[],[],[],[]]")
+    return 0
+
+  parser = OptionParser()
+  parser.add_option('-d', '--debug', action='store_true')
+  parser.add_option('-p', action='store', dest='pkg_config', type='string',
+                    default='pkg-config')
+  parser.add_option('-v', action='append', dest='strip_out', type='string')
+  parser.add_option('-s', action='store', dest='sysroot', type='string')
+  parser.add_option('-a', action='store', dest='arch', type='string')
+  parser.add_option('--system_libdir', action='store', dest='system_libdir',
+                    type='string', default='lib')
+  parser.add_option('--atleast-version', action='store',
+                    dest='atleast_version', type='string')
+  parser.add_option('--libdir', action='store_true', dest='libdir')
+  parser.add_option('--dridriverdir', action='store_true', dest='dridriverdir')
+  parser.add_option('--version-as-components', action='store_true',
+                    dest='version_as_components')
+  (options, args) = parser.parse_args()
+
+  # Make a list of regular expressions to strip out.
+  strip_out = []
+  if options.strip_out != None:
+    for regexp in options.strip_out:
+      strip_out.append(re.compile(regexp))
+
+  if options.sysroot:
+    libdir = SetConfigPath(options)
+    if options.debug:
+      sys.stderr.write('PKG_CONFIG_LIBDIR=%s\n' % libdir)
+    prefix = GetPkgConfigPrefixToStrip(options, args)
+  else:
+    prefix = ''
+
+  if options.atleast_version:
+    # When asking for the return value, just run pkg-config and print the return
+    # value, no need to do other work.
+    if not subprocess.call([options.pkg_config,
+                            "--atleast-version=" + options.atleast_version] +
+                            args):
+      print("true")
+    else:
+      print("false")
+    return 0
+
+  if options.version_as_components:
+    cmd = [options.pkg_config, "--modversion"] + args
+    try:
+      version_string = subprocess.check_output(cmd).decode('utf-8')
+    except:
+      sys.stderr.write('Error from pkg-config.\n')
+      return 1
+    print(json.dumps(list(map(int, version_string.strip().split(".")))))
+    return 0
+
+
+  if options.libdir:
+    cmd = [options.pkg_config, "--variable=libdir"] + args
+    if options.debug:
+      sys.stderr.write('Running: %s\n' % cmd)
+    try:
+      libdir = subprocess.check_output(cmd).decode('utf-8')
+    except:
+      print("Error from pkg-config.")
+      return 1
+    sys.stdout.write(libdir.strip())
+    return 0
+
+  if options.dridriverdir:
+    cmd = [options.pkg_config, "--variable=dridriverdir"] + args
+    if options.debug:
+      sys.stderr.write('Running: %s\n' % cmd)
+    try:
+      dridriverdir = subprocess.check_output(cmd).decode('utf-8')
+    except:
+      print("Error from pkg-config.")
+      return 1
+    sys.stdout.write(dridriverdir.strip())
+    return
+
+  cmd = [options.pkg_config, "--cflags", "--libs"] + args
+  if options.debug:
+    sys.stderr.write('Running: %s\n' % ' '.join(cmd))
+
+  try:
+    flag_string = subprocess.check_output(cmd).decode('utf-8')
+  except:
+    sys.stderr.write('Could not run pkg-config.\n')
+    return 1
+
+  # For now just split on spaces to get the args out. This will break if
+  # pkgconfig returns quoted things with spaces in them, but that doesn't seem
+  # to happen in practice.
+  all_flags = flag_string.strip().split(' ')
+
+
+  sysroot = options.sysroot
+  if not sysroot:
+    sysroot = ''
+
+  includes = []
+  cflags = []
+  libs = []
+  lib_dirs = []
+
+  for flag in all_flags[:]:
+    if len(flag) == 0 or MatchesAnyRegexp(flag, strip_out):
+      continue;
+
+    if flag[:2] == '-l':
+      libs.append(RewritePath(flag[2:], prefix, sysroot))
+    elif flag[:2] == '-L':
+      lib_dirs.append(RewritePath(flag[2:], prefix, sysroot))
+    elif flag[:2] == '-I':
+      includes.append(RewritePath(flag[2:], prefix, sysroot))
+    elif flag[:3] == '-Wl':
+      # Don't allow libraries to control ld flags.  These should be specified
+      # only in build files.
+      pass
+    elif flag == '-pthread':
+      # Many libs specify "-pthread" which we don't need since we always include
+      # this anyway. Removing it here prevents a bunch of duplicate inclusions
+      # on the command line.
+      pass
+    else:
+      cflags.append(flag)
+
+  # Output a GN array, the first one is the cflags, the second are the libs. The
+  # JSON formatter prints GN compatible lists when everything is a list of
+  # strings.
+  print(json.dumps([includes, cflags, libs, lib_dirs]))
+  return 0
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/pkgs/development/compilers/flutter/engine/source.nix b/pkgs/development/compilers/flutter/engine/source.nix
new file mode 100644
index 0000000000000..056cb47b5d5d1
--- /dev/null
+++ b/pkgs/development/compilers/flutter/engine/source.nix
@@ -0,0 +1,78 @@
+{
+  callPackage,
+  hostPlatform,
+  targetPlatform,
+  tools ? callPackage ./tools.nix { inherit hostPlatform; },
+  curl,
+  pkg-config,
+  git,
+  python3,
+  runCommand,
+  writeText,
+  cacert,
+  version,
+  hashes,
+  url,
+}:
+let
+  constants = callPackage ./constants.nix { inherit targetPlatform; };
+in
+runCommand "flutter-engine-source-${version}-${targetPlatform.system}"
+  {
+    pname = "flutter-engine-source";
+    inherit version;
+
+    inherit (tools) depot_tools;
+
+    nativeBuildInputs = [
+      curl
+      pkg-config
+      git
+      tools.cipd
+      (python3.withPackages (
+        ps: with ps; [
+          httplib2
+          six
+        ]
+      ))
+    ];
+
+    gclient = writeText "flutter-engine-${version}.gclient" ''
+      solutions = [{
+        "managed": False,
+        "name": "src/flutter",
+        "url": "${url}",
+      }]
+    '';
+
+    NIX_SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt";
+    GIT_SSL_CAINFO = "${cacert}/etc/ssl/certs/ca-bundle.crt";
+    SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt";
+    DEPOT_TOOLS_UPDATE = "0";
+    DEPOT_TOOLS_COLLECT_METRICS = "0";
+    PYTHONDONTWRITEBYTECODE = "1";
+
+    outputHashAlgo = "sha256";
+    outputHashMode = "recursive";
+    outputHash = hashes.${targetPlatform.system} or (throw "Hash not set for ${targetPlatform.system}");
+  }
+  ''
+    source ${../../../../build-support/fetchgit/deterministic-git}
+    export -f clean_git
+    export -f make_deterministic_repo
+
+    mkdir -p $out
+    cp $gclient $out/.gclient
+    cd $out
+
+    export PATH=$PATH:$depot_tools
+    python3 $depot_tools/gclient.py sync --no-history --shallow --nohooks
+    find $out -name '.git' -exec dirname {} \; | xargs bash -c 'make_deterministic_repo $@' _
+    find $out -path '*/.git/*' ! -name 'HEAD' -prune -exec rm -rf {} \;
+    find $out -name '.git' -exec mkdir {}/logs \;
+    find $out -name '.git' -exec cp {}/HEAD {}/logs/HEAD \;
+
+    python3 src/build/linux/sysroot_scripts/install-sysroot.py --arch=${constants.arch}
+
+    rm -rf $out/.cipd $out/.gclient $out/.gclient_entries $out/.gclient_previous_custom_vars $out/.gclient_previous_sync_commits
+  ''
diff --git a/pkgs/development/compilers/flutter/engine/tools.nix b/pkgs/development/compilers/flutter/engine/tools.nix
new file mode 100644
index 0000000000000..a35398058181b
--- /dev/null
+++ b/pkgs/development/compilers/flutter/engine/tools.nix
@@ -0,0 +1,62 @@
+{
+  callPackage,
+  fetchgit,
+  fetchurl,
+  writeText,
+  runCommand,
+  hostPlatform,
+  darwin,
+  writeShellScriptBin,
+  depot_toolsCommit ? "7d95eb2eb054447592585c73a8ff7adad97ecba1",
+  depot_toolsHash ? "sha256-F7KDuVg11qLKkohIjuXpNdxpnSsT6Z3hE9+wFIG2sSk=",
+  cipdCommit ? "89ada246fcbf10f330011e4991d017332af2365b",
+  cipdHashes ? {
+    "linux-386" = "7f264198598af2ef9d8878349d33c1940f1f3739e46d986962c352ec4cce2690";
+    "linux-amd64" = "2ada6b46ad1cd1350522c5c05899d273f5c894c7665e30104e7f57084a5aeeb9";
+    "linux-arm64" = "96eca7e49f6732c50122b94b793c3a5e62ed77bce1686787a8334906791b4168";
+    "linux-armv6l" = "06394601130652c5e1b055a7e4605c21fc7c6643af0b3b3cac8d2691491afa81";
+    "linux-mips64" = "f3eda6542b381b7aa8f582698498b0e197972c894590ec35f18faa467c868f5c";
+    "linux-mips64le" = "74229ada8e2afd9c8e7c58991126869b2880547780d4a197a27c1dfa96851622";
+    "linux-mipsle" = "2f3c18ec0ad48cd44a9ff39bb60e9afded83ca43fb9c7a5ea9949f6fdd4e1394";
+    "linux-ppc64" = "79425c0795fb8ba12b39a8856bf7ccb853e85def4317aa6413222f307d4c2dbd";
+    "linux-ppc64le" = "f9b3d85dde70f1b78cd7a41d2477834c15ac713a59317490a4cdac9f8f092325";
+    "linux-riscv64" = "bd695164563a66e8d3799e8835f90a398fbae9a4eec24e876c92d5f213943482";
+    "linux-s390x" = "6f501af80541e733fda23b4208a21ea05919c95d236036a2121e6b6334a2792c";
+    "macos-amd64" = "41d05580c0014912d6c32619c720646fd136e4557c9c7d7571ecc8c0462733a1";
+    "macos-arm64" = "dc672bd16d9faf277dd562f1dc00644b10c03c5d838d3cc3d3ea29925d76d931";
+    "windows-386" = "fa6ed0022a38ffc51ff8a927e3947fe7e59a64b2019dcddca9d3afacf7630444";
+    "windows-amd64" = "b5423e4b4429837f7fe4d571ce99c068aa0ccb37ddbebc1978a423fd2b0086df";
+  },
+}:
+let
+  constants = callPackage ./constants.nix { targetPlatform = hostPlatform; };
+in
+{
+  depot_tools = fetchgit {
+    url = "https://chromium.googlesource.com/chromium/tools/depot_tools.git";
+    rev = depot_toolsCommit;
+    hash = depot_toolsHash;
+  };
+
+  cipd =
+    runCommand "cipd-${cipdCommit}"
+      {
+        unwrapped = fetchurl {
+          name = "cipd-${cipdCommit}-unwrapped";
+          url = "https://chrome-infra-packages.appspot.com/client?platform=${constants.platform}&version=git_revision:${cipdCommit}";
+          sha256 = cipdHashes.${constants.platform};
+        };
+      }
+      ''
+        mkdir -p $out/bin
+        install -m755 $unwrapped $out/bin/cipd
+      '';
+
+  vpython =
+    pythonPkg:
+    runCommand "vpython3" { } "mkdir -p $out/bin && ln -s ${pythonPkg}/bin/python $out/bin/vpython3";
+
+  xcode-select = writeShellScriptBin "xcode-select" ''
+    echo ${darwin.xcode}/Contents/Developer
+  '';
+}
diff --git a/pkgs/development/compilers/flutter/flutter.nix b/pkgs/development/compilers/flutter/flutter.nix
index 2db287a45a901..757766d031524 100644
--- a/pkgs/development/compilers/flutter/flutter.nix
+++ b/pkgs/development/compilers/flutter/flutter.nix
@@ -1,5 +1,10 @@
-{ version
+{ useNixpkgsEngine ? false
+, version
 , engineVersion
+, engineHashes ? {}
+, engineUrl ? "https://github.com/flutter/engine.git@${engineVersion}"
+, enginePatches ? []
+, engineRuntimeModes ? [ "release" "debug" ]
 , patches
 , channel
 , dart
@@ -21,9 +26,20 @@
     inherit pubspecLock;
     systemPlatform = stdenv.hostPlatform.system;
   }
-}:
+}@args:
 
 let
+  engine = if args.useNixpkgsEngine or false then
+    callPackage ./engine/default.nix {
+      dartSdkVersion = dart.version;
+      flutterVersion = version;
+      version = engineVersion;
+      hashes = engineHashes;
+      url = engineUrl;
+      patches = enginePatches;
+      runtimeModes = engineRuntimeModes;
+    } else null;
+
   unwrapped =
     stdenv.mkDerivation {
       name = "flutter-${version}-unwrapped";
@@ -125,12 +141,15 @@ let
       '';
 
       passthru = {
+        # TODO: rely on engine.version instead of engineVersion
         inherit dart engineVersion artifactHashes channel;
         tools = flutterTools;
         # The derivation containing the original Flutter SDK files.
         # When other derivations wrap this one, any unmodified files
         # found here should be included as-is, for tooling compatibility.
         sdk = unwrapped;
+      } // lib.optionalAttrs (engine != null && engine.meta.available) {
+        inherit engine;
       };
 
       meta = with lib; {
diff --git a/pkgs/development/compilers/flutter/update/get-engine-hashes.nix.in b/pkgs/development/compilers/flutter/update/get-engine-hashes.nix.in
new file mode 100644
index 0000000000000..f61b9b14fd07a
--- /dev/null
+++ b/pkgs/development/compilers/flutter/update/get-engine-hashes.nix.in
@@ -0,0 +1,23 @@
+{ callPackage, symlinkJoin, lib }:
+let
+  nixpkgsRoot = "@nixpkgs_root@";
+  engineVersion = "@engine_version@";
+
+  systemPlatforms = [
+    "x86_64-linux"
+    "aarch64-linux"
+  ];
+
+  derivations = builtins.map
+    (systemPlatform: callPackage "${nixpkgsRoot}/pkgs/development/compilers/flutter/engine/source.nix" {
+      targetPlatform = lib.systems.elaborate systemPlatform;
+      version = engineVersion;
+      url = "https://github.com/flutter/engine.git@${engineVersion}";
+      hashes."${systemPlatform}" = lib.fakeSha256;
+    })
+    systemPlatforms;
+in
+symlinkJoin {
+  name = "evaluate-derivations";
+  paths = derivations;
+}
diff --git a/pkgs/development/compilers/flutter/update/update.py b/pkgs/development/compilers/flutter/update/update.py
index 1e6fbe1354565..a782b46514a92 100755
--- a/pkgs/development/compilers/flutter/update/update.py
+++ b/pkgs/development/compilers/flutter/update/update.py
@@ -85,6 +85,32 @@ def nix_build_to_fail(code):
     return stderr
 
 
+def get_engine_hashes(engine_version):
+    code = load_code("get-engine-hashes.nix",
+                     nixpkgs_root=NIXPKGS_ROOT,
+                     engine_version=engine_version)
+
+    stderr = nix_build_to_fail(code)
+
+    pattern = re.compile(
+        r"/nix/store/.*-flutter-engine-source-(.+?)-(.+?).drv':\n\s+specified: .*\n\s+got:\s+(.+?)\n")
+    matches = pattern.findall(stderr)
+    result_dict = {}
+
+    for match in matches:
+        _, system, got = match
+        result_dict[system] = got
+
+    def sort_dict_recursive(d):
+        return {
+            k: sort_dict_recursive(v) if isinstance(
+                v, dict) else v for k, v in sorted(
+                d.items())}
+    result_dict = sort_dict_recursive(result_dict)
+
+    return result_dict
+
+
 def get_artifact_hashes(flutter_compact_version):
     code = load_code("get-artifact-hashes.nix",
                      nixpkgs_root=NIXPKGS_ROOT,
@@ -180,6 +206,7 @@ def write_data(
         flutter_version,
         channel,
         engine_hash,
+        engine_hashes,
         dart_version,
         dart_hash,
         flutter_hash,
@@ -190,6 +217,7 @@ def write_data(
             "version": flutter_version,
             "engineVersion": engine_hash,
             "channel": channel,
+            "engineHashes": engine_hashes,
             "dartVersion": dart_version,
             "dartHash": dart_hash,
             "flutterHash": flutter_hash,
@@ -205,7 +233,9 @@ def update_all_packages():
         int(x.split('_')[0]), int(x.split('_')[1])), reverse=True)
 
     new_content = [
-        "flutterPackages = recurseIntoAttrs (callPackage ../development/compilers/flutter { });",
+        "flutterPackages-bin = recurseIntoAttrs (callPackage ../development/compilers/flutter { });",
+        "flutterPackages-source = recurseIntoAttrs (callPackage ../development/compilers/flutter { useNixpkgsEngine = true; });",
+        "flutterPackages = flutterPackages-bin;"
         "flutter = flutterPackages.stable;",
     ] + [f"flutter{version.replace('_', '')} = flutterPackages.v{version};" for version in versions]
 
@@ -215,7 +245,7 @@ def update_all_packages():
     start = -1
     end = -1
     for i, line in enumerate(lines):
-        if "flutterPackages = recurseIntoAttrs (callPackage ../development/compilers/flutter { });" in line:
+        if "flutterPackages-bin = recurseIntoAttrs (callPackage ../development/compilers/flutter { });" in line:
             start = i
         if start != -1 and len(line.strip()) == 0:
             end = i
@@ -329,6 +359,7 @@ def main():
     write_data(
         pubspec_lock={},
         artifact_hashes={},
+        engine_hashes={},
         **common_data_args)
 
     pubspec_lock = get_pubspec_lock(flutter_compact_version, flutter_src)
@@ -336,6 +367,7 @@ def main():
     write_data(
         pubspec_lock=pubspec_lock,
         artifact_hashes={},
+        engine_hashes={},
         **common_data_args)
 
     artifact_hashes = get_artifact_hashes(flutter_compact_version)
@@ -343,6 +375,15 @@ def main():
     write_data(
         pubspec_lock=pubspec_lock,
         artifact_hashes=artifact_hashes,
+        engine_hashes={},
+        **common_data_args)
+
+    engine_hashes = get_engine_hashes(engine_hash)
+
+    write_data(
+        pubspec_lock=pubspec_lock,
+        artifact_hashes=artifact_hashes,
+        engine_hashes=engine_hashes,
         **common_data_args)
 
 
diff --git a/pkgs/development/compilers/flutter/versions/3_13/data.json b/pkgs/development/compilers/flutter/versions/3_13/data.json
index 3f68f86133684..eb707f74f7c26 100644
--- a/pkgs/development/compilers/flutter/versions/3_13/data.json
+++ b/pkgs/development/compilers/flutter/versions/3_13/data.json
@@ -2,6 +2,9 @@
   "version": "3.13.8",
   "engineVersion": "767d8c75e898091b925519803830fc2721658d07",
   "channel": "stable",
+  "engineHashes": {
+    "aarch64-linux": "sha256-1s7I+AWb2kNDzJ5k2XYm7rSK8yj1wqTjPUuS0f85Jig="
+  },
   "dartVersion": "3.1.4",
   "dartHash": {
     "x86_64-linux": "sha256-42wrqzjRcFDWw2aEY6+/faX+QE9PA8FmRWP4M/NkgBE=",
diff --git a/pkgs/development/compilers/flutter/versions/3_16/data.json b/pkgs/development/compilers/flutter/versions/3_16/data.json
index fcd5975778d0d..477328b4aa6b2 100644
--- a/pkgs/development/compilers/flutter/versions/3_16/data.json
+++ b/pkgs/development/compilers/flutter/versions/3_16/data.json
@@ -2,6 +2,9 @@
   "version": "3.16.7",
   "engineVersion": "4a585b79294e830fa89c24924d58a27cc8fbf406",
   "channel": "stable",
+  "engineHashes": {
+    "aarch64-linux": "sha256-xqniT1rYrzCuq6542KfqWRigYtLnmaT0z5Es/59iFMw="
+  },
   "dartVersion": "3.2.4",
   "dartHash": {
     "x86_64-linux": "sha256-qslf+wgmNz9r+e45o3Bg9/vDj75GkM9gQE2tb5rbIvw=",
diff --git a/pkgs/development/compilers/flutter/versions/3_19/data.json b/pkgs/development/compilers/flutter/versions/3_19/data.json
index e4bcedc110d82..c09d3e99a3cac 100644
--- a/pkgs/development/compilers/flutter/versions/3_19/data.json
+++ b/pkgs/development/compilers/flutter/versions/3_19/data.json
@@ -2,6 +2,11 @@
   "version": "3.19.4",
   "engineVersion": "a5c24f538d05aaf66f7972fb23959d8cafb9f95a",
   "channel": "stable",
+  "engineHashes": {
+    "x86_64-linux": "sha256-xhihh4v9bh2ZxAewKEdhpXerLDoXFm8YO72+tGRnkCw=",
+    "aarch64-linux": "sha256-mUimQRg0UqvTueuDWO8Isy0FKOxJLvVZrehv4SMj0XY=",
+    "aarch64-darwin": "sha256-5DcD7ebrANznB++QOQOoynr1aOgJqTF8QfSihQnghoY="
+  },
   "dartVersion": "3.3.2",
   "dartHash": {
     "x86_64-linux": "sha256-eO8qcSQNWGEz/5oVaJ5tjRMnGy2aq3PbcF15z/Pi3xQ=",
diff --git a/pkgs/development/compilers/flutter/versions/3_19/engine/patches/flutter-140969.patch b/pkgs/development/compilers/flutter/versions/3_19/engine/patches/flutter-140969.patch
new file mode 100644
index 0000000000000..bf5d9320a0a39
--- /dev/null
+++ b/pkgs/development/compilers/flutter/versions/3_19/engine/patches/flutter-140969.patch
@@ -0,0 +1,41 @@
+From dd74740ddceac81e748a7e7834c28135abc59454 Mon Sep 17 00:00:00 2001
+From: Brandon DeRosier <bdero@google.com>
+Date: Tue, 16 Jan 2024 11:00:34 -0800
+Subject: [PATCH] [Flutter GPU] Fix playground shader paths. (#49790)
+
+Resolves https://github.com/flutter/flutter/issues/140969.
+
+Makes the shader paths absolute to prevent issues caused by the working
+directory differing across build environments.
+---
+ impeller/fixtures/BUILD.gn  | 3 ++-
+ impeller/tools/impeller.gni | 2 +-
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/impeller/fixtures/BUILD.gn b/impeller/fixtures/BUILD.gn
+index 9165f06542a2a..5ea90ab3969f3 100644
+--- a/impeller/fixtures/BUILD.gn
++++ b/impeller/fixtures/BUILD.gn
+@@ -131,7 +131,8 @@
+     "flutter_gpu_texture.vert",
+   ]
+   shader_target_flags = [ "--runtime-stage-metal" ]
+-  shader_bundle = "{\"UnlitFragment\": {\"type\": \"fragment\", \"file\": \"../../flutter/impeller/fixtures/flutter_gpu_unlit.frag\"}, \"UnlitVertex\": {\"type\": \"vertex\", \"file\": \"../../flutter/impeller/fixtures/flutter_gpu_unlit.vert\"}, \"TextureFragment\": {\"type\": \"fragment\", \"file\": \"../../flutter/impeller/fixtures/flutter_gpu_texture.frag\"}, \"TextureVertex\": {\"type\": \"vertex\", \"file\": \"../../flutter/impeller/fixtures/flutter_gpu_texture.vert\"}}"
++  fixtures = rebase_path("//flutter/impeller/fixtures")
++  shader_bundle = "{\"UnlitFragment\": {\"type\": \"fragment\", \"file\": \"${fixtures}/flutter_gpu_unlit.frag\"}, \"UnlitVertex\": {\"type\": \"vertex\", \"file\": \"${fixtures}/flutter_gpu_unlit.vert\"}, \"TextureFragment\": {\"type\": \"fragment\", \"file\": \"${fixtures}/flutter_gpu_texture.frag\"}, \"TextureVertex\": {\"type\": \"vertex\", \"file\": \"${fixtures}/flutter_gpu_texture.vert\"}}"
+   shader_bundle_output = "playground.shaderbundle"
+ }
+
+diff --git a/impeller/tools/impeller.gni b/impeller/tools/impeller.gni
+index 6541c3b12173b..2ab7ec0f0b07a 100644
+--- a/impeller/tools/impeller.gni
++++ b/impeller/tools/impeller.gni
+@@ -313,7 +313,7 @@
+   if (defined(invoker.shader_bundle)) {
+     assert(
+         defined(invoker.shader_bundle_output),
+-        "When shader_bundle is specified, shader_output_bundle must also be specified.")
++        "When shader_bundle is specified, shader_bundle_output must also be specified.")
+   }
+ 
+   sksl = false
diff --git a/pkgs/development/compilers/flutter/versions/3_22/data.json b/pkgs/development/compilers/flutter/versions/3_22/data.json
index 12da5e9b418a8..968fde9d7b27c 100644
--- a/pkgs/development/compilers/flutter/versions/3_22/data.json
+++ b/pkgs/development/compilers/flutter/versions/3_22/data.json
@@ -2,6 +2,10 @@
   "version": "3.22.2",
   "engineVersion": "edd8546116457bdf1c5bdfb13ecb9463d2bb5ed4",
   "channel": "stable",
+  "engineHashes": {
+    "aarch64-linux": "sha256-xPVhLxO9AgXC2+Hwm1lWRfNZhLwZHdKW92WXgv3ImZk=",
+    "x86_64-linux": "sha256-klODJpmlWynYx+MqqGGeTzzPtmQTEUV47hnzjIVDCK8="
+  },
   "dartVersion": "3.4.3",
   "dartHash": {
     "x86_64-linux": "sha256-wDIdoWoKlutP8kixd12Lppzv2aYeiTJ1A1Sy6lguXgg=",
diff --git a/pkgs/development/compilers/flutter/versions/3_23/data.json b/pkgs/development/compilers/flutter/versions/3_23/data.json
index 0bfbb69af1516..3c3fedbdecaeb 100644
--- a/pkgs/development/compilers/flutter/versions/3_23/data.json
+++ b/pkgs/development/compilers/flutter/versions/3_23/data.json
@@ -2,6 +2,9 @@
   "version": "3.23.0-0.1.pre",
   "engineVersion": "bb10c5466638e963479ba5e64e601e42d1a43447",
   "channel": "beta",
+  "engineHashes": {
+    "aarch64-linux": "sha256-WHWxYOHd3jxE5CQNt0+9qxlsCLK5y9iJsVERtJ4Ylbk="
+  },
   "dartVersion": "3.5.0-180.3.beta",
   "dartHash": {
     "x86_64-linux": "sha256-DXGyUTu9I602lLnDz9BKLfHEAeaMKtbZjxgmPPSTEv0=",
diff --git a/pkgs/development/compilers/flutter/wrapper.nix b/pkgs/development/compilers/flutter/wrapper.nix
index f5b8b2e2059da..4b20cf7f43f06 100644
--- a/pkgs/development/compilers/flutter/wrapper.nix
+++ b/pkgs/development/compilers/flutter/wrapper.nix
@@ -145,7 +145,10 @@ in
     mkdir -p $out/bin
     makeWrapper '${immutableFlutter}' $out/bin/flutter \
       --set-default ANDROID_EMULATOR_USE_SYSTEM_LIBS 1 \
-      --suffix PATH : '${lib.makeBinPath (tools ++ buildTools)}' \
+      '' + lib.optionalString (flutter ? engine && flutter.engine.meta.available) ''
+        --set-default FLUTTER_ENGINE "${flutter.engine}" \
+        --add-flags "--local-engine-host host_${flutter.engine.runtimeMode}${lib.optionalString (!flutter.engine.isOptimized) "_unopt"}" \
+      '' + '' --suffix PATH : '${lib.makeBinPath (tools ++ buildTools)}' \
       --suffix PKG_CONFIG_PATH : "$FLUTTER_PKG_CONFIG_PATH" \
       --suffix LIBRARY_PATH : '${lib.makeLibraryPath appStaticBuildDeps}' \
       --prefix CXXFLAGS "''\t" '${builtins.concatStringsSep " " (includeFlags ++ extraCxxFlags)}' \
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index dc479f0fddf90..d12ff3f330bae 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -15367,7 +15367,9 @@ with pkgs;
 
   fluidd = callPackage ../applications/misc/fluidd { };
 
-  flutterPackages = recurseIntoAttrs (callPackage ../development/compilers/flutter { });
+  flutterPackages-bin = recurseIntoAttrs (callPackage ../development/compilers/flutter { });
+  flutterPackages-source = recurseIntoAttrs (callPackage ../development/compilers/flutter { useNixpkgsEngine = true; });
+  flutterPackages = flutterPackages-bin;
   flutter = flutterPackages.stable;
   flutter323 = flutterPackages.v3_23;
   flutter322 = flutterPackages.v3_22;