1{ lib
2, stdenv
3, darwin
4, callPackage
5, flutter
6, supportsLinuxDesktop ? stdenv.hostPlatform.isLinux
7, supportsAndroid ? (stdenv.hostPlatform.isx86_64 || stdenv.hostPlatform.isDarwin)
8, supportsDarwin ? stdenv.hostPlatform.isDarwin
9, supportsIOS ? stdenv.hostPlatform.isDarwin
10, includedEngineArtifacts ? {
11 common = [
12 "flutter_patched_sdk"
13 "flutter_patched_sdk_product"
14 ];
15 platform = {
16 android = lib.optionalAttrs supportsAndroid
17 ((lib.genAttrs [ "arm" "arm64" "x64" ] (architecture: [ "profile" "release" ])) // { x86 = [ "jit-release" ]; });
18 darwin = lib.optionalAttrs supportsDarwin
19 ((lib.genAttrs [ "arm64" "x64" ] (architecture: [ "profile" "release" ])));
20 ios = lib.optionalAttrs supportsIOS
21 ((lib.genAttrs [ "" ] (architecture: [ "profile" "release" ])));
22 linux = lib.optionalAttrs supportsLinuxDesktop
23 (lib.genAttrs ((lib.optional stdenv.hostPlatform.isx86_64 "x64") ++ (lib.optional stdenv.hostPlatform.isAarch64 "arm64"))
24 (architecture: [ "debug" "profile" "release" ]));
25 };
26 }
27, extraPkgConfigPackages ? [ ]
28, extraLibraries ? [ ]
29, extraIncludes ? [ ]
30, extraCxxFlags ? [ ]
31, extraCFlags ? [ ]
32, extraLinkerFlags ? [ ]
33, makeWrapper
34, runCommandLocal
35, writeShellScript
36, wrapGAppsHook
37, git
38, which
39, pkg-config
40, atk
41, cairo
42, gdk-pixbuf
43, glib
44, gtk3
45, harfbuzz
46, libepoxy
47, pango
48, libX11
49, xorgproto
50, libdeflate
51, zlib
52, cmake
53, ninja
54, clang
55, lndir
56, symlinkJoin
57}:
58
59let
60 engineArtifacts = callPackage ./engine-artifacts {
61 inherit (flutter) engineVersion;
62 flutterVersion = flutter.version;
63 };
64 mkCommonArtifactLinkCommand = { artifact }:
65 ''
66 mkdir -p $out/artifacts/engine/common
67 lndir -silent ${artifact} $out/artifacts/engine/common
68 '';
69 mkPlatformArtifactLinkCommand = { artifact, os, architecture, variant ? null }:
70 let
71 artifactDirectory = "${os}-${architecture}${lib.optionalString (variant != null) "-${variant}"}";
72 in
73 ''
74 mkdir -p $out/artifacts/engine/${artifactDirectory}
75 lndir -silent ${artifact} $out/artifacts/engine/${artifactDirectory}
76 '';
77 engineArtifactDirectory =
78 runCommandLocal "flutter-engine-artifacts-${flutter.version}" { nativeBuildInputs = [ lndir ]; }
79 (
80 builtins.concatStringsSep "\n"
81 ((map
82 (name: mkCommonArtifactLinkCommand {
83 artifact = engineArtifacts.common.${name};
84 })
85 (includedEngineArtifacts.common or [ ])) ++
86 (builtins.foldl'
87 (commands: os: commands ++
88 (builtins.foldl'
89 (commands: architecture: commands ++
90 (builtins.foldl'
91 (commands: variant: commands ++
92 (map
93 (artifact: mkPlatformArtifactLinkCommand {
94 inherit artifact os architecture variant;
95 })
96 engineArtifacts.platform.${os}.${architecture}.variants.${variant}))
97 (map
98 (artifact: mkPlatformArtifactLinkCommand {
99 inherit artifact os architecture;
100 })
101 engineArtifacts.platform.${os}.${architecture}.base)
102 includedEngineArtifacts.platform.${os}.${architecture}))
103 [ ]
104 (builtins.attrNames includedEngineArtifacts.platform.${os})))
105 [ ]
106 (builtins.attrNames (includedEngineArtifacts.platform or { }))))
107 );
108
109 cacheDir = symlinkJoin {
110 name = "flutter-cache-dir";
111 paths = [
112 engineArtifactDirectory
113 "${flutter}/bin/cache"
114 ];
115 };
116
117 # By default, Flutter stores downloaded files (such as the Pub cache) in the SDK directory.
118 # Wrap it to ensure that it does not do that, preferring home directories instead.
119 # The sh file `$out/bin/internal/shared.sh` runs when launching Flutter and calls `"$FLUTTER_ROOT/bin/cache/` instead of our environment variable `FLUTTER_CACHE_DIR`.
120 # We do not patch it since the script doesn't require engine artifacts(which are the only thing not added by the unwrapped derivation), so it shouldn't fail, and patching it will just be harder to maintain.
121 immutableFlutter = writeShellScript "flutter_immutable" ''
122 export PUB_CACHE=''${PUB_CACHE:-"$HOME/.pub-cache"}
123 export FLUTTER_CACHE_DIR=${cacheDir}
124 ${flutter}/bin/flutter "$@"
125 '';
126
127 # Tools that the Flutter tool depends on.
128 tools = [ git which ];
129
130 # Libraries that Flutter apps depend on at runtime.
131 appRuntimeDeps = lib.optionals supportsLinuxDesktop [
132 atk
133 cairo
134 gdk-pixbuf
135 glib
136 gtk3
137 harfbuzz
138 libepoxy
139 pango
140 libX11
141 libdeflate
142 ];
143
144 # Development packages required for compilation.
145 appBuildDeps =
146 let
147 # https://discourse.nixos.org/t/handling-transitive-c-dependencies/5942/3
148 deps = pkg: builtins.filter lib.isDerivation ((pkg.buildInputs or [ ]) ++ (pkg.propagatedBuildInputs or [ ]));
149 collect = pkg: lib.unique ([ pkg ] ++ deps pkg ++ builtins.concatMap collect (deps pkg));
150 in
151 builtins.concatMap collect appRuntimeDeps;
152
153 # Some header files and libraries are not properly located by the Flutter SDK.
154 # They must be manually included.
155 appStaticBuildDeps = (lib.optionals supportsLinuxDesktop [ libX11 xorgproto zlib ]) ++ extraLibraries;
156
157 # Tools used by the Flutter SDK to compile applications.
158 buildTools = lib.optionals supportsLinuxDesktop [
159 pkg-config
160 cmake
161 ninja
162 clang
163 ];
164
165 # Nix-specific compiler configuration.
166 pkgConfigPackages = map (lib.getOutput "dev") (appBuildDeps ++ extraPkgConfigPackages);
167 includeFlags = map (pkg: "-isystem ${lib.getOutput "dev" pkg}/include") (appStaticBuildDeps ++ extraIncludes);
168 linkerFlags = (map (pkg: "-rpath,${lib.getOutput "lib" pkg}/lib") appRuntimeDeps) ++ extraLinkerFlags;
169in
170(callPackage ./sdk-symlink.nix { }) (stdenv.mkDerivation
171{
172 pname = "flutter-wrapped";
173 inherit (flutter) version;
174
175 nativeBuildInputs = [ makeWrapper ]
176 ++ lib.optionals stdenv.hostPlatform.isDarwin [ darwin.DarwinTools ]
177 ++ lib.optionals supportsLinuxDesktop [ glib wrapGAppsHook ];
178
179 passthru = flutter.passthru // {
180 inherit (flutter) version;
181 unwrapped = flutter;
182 inherit engineArtifacts;
183 };
184
185 dontUnpack = true;
186 dontWrapGApps = true;
187
188 installPhase = ''
189 runHook preInstall
190
191 for path in ${builtins.concatStringsSep " " (builtins.foldl' (paths: pkg: paths ++ (map (directory: "'${pkg}/${directory}/pkgconfig'") ["lib" "share"])) [ ] pkgConfigPackages)}; do
192 addToSearchPath FLUTTER_PKG_CONFIG_PATH "$path"
193 done
194
195 mkdir -p $out/bin
196 makeWrapper '${immutableFlutter}' $out/bin/flutter \
197 --set-default ANDROID_EMULATOR_USE_SYSTEM_LIBS 1 \
198 --suffix PATH : '${lib.makeBinPath (tools ++ buildTools)}' \
199 --suffix PKG_CONFIG_PATH : "$FLUTTER_PKG_CONFIG_PATH" \
200 --suffix LIBRARY_PATH : '${lib.makeLibraryPath appStaticBuildDeps}' \
201 --prefix CXXFLAGS "''\t" '${builtins.concatStringsSep " " (includeFlags ++ extraCxxFlags)}' \
202 --prefix CFLAGS "''\t" '${builtins.concatStringsSep " " (includeFlags ++ extraCFlags)}' \
203 --prefix LDFLAGS "''\t" '${builtins.concatStringsSep " " (map (flag: "-Wl,${flag}") linkerFlags)}' \
204 ''${gappsWrapperArgs[@]}
205
206 runHook postInstall
207 '';
208
209 inherit (flutter) meta;
210})