Merge pull request #201027 from hacker1024/patch-3

This commit is contained in:
Maciej Krüger 2023-04-25 11:16:53 +02:00 committed by GitHub
commit 9096817104
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 3643 additions and 678 deletions

View file

@ -2,19 +2,13 @@
, flutter
, python3
, fetchFromGitHub
, stdenv
, pcre2
, gnome
, makeWrapper
, removeReferencesTo
}:
let
vendorHashes = {
x86_64-linux = "sha256-Upe0cEDG02RJD50Ht9VNMwkelsJHX8zOuJZssAhMuMY=";
aarch64-linux = "sha256-lKER4+gcyFqnCvgBl/qdVBCbUpocWUnXGLXsX82MSy4=";
};
in
flutter.mkFlutterApp rec {
flutter.buildFlutterApplication rec {
pname = "yubioath-flutter";
version = "6.1.0";
@ -27,7 +21,8 @@ flutter.mkFlutterApp rec {
passthru.helper = python3.pkgs.callPackage ./helper.nix { inherit src version meta; };
vendorHash = vendorHashes.${stdenv.system};
depsListFile = ./deps.json;
vendorHash = "sha256-WfZiB7MO4wHUg81xm67BMu4zQdC9CfhN5BQol+AI2S8=";
postPatch = ''
substituteInPlace linux/CMakeLists.txt \
@ -89,6 +84,6 @@ flutter.mkFlutterApp rec {
homepage = "https://github.com/Yubico/yubioath-flutter";
license = licenses.asl20;
maintainers = with maintainers; [ lukegb ];
platforms = builtins.attrNames vendorHashes;
platforms = [ "x86_64-linux" "aarch64-linux" ];
};
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,186 @@
{ stdenvNoCC
, lib
, makeSetupHook
, dart
, git
, cacert
, jq
}:
{
# The output hash of the dependencies for this project.
vendorHash ? ""
# Commands to run once before using Dart or pub.
, sdkSetupScript ? ""
# Commands to run to populate the pub cache.
, pubGetScript ? "dart pub get"
# A path to a pubspec.lock file to use instead of the one in the source directory.
, pubspecLockFile ? null
# Arguments used in the derivation that builds the Dart package.
# Passing these is recommended to ensure that the same steps are made to prepare the sources in both this
# derivation and the one that builds the Dart package.
, buildDrvArgs ? { }
, ...
}@args:
# This is a fixed-output derivation and setup hook that can be used to fetch dependencies for Dart projects.
# It is designed to be placed in the nativeBuildInputs of a derivation that builds a Dart package.
# Providing the buildDrvArgs argument is highly recommended.
let
buildDrvInheritArgNames = [
"name"
"pname"
"version"
"src"
"sourceRoot"
"setSourceRoot"
"preUnpack"
"unpackPhase"
"unpackCmd"
"postUnpack"
"prePatch"
"patchPhase"
"patches"
"patchFlags"
"postPatch"
];
buildDrvInheritArgs = builtins.foldl'
(attrs: arg:
if buildDrvArgs ? ${arg}
then attrs // { ${arg} = buildDrvArgs.${arg}; }
else attrs)
{ }
buildDrvInheritArgNames;
drvArgs = buildDrvInheritArgs // (removeAttrs args [ "buildDrvArgs" ]);
name = (if drvArgs ? name then drvArgs.name else "${drvArgs.pname}-${drvArgs.version}");
deps =
stdenvNoCC.mkDerivation ({
name = "${name}-dart-deps";
nativeBuildInputs = [
dart
git
];
# avoid pub phase
dontBuild = true;
configurePhase = ''
# Configure the package cache
export PUB_CACHE="$out/cache/.pub-cache"
mkdir -p "$PUB_CACHE"
${sdkSetupScript}
'';
installPhase = ''
_pub_get() {
${pubGetScript}
}
# so we can use lock, diff yaml
mkdir -p "$out/pubspec"
cp "pubspec.yaml" "$out/pubspec"
${lib.optionalString (pubspecLockFile != null) "install -m644 ${pubspecLockFile} pubspec.lock"}
if ! cp "pubspec.lock" "$out/pubspec"; then
echo 1>&2 -e '\nThe pubspec.lock file is missing. This is a requirement for reproducible builds.' \
'\nThe following steps should be taken to fix this issue:' \
'\n 1. If you are building an application, contact the developer(s).' \
'\n The pubspec.lock file should be provided with the source code.' \
'\n https://dart.dev/guides/libraries/private-files#pubspeclock' \
'\n 2. An attempt to generate and print a compressed pubspec.lock file will be made now.' \
'\n It is compressed with gzip and base64 encoded.' \
'\n Paste it to a file and extract it with `base64 -d pubspec.lock.in | gzip -d > pubspec.lock`.' \
'\n Provide the path to the pubspec.lock file in the pubspecLockFile argument.' \
'\n This must be updated whenever the application is updated.' \
'\n'
_pub_get
echo ""
gzip --to-stdout --best pubspec.lock | base64 1>&2
echo 1>&2 -e '\nA gzipped pubspec.lock file has been printed. Please see the informational message above.'
exit 1
fi
_pub_get
# nuke nondeterminism
# Remove Git directories in the Git package cache - these are rarely used by Pub,
# which instead maintains a corresponsing mirror and clones cached packages through it.
#
# An exception is made to keep .git/pub-packages files, which are important.
# https://github.com/dart-lang/pub/blob/c890afa1d65b340fa59308172029680c2f8b0fc6/lib/src/source/git.dart#L621
if [ -d "$PUB_CACHE"/git ]; then
find "$PUB_CACHE"/git -maxdepth 4 -path "*/.git/*" ! -name "pub-packages" -prune -exec rm -rf {} +
fi
# Remove continuously updated package metadata caches
rm -rf "$PUB_CACHE"/hosted/*/.cache # Not pinned by pubspec.lock
rm -rf "$PUB_CACHE"/git/cache/*/* # Recreate this on the other end. See: https://github.com/dart-lang/pub/blob/c890afa1d65b340fa59308172029680c2f8b0fc6/lib/src/source/git.dart#L531
# Miscelaneous transient package cache files
rm -f "$PUB_CACHE"/README.md # May change with different Dart versions
rm -rf "$PUB_CACHE"/_temp # https://github.com/dart-lang/pub/blob/c890afa1d65b340fa59308172029680c2f8b0fc6/lib/src/system_cache.dart#L131
rm -rf "$PUB_CACHE"/log # https://github.com/dart-lang/pub/blob/c890afa1d65b340fa59308172029680c2f8b0fc6/lib/src/command.dart#L348
'';
GIT_SSL_CAINFO = "${cacert}/etc/ssl/certs/ca-bundle.crt";
SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt";
impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ [
"GIT_PROXY_COMMAND"
"NIX_GIT_SSL_CAINFO"
"SOCKS_SERVER"
];
# Patching shebangs introduces input references to this fixed-output derivation.
# This triggers a bug in Nix, causing the output path to change unexpectedly.
# https://github.com/NixOS/nix/issues/6660
dontPatchShebangs = true;
# The following operations are not generally useful for this derivation.
# If a package does contain some native components used at build time,
# please file an issue.
dontStrip = true;
dontMoveSbin = true;
dontPatchELF = true;
outputHashAlgo = "sha256";
outputHashMode = "recursive";
outputHash = if vendorHash != "" then vendorHash else lib.fakeSha256;
} // (removeAttrs drvArgs [ "name" "pname" ]));
depsListDrv = stdenvNoCC.mkDerivation ({
name = "${name}-dart-deps-list.json";
nativeBuildInputs = [ hook dart jq ];
configurePhase = ''
runHook preConfigure
dart pub get --offline
runHook postConfigure
'';
buildPhase = ''
runHook preBuild
dart pub deps --json | jq .packages > $out
runHook postBuild
'';
} // buildDrvInheritArgs);
hook = (makeSetupHook {
# The setup hook should not be part of the fixed-output derivation.
# Updates to the hook script should not change vendor hashes, and it won't
# work at all anyway due to https://github.com/NixOS/nix/issues/6660.
name = "${name}-dart-deps-setup-hook";
substitutions = { inherit deps; };
propagatedBuildInputs = [ dart git ];
passthru = {
files = deps.outPath;
depsListFile = depsListDrv.outPath;
};
}) ./setup-hook.sh;
in
hook

View file

@ -0,0 +1,41 @@
preConfigureHooks+=(_setupPubCache)
_setupPubCache() {
deps="@deps@"
# Configure the package cache.
export PUB_CACHE="$(mktemp -d)"
mkdir -p "$PUB_CACHE"
if [ -d "$deps/cache/.pub-cache/git" ]; then
# Link the Git package cache.
mkdir -p "$PUB_CACHE/git"
ln -s "$deps/cache/.pub-cache/git"/* "$PUB_CACHE/git"
# Recreate the internal Git cache subdirectory.
# See: https://github.com/dart-lang/pub/blob/c890afa1d65b340fa59308172029680c2f8b0fc6/lib/src/source/git.dart#L339)
# Blank repositories are created instead of attempting to match the cache mirrors to checkouts.
# This is not an issue, as pub does not need the mirrors in the Flutter build process.
rm "$PUB_CACHE/git/cache" && mkdir "$PUB_CACHE/git/cache"
for mirror in $(ls -A "$deps/cache/.pub-cache/git/cache"); do
git --git-dir="$PUB_CACHE/git/cache/$mirror" init --bare --quiet
done
fi
# Link the remaining package cache directories.
# At this point, any subdirectories that must be writable must have been taken care of.
for file in $(comm -23 <(ls -A "$deps/cache/.pub-cache") <(ls -A "$PUB_CACHE")); do
ln -s "$deps/cache/.pub-cache/$file" "$PUB_CACHE/$file"
done
# ensure we're using a lockfile for the right package version
if [ ! -e pubspec.lock ]; then
cp -v "$deps/pubspec/pubspec.lock" .
# Sometimes the pubspec.lock will get opened in write mode, even when offline.
chmod u+w pubspec.lock
elif ! { diff -u pubspec.lock "$deps/pubspec/pubspec.lock" && diff -u pubspec.yaml "$deps/pubspec/pubspec.yaml"; }; then
echo 1>&2 -e 'The pubspec.lock or pubspec.yaml of the project derivation differs from the one in the dependency derivation.' \
'\nYou most likely forgot to update the vendorHash while updating the sources.'
exit 1
fi
}

View file

@ -1,284 +1,159 @@
{ flutter
, lib
, llvmPackages_13
, cmake
, ninja
, pkg-config
, wrapGAppsHook
, autoPatchelfHook
, util-linux
, libselinux
, libsepol
, libthai
, libdatrie
, libxkbcommon
, at-spi2-core
, libsecret
, jsoncpp
, xorg
, dbus
, gtk3
, glib
, pcre
, libepoxy
{ lib
, callPackage
, stdenvNoCC
, makeWrapper
, llvmPackages_13
, cacert
, git
, dart
, nukeReferences
, bash
, curl
, unzip
, which
, xz
, flutter
, jq
}:
# absolutely no mac support for now
args:
{ pubGetScript ? "flutter pub get"
, flutterBuildFlags ? [ ]
, runtimeDependencies ? [ ]
, customPackageOverrides ? { }
, autoDepsList ? false
, depsListFile ? null
, vendorHash
, pubspecLockFile ? null
, nativeBuildInputs ? [ ]
, preUnpack ? ""
, postFixup ? ""
, ...
}@args:
let
pl = n: "##FLUTTER_${n}_PLACEHOLDER_MARKER##";
placeholder_deps = pl "DEPS";
placeholder_flutter = pl "FLUTTER";
fetchAttrs = [ "src" "sourceRoot" "setSourceRoot" "unpackPhase" "patches" ];
getAttrsOrNull = names: attrs: lib.genAttrs names (name: if attrs ? ${name} then attrs.${name} else null);
flutterDeps = [
# flutter deps
flutter.unwrapped
bash
curl
flutter.dart
git
unzip
which
xz
];
self =
(self: llvmPackages_13.stdenv.mkDerivation (args // {
deps = stdenvNoCC.mkDerivation (lib.recursiveUpdate (getAttrsOrNull fetchAttrs args) {
name = "${self.name}-deps-flutter-v${flutter.unwrapped.version}-${stdenvNoCC.targetPlatform.system}.tar.gz";
flutterSetupScript = ''
export HOME="$NIX_BUILD_TOP"
flutter config --no-analytics &>/dev/null # mute first-run
flutter config --enable-linux-desktop >/dev/null
'';
nativeBuildInputs = flutterDeps ++ [
nukeReferences
];
deps = callPackage ../dart/fetch-dart-deps { dart = flutter; } {
sdkSetupScript = flutterSetupScript;
inherit pubGetScript vendorHash pubspecLockFile;
buildDrvArgs = args;
};
# avoid pub phase
dontBuild = true;
baseDerivation = llvmPackages_13.stdenv.mkDerivation (finalAttrs: args // {
inherit flutterBuildFlags runtimeDependencies;
installPhase = ''
. ${../fetchgit/deterministic-git}
outputs = [ "out" "debug" ];
TMP=$(mktemp -d)
nativeBuildInputs = [
makeWrapper
deps
flutter
jq
] ++ nativeBuildInputs;
export HOME="$TMP"
export PUB_CACHE=''${PUB_CACHE:-"$HOME/.pub-cache"}
export ANDROID_EMULATOR_USE_SYSTEM_LIBS=1
preUnpack = ''
${lib.optionalString (!autoDepsList) ''
if ! { [ '${lib.boolToString (depsListFile != null)}' = 'true' ] ${lib.optionalString (depsListFile != null) "&& cmp -s <(jq -Sc . '${depsListFile}') <(jq -Sc . '${finalAttrs.passthru.depsListFile}')"}; }; then
echo 1>&2 -e '\nThe dependency list file was either not given or differs from the expected result.' \
'\nPlease choose one of the following solutions:' \
'\n - Duplicate the following file and pass it to the depsListFile argument.' \
'\n ${finalAttrs.passthru.depsListFile}' \
'\n - Set autoDepsList to true (not supported by Hydra or permitted in Nixpkgs)'.
exit 1
fi
''}
flutter config --no-analytics &>/dev/null # mute first-run
flutter config --enable-linux-desktop
flutter packages get
flutter build linux || true # so it downloads tools
${lib.optionalString (args ? flutterExtraFetchCommands) args.flutterExtraFetchCommands}
RES="$TMP"
mkdir -p "$RES/f"
# so we can use lock, diff yaml
cp "pubspec.yaml" "$RES"
cp "pubspec.lock" "$RES"
[[ -e .packages ]] && mv .packages "$RES/f"
mv .dart_tool .flutter-plugins .flutter-plugins-dependencies "$RES/f"
# replace paths with placeholders
find "$RES" -type f -exec sed -i \
-e s,$TMP,${placeholder_deps},g \
-e s,${flutter.unwrapped},${placeholder_flutter},g \
{} +
remove_line_matching() {
replace_line_matching "$1" "$2" ""
}
replace_line_matching() {
sed "s|.*$2.*|$3|g" -r -i "$1"
}
# nuke nondeterminism
# clientId is random
remove_line_matching "$RES/.flutter" clientId
# deterministic git repos
find "$RES" -iname .git -type d | while read -r repoGit; do
make_deterministic_repo "$(dirname "$repoGit")"
done
# dart _fetchedAt, etc
DART_DATE=$(date --date="@$SOURCE_DATE_EPOCH" -In | sed "s|,|.|g" | sed "s|+.*||g")
find "$RES/.pub-cache" -iname "*.json" -exec sed -r 's|.*_fetchedAt.*| "_fetchedAt": "'"$DART_DATE"'",|g' -i {} +
replace_line_matching "$RES/f/.dart_tool/package_config.json" '"generated"' '"generated": "'"$DART_DATE"'",'
replace_line_matching "$RES/f/.flutter-plugins-dependencies" '"date_created"' '"date_created": "'"$DART_DATE"'",'
[[ -e "$RES/f/.packages" ]] && remove_line_matching "$RES/f/.packages" "Generated by pub"
# nuke refs
find "$RES" -type f -exec nuke-refs {} +
# Build a reproducible tar, per instructions at https://reproducible-builds.org/docs/archives/
tar --owner=0 --group=0 --numeric-owner --format=gnu \
--sort=name --mtime="@$SOURCE_DATE_EPOCH" \
-czf "$out" -C "$RES" .
${preUnpack}
'';
GIT_SSL_CAINFO = "${cacert}/etc/ssl/certs/ca-bundle.crt";
SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt";
configurePhase = ''
runHook preConfigure
impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ [
"GIT_PROXY_COMMAND" "NIX_GIT_SSL_CAINFO" "SOCKS_SERVER"
];
${flutterSetupScript}
# unnecesarry
dontFixup = true;
runHook postConfigure
'';
outputHashAlgo = if self ? vendorHash then null else "sha256";
# outputHashMode = "recursive";
outputHash = if self ? vendorHash then
self.vendorHash
else if self ? vendorSha256 then
self.vendorSha256
else
lib.fakeSha256;
buildPhase = ''
runHook preBuild
mkdir -p build/flutter_assets/fonts
flutter packages get --offline -v
flutter build linux -v --release --split-debug-info="$debug" ${builtins.concatStringsSep " " (map (flag: "\"${flag}\"") finalAttrs.flutterBuildFlags)}
runHook postBuild
'';
installPhase = ''
runHook preInstall
built=build/linux/*/release/bundle
mkdir -p $out/bin
mv $built $out/app
for f in $(find $out/app -iname "*.desktop" -type f); do
install -D $f $out/share/applications/$(basename $f)
done
for f in $(find $out/app -maxdepth 1 -type f); do
ln -s $f $out/bin/$(basename $f)
done
# make *.so executable
find $out/app -iname "*.so" -type f -exec chmod +x {} +
# remove stuff like /build/source/packages/ubuntu_desktop_installer/linux/flutter/ephemeral
for f in $(find $out/app -executable -type f); do
if patchelf --print-rpath "$f" | grep /build; then # this ignores static libs (e,g. libapp.so) also
echo "strip RPath of $f"
newrp=$(patchelf --print-rpath $f | sed -r "s|/build.*ephemeral:||g" | sed -r "s|/build.*profile:||g")
patchelf --set-rpath "$newrp" "$f"
fi
done
runHook postInstall
'';
postFixup = ''
# Add runtime library dependencies to the LD_LIBRARY_PATH.
# For some reason, the RUNPATH of the executable is not used to load dynamic libraries in dart:ffi with DynamicLibrary.open().
#
# This could alternatively be fixed with patchelf --add-needed, but this would cause all the libraries to be opened immediately,
# which is not what application authors expect.
for f in "$out"/bin/*; do
wrapProgram "$f" \
--suffix LD_LIBRARY_PATH : '${lib.makeLibraryPath finalAttrs.runtimeDependencies}'
done
${postFixup}
'';
passthru = {
inherit (deps) depsListFile;
};
});
nativeBuildInputs = flutterDeps ++ [
# flutter dev tools
cmake
ninja
pkg-config
wrapGAppsHook
# flutter likes dynamic linking
autoPatchelfHook
] ++ lib.optionals (args ? nativeBuildInputs) args.nativeBuildInputs;
buildInputs = [
# cmake deps
gtk3
glib
pcre
util-linux
# also required by cmake, not sure if really needed or dep of all packages
libselinux
libsepol
libthai
libdatrie
xorg.libXdmcp
xorg.libXtst
libxkbcommon
dbus
at-spi2-core
libsecret
jsoncpp
# build deps
xorg.libX11
# directly required by build
libepoxy
] ++ lib.optionals (args ? buildInputs) args.buildInputs;
# TODO: do we need this?
NIX_LDFLAGS = "-rpath ${lib.makeLibraryPath self.buildInputs}";
env.NIX_CFLAGS_COMPILE = "-I${xorg.libX11}/include";
LD_LIBRARY_PATH = lib.makeLibraryPath self.buildInputs;
configurePhase = ''
runHook preConfigure
# for some reason fluffychat build breaks without this - seems file gets overriden by some tool
cp pubspec.yaml pubspec-backup
# we get this from $depsFolder so disabled for now, but we might need it again once deps are fetched properly
# flutter config --no-analytics >/dev/null 2>/dev/null # mute first-run
# flutter config --enable-linux-desktop
# extract deps
depsFolder=$(mktemp -d)
tar xzf "$deps" -C "$depsFolder"
# after extracting update paths to point to real paths
find "$depsFolder" -type f -exec sed -i \
-e s,${placeholder_deps},$depsFolder,g \
-e s,${placeholder_flutter},${flutter.unwrapped},g \
{} +
# ensure we're using a lockfile for the right package version
if [ -e pubspec.lock ]; then
# FIXME: currently this is broken. in theory this should not break, but flutter has it's own way of doing things.
# diff -u pubspec.lock $depsFolder/pubspec.lock
true
packageOverrideRepository = (callPackage ../../development/compilers/flutter/package-overrides { }) // customPackageOverrides;
productPackages = builtins.filter (package: package.kind != "dev")
(if autoDepsList
then builtins.fromJSON (builtins.readFile deps.depsListFile)
else
cp -v "$depsFolder/pubspec.lock" .
fi
diff -u pubspec.yaml $depsFolder/pubspec.yaml
mv -v $(find $depsFolder/f -type f) .
# prepare
export HOME=$depsFolder
export PUB_CACHE=''${PUB_CACHE:-"$HOME/.pub-cache"}
export ANDROID_EMULATOR_USE_SYSTEM_LIBS=1
# binaries need to be patched
autoPatchelf -- "$depsFolder"
runHook postConfigure
'';
buildPhase = ''
runHook preBuild
# for some reason fluffychat build breaks without this - seems file gets overriden by some tool
mv pubspec-backup pubspec.yaml
mkdir -p build/flutter_assets/fonts
flutter packages get --offline -v
flutter build linux --release -v
runHook postBuild
'';
installPhase = ''
runHook preInstall
built=build/linux/*/release/bundle
mkdir -p $out/bin
mv $built $out/app
for f in $(find $out/app -iname "*.desktop" -type f); do
install -D $f $out/share/applications/$(basename $f)
done
for f in $(find $out/app -maxdepth 1 -type f); do
ln -s $f $out/bin/$(basename $f)
done
# this confuses autopatchelf hook otherwise
rm -rf "$depsFolder"
# make *.so executable
find $out/app -iname "*.so" -type f -exec chmod +x {} +
# remove stuff like /build/source/packages/ubuntu_desktop_installer/linux/flutter/ephemeral
for f in $(find $out/app -executable -type f); do
if patchelf --print-rpath "$f" | grep /build; then # this ignores static libs (e,g. libapp.so) also
echo "strip RPath of $f"
newrp=$(patchelf --print-rpath $f | sed -r "s|/build.*ephemeral:||g" | sed -r "s|/build.*profile:||g")
patchelf --set-rpath "$newrp" "$f"
fi
done
runHook postInstall
'';
})) self;
if depsListFile == null
then [ ]
else builtins.fromJSON (builtins.readFile depsListFile));
in
self
builtins.foldl'
(prev: package:
if packageOverrideRepository ? ${package.name}
then
prev.overrideAttrs
(packageOverrideRepository.${package.name} {
inherit (package)
name
version
kind
source
dependencies;
})
else prev)
baseDerivation
productPackages

View file

@ -1,25 +1,26 @@
{ callPackage, fetchurl, dart }:
{ callPackage, fetchzip, dart }:
let
mkFlutter = opts: callPackage (import ./flutter.nix opts) { };
mkFlutter = { version, engineVersion, patches, dart, src }: callPackage ./flutter.nix { inherit version engineVersion patches dart src; };
wrapFlutter = flutter: callPackage ./wrapper.nix { inherit flutter; };
getPatches = dir:
let files = builtins.attrNames (builtins.readDir dir);
in map (f: dir + ("/" + f)) files;
flutterDrv = { version, pname, dartVersion, hash, dartHash, patches }: mkFlutter {
inherit version pname patches;
flutterDrv = { version, engineVersion, dartVersion, hash, dartHash, patches }: mkFlutter {
inherit version engineVersion patches;
dart = dart.override {
version = dartVersion;
sources = {
"${dartVersion}-x86_64-linux" = fetchurl {
"${dartVersion}-x86_64-linux" = fetchzip {
url = "https://storage.googleapis.com/dart-archive/channels/stable/release/${dartVersion}/sdk/dartsdk-linux-x64-release.zip";
sha256 = dartHash.x86_64-linux;
};
"${dartVersion}-aarch64-linux" = fetchurl {
"${dartVersion}-aarch64-linux" = fetchzip {
url = "https://storage.googleapis.com/dart-archive/channels/stable/release/${dartVersion}/sdk/dartsdk-linux-arm64-release.zip";
sha256 = dartHash.aarch64-linux;
};
};
};
src = fetchurl {
src = fetchzip {
url = "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${version}-stable.tar.xz";
sha256 = hash;
};
@ -28,27 +29,27 @@ let
flutter3Patches = getPatches ./patches/flutter3;
in
{
inherit mkFlutter flutterDrv flutter2Patches flutter3Patches;
inherit mkFlutter wrapFlutter flutterDrv flutter3Patches flutter2Patches;
stable = flutterDrv {
pname = "flutter";
version = "3.3.8";
dartVersion = "2.18.4";
hash = "sha256-QH+10F6a0XYEvBetiAi45Sfy7WTdVZ1i8VOO4JuSI24=";
version = "3.7.12";
engineVersion = "1a65d409c7a1438a34d21b60bf30a6fd5db59314";
dartVersion = "2.19.6";
hash = "sha256-5ExDBQXIpoZ5NwS66seY3m9/V8xDiyq/RdzldAyHdEE=";
dartHash = {
x86_64-linux = "sha256-lFw+KaxzhuAMnu6ypczINqywzpiD+8Kd+C/UHJDrO9Y=";
aarch64-linux = "sha256-snlFTY4oJ4ALGLc210USbI2Z///cx1IVYUWm7Vo5z2I=";
x86_64-linux = "sha256-4ezRuwhQHVCxZg5WbzU/tBUDvZVpfCo6coDE4K0UzXo=";
aarch64-linux = "sha256-pYmClIqOo0sRPOkrcF4xQbo0mHlrr1TkhT1fnNyYNck=";
};
patches = flutter3Patches;
};
v2 = flutterDrv {
pname = "flutter";
version = "2.10.5";
engineVersion = "57d3bac3dd5cb5b0e464ab70e7bc8a0d8cf083ab";
dartVersion = "2.16.2";
hash = "sha256-DTZwxlMUYk8NS1SaWUJolXjD+JnRW73Ps5CdRHDGnt0=";
hash = "sha256-MxaWvlcCfXN8gsC116UMzqb4LgixHL3YjrGWy7WYgW4=";
dartHash = {
x86_64-linux = "sha256-egrYd7B4XhkBiHPIFE2zopxKtQ58GqlogAKA/UeiXnI=";
aarch64-linux = "sha256-vmerjXkUAUnI8FjK+62qLqgETmA+BLPEZXFxwYpI+KY=";
x86_64-linux = "sha256-vxKxysg6e3Qxtlp4dLxOZaBtgHGtl7XYd73zFZd9yJc=";
aarch64-linux = "sha256-ZfpR6fj/a9Bsgrg31Z/uIJaCHIWtcQH3VTTVkDJKkwA=";
};
patches = flutter2Patches;
};

View file

@ -0,0 +1,128 @@
{ lib
, stdenv
, hostPlatform
, engineVersion
, fetchzip
, autoPatchelfHook
, gtk3
}:
let
hashes = (import ./hashes.nix).${engineVersion} or
(throw "There are no known artifact hashes for Flutter engine version ${engineVersion}.");
artifacts =
{
common = {
flutter_patched_sdk = { archive = "flutter_patched_sdk.zip"; };
flutter_patched_sdk_product = { archive = "flutter_patched_sdk_product.zip"; };
};
platform = {
android =
(lib.genAttrs
[ "arm" "arm64" "x64" ]
(arch:
{
base = [
{ archive = "artifacts.zip"; }
];
variants = lib.genAttrs [ "profile" "release" ]
(variant: [
{ archive = "artifacts.zip"; }
{ archive = "${lib.toLower hostPlatform.uname.system}-x64.zip"; }
]);
})) //
{
"x86" = {
base = [
{ archive = "artifacts.zip"; }
];
variants.jit-release = [
{ archive = "artifacts.zip"; }
];
};
};
linux = lib.genAttrs
[ "arm64" "x64" ]
(arch:
let
linux-flutter-gtk = {
archive = "linux-${arch}-flutter-gtk.zip";
buildInputs = [ gtk3 ];
};
in
{
base = [
({ archive = "artifacts.zip"; } // lib.optionalAttrs (arch == "arm64") {
# For some reason, the arm64 artifacts are missing shader code.
postPatch = ''
if [ -d shader_lib ]; then
The shader_lib directory has been included in the artifact archive.
This patch should be removed.
fi
ln -s ${lib.findSingle
(pkg: lib.getName pkg == "flutter-artifact-linux-x64-artifacts")
(throw "Could not find the x64 artifact archive.")
(throw "Could not find the correct x64 artifact archive.")
artifactDerivations.platform.linux.x64.base
}/shader_lib .
'';
})
{ archive = "font-subset.zip"; }
linux-flutter-gtk
];
variants = lib.genAttrs [ "debug" "profile" "release" ] (variant: [
linux-flutter-gtk
]);
});
};
};
mkArtifactDerivation = { platform ? null, variant ? null, archive, ... }@args:
let
artifactDirectory = if platform == null then null else "${platform}${lib.optionalString (variant != null) "-${variant}"}";
archiveBasename = lib.removeSuffix ".${(lib.last (lib.splitString "." archive))}" archive;
in
stdenv.mkDerivation ({
pname = "flutter-artifact${lib.optionalString (platform != null) "-${artifactDirectory}"}-${archiveBasename}";
version = engineVersion;
src = fetchzip {
url = "https://storage.googleapis.com/flutter_infra_release/flutter/${engineVersion}${lib.optionalString (platform != null) "/${artifactDirectory}"}/${archive}";
stripRoot = false;
hash = (if artifactDirectory == null then hashes else hashes.${artifactDirectory}).${archive};
};
nativeBuildInputs = [ autoPatchelfHook ];
installPhase = "cp -r . $out";
} // args);
artifactDerivations = {
common = builtins.mapAttrs (name: mkArtifactDerivation) artifacts.common;
platform =
builtins.mapAttrs
(os: architectures:
builtins.mapAttrs
(architecture: variants: {
base = map
(args: mkArtifactDerivation ({
platform = "${os}-${architecture}";
} // args))
variants.base;
variants = builtins.mapAttrs
(variant: variantArtifacts: map
(args: mkArtifactDerivation ({
platform = "${os}-${architecture}";
inherit variant;
} // args))
variantArtifacts)
variants.variants;
})
architectures)
artifacts.platform;
};
in
artifactDerivations

View file

@ -0,0 +1,144 @@
{
"1a65d409c7a1438a34d21b60bf30a6fd5db59314" = {
"flutter_patched_sdk.zip" = "sha256-Pvsjttm5OwpJ/pW4UQXvvEiJYCM5CoZZfVXz5jef37k=";
"flutter_patched_sdk_product.zip" = "sha256-fhj2uUOrLwrzHrM6RNVpPNize5Qu6mLQDcSzLT2TbRA=";
"android-arm" = {
"artifacts.zip" = "sha256-KDMiI6SQoZHfFV5LJJZ7VOGyEKC4UxzRc777j4BbXgM=";
};
"android-arm-profile" = {
"artifacts.zip" = "sha256-MErLoGJWXg4yJ6b6c5bqP8Nat6O7eYSfM71mMNAAQf4=";
"linux-x64.zip" = "sha256-0TZQ05HR7NRqHzeoHZ/sOrjKiSvCpMUH85YXXzV4URg=";
};
"android-arm-release" = {
"artifacts.zip" = "sha256-hU4S4FOqUGokByZ47nzOqQ4A9QFshruqrpJvJUBHUho=";
"linux-x64.zip" = "sha256-AqNlqjOht+c2sdW5ReoF66ZJWJl1W4vGKbQ3YyderRY=";
};
"android-arm64" = {
"artifacts.zip" = "sha256-ApNg3Uu9gyGNsx7sdpTCz1yADVAI5ZuNHgvgiuH9IpQ=";
};
"android-arm64-profile" = {
"artifacts.zip" = "sha256-D/8+WKPIkOaV3PwkCHiJROFlokm4lWWmtPQb93Yqwr0=";
"linux-x64.zip" = "sha256-S0RHLov6/C22VvGdvZV87Ybaxun8YBrw1gTgNklRcM0=";
};
"android-arm64-release" = {
"artifacts.zip" = "sha256-OoYqHtwmT+VWJ+G+sMXM5+ux3h1Fnyo9Vj2za9cm5eE=";
"linux-x64.zip" = "sha256-NuXclg1a+Ofw5AWJ1tajpn2jYEZw6DluWxrFVL8rPfg=";
};
"android-x86" = {
"artifacts.zip" = "sha256-nN66nIrcbJHq2S4oIT5e2NCv7mS5Kw+HBv3ReHs+d3Y=";
};
"android-x86-jit-release" = {
"artifacts.zip" = "sha256-A8F6K78Ykp1rMsUmjD7B9nFFPAubZnqAqgWSzbNCRwk=";
};
"android-x64" = {
"artifacts.zip" = "sha256-hrBvnzCj/24h5kat96avlgXi6WhMsos5aPlkgxOYo8Q=";
};
"android-x64-profile" = {
"artifacts.zip" = "sha256-xzSj/2ah9aQoosaNGkSWFP3bMNJqRSFc0+78XEBHwzM=";
"linux-x64.zip" = "sha256-HfBiz1JWlBQ8KEfmf8uDlVzFlDt3+VF2VeY82tsMjHs=";
};
"android-x64-release" = {
"artifacts.zip" = "sha256-TcfMeA+8Uf9yRrYdEIsjip0cKmSUm2Ow1tkoE9803XY=";
"linux-x64.zip" = "sha256-D6efb6pj9+xjPnJu3O+ZCmwfatBzasuFZEFRntAiU9U=";
};
"linux-arm64" = {
"artifacts.zip" = "sha256-xyKVaEFb5gVkVrPzDrOql5BmXGO0FnCSeXOoQ10ZFrw=";
"font-subset.zip" = "sha256-Ulwb6q2SzB4suMJhAM3zAwWOzlEImlu9Ha+w5u4QqIU=";
"linux-arm64-flutter-gtk.zip" = "sha256-SiYOH++py4zeoD3BkNayqy/C9Zz9OiYQ5+u+pDLIpWg=";
};
"linux-arm64-debug" = {
"linux-arm64-flutter-gtk.zip" = "sha256-SiYOH++py4zeoD3BkNayqy/C9Zz9OiYQ5+u+pDLIpWg=";
};
"linux-arm64-profile" = {
"linux-arm64-flutter-gtk.zip" = "sha256-xB0eqrBYD7vhOwYUgJwNaBftNZJgdwxA9AUpEfX0iFs=";
};
"linux-arm64-release" = {
"linux-arm64-flutter-gtk.zip" = "sha256-aHLKV129WIRsLUG6xTMwCKB4eXD3jonqinjI8KSsOus=";
};
"linux-x64" = {
"artifacts.zip" = "sha256-+zIABFXUpiqn3OMoLcU4NDLxZ1y9z0r46iCTNRHAkz8=";
"font-subset.zip" = "sha256-W4SRPvA4rraVqN1ehbY6MFL7ZIWDHVJhjlLtxyUJJKY=";
"linux-x64-flutter-gtk.zip" = "sha256-boICnuJF4zqGb7kaN5haO/df9hC9KeJidt3uIK06S7M=";
};
"linux-x64-debug" = {
"linux-x64-flutter-gtk.zip" = "sha256-boICnuJF4zqGb7kaN5haO/df9hC9KeJidt3uIK06S7M=";
};
"linux-x64-profile" = {
"linux-x64-flutter-gtk.zip" = "sha256-RAsgupVF18IxLaP8tJ7XRQ8y/um46nlpA8fDITPwLqY=";
};
"linux-x64-release" = {
"linux-x64-flutter-gtk.zip" = "sha256-RAsgupVF18IxLaP8tJ7XRQ8y/um46nlpA8fDITPwLqY=";
};
};
"57d3bac3dd5cb5b0e464ab70e7bc8a0d8cf083ab" = {
"flutter_patched_sdk.zip" = "sha256-A/y5Y+Aw0CUhXABbdyQcGCSnSbO7Ask+71m8LZDSjH4=";
"flutter_patched_sdk_product.zip" = "sha256-VPxF4NrTUhFbpztyPnLEiC9Cy0kDDbYvy21kA5ES4HM=";
"android-arm" = {
"artifacts.zip" = "sha256-3igOO+rgFh0fNTIIiiucqSmqC+NKFPG5H1CnIa9bDcM=";
};
"android-arm-profile" = {
"artifacts.zip" = "sha256-qai254LNrQXJBsaoQgXao6mBpzzcYHh4sUESurSyxNA=";
"linux-x64.zip" = "sha256-hBkntf1fX5w752ly6lVUHm6wEM/4ep9guJGma3SKjxU=";
};
"android-arm-release" = {
"artifacts.zip" = "sha256-7yuXIJyErb1PZyk56+TtlJY0o1EOwmdAvpVfGGAteuA=";
"linux-x64.zip" = "sha256-v/jBnE662XOX/fOhYbve7ZiQwVu0haIMOD532Vdj9Yw=";
};
"android-arm64" = {
"artifacts.zip" = "sha256-Llxu8+SkYEtnoiMf01rffPpF/AjrlV+QPuAW850oMzo=";
};
"android-arm64-profile" = {
"artifacts.zip" = "sha256-su4U80supv8Q+2kE/5FTybiA5NFbKNMHqdB0NHCqrVI=";
"linux-x64.zip" = "sha256-yGt0SztNxYHDwZ1DwzLg5REE8rmMRKNn7GfCQ+GEHBw=";
};
"android-arm64-release" = {
"artifacts.zip" = "sha256-+p1+SXSEglR3jqWc/jKgmtR9nOGgMRGC+anoTs1kRc8=";
"linux-x64.zip" = "sha256-5UiG5gxOso8NO+7nkb6bjxW8e/Tr7mlvPRUagSRTCNs=";
};
"android-x86" = {
"artifacts.zip" = "sha256-Cbo17VYWaclyO1RLHkwjbqoFVZ283IgGdN0uDdiWvQs=";
};
"android-x86-jit-release" = {
"artifacts.zip" = "sha256-gSPm2tClTj2vEYtGKgobD/mebWLNlDp8nEoFX0rhEOk=";
};
"android-x64" = {
"artifacts.zip" = "sha256-PVb1aKMMTlDT41O2MZRAUjCq8h+m/s2h5qOnEFPd77w=";
};
"android-x64-profile" = {
"artifacts.zip" = "sha256-gZSSRCDy42AMLMiu/KH7YsDuFVaxRcoyXzUgV8V025Y=";
"linux-x64.zip" = "sha256-9+LCjeI18u/GlPDMIl6Jx6b++lc90fJ5tVBlDR+ctDs=";
};
"android-x64-release" = {
"artifacts.zip" = "sha256-rsS08VP86/b2S0TEYusCEJBvS4BuevsmV9REAxRgJIc=";
"linux-x64.zip" = "sha256-H4nFCJ+iCUzIwHogYzS+h33eDMaFnz71dcDLSQW1aPg=";
};
"linux-arm64" = {
"artifacts.zip" = "sha256-kCxsKQQQX6wzhD46bfoflKdz3AYYkoSyavhfyTDuHLU=";
"font-subset.zip" = "sha256-Yk6JsNWe7ftEQU/TsjDUZSFeLzeIbcS63lhl8fsWsdk=";
"linux-arm64-flutter-gtk.zip" = "sha256-girVdkXrTO5tssoi+eKwG9ykstCR/VOx8zWtcAz8AKM=";
};
"linux-arm64-debug" = {
"linux-arm64-flutter-gtk.zip" = "sha256-girVdkXrTO5tssoi+eKwG9ykstCR/VOx8zWtcAz8AKM=";
};
"linux-arm64-profile" = {
"linux-arm64-flutter-gtk.zip" = "sha256-VL5cwYaZ1FOJ3TwJzbgvHDQwkU9NrHGnf/tQhZ/dAGg=";
};
"linux-arm64-release" = {
"linux-arm64-flutter-gtk.zip" = "sha256-27hy7mLFCLkqJbn+5p5eJdYnfBKTyfFe98iUMmKyz4g=";
};
"linux-x64" = {
"artifacts.zip" = "sha256-JgEX+rKxdcWBBaxyR42eC7qOAvaawF9M2+rfaD4IgeA=";
"font-subset.zip" = "sha256-5EoxBrxSjaLLd+rKrxVYNoUZaejk0qcQ5LVsmqtKc2g=";
"linux-x64-flutter-gtk.zip" = "sha256-MH5HDPoXXi/KpQLQ0U1tQzZ0sbZx1RVhZtQ7L+WhZgk=";
};
"linux-x64-debug" = {
"linux-x64-flutter-gtk.zip" = "sha256-MH5HDPoXXi/KpQLQ0U1tQzZ0sbZx1RVhZtQ7L+WhZgk=";
};
"linux-x64-profile" = {
"linux-x64-flutter-gtk.zip" = "sha256-r2hB/AKrB5vNga2fve4tTM4j+Zp9KDqNlTjKQhQvbaI=";
};
"linux-x64-release" = {
"linux-x64-flutter-gtk.zip" = "sha256-muREs2iUiHCZM+SGN5q3HRRGnejJapKN582Aeog49MI=";
};
};
}

View file

@ -1,190 +1,196 @@
{ pname
, version
{ version
, engineVersion
, patches
, dart
, src
}:
{ bash
, buildFHSEnv
, cacert
, git
, runCommand
, stdenv
, lib
, alsa-lib
, dbus
, expat
, libpulseaudio
, libuuid
, libX11
, libxcb
, libXcomposite
, libXcursor
, libXdamage
, libXfixes
, libXrender
, libXtst
, libXi
, libXext
, libGL
, nspr
, nss
, systemd
, which
, callPackage
}:
let
drvName = "flutter-${version}";
flutter = stdenv.mkDerivation {
name = "${drvName}-unwrapped";
buildInputs = [ git ];
inherit src patches version;
postPatch = ''
patchShebangs --build ./bin/
'';
buildPhase = ''
export FLUTTER_ROOT="$(pwd)"
export FLUTTER_TOOLS_DIR="$FLUTTER_ROOT/packages/flutter_tools"
export SCRIPT_PATH="$FLUTTER_TOOLS_DIR/bin/flutter_tools.dart"
export SNAPSHOT_PATH="$FLUTTER_ROOT/bin/cache/flutter_tools.snapshot"
export STAMP_PATH="$FLUTTER_ROOT/bin/cache/flutter_tools.stamp"
export DART_SDK_PATH="${dart}"
HOME=../.. # required for pub upgrade --offline, ~/.pub-cache
# path is relative otherwise it's replaced by /build/flutter
pushd "$FLUTTER_TOOLS_DIR"
${dart}/bin/dart pub get --offline
popd
local revision="$(cd "$FLUTTER_ROOT"; git rev-parse HEAD)"
${dart}/bin/dart --snapshot="$SNAPSHOT_PATH" --packages="$FLUTTER_TOOLS_DIR/.dart_tool/package_config.json" "$SCRIPT_PATH"
echo "$revision" > "$STAMP_PATH"
echo -n "${version}" > version
rm -r bin/cache/{artifacts,dart-sdk,downloads}
rm bin/cache/*.stamp
'';
installPhase = ''
runHook preInstall
mkdir -p $out
cp -r . $out
mkdir -p $out/bin/cache/
ln -sf ${dart} $out/bin/cache/dart-sdk
runHook postInstall
'';
doInstallCheck = true;
nativeInstallCheckInputs = [ which ];
installCheckPhase = ''
runHook preInstallCheck
export HOME="$(mktemp -d)"
$out/bin/flutter config --android-studio-dir $HOME
$out/bin/flutter config --android-sdk $HOME
$out/bin/flutter --version | fgrep -q '${version}'
runHook postInstallCheck
'';
};
# Wrap flutter inside an fhs user env to allow execution of binary,
# like adb from $ANDROID_HOME or java from android-studio.
fhsEnv = buildFHSEnv {
name = "${drvName}-fhs-env";
multiPkgs = pkgs: [
# Flutter only use these certificates
(runCommand "fedoracert" { } ''
mkdir -p $out/etc/pki/tls/
ln -s ${cacert}/etc/ssl/certs $out/etc/pki/tls/certs
'')
pkgs.zlib
, includedEngineArtifacts ? {
common = [
"flutter_patched_sdk"
"flutter_patched_sdk_product"
];
targetPkgs = pkgs:
with pkgs; [
bash
curl
dart
git
unzip
which
xz
# flutter test requires this lib
libGLU
# for android emulator
alsa-lib
dbus
expat
libpulseaudio
libuuid
libX11
libxcb
libXcomposite
libXcursor
libXdamage
libXext
libXfixes
libXi
libXrender
libXtst
libGL
nspr
nss
systemd
];
};
in
let
self = (self:
runCommand drvName
{
startScript = ''
#!${bash}/bin/bash
export PUB_CACHE=''${PUB_CACHE:-"$HOME/.pub-cache"}
export ANDROID_EMULATOR_USE_SYSTEM_LIBS=1
${fhsEnv}/bin/${drvName}-fhs-env ${flutter}/bin/flutter --no-version-check "$@"
'';
preferLocalBuild = true;
allowSubstitutes = false;
passthru = {
unwrapped = flutter;
inherit dart;
mkFlutterApp = callPackage ../../../build-support/flutter {
flutter = self;
platform = {
android = lib.optionalAttrs stdenv.hostPlatform.isx86_64
((lib.genAttrs [ "arm" "arm64" "x64" ] (architecture: [ "profile" "release" ])) // { x86 = [ "jit-release" ]; });
linux = lib.optionals stdenv.hostPlatform.isLinux
(lib.genAttrs ((lib.optional stdenv.hostPlatform.isx86_64 "x64") ++ (lib.optional stdenv.hostPlatform.isAarch64 "arm64"))
(architecture: [ "debug" "profile" "release" ]));
};
};
meta = with lib; {
description = "Flutter is Google's SDK for building mobile, web and desktop with Dart";
longDescription = ''
Flutter is Googles UI toolkit for building beautiful,
natively compiled applications for mobile, web, and desktop from a single codebase.
'';
homepage = "https://flutter.dev";
license = licenses.bsd3;
platforms = [ "x86_64-linux" "aarch64-linux" ];
maintainers = with maintainers; [ babariviere ericdallo h7x4 ];
};
} ''
mkdir -p $out/bin
}
mkdir -p $out/bin/cache/
ln -sf ${dart} $out/bin/cache/dart-sdk
, lib
, callPackage
, stdenv
, runCommandLocal
, symlinkJoin
, lndir
, git
, which
}@args:
echo -n "$startScript" > $out/bin/${pname}
chmod +x $out/bin/${pname}
'') self;
let
engineArtifactDirectory =
let
engineArtifacts = callPackage ./engine-artifacts { inherit engineVersion; };
in
runCommandLocal "flutter-engine-artifacts-${version}" { }
(
let
mkCommonArtifactLinkCommand = { artifact }:
''
mkdir -p $out/common
${lndir}/bin/lndir -silent ${artifact} $out/common
'';
mkPlatformArtifactLinkCommand = { artifact, os, architecture, variant ? null }:
let
artifactDirectory = "${os}-${architecture}${lib.optionalString (variant != null) "-${variant}"}";
in
''
mkdir -p $out/${artifactDirectory}
${lndir}/bin/lndir -silent ${artifact} $out/${artifactDirectory}
'';
in
''
${
builtins.concatStringsSep "\n"
((map (name: mkCommonArtifactLinkCommand {
artifact = engineArtifacts.common.${name};
}) (if includedEngineArtifacts ? common then includedEngineArtifacts.common else [ ])) ++
(builtins.foldl' (commands: os: commands ++
(builtins.foldl' (commands: architecture: commands ++
(builtins.foldl' (commands: variant: commands ++
(map (artifact: mkPlatformArtifactLinkCommand {
inherit artifact os architecture variant;
}) engineArtifacts.platform.${os}.${architecture}.variants.${variant}))
(map (artifact: mkPlatformArtifactLinkCommand {
inherit artifact os architecture;
}) engineArtifacts.platform.${os}.${architecture}.base)
includedEngineArtifacts.platform.${os}.${architecture}))
[] (builtins.attrNames includedEngineArtifacts.platform.${os})))
[] (builtins.attrNames (if includedEngineArtifacts ? platform then includedEngineArtifacts.platform else { }))))
}
''
);
unwrapped =
stdenv.mkDerivation {
name = "flutter-${version}-unwrapped";
inherit src patches version;
outputs = [ "out" "cache" ];
buildInputs = [ git ];
preConfigure = ''
if [ "$(< bin/internal/engine.version)" != '${engineVersion}' ]; then
echo 1>&2 "The given engine version (${engineVersion}) does not match the version required by the Flutter SDK ($(< bin/internal/engine.version))."
exit 1
fi
'';
postPatch = ''
patchShebangs --build ./bin/
'';
buildPhase = ''
export FLUTTER_ROOT="$(pwd)"
export FLUTTER_TOOLS_DIR="$FLUTTER_ROOT/packages/flutter_tools"
export SCRIPT_PATH="$FLUTTER_TOOLS_DIR/bin/flutter_tools.dart"
export SNAPSHOT_PATH="$FLUTTER_ROOT/bin/cache/flutter_tools.snapshot"
export STAMP_PATH="$FLUTTER_ROOT/bin/cache/flutter_tools.stamp"
export DART_SDK_PATH="${dart}"
# The Flutter tool compilation requires dependencies to be cached, as there is no Internet access.
# Dart expects package caches to be mutable, and does not support composing cache directories.
# The packages cached during the build therefore cannot be easily used. They are provided through
# the derivation's "cache" output, though, in case they are needed.
#
# Note that non-cached packages will normally be fetched from the Internet when they are needed, so Flutter
# will function without an existing package cache as long as it has an Internet connection.
export PUB_CACHE="$cache"
if [ -d .pub-preload-cache ]; then
${dart}/bin/dart pub cache preload .pub-preload-cache/*
elif [ -d .pub-cache ]; then
mv .pub-cache "$PUB_CACHE"
else
echo 'ERROR: Failed to locate the Dart package cache required to build the Flutter tool.'
exit 1
fi
pushd "$FLUTTER_TOOLS_DIR"
${dart}/bin/dart pub get --offline
popd
local revision="$(cd "$FLUTTER_ROOT"; git rev-parse HEAD)"
${dart}/bin/dart --snapshot="$SNAPSHOT_PATH" --packages="$FLUTTER_TOOLS_DIR/.dart_tool/package_config.json" "$SCRIPT_PATH"
echo "$revision" > "$STAMP_PATH"
echo -n "${version}" > version
# Certain prebuilts should be replaced with Nix-built (or at least Nix-patched) equivalents.
rm -r \
bin/cache/dart-sdk \
bin/cache/artifacts/engine
'';
installPhase = ''
runHook preInstall
mkdir -p $out
cp -r . $out
ln -sf ${dart} $out/bin/cache/dart-sdk
ln -sf ${engineArtifactDirectory} $out/bin/cache/artifacts/engine
runHook postInstall
'';
doInstallCheck = true;
nativeInstallCheckInputs = [ which ];
installCheckPhase = ''
runHook preInstallCheck
export HOME="$(mktemp -d)"
$out/bin/flutter config --android-studio-dir $HOME
$out/bin/flutter config --android-sdk $HOME
$out/bin/flutter --version | fgrep -q '${version}'
runHook postInstallCheck
'';
passthru = {
inherit dart;
# 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;
buildFlutterApplication = callPackage ../../../build-support/flutter {
# Package a minimal version of Flutter that only uses Linux desktop release artifacts.
flutter = callPackage ./wrapper.nix {
flutter = callPackage ./flutter.nix (args // {
includedEngineArtifacts = {
common = [ "flutter_patched_sdk_product" ];
platform.linux = lib.optionals stdenv.hostPlatform.isLinux
(lib.genAttrs ((lib.optional stdenv.hostPlatform.isx86_64 "x64") ++ (lib.optional stdenv.hostPlatform.isAarch64 "arm64"))
(architecture: [ "release" ]));
};
});
};
};
};
meta = with lib; {
description = "Flutter is Google's SDK for building mobile, web and desktop with Dart";
longDescription = ''
Flutter is Googles UI toolkit for building beautiful,
natively compiled applications for mobile, web, and desktop from a single codebase.
'';
homepage = "https://flutter.dev";
license = licenses.bsd3;
platforms = [ "x86_64-linux" "aarch64-linux" ];
maintainers = with maintainers; [ babariviere ericdallo FlafyDev gilice hacker1024 ];
};
};
in
self
unwrapped

View file

@ -0,0 +1,4 @@
{ callPackage }:
{
}

View file

@ -0,0 +1,17 @@
diff --git a/packages/flutter_tools/lib/src/build_system/targets/assets.dart b/packages/flutter_tools/lib/src/build_system/targets/assets.dart
index 68a4cd0257..1e212b9b0d 100644
--- a/packages/flutter_tools/lib/src/build_system/targets/assets.dart
+++ b/packages/flutter_tools/lib/src/build_system/targets/assets.dart
@@ -101,7 +101,11 @@ Future<Depfile> copyAssets(Environment environment, Directory outputDirectory, {
outputPath: file.path,
relativePath: entry.key,
)) {
- await (content.file as File).copy(file.path);
+ // Not using File.copy because it preserves permissions.
+ final sourceFile = content.file as File;
+ final destinationFile = file;
+
+ await destinationFile.writeAsBytes(await sourceFile.readAsBytes(), flush: true);
}
} else {
await file.writeAsBytes(await entry.value.contentsAsBytes());

View file

@ -34,3 +34,16 @@ index 396756808e..d324a6df59 100644
// See if the user specified a specific device.
globals.deviceManager?.specifiedDeviceId = topLevelResults['device-id'] as String?;
diff --git a/packages/flutter_tools/lib/src/cache.dart b/packages/flutter_tools/lib/src/cache.dart
index defc86cc20..6c0824c965 100644
--- a/packages/flutter_tools/lib/src/cache.dart
+++ b/packages/flutter_tools/lib/src/cache.dart
@@ -666,6 +666,7 @@ class Cache {
/// Update the cache to contain all `requiredArtifacts`.
Future<void> updateAll(Set<DevelopmentArtifact> requiredArtifacts) async {
+ return;
if (!_lockEnabled) {
return;
}

View file

@ -1,31 +1,5 @@
diff --git a/packages/flutter_tools/lib/src/asset.dart b/packages/flutter_tools/lib/src/asset.dart
index ed42baea29..12941f733a 100644
--- a/packages/flutter_tools/lib/src/asset.dart
+++ b/packages/flutter_tools/lib/src/asset.dart
@@ -11,11 +11,11 @@ import 'base/file_system.dart';
import 'base/logger.dart';
import 'base/platform.dart';
import 'build_info.dart';
-import 'cache.dart';
import 'convert.dart';
import 'dart/package_map.dart';
import 'devfs.dart';
import 'flutter_manifest.dart';
+import 'globals.dart' as globals;
import 'license_collector.dart';
import 'project.dart';
@@ -504,7 +504,7 @@ class ManifestAssetBundle implements AssetBundle {
}
final Uri entryUri = _fileSystem.path.toUri(asset);
result.add(_Asset(
- baseDir: _fileSystem.path.join(Cache.flutterRoot!, 'bin', 'cache', 'artifacts', 'material_fonts'),
+ baseDir: _fileSystem.path.join(globals.fsUtils.homeDirPath!, '.cache', 'flutter', 'artifacts', 'material_fonts'),
relativeUri: Uri(path: entryUri.pathSegments.last),
entryUri: entryUri,
package: null,
diff --git a/packages/flutter_tools/lib/src/cache.dart b/packages/flutter_tools/lib/src/cache.dart
index defc86cc20..7fdf14d112 100644
index dd80b1e46e..8e54517765 100644
--- a/packages/flutter_tools/lib/src/cache.dart
+++ b/packages/flutter_tools/lib/src/cache.dart
@@ -22,6 +22,7 @@ import 'base/user_messages.dart';
@ -36,7 +10,7 @@ index defc86cc20..7fdf14d112 100644
const String kFlutterRootEnvironmentVariableName = 'FLUTTER_ROOT'; // should point to //flutter/ (root of flutter/flutter repo)
const String kFlutterEngineEnvironmentVariableName = 'FLUTTER_ENGINE'; // should point to //engine/src/ (root of flutter/engine repo)
@@ -322,8 +323,13 @@ class Cache {
@@ -318,8 +319,13 @@ class Cache {
return;
}
assert(_lock == null);
@ -51,7 +25,7 @@ index defc86cc20..7fdf14d112 100644
try {
_lock = lockFile.openSync(mode: FileMode.write);
} on FileSystemException catch (e) {
@@ -382,8 +388,7 @@ class Cache {
@@ -378,8 +384,7 @@ class Cache {
String get devToolsVersion {
if (_devToolsVersion == null) {
@ -61,12 +35,3 @@ index defc86cc20..7fdf14d112 100644
if (!devToolsDir.existsSync()) {
throw Exception('Could not find directory at ${devToolsDir.path}');
}
@@ -536,7 +541,7 @@ class Cache {
if (_rootOverride != null) {
return _fileSystem.directory(_fileSystem.path.join(_rootOverride!.path, 'bin', 'cache'));
} else {
- return _fileSystem.directory(_fileSystem.path.join(flutterRoot!, 'bin', 'cache'));
+ return _fileSystem.directory(_fileSystem.path.join(globals.fsUtils.homeDirPath!, '.cache', 'flutter'));
}
}

View file

@ -0,0 +1,17 @@
diff --git a/packages/flutter_tools/lib/src/build_system/targets/assets.dart b/packages/flutter_tools/lib/src/build_system/targets/assets.dart
index 5f458bd53e..7a6c59f98d 100644
--- a/packages/flutter_tools/lib/src/build_system/targets/assets.dart
+++ b/packages/flutter_tools/lib/src/build_system/targets/assets.dart
@@ -128,7 +128,11 @@ Future<Depfile> copyAssets(
break;
}
if (doCopy) {
- await (content.file as File).copy(file.path);
+ // Not using File.copy because it preserves permissions.
+ final sourceFile = content.file as File;
+ final destinationFile = file;
+
+ await destinationFile.writeAsBytes(await sourceFile.readAsBytes(), flush: true);
}
} else {
await file.writeAsBytes(await entry.value.contentsAsBytes());

View file

@ -34,3 +34,16 @@ index 738fef987d..03a152e64f 100644
// See if the user specified a specific device.
globals.deviceManager?.specifiedDeviceId = topLevelResults['device-id'] as String?;
diff --git a/packages/flutter_tools/lib/src/cache.dart b/packages/flutter_tools/lib/src/cache.dart
index dd80b1e46e..8e54517765 100644
--- a/packages/flutter_tools/lib/src/cache.dart
+++ b/packages/flutter_tools/lib/src/cache.dart
@@ -668,6 +668,7 @@
/// Update the cache to contain all `requiredArtifacts`.
Future<void> updateAll(Set<DevelopmentArtifact> requiredArtifacts, {bool offline = false}) async {
+ return;
if (!_lockEnabled) {
return;
}

View file

@ -0,0 +1,12 @@
diff --git a/packages/flutter_tools/lib/src/doctor.dart b/packages/flutter_tools/lib/src/doctor.dart
index 651dc6cf36..236eb370e1 100644
--- a/packages/flutter_tools/lib/src/doctor.dart
+++ b/packages/flutter_tools/lib/src/doctor.dart
@@ -515,7 +515,6 @@ class FlutterValidator extends DoctorValidator {
final String flutterRoot = _flutterRoot();
messages.add(_getFlutterVersionMessage(frameworkVersion, versionChannel, flutterRoot));
- _validateRequiredBinaries(flutterRoot).forEach(messages.add);
messages.add(_getFlutterUpstreamMessage(version));
if (gitUrl != null) {
messages.add(ValidationMessage(_userMessages.flutterGitUrl(gitUrl)));

View file

@ -1,26 +1,3 @@
diff --git a/packages/flutter_tools/lib/src/artifacts.dart b/packages/flutter_tools/lib/src/artifacts.dart
diff --git a/packages/flutter_tools/lib/src/asset.dart b/packages/flutter_tools/lib/src/asset.dart
index 9dd7272fbe..642c8e48e4 100644
--- a/packages/flutter_tools/lib/src/asset.dart
+++ b/packages/flutter_tools/lib/src/asset.dart
@@ -16,6 +16,7 @@ import 'convert.dart';
import 'dart/package_map.dart';
import 'devfs.dart';
import 'flutter_manifest.dart';
+import 'globals.dart' as globals;
import 'license_collector.dart';
import 'project.dart';
@@ -530,8 +531,7 @@ class ManifestAssetBundle implements AssetBundle {
final Uri entryUri = _fileSystem.path.toUri(asset);
result.add(_Asset(
baseDir: _fileSystem.path.join(
- Cache.flutterRoot!,
- 'bin', 'cache', 'artifacts', 'material_fonts',
+ globals.fsUtils.homeDirPath!, '.cache', 'flutter', 'artifacts', 'material_fonts',
),
relativeUri: Uri(path: entryUri.pathSegments.last),
entryUri: entryUri,
diff --git a/packages/flutter_tools/lib/src/cache.dart b/packages/flutter_tools/lib/src/cache.dart
index dd80b1e46e..8e54517765 100644
--- a/packages/flutter_tools/lib/src/cache.dart
@ -58,141 +35,3 @@ index dd80b1e46e..8e54517765 100644
if (!devToolsDir.existsSync()) {
throw Exception('Could not find directory at ${devToolsDir.path}');
}
@@ -532,7 +537,7 @@ class Cache {
if (_rootOverride != null) {
return _fileSystem.directory(_fileSystem.path.join(_rootOverride!.path, 'bin', 'cache'));
} else {
- return _fileSystem.directory(_fileSystem.path.join(flutterRoot!, 'bin', 'cache'));
+ return _fileSystem.directory(_fileSystem.path.join(globals.fsUtils.homeDirPath!, '.cache', 'flutter'));
}
}
index c539d67156..4e0a64f7a9 100644
--- a/packages/flutter_tools/lib/src/artifacts.dart
+++ b/packages/flutter_tools/lib/src/artifacts.dart
@@ -346,10 +346,10 @@ class CachedArtifacts implements Artifacts {
) {
switch (artifact) {
case HostArtifact.engineDartSdkPath:
- final String path = _dartSdkPath(_cache);
+ final String path = _dartSdkPath(_fileSystem);
return _fileSystem.directory(path);
case HostArtifact.engineDartBinary:
- final String path = _fileSystem.path.join(_dartSdkPath(_cache), 'bin', _hostArtifactToFileName(artifact, _platform));
+ final String path = _fileSystem.path.join(_dartSdkPath(_fileSystem), 'bin', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.flutterWebSdk:
final String path = _getFlutterWebSdkPath();
@@ -398,7 +398,7 @@ class CachedArtifacts implements Artifacts {
case HostArtifact.dart2jsSnapshot:
case HostArtifact.dartdevcSnapshot:
case HostArtifact.kernelWorkerSnapshot:
- final String path = _fileSystem.path.join(_dartSdkPath(_cache), 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform));
+ final String path = _fileSystem.path.join(_dartSdkPath(_fileSystem), 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.iosDeploy:
final String artifactFileName = _hostArtifactToFileName(artifact, _platform);
@@ -465,11 +465,13 @@ class CachedArtifacts implements Artifacts {
String _getAndroidArtifactPath(Artifact artifact, TargetPlatform platform, BuildMode mode) {
final String engineDir = _getEngineArtifactsPath(platform, mode)!;
switch (artifact) {
+ case Artifact.frontendServerSnapshotForEngineDartSdk:
+ assert(mode != BuildMode.debug, 'Artifact $artifact only available in non-debug mode.');
+ return _fileSystem.path.join(engineDir, _artifactToFileName(artifact));
case Artifact.genSnapshot:
assert(mode != BuildMode.debug, 'Artifact $artifact only available in non-debug mode.');
final String hostPlatform = getNameForHostPlatform(getCurrentHostPlatform());
return _fileSystem.path.join(engineDir, hostPlatform, _artifactToFileName(artifact));
- case Artifact.frontendServerSnapshotForEngineDartSdk:
case Artifact.constFinder:
case Artifact.flutterFramework:
case Artifact.flutterMacOSFramework:
@@ -497,13 +499,13 @@ class CachedArtifacts implements Artifacts {
switch (artifact) {
case Artifact.genSnapshot:
case Artifact.flutterXcframework:
+ case Artifact.frontendServerSnapshotForEngineDartSdk:
final String artifactFileName = _artifactToFileName(artifact)!;
final String engineDir = _getEngineArtifactsPath(platform, mode)!;
return _fileSystem.path.join(engineDir, artifactFileName);
case Artifact.flutterFramework:
final String engineDir = _getEngineArtifactsPath(platform, mode)!;
return _getIosEngineArtifactPath(engineDir, environmentType, _fileSystem);
- case Artifact.frontendServerSnapshotForEngineDartSdk:
case Artifact.constFinder:
case Artifact.flutterMacOSFramework:
case Artifact.flutterPatchedSdkPath:
@@ -586,14 +588,10 @@ class CachedArtifacts implements Artifacts {
// For script snapshots any gen_snapshot binary will do. Returning gen_snapshot for
// android_arm in profile mode because it is available on all supported host platforms.
return _getAndroidArtifactPath(artifact, TargetPlatform.android_arm, BuildMode.profile);
- case Artifact.frontendServerSnapshotForEngineDartSdk:
- return _fileSystem.path.join(
- _dartSdkPath(_cache), 'bin', 'snapshots',
- _artifactToFileName(artifact),
- );
case Artifact.flutterTester:
case Artifact.vmSnapshotData:
case Artifact.isolateSnapshotData:
+ case Artifact.frontendServerSnapshotForEngineDartSdk:
case Artifact.icuData:
final String engineArtifactsPath = _cache.getArtifactDirectory('engine').path;
final String platformDirName = _enginePlatformDirectoryName(platform);
@@ -776,7 +774,7 @@ class CachedLocalEngineArtifacts implements LocalEngineArtifacts {
final String path = _fileSystem.path.join(_hostEngineOutPath, 'dart-sdk', 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.dartdevcSnapshot:
- final String path = _fileSystem.path.join(_dartSdkPath(_cache), 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform));
+ final String path = _fileSystem.path.join(_dartSdkPath(_fileSystem), 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform));
return _fileSystem.file(path);
case HostArtifact.kernelWorkerSnapshot:
final String path = _fileSystem.path.join(_hostEngineOutPath, 'dart-sdk', 'bin', 'snapshots', _hostArtifactToFileName(artifact, _platform));
@@ -901,9 +899,7 @@ class CachedLocalEngineArtifacts implements LocalEngineArtifacts {
case Artifact.windowsCppClientWrapper:
return _fileSystem.path.join(_hostEngineOutPath, artifactFileName);
case Artifact.frontendServerSnapshotForEngineDartSdk:
- return _fileSystem.path.join(
- _hostEngineOutPath, 'dart-sdk', 'bin', 'snapshots', artifactFileName,
- );
+ return _fileSystem.path.join(_hostEngineOutPath, 'gen', artifactFileName);
}
}
@@ -1011,8 +1007,8 @@ class OverrideArtifacts implements Artifacts {
}
/// Locate the Dart SDK.
-String _dartSdkPath(Cache cache) {
- return cache.getRoot().childDirectory('dart-sdk').path;
+String _dartSdkPath(FileSystem fileSystem) {
+ return fileSystem.path.join(Cache.flutterRoot!, 'bin', 'cache', 'dart-sdk');
}
class _TestArtifacts implements Artifacts {
diff --git a/packages/flutter_tools/test/general.shard/artifacts_test.dart b/packages/flutter_tools/test/general.shard/artifacts_test.dart
index aed3eb9285..81b8362648 100644
--- a/packages/flutter_tools/test/general.shard/artifacts_test.dart
+++ b/packages/flutter_tools/test/general.shard/artifacts_test.dart
@@ -141,10 +141,6 @@ void main() {
artifacts.getArtifactPath(Artifact.flutterTester, platform: TargetPlatform.linux_arm64),
fileSystem.path.join('root', 'bin', 'cache', 'artifacts', 'engine', 'linux-arm64', 'flutter_tester'),
);
- expect(
- artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk),
- fileSystem.path.join('root', 'bin', 'cache', 'dart-sdk', 'bin', 'snapshots', 'frontend_server.dart.snapshot')
- );
});
testWithoutContext('precompiled web artifact paths are correct', () {
@@ -310,11 +306,6 @@ void main() {
artifacts.getHostArtifact(HostArtifact.engineDartSdkPath).path,
fileSystem.path.join('/out', 'host_debug_unopt', 'dart-sdk'),
);
- expect(
- artifacts.getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk),
- fileSystem.path.join('/out', 'host_debug_unopt', 'dart-sdk', 'bin',
- 'snapshots', 'frontend_server.dart.snapshot')
- );
expect(
artifacts.getHostArtifact(HostArtifact.impellerc).path,
fileSystem.path.join('/out', 'host_debug_unopt', 'impellerc'),

View file

@ -0,0 +1,24 @@
{ symlinkJoin }: flutter:
let
self =
symlinkJoin {
name = "${flutter.name}-sdk-links";
paths = [ flutter flutter.sdk ];
passthru = flutter.passthru // {
# Update the SDK attribute.
# This allows any modified SDK files to be included
# in future invocations.
sdk = self;
};
meta = flutter.meta // {
longDescription = ''
${flutter.meta.longDescription}
Modified binaries are linked into the original SDK directory for use with tools that use the whole SDK.
'';
};
};
in
self

View file

@ -0,0 +1,110 @@
{ lib
, stdenv
, callPackage
, flutter
, supportsLinuxDesktop ? stdenv.isLinux
, extraPkgConfigPackages ? [ ]
, extraLibraries ? [ ]
, extraIncludes ? [ ]
, extraCxxFlags ? [ ]
, extraCFlags ? [ ]
, extraLinkerFlags ? [ ]
, makeWrapper
, runCommandLocal
, writeShellScript
, git
, which
, pkg-config
, atk
, cairo
, gdk-pixbuf
, glib
, gtk3
, harfbuzz
, libepoxy
, pango
, libX11
, xorgproto
, libdeflate
, zlib
, cmake
, ninja
, clang
}:
let
# By default, Flutter stores downloaded files (such as the Pub cache) in the SDK directory.
# Wrap it to ensure that it does not do that, preferring home directories instead.
immutableFlutter = writeShellScript "flutter_immutable" ''
export PUB_CACHE=''${PUB_CACHE:-"$HOME/.pub-cache"}
${flutter}/bin/flutter "$@"
'';
# Tools that the Flutter tool depends on.
tools = [ git which ];
# Libraries that Flutter apps depend on at runtime.
appRuntimeDeps = lib.optionals supportsLinuxDesktop [
atk
cairo
gdk-pixbuf
glib
gtk3
harfbuzz
libepoxy
pango
libX11
libdeflate
];
# Development packages required for compilation.
appBuildDeps =
let
# https://discourse.nixos.org/t/handling-transitive-c-dependencies/5942/3
deps = pkg: builtins.filter lib.isDerivation ((pkg.buildInputs or [ ]) ++ (pkg.propagatedBuildInputs or [ ]));
collect = pkg: lib.unique ([ pkg ] ++ deps pkg ++ builtins.concatMap collect (deps pkg));
in
builtins.concatMap collect appRuntimeDeps;
# Some header files and libraries are not properly located by the Flutter SDK.
# They must be manually included.
appStaticBuildDeps = (lib.optionals supportsLinuxDesktop [ libX11 xorgproto zlib ]) ++ extraLibraries;
# Tools used by the Flutter SDK to compile applications.
buildTools = lib.optionals supportsLinuxDesktop [
pkg-config
cmake
ninja
clang
];
# Nix-specific compiler configuration.
pkgConfigPackages = map (lib.getOutput "dev") (appBuildDeps ++ extraPkgConfigPackages);
includeFlags = map (pkg: "-isystem ${lib.getOutput "dev" pkg}/include") (appStaticBuildDeps ++ extraIncludes);
linkerFlags = (map (pkg: "-rpath,${lib.getOutput "lib" pkg}/lib") appRuntimeDeps) ++ extraLinkerFlags;
in
(callPackage ./sdk-symlink.nix { }) (runCommandLocal "flutter-wrapped"
{
nativeBuildInputs = [ makeWrapper ];
passthru = flutter.passthru // {
inherit (flutter) version;
unwrapped = flutter;
};
inherit (flutter) meta;
} ''
for path in ${builtins.concatStringsSep " " (builtins.foldl' (paths: pkg: paths ++ (map (directory: "'${pkg}/${directory}/pkgconfig'") ["lib" "share"])) [ ] pkgConfigPackages)}; do
addToSearchPath FLUTTER_PKG_CONFIG_PATH "$path"
done
mkdir -p $out/bin
makeWrapper '${immutableFlutter}' $out/bin/flutter \
--set-default ANDROID_EMULATOR_USE_SYSTEM_LIBS 1 \
--prefix PATH : '${lib.makeBinPath (tools ++ buildTools)}' \
--prefix PKG_CONFIG_PATH : "$FLUTTER_PKG_CONFIG_PATH" \
--prefix LIBRARY_PATH : '${lib.makeLibraryPath appStaticBuildDeps}' \
--prefix CXXFLAGS "''\t" '${builtins.concatStringsSep " " (includeFlags ++ extraCxxFlags)}' \
--prefix CFLAGS "''\t" '${builtins.concatStringsSep " " (includeFlags ++ extraCFlags)}' \
--prefix LDFLAGS "''\t" '${builtins.concatStringsSep " " (map (flag: "-Wl,${flag}") linkerFlags)}'
'')

View file

@ -1,17 +1,15 @@
{ lib
, flutter2
, fetchFromGitHub
, stdenv
}:
flutter2.mkFlutterApp {
flutter2.buildFlutterApplication {
pname = "firmware-updater";
version = "unstable";
vendorHash =
if stdenv.system == "aarch64-linux"
then "sha256-+ACmcIKXtGtaYBuwc7jY9hEdIS9qxQCbuxRKJQohX5A="
else "sha256-nPblucEpNCBJYpIqx1My6SWq8CjXYuHDG/uphdcrWjQ=";
pubspecLockFile = ./pubspec.lock;
depsListFile = ./deps.json;
vendorHash = "sha256-kKfe+7obb2fihrca+mjCM2+51wNkbPLEPFLpXzK5Wvc=";
src = fetchFromGitHub {
owner = "canonical";

View file

@ -0,0 +1,763 @@
[
{
"name": "firmware_updater",
"version": "0.0.0",
"kind": "root",
"source": "root",
"dependencies": [
"collection",
"dio",
"flutter",
"flutter_html",
"flutter_localizations",
"fwupd",
"path",
"provider",
"yaru",
"yaru_icons",
"yaru_widgets",
"flutter_lints",
"flutter_test"
]
},
{
"name": "flutter_test",
"version": "0.0.0",
"kind": "dev",
"source": "sdk",
"dependencies": [
"flutter",
"test_api",
"path",
"fake_async",
"clock",
"stack_trace",
"vector_math",
"async",
"boolean_selector",
"characters",
"charcode",
"collection",
"matcher",
"material_color_utilities",
"meta",
"source_span",
"stream_channel",
"string_scanner",
"term_glyph",
"typed_data"
]
},
{
"name": "typed_data",
"version": "1.3.0",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"collection"
]
},
{
"name": "collection",
"version": "1.15.0",
"kind": "direct",
"source": "hosted",
"dependencies": []
},
{
"name": "term_glyph",
"version": "1.2.0",
"kind": "transitive",
"source": "hosted",
"dependencies": []
},
{
"name": "string_scanner",
"version": "1.1.0",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"charcode",
"source_span"
]
},
{
"name": "source_span",
"version": "1.8.1",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"collection",
"path",
"term_glyph"
]
},
{
"name": "path",
"version": "1.8.0",
"kind": "direct",
"source": "hosted",
"dependencies": []
},
{
"name": "charcode",
"version": "1.3.1",
"kind": "transitive",
"source": "hosted",
"dependencies": []
},
{
"name": "stream_channel",
"version": "2.1.0",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"async"
]
},
{
"name": "async",
"version": "2.8.2",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"collection",
"meta"
]
},
{
"name": "meta",
"version": "1.7.0",
"kind": "transitive",
"source": "hosted",
"dependencies": []
},
{
"name": "material_color_utilities",
"version": "0.1.3",
"kind": "transitive",
"source": "hosted",
"dependencies": []
},
{
"name": "matcher",
"version": "0.12.11",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"stack_trace"
]
},
{
"name": "stack_trace",
"version": "1.10.0",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"path"
]
},
{
"name": "characters",
"version": "1.2.0",
"kind": "transitive",
"source": "hosted",
"dependencies": []
},
{
"name": "boolean_selector",
"version": "2.1.0",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"source_span",
"string_scanner"
]
},
{
"name": "vector_math",
"version": "2.1.1",
"kind": "transitive",
"source": "hosted",
"dependencies": []
},
{
"name": "clock",
"version": "1.1.0",
"kind": "transitive",
"source": "hosted",
"dependencies": []
},
{
"name": "fake_async",
"version": "1.2.0",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"clock",
"collection"
]
},
{
"name": "test_api",
"version": "0.4.8",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"async",
"boolean_selector",
"collection",
"meta",
"source_span",
"stack_trace",
"stream_channel",
"string_scanner",
"term_glyph",
"matcher"
]
},
{
"name": "flutter",
"version": "0.0.0",
"kind": "direct",
"source": "sdk",
"dependencies": [
"characters",
"collection",
"material_color_utilities",
"meta",
"typed_data",
"vector_math",
"sky_engine"
]
},
{
"name": "sky_engine",
"version": "0.0.99",
"kind": "transitive",
"source": "sdk",
"dependencies": []
},
{
"name": "flutter_lints",
"version": "1.0.4",
"kind": "dev",
"source": "hosted",
"dependencies": [
"lints"
]
},
{
"name": "lints",
"version": "1.0.1",
"kind": "transitive",
"source": "hosted",
"dependencies": []
},
{
"name": "yaru_widgets",
"version": "1.0.8",
"kind": "direct",
"source": "hosted",
"dependencies": [
"flutter"
]
},
{
"name": "yaru_icons",
"version": "0.1.3",
"kind": "direct",
"source": "hosted",
"dependencies": [
"flutter"
]
},
{
"name": "yaru",
"version": "0.2.5",
"kind": "direct",
"source": "hosted",
"dependencies": [
"flutter"
]
},
{
"name": "provider",
"version": "6.0.5",
"kind": "direct",
"source": "hosted",
"dependencies": [
"collection",
"flutter",
"nested"
]
},
{
"name": "nested",
"version": "1.0.0",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"flutter"
]
},
{
"name": "fwupd",
"version": "0.2.2",
"kind": "direct",
"source": "hosted",
"dependencies": [
"collection",
"dbus",
"meta"
]
},
{
"name": "dbus",
"version": "0.7.3",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"args",
"ffi",
"meta",
"xml"
]
},
{
"name": "xml",
"version": "5.3.1",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"collection",
"meta",
"petitparser"
]
},
{
"name": "petitparser",
"version": "4.4.0",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"meta"
]
},
{
"name": "ffi",
"version": "1.2.1",
"kind": "transitive",
"source": "hosted",
"dependencies": []
},
{
"name": "args",
"version": "2.3.1",
"kind": "transitive",
"source": "hosted",
"dependencies": []
},
{
"name": "flutter_localizations",
"version": "0.0.0",
"kind": "direct",
"source": "sdk",
"dependencies": [
"flutter",
"intl",
"characters",
"clock",
"collection",
"material_color_utilities",
"meta",
"path",
"typed_data",
"vector_math"
]
},
{
"name": "intl",
"version": "0.17.0",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"clock",
"path"
]
},
{
"name": "flutter_html",
"version": "2.2.1",
"kind": "direct",
"source": "hosted",
"dependencies": [
"html",
"csslib",
"flutter_layout_grid",
"video_player",
"chewie",
"webview_flutter",
"chewie_audio",
"flutter_svg",
"flutter_math_fork",
"collection",
"numerus",
"flutter"
]
},
{
"name": "numerus",
"version": "1.1.1",
"kind": "transitive",
"source": "hosted",
"dependencies": []
},
{
"name": "flutter_math_fork",
"version": "0.5.0",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"flutter",
"flutter_svg",
"provider",
"meta",
"collection",
"tuple"
]
},
{
"name": "tuple",
"version": "2.0.1",
"kind": "transitive",
"source": "hosted",
"dependencies": []
},
{
"name": "flutter_svg",
"version": "0.23.0+1",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"flutter",
"meta",
"path_drawing",
"vector_math",
"xml"
]
},
{
"name": "path_drawing",
"version": "0.5.1+1",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"vector_math",
"meta",
"path_parsing",
"flutter"
]
},
{
"name": "path_parsing",
"version": "0.2.1",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"vector_math",
"meta"
]
},
{
"name": "chewie_audio",
"version": "1.3.0",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"cupertino_icons",
"flutter",
"video_player"
]
},
{
"name": "video_player",
"version": "2.5.1",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"flutter",
"html",
"video_player_android",
"video_player_avfoundation",
"video_player_platform_interface",
"video_player_web"
]
},
{
"name": "video_player_web",
"version": "2.0.13",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"flutter",
"flutter_web_plugins",
"video_player_platform_interface"
]
},
{
"name": "video_player_platform_interface",
"version": "6.0.1",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"flutter",
"plugin_platform_interface"
]
},
{
"name": "plugin_platform_interface",
"version": "2.1.3",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"meta"
]
},
{
"name": "flutter_web_plugins",
"version": "0.0.0",
"kind": "transitive",
"source": "sdk",
"dependencies": [
"flutter",
"js",
"characters",
"collection",
"material_color_utilities",
"meta",
"typed_data",
"vector_math"
]
},
{
"name": "js",
"version": "0.6.3",
"kind": "transitive",
"source": "hosted",
"dependencies": []
},
{
"name": "video_player_avfoundation",
"version": "2.3.8",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"flutter",
"video_player_platform_interface"
]
},
{
"name": "video_player_android",
"version": "2.3.10",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"flutter",
"video_player_platform_interface"
]
},
{
"name": "html",
"version": "0.15.1",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"csslib",
"source_span"
]
},
{
"name": "csslib",
"version": "0.17.2",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"source_span"
]
},
{
"name": "cupertino_icons",
"version": "1.0.5",
"kind": "transitive",
"source": "hosted",
"dependencies": []
},
{
"name": "webview_flutter",
"version": "2.8.0",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"flutter",
"webview_flutter_android",
"webview_flutter_platform_interface",
"webview_flutter_wkwebview"
]
},
{
"name": "webview_flutter_wkwebview",
"version": "2.7.5",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"flutter",
"path",
"webview_flutter_platform_interface"
]
},
{
"name": "webview_flutter_platform_interface",
"version": "1.9.5",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"flutter",
"meta",
"plugin_platform_interface"
]
},
{
"name": "webview_flutter_android",
"version": "2.8.14",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"flutter",
"webview_flutter_platform_interface"
]
},
{
"name": "chewie",
"version": "1.4.0",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"cupertino_icons",
"flutter",
"provider",
"video_player",
"wakelock"
]
},
{
"name": "wakelock",
"version": "0.6.2",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"flutter",
"meta",
"wakelock_macos",
"wakelock_platform_interface",
"wakelock_web",
"wakelock_windows"
]
},
{
"name": "wakelock_windows",
"version": "0.2.0",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"flutter",
"wakelock_platform_interface",
"win32"
]
},
{
"name": "win32",
"version": "2.5.2",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"ffi"
]
},
{
"name": "wakelock_platform_interface",
"version": "0.3.0",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"flutter",
"meta"
]
},
{
"name": "wakelock_web",
"version": "0.4.0",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"flutter",
"flutter_web_plugins",
"js",
"wakelock_platform_interface"
]
},
{
"name": "wakelock_macos",
"version": "0.4.0",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"flutter",
"flutter_web_plugins",
"wakelock_platform_interface"
]
},
{
"name": "flutter_layout_grid",
"version": "1.0.6",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"flutter",
"collection",
"meta",
"quiver"
]
},
{
"name": "quiver",
"version": "3.1.0",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"matcher"
]
},
{
"name": "dio",
"version": "4.0.6",
"kind": "direct",
"source": "hosted",
"dependencies": [
"http_parser",
"path"
]
},
{
"name": "http_parser",
"version": "4.0.2",
"kind": "transitive",
"source": "hosted",
"dependencies": [
"collection",
"source_span",
"string_scanner",
"typed_data"
]
}
]

View file

@ -0,0 +1,493 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
args:
dependency: transitive
description:
name: args
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.1"
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.8.2"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
chewie:
dependency: transitive
description:
name: chewie
url: "https://pub.dartlang.org"
source: hosted
version: "1.4.0"
chewie_audio:
dependency: transitive
description:
name: chewie_audio
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
collection:
dependency: "direct main"
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.15.0"
csslib:
dependency: transitive
description:
name: csslib
url: "https://pub.dartlang.org"
source: hosted
version: "0.17.2"
cupertino_icons:
dependency: transitive
description:
name: cupertino_icons
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.5"
dbus:
dependency: transitive
description:
name: dbus
url: "https://pub.dartlang.org"
source: hosted
version: "0.7.3"
dio:
dependency: "direct main"
description:
name: dio
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.6"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
ffi:
dependency: transitive
description:
name: ffi
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_html:
dependency: "direct main"
description:
name: flutter_html
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.1"
flutter_layout_grid:
dependency: transitive
description:
name: flutter_layout_grid
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.6"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
flutter_localizations:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_math_fork:
dependency: transitive
description:
name: flutter_math_fork
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.0"
flutter_svg:
dependency: transitive
description:
name: flutter_svg
url: "https://pub.dartlang.org"
source: hosted
version: "0.23.0+1"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
fwupd:
dependency: "direct main"
description:
name: fwupd
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.2"
html:
dependency: transitive
description:
name: html
url: "https://pub.dartlang.org"
source: hosted
version: "0.15.1"
http_parser:
dependency: transitive
description:
name: http_parser
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.2"
intl:
dependency: transitive
description:
name: intl
url: "https://pub.dartlang.org"
source: hosted
version: "0.17.0"
js:
dependency: transitive
description:
name: js
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.3"
lints:
dependency: transitive
description:
name: lints
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.11"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.3"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
nested:
dependency: transitive
description:
name: nested
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
numerus:
dependency: transitive
description:
name: numerus
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
path:
dependency: "direct main"
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0"
path_drawing:
dependency: transitive
description:
name: path_drawing
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.1+1"
path_parsing:
dependency: transitive
description:
name: path_parsing
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.1"
petitparser:
dependency: transitive
description:
name: petitparser
url: "https://pub.dartlang.org"
source: hosted
version: "4.4.0"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
provider:
dependency: "direct main"
description:
name: provider
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.5"
quiver:
dependency: transitive
description:
name: quiver
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.0"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
source_span:
dependency: transitive
description:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.1"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
version: "1.10.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.8"
tuple:
dependency: transitive
description:
name: tuple
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
video_player:
dependency: transitive
description:
name: video_player
url: "https://pub.dartlang.org"
source: hosted
version: "2.5.1"
video_player_android:
dependency: transitive
description:
name: video_player_android
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.10"
video_player_avfoundation:
dependency: transitive
description:
name: video_player_avfoundation
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.8"
video_player_platform_interface:
dependency: transitive
description:
name: video_player_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.1"
video_player_web:
dependency: transitive
description:
name: video_player_web
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.13"
wakelock:
dependency: transitive
description:
name: wakelock
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.2"
wakelock_macos:
dependency: transitive
description:
name: wakelock_macos
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.0"
wakelock_platform_interface:
dependency: transitive
description:
name: wakelock_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.0"
wakelock_web:
dependency: transitive
description:
name: wakelock_web
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.0"
wakelock_windows:
dependency: transitive
description:
name: wakelock_windows
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0"
webview_flutter:
dependency: transitive
description:
name: webview_flutter
url: "https://pub.dartlang.org"
source: hosted
version: "2.8.0"
webview_flutter_android:
dependency: transitive
description:
name: webview_flutter_android
url: "https://pub.dartlang.org"
source: hosted
version: "2.8.14"
webview_flutter_platform_interface:
dependency: transitive
description:
name: webview_flutter_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.5"
webview_flutter_wkwebview:
dependency: transitive
description:
name: webview_flutter_wkwebview
url: "https://pub.dartlang.org"
source: hosted
version: "2.7.5"
win32:
dependency: transitive
description:
name: win32
url: "https://pub.dartlang.org"
source: hosted
version: "2.5.2"
xml:
dependency: transitive
description:
name: xml
url: "https://pub.dartlang.org"
source: hosted
version: "5.3.1"
yaru:
dependency: "direct main"
description:
name: yaru
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.5"
yaru_icons:
dependency: "direct main"
description:
name: yaru_icons
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.3"
yaru_widgets:
dependency: "direct main"
description:
name: yaru_widgets
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.8"
sdks:
dart: ">=2.15.0 <3.0.0"
flutter: ">=2.10.0"

View file

@ -14651,8 +14651,10 @@ with pkgs;
flutterPackages =
recurseIntoAttrs (callPackage ../development/compilers/flutter { });
flutter = flutterPackages.stable;
flutter2 = flutterPackages.v2;
flutter-unwrapped = flutterPackages.stable;
flutter2-unwrapped = flutterPackages.v2;
flutter = flutterPackages.wrapFlutter flutter-unwrapped;
flutter2 = flutterPackages.wrapFlutter flutter2-unwrapped;
fnm = callPackage ../development/tools/fnm {
inherit (darwin.apple_sdk.frameworks) DiskArbitration Foundation Security;