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