flutter: Redesign wrapping architecture

The following principles are now in place:

- All wrappers will include SDK file symlinks. There is not much of a reason to not do so, and removing the option to omit it makes it easier to understand what each wrapper does.
- There is no longer a way to get the previous derivation from a wrapper. This could yield unexpected results based on the wrapping order. Instead, "sdk", "unwrapped", and "noFHS" passthru attributes are provided where appropriate.
This commit is contained in:
hacker1024 2023-02-18 00:43:17 +11:00
parent aa33cb9956
commit 341fa709ff
6 changed files with 161 additions and 143 deletions

View File

@ -3,7 +3,6 @@ let
mkFlutter = opts: callPackage (import ./flutter.nix opts) { };
wrapFlutter = flutter: callPackage (import ./wrapper.nix) { flutter = flutter; };
mkFlutterFHS = flutter: callPackage (import ./fhs.nix) { flutter = flutter; };
mkFakeSdk = flutter: callPackage (import ./fake-sdk.nix) { flutter = flutter; };
getPatches = dir:
let files = builtins.attrNames (builtins.readDir dir);
in map (f: dir + ("/" + f)) files;
@ -29,7 +28,7 @@ let
};
in
{
inherit mkFlutter wrapFlutter mkFlutterFHS mkFakeSdk flutterDrv;
inherit mkFlutter wrapFlutter mkFlutterFHS flutterDrv;
stable = flutterDrv {
version = "3.3.3";
dartVersion = "2.18.2";

View File

@ -1,15 +0,0 @@
{ flutter, symlinkJoin }:
symlinkJoin {
name = "flutter-fake-${flutter.name}";
paths = [ flutter flutter.unwrapped ];
inherit (flutter) passthru;
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.
'';
};
}

View File

@ -7,73 +7,77 @@
, supportsAndroidEmulator ? stdenv.isLinux
}:
let
# Wrap flutter inside an fhs user env to allow execution of binary,
# like adb from $ANDROID_HOME or java from android-studio.
self = buildFHSUserEnv {
name = flutter.name;
multiPkgs = pkgs: with pkgs; ([
# Flutter only use these certificates
(runCommandLocal "fedoracert" { } ''
mkdir -p $out/etc/pki/tls/
ln -s ${cacert}/etc/ssl/certs $out/etc/pki/tls/certs
'')
zlib
]);
# Wrap flutter inside an fhs user env to allow execution of binary,
# like adb from $ANDROID_HOME or java from android-studio.
(callPackage ./sdk-symlink.nix { }) (buildFHSUserEnv rec {
name = "${flutter.name}-fhs";
targetPkgs = pkgs: with pkgs; ([
flutter
multiPkgs = pkgs: with pkgs; ([
# Flutter only use these certificates
(runCommandLocal "fedoracert" { } ''
mkdir -p $out/etc/pki/tls/
ln -s ${cacert}/etc/ssl/certs $out/etc/pki/tls/certs
'')
zlib
]);
# General ecosystem dependencies
bash
curl
git
unzip
which
xz
targetPkgs = pkgs: with pkgs; ([
flutter
# flutter test requires this lib
libGLU
] ++ lib.optional supportsAndroidEmulator [
# for android emulator
alsa-lib
dbus
expat
libpulseaudio
libuuid
xorg.libX11
xorg.libxcb
xorg.libXcomposite
xorg.libXcursor
xorg.libXdamage
xorg.libXext
xorg.libXfixes
xorg.libXi
xorg.libXrender
xorg.libXtst
libGL
nspr
nss
systemd
]);
# General ecosystem dependencies
bash
curl
git
unzip
which
xz
runScript = "flutter";
# flutter test requires this lib
libGLU
] ++ lib.optional supportsAndroidEmulator [
# for android emulator
alsa-lib
dbus
expat
libpulseaudio
libuuid
xorg.libX11
xorg.libxcb
xorg.libXcomposite
xorg.libXcursor
xorg.libXdamage
xorg.libXext
xorg.libXfixes
xorg.libXi
xorg.libXrender
xorg.libXtst
libGL
nspr
nss
systemd
]);
passthru = flutter.passthru // {
wrapped = flutter;
mkFlutterApp = callPackage ../../../build-support/flutter {
flutter = callPackage ./fhs.nix { supportsAndroidEmulator = false; };
};
fakeSdk = callPackage ./fake-sdk.nix { flutter = self; };
};
runScript = "flutter";
meta = flutter.meta // {
longDescription = ''
${flutter.meta.longDescription}
Wrapped in a FHS environment to improve compatibility with internal tools and tools in the ecosystem.
'';
extraInstallCommands = ''
# By default, the derivation name is used as the binary name.
# This is not the desired behaviour in this case.
# https://github.com/NixOS/nixpkgs/blob/cb4536bf3606a7b6b54b69afe22ccd82e2906d92/pkgs/build-support/build-fhs-userenv/default.nix#L43
mv $out/bin/${name} $out/bin/flutter
'';
passthru = flutter.passthru // {
nonFHS = flutter;
mkFlutterApp = callPackage ../../../build-support/flutter {
flutter = callPackage ./fhs.nix { supportsAndroidEmulator = false; };
};
};
in
self
meta = flutter.meta // {
longDescription = ''
${flutter.meta.longDescription}
Wrapped in a FHS environment to improve compatibility with internal tools and tools in the ecosystem.
'';
};
})

View File

@ -10,80 +10,90 @@
, which
}:
stdenv.mkDerivation {
name = "$flutter-${version}-unwrapped";
let
self =
stdenv.mkDerivation {
name = "$flutter-${version}-unwrapped";
buildInputs = [ git ];
buildInputs = [ git ];
inherit src patches version;
inherit src patches version;
postPatch = ''
patchShebangs --build ./bin/
'';
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"
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 SNAPSHOT_PATH="$FLUTTER_ROOT/bin/cache/flutter_tools.snapshot"
export STAMP_PATH="$FLUTTER_ROOT/bin/cache/flutter_tools.stamp"
export DART_SDK_PATH="${dart}"
export DART_SDK_PATH="${dart}"
HOME=../.. # required for pub upgrade --offline, ~/.pub-cache
# path is relative otherwise it's replaced by /build/flutter
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
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
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
'';
rm -r bin/cache/{artifacts,dart-sdk,downloads}
rm bin/cache/*.stamp
'';
installPhase = ''
runHook preInstall
installPhase = ''
runHook preInstall
mkdir -p $out
cp -r . $out
mkdir -p $out/bin/cache/
ln -sf ${dart} $out/bin/cache/dart-sdk
mkdir -p $out
cp -r . $out
mkdir -p $out/bin/cache/
ln -sf ${dart} $out/bin/cache/dart-sdk
runHook postInstall
'';
runHook postInstall
'';
doInstallCheck = true;
installCheckInputs = [ which ];
installCheckPhase = ''
runHook preInstallCheck
doInstallCheck = true;
installCheckInputs = [ 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}'
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
'';
runHook postInstallCheck
'';
passthru = {
inherit dart;
};
passthru = {
inherit dart;
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 ];
};
}
# 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 = self;
};
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 ];
};
}
;
in
self

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

@ -79,7 +79,7 @@ let
cppFlags = map (pkg: "-isystem ${lib.getOutput "dev" pkg}/include") appStaticBuildDeps;
linkerFlags = map (pkg: "-rpath,${lib.getOutput "lib" pkg}/lib") appRuntimeDeps;
in
runCommandLocal "flutter"
(callPackage ./sdk-symlink.nix { }) (runCommandLocal "flutter-wrapped"
{
buildInputs = [ makeWrapper ];
@ -90,10 +90,6 @@ runCommandLocal "flutter"
inherit (flutter) meta;
} ''
mkdir -p $out/bin
mkdir -p $out/bin/cache/
ln -sf ${flutter.dart} $out/bin/cache/dart-sdk
makeWrapper '${immutableFlutter}' $out/bin/flutter \
--set-default ANDROID_EMULATOR_USE_SYSTEM_LIBS 1 \
--prefix PATH : '${lib.makeBinPath buildTools}' \
@ -101,4 +97,4 @@ runCommandLocal "flutter"
--prefix CXXFLAGS "''\t" '${builtins.concatStringsSep " " cppFlags}' \
--prefix LDFLAGS "''\t" '${builtins.concatStringsSep " " (map (flag: "-Wl,${flag}") linkerFlags)}' \
--suffix LD_LIBRARY_PATH : '${lib.makeLibraryPath appPrebuiltDeps}'
''
'')