1{ version
2, engineVersion
3, patches
4, dart
5, src
6, includedEngineArtifacts ? {
7 common = [
8 "flutter_patched_sdk"
9 "flutter_patched_sdk_product"
10 ];
11 platform = {
12 android = lib.optionalAttrs stdenv.hostPlatform.isx86_64
13 ((lib.genAttrs [ "arm" "arm64" "x64" ] (architecture: [ "profile" "release" ])) // { x86 = [ "jit-release" ]; });
14 linux = lib.optionals stdenv.hostPlatform.isLinux
15 (lib.genAttrs ((lib.optional stdenv.hostPlatform.isx86_64 "x64") ++ (lib.optional stdenv.hostPlatform.isAarch64 "arm64"))
16 (architecture: [ "debug" "profile" "release" ]));
17 };
18 }
19
20, lib
21, callPackage
22, stdenv
23, runCommandLocal
24, symlinkJoin
25, lndir
26, git
27, which
28}:
29
30let
31 engineArtifactDirectory =
32 let
33 engineArtifacts = callPackage ./engine-artifacts { inherit engineVersion; };
34 in
35 runCommandLocal "flutter-engine-artifacts-${version}" { }
36 (
37 let
38 mkCommonArtifactLinkCommand = { artifact }:
39 ''
40 mkdir -p $out/common
41 ${lndir}/bin/lndir -silent ${artifact} $out/common
42 '';
43 mkPlatformArtifactLinkCommand = { artifact, os, architecture, variant ? null }:
44 let
45 artifactDirectory = "${os}-${architecture}${lib.optionalString (variant != null) "-${variant}"}";
46 in
47 ''
48 mkdir -p $out/${artifactDirectory}
49 ${lndir}/bin/lndir -silent ${artifact} $out/${artifactDirectory}
50 '';
51 in
52 ''
53 ${
54 builtins.concatStringsSep "\n"
55 ((map (name: mkCommonArtifactLinkCommand {
56 artifact = engineArtifacts.common.${name};
57 }) (if includedEngineArtifacts ? common then includedEngineArtifacts.common else [ ])) ++
58 (builtins.foldl' (commands: os: commands ++
59 (builtins.foldl' (commands: architecture: commands ++
60 (builtins.foldl' (commands: variant: commands ++
61 (map (artifact: mkPlatformArtifactLinkCommand {
62 inherit artifact os architecture variant;
63 }) engineArtifacts.platform.${os}.${architecture}.variants.${variant}))
64 (map (artifact: mkPlatformArtifactLinkCommand {
65 inherit artifact os architecture;
66 }) engineArtifacts.platform.${os}.${architecture}.base)
67 includedEngineArtifacts.platform.${os}.${architecture}))
68 [] (builtins.attrNames includedEngineArtifacts.platform.${os})))
69 [] (builtins.attrNames (if includedEngineArtifacts ? platform then includedEngineArtifacts.platform else { }))))
70 }
71 ''
72 );
73
74 unwrapped =
75 stdenv.mkDerivation {
76 name = "flutter-${version}-unwrapped";
77 inherit src patches version;
78
79 outputs = [ "out" "cache" ];
80
81 buildInputs = [ git ];
82
83 preConfigure = ''
84 if [ "$(< bin/internal/engine.version)" != '${engineVersion}' ]; then
85 echo 1>&2 "The given engine version (${engineVersion}) does not match the version required by the Flutter SDK ($(< bin/internal/engine.version))."
86 exit 1
87 fi
88 '';
89
90 postPatch = ''
91 patchShebangs --build ./bin/
92 '';
93
94 buildPhase = ''
95 export FLUTTER_ROOT="$(pwd)"
96 export FLUTTER_TOOLS_DIR="$FLUTTER_ROOT/packages/flutter_tools"
97 export SCRIPT_PATH="$FLUTTER_TOOLS_DIR/bin/flutter_tools.dart"
98
99 export SNAPSHOT_PATH="$FLUTTER_ROOT/bin/cache/flutter_tools.snapshot"
100 export STAMP_PATH="$FLUTTER_ROOT/bin/cache/flutter_tools.stamp"
101
102 export DART_SDK_PATH="${dart}"
103
104 # The Flutter tool compilation requires dependencies to be cached, as there is no Internet access.
105 # Dart expects package caches to be mutable, and does not support composing cache directories.
106 # The packages cached during the build therefore cannot be easily used. They are provided through
107 # the derivation's "cache" output, though, in case they are needed.
108 #
109 # Note that non-cached packages will normally be fetched from the Internet when they are needed, so Flutter
110 # will function without an existing package cache as long as it has an Internet connection.
111 export PUB_CACHE="$cache"
112
113 if [ -d .pub-preload-cache ]; then
114 ${dart}/bin/dart pub cache preload .pub-preload-cache/*
115 elif [ -d .pub-cache ]; then
116 mv .pub-cache "$PUB_CACHE"
117 else
118 echo 'ERROR: Failed to locate the Dart package cache required to build the Flutter tool.'
119 exit 1
120 fi
121
122 pushd "$FLUTTER_TOOLS_DIR"
123 ${dart}/bin/dart pub get --offline
124 popd
125
126 local revision="$(cd "$FLUTTER_ROOT"; git rev-parse HEAD)"
127 ${dart}/bin/dart --snapshot="$SNAPSHOT_PATH" --packages="$FLUTTER_TOOLS_DIR/.dart_tool/package_config.json" "$SCRIPT_PATH"
128 echo "$revision" > "$STAMP_PATH"
129 echo -n "${version}" > version
130
131 # Certain prebuilts should be replaced with Nix-built (or at least Nix-patched) equivalents.
132 rm -r \
133 bin/cache/dart-sdk \
134 bin/cache/artifacts/engine
135 '';
136
137 installPhase = ''
138 runHook preInstall
139
140 mkdir -p $out
141 cp -r . $out
142 ln -sf ${dart} $out/bin/cache/dart-sdk
143 ln -sf ${engineArtifactDirectory} $out/bin/cache/artifacts/engine
144
145 runHook postInstall
146 '';
147
148 doInstallCheck = true;
149 nativeInstallCheckInputs = [ which ];
150 installCheckPhase = ''
151 runHook preInstallCheck
152
153 export HOME="$(mktemp -d)"
154 $out/bin/flutter config --android-studio-dir $HOME
155 $out/bin/flutter config --android-sdk $HOME
156 $out/bin/flutter --version | fgrep -q '${version}'
157
158 runHook postInstallCheck
159 '';
160
161 passthru = {
162 inherit dart;
163 # The derivation containing the original Flutter SDK files.
164 # When other derivations wrap this one, any unmodified files
165 # found here should be included as-is, for tooling compatibility.
166 sdk = unwrapped;
167 };
168
169 meta = with lib; {
170 description = "Flutter is Google's SDK for building mobile, web and desktop with Dart";
171 longDescription = ''
172 Flutter is Google’s UI toolkit for building beautiful,
173 natively compiled applications for mobile, web, and desktop from a single codebase.
174 '';
175 homepage = "https://flutter.dev";
176 license = licenses.bsd3;
177 platforms = [ "x86_64-linux" "aarch64-linux" ];
178 maintainers = with maintainers; [ babariviere ericdallo FlafyDev gilice hacker1024 ];
179 };
180 };
181in
182unwrapped