at 24.11-pre 179 lines 5.9 kB view raw
1{ lib 2, callPackage 3, runCommand 4, makeWrapper 5, wrapGAppsHook3 6, buildDartApplication 7, cacert 8, glib 9, flutter 10, pkg-config 11, jq 12, yq 13, moreutils 14}: 15 16# absolutely no mac support for now 17 18{ pubGetScript ? "flutter pub get" 19, flutterBuildFlags ? [ ] 20, targetFlutterPlatform ? "linux" 21, extraWrapProgramArgs ? "" 22, ... 23}@args: 24 25let 26 builderArgs = rec { 27 universal = args // { 28 sdkSetupScript = '' 29 # Pub needs SSL certificates. Dart normally looks in a hardcoded path. 30 # https://github.com/dart-lang/sdk/blob/3.1.0/runtime/bin/security_context_linux.cc#L48 31 # 32 # Dart does not respect SSL_CERT_FILE... 33 # https://github.com/dart-lang/sdk/issues/48506 34 # ...and Flutter does not support --root-certs-file, so the path cannot be manually set. 35 # https://github.com/flutter/flutter/issues/56607 36 # https://github.com/flutter/flutter/issues/113594 37 # 38 # libredirect is of no use either, as Flutter does not pass any 39 # environment variables (including LD_PRELOAD) to the Pub process. 40 # 41 # Instead, Flutter is patched to allow the path to the Dart binary used for 42 # Pub commands to be overriden. 43 export NIX_FLUTTER_PUB_DART="${runCommand "dart-with-certs" { nativeBuildInputs = [ makeWrapper ]; } '' 44 mkdir -p "$out/bin" 45 makeWrapper ${flutter.dart}/bin/dart "$out/bin/dart" \ 46 --add-flags "--root-certs-file=${cacert}/etc/ssl/certs/ca-bundle.crt" 47 ''}/bin/dart" 48 49 export HOME="$NIX_BUILD_TOP" 50 flutter config --no-analytics &>/dev/null # mute first-run 51 flutter config --enable-linux-desktop >/dev/null 52 ''; 53 54 inherit pubGetScript; 55 56 sdkSourceBuilders = { 57 # https://github.com/dart-lang/pub/blob/68dc2f547d0a264955c1fa551fa0a0e158046494/lib/src/sdk/flutter.dart#L81 58 "flutter" = name: runCommand "flutter-sdk-${name}" { passthru.packageRoot = "."; } '' 59 for path in '${flutter}/packages/${name}' '${flutter}/bin/cache/pkg/${name}'; do 60 if [ -d "$path" ]; then 61 ln -s "$path" "$out" 62 break 63 fi 64 done 65 66 if [ ! -e "$out" ]; then 67 echo 1>&2 'The Flutter SDK does not contain the requested package: ${name}!' 68 exit 1 69 fi 70 ''; 71 }; 72 73 extraPackageConfigSetup = '' 74 # https://github.com/flutter/flutter/blob/3.13.8/packages/flutter_tools/lib/src/dart/pub.dart#L755 75 if [ "$('${yq}/bin/yq' '.flutter.generate // false' pubspec.yaml)" = "true" ]; then 76 '${jq}/bin/jq' '.packages |= . + [{ 77 name: "flutter_gen", 78 rootUri: "flutter_gen", 79 languageVersion: "2.12", 80 }]' "$out" | '${moreutils}/bin/sponge' "$out" 81 fi 82 ''; 83 }; 84 85 linux = universal // { 86 outputs = universal.outputs or [ ] ++ [ "debug" ]; 87 88 nativeBuildInputs = (universal.nativeBuildInputs or [ ]) ++ [ 89 wrapGAppsHook3 90 91 # Flutter requires pkg-config for Linux desktop support, and many plugins 92 # attempt to use it. 93 # 94 # It is available to the `flutter` tool through its wrapper, but it must be 95 # added here as well so the setup hook adds plugin dependencies to the 96 # pkg-config search paths. 97 pkg-config 98 ]; 99 100 buildInputs = (universal.buildInputs or [ ]) ++ [ glib ]; 101 102 dontDartBuild = true; 103 buildPhase = universal.buildPhase or '' 104 runHook preBuild 105 106 mkdir -p build/flutter_assets/fonts 107 108 flutter build linux -v --release --split-debug-info="$debug" ${builtins.concatStringsSep " " (map (flag: "\"${flag}\"") flutterBuildFlags)} 109 110 runHook postBuild 111 ''; 112 113 dontDartInstall = true; 114 installPhase = universal.installPhase or '' 115 runHook preInstall 116 117 built=build/linux/*/release/bundle 118 119 mkdir -p $out/bin 120 mv $built $out/app 121 122 for f in $(find $out/app -iname "*.desktop" -type f); do 123 install -D $f $out/share/applications/$(basename $f) 124 done 125 126 for f in $(find $out/app -maxdepth 1 -type f); do 127 ln -s $f $out/bin/$(basename $f) 128 done 129 130 # make *.so executable 131 find $out/app -iname "*.so" -type f -exec chmod +x {} + 132 133 # remove stuff like /build/source/packages/ubuntu_desktop_installer/linux/flutter/ephemeral 134 for f in $(find $out/app -executable -type f); do 135 if patchelf --print-rpath "$f" | grep /build; then # this ignores static libs (e,g. libapp.so) also 136 echo "strip RPath of $f" 137 newrp=$(patchelf --print-rpath $f | sed -r "s|/build.*ephemeral:||g" | sed -r "s|/build.*profile:||g") 138 patchelf --set-rpath "$newrp" "$f" 139 fi 140 done 141 142 runHook postInstall 143 ''; 144 145 dontWrapGApps = true; 146 extraWrapProgramArgs = '' 147 ''${gappsWrapperArgs[@]} \ 148 ${extraWrapProgramArgs} 149 ''; 150 }; 151 152 web = universal // { 153 dontDartBuild = true; 154 buildPhase = universal.buildPhase or '' 155 runHook preBuild 156 157 mkdir -p build/flutter_assets/fonts 158 159 flutter build web -v --release ${builtins.concatStringsSep " " (map (flag: "\"${flag}\"") flutterBuildFlags)} 160 161 runHook postBuild 162 ''; 163 164 dontDartInstall = true; 165 installPhase = universal.installPhase or '' 166 runHook preInstall 167 168 cp -r build/web "$out" 169 170 runHook postInstall 171 ''; 172 }; 173 }.${targetFlutterPlatform} or (throw "Unsupported Flutter host platform: ${targetFlutterPlatform}"); 174 175 minimalFlutter = flutter.override { supportedTargetFlutterPlatforms = [ "universal" targetFlutterPlatform ]; }; 176 177 buildAppWith = flutter: buildDartApplication.override { dart = flutter; }; 178in 179buildAppWith minimalFlutter (builderArgs // { passthru = builderArgs.passthru or { } // { multiShell = buildAppWith flutter builderArgs; }; })