From 42c0f81a19737cd3027348c73398bd2025c870dd Mon Sep 17 00:00:00 2001 From: kyehn Date: Sat, 28 Feb 2026 09:29:22 +0800 Subject: [PATCH 1/2] flutter.buildFlutterApplication: add support for finalAttrs --- doc/languages-frameworks/dart.section.md | 24 +- .../dart/build-dart-application/default.nix | 251 +++++++++--------- .../build-flutter-application.nix | 101 +++---- 3 files changed, 200 insertions(+), 176 deletions(-) diff --git a/doc/languages-frameworks/dart.section.md b/doc/languages-frameworks/dart.section.md index bd0cc85a1e02..7c210ac1e4c6 100644 --- a/doc/languages-frameworks/dart.section.md +++ b/doc/languages-frameworks/dart.section.md @@ -36,19 +36,19 @@ Dart supports multiple [outputs types](https://dart.dev/tools/dart-compile#types fetchFromGitHub, }: -buildDartApplication rec { +buildDartApplication (finalAttrs: { pname = "dart-sass"; version = "1.62.1"; src = fetchFromGitHub { owner = "sass"; repo = "dart-sass"; - tag = version; + tag = finalAttrs.version; hash = "sha256-U6enz8yJcc4Wf8m54eYIAnVg/jsGi247Wy8lp1r1wg4="; }; pubspecLock = lib.importJSON ./pubspec.lock.json; -} +}) ``` ### Patching dependencies {#ssec-dart-applications-patching-dependencies} @@ -102,14 +102,14 @@ The function `buildFlutterApplication` builds Flutter applications. See the [Dart documentation](#ssec-dart-applications) for more details on required files and arguments. -`flutter` in Nixpkgs always points to `flutterPackages.stable`, which is the latest packaged version. To avoid unforeseen breakage during upgrade, packages in Nixpkgs should use a specific flutter version, such as `flutter319` and `flutter322`, instead of using `flutter` directly. +`flutter` in Nixpkgs always points to `flutterPackages.stable`, which is the latest packaged version. To avoid unforeseen breakage during upgrade, packages in Nixpkgs should use a specific flutter version, such as `flutter335` and `flutter338`, instead of using `flutter` directly. ```nix -{ flutter322, fetchFromGitHub }: +{ flutter335, fetchFromGitHub }: -flutter322.buildFlutterApplication { +flutter335.buildFlutterApplication (finalAttrs: { pname = "firmware-updater"; - version = "0-unstable-2023-04-30"; + version = "0-unstable-2025-09-09"; # To build for the Web, use the targetFlutterPlatform argument. # targetFlutterPlatform = "web"; @@ -117,13 +117,17 @@ flutter322.buildFlutterApplication { src = fetchFromGitHub { owner = "canonical"; repo = "firmware-updater"; - rev = "6e7dbdb64e344633ea62874b54ff3990bd3b8440"; - hash = "sha256-s5mwtr5MSPqLMN+k851+pFIFFPa0N1hqz97ys050tFA="; + rev = "402e97254b9d63c8d962c46724995e377ff922c8"; + hash = "sha256-nQn5mlgNj157h++67+mhez/F1ALz4yY+bxiGsi0/xX8="; fetchSubmodules = true; }; pubspecLock = lib.importJSON ./pubspec.lock.json; -} + + sourceRoot = "${finalAttrs.src.name}/apps/firmware_updater"; + + gitHashes.fwupd = "sha256-l/+HrrJk1mE2Mrau+NmoQ7bu9qhHU6wX68+m++9Hjd4="; +}) ``` ### Usage with nix-shell {#ssec-dart-flutter-nix-shell} diff --git a/pkgs/build-support/dart/build-dart-application/default.nix b/pkgs/build-support/dart/build-dart-application/default.nix index aa847b0efdf9..ed07a06551b5 100644 --- a/pkgs/build-support/dart/build-dart-application/default.nix +++ b/pkgs/build-support/dart/build-dart-application/default.nix @@ -14,123 +14,137 @@ yq, }: -{ - src, - sourceRoot ? "source", - packageRoot ? (lib.removePrefix "/" (lib.removePrefix "source" sourceRoot)), - gitHashes ? { }, - sdkSourceBuilders ? { }, - customSourceBuilders ? { }, +lib.extendMkDerivation { + constructDrv = stdenv.mkDerivation; - sdkSetupScript ? "", - extraPackageConfigSetup ? "", + excludeDrvArgNames = [ + "gitHashes" + "sdkSourceBuilders" + "pubspecLock" + "customSourceBuilders" + ]; - # Output type to produce. Can be any kind supported by dart - # https://dart.dev/tools/dart-compile#types-of-output - # If using jit, you might want to pass some arguments to `dartJitFlags` - dartOutputType ? "exe", - dartCompileCommand ? "dart compile", - dartCompileFlags ? [ ], - # These come at the end of the command, useful to pass flags to the jit run - dartJitFlags ? [ ], - - # Attrset of entry point files to build and install. - # Where key is the final binary path and value is the source file path - # e.g. { "bin/foo" = "bin/main.dart"; } - # Set to null to read executables from pubspec.yaml - dartEntryPoints ? null, - # Used when wrapping aot, jit, kernel, and js builds. - # Set to null to disable wrapping. - dartRuntimeCommand ? - if dartOutputType == "aot-snapshot" then - "${dart}/bin/dartaotruntime" - else if (dartOutputType == "jit-snapshot" || dartOutputType == "kernel") then - "${dart}/bin/dart" - else if dartOutputType == "js" then - "${nodejs}/bin/node" - else - null, - - runtimeDependencies ? [ ], - extraWrapProgramArgs ? "", - - autoPubspecLock ? null, - pubspecLock ? - if autoPubspecLock == null then - throw "The pubspecLock argument is required. If import-from-derivation is allowed (it isn't in Nixpkgs), you can set autoPubspecLock to the path to a pubspec.lock instead." - else - assert lib.assertMsg (builtins.pathExists autoPubspecLock) - "The pubspec.lock file could not be found!"; - lib.importJSON ( - runCommand "${lib.getName args}-pubspec-lock-json" { - nativeBuildInputs = [ yq ]; - } ''yq . '${autoPubspecLock}' > "$out"'' - ), - ... -}@args: - -let - generators = callPackage ./generators.nix { inherit dart; } { buildDrvArgs = args; }; - - pubspecLockFile = builtins.toJSON pubspecLock; - pubspecLockData = pub2nix.readPubspecLock { - inherit - src - packageRoot - pubspecLock - gitHashes - customSourceBuilders - ; - sdkSourceBuilders = { - # https://github.com/dart-lang/pub/blob/e1fbda73d1ac597474b82882ee0bf6ecea5df108/lib/src/sdk/dart.dart#L80 - "dart" = - name: - runCommand "dart-sdk-${name}" { passthru.packageRoot = "."; } '' - for path in '${dart}/pkg/${name}'; do - if [ -d "$path" ]; then - ln -s "$path" "$out" - break - fi - done - - if [ ! -e "$out" ]; then - echo 1>&2 'The Dart SDK does not contain the requested package: ${name}!' - exit 1 - fi - ''; - } - // sdkSourceBuilders; - }; - packageConfig = generators.linkPackageConfig { - inherit pubspecLock; - packageConfig = pub2nix.generatePackageConfig { - pname = if args.pname != null then "${args.pname}-${args.version}" else null; - - dependencies = - # Ideally, we'd only include the main dependencies and their transitive - # dependencies. - # - # The pubspec.lock file does not contain information about where - # transitive dependencies come from, though, and it would be weird to - # include the transitive dependencies of dev and override dependencies - # without including the dev and override dependencies themselves. - builtins.concatLists (builtins.attrValues pubspecLockData.dependencies); - - inherit (pubspecLockData) dependencySources; - }; - extraSetupCommands = extraPackageConfigSetup; - }; - - inherit (dartHooks.override { inherit dart; }) - dartConfigHook - dartBuildHook - dartInstallHook - dartFixupHook - ; - - baseDerivation = stdenv.mkDerivation ( + extendDrvArgs = finalAttrs: - (removeAttrs args [ + args@{ + src, + sourceRoot ? "source", + packageRoot ? (lib.removePrefix "/" (lib.removePrefix "source" sourceRoot)), + gitHashes ? { }, + sdkSourceBuilders ? { }, + customSourceBuilders ? { }, + + sdkSetupScript ? "", + extraPackageConfigSetup ? "", + + # Output type to produce. Can be any kind supported by dart + # https://dart.dev/tools/dart-compile#types-of-output + # If using jit, you might want to pass some arguments to `dartJitFlags` + dartOutputType ? "exe", + dartCompileCommand ? "dart compile", + dartCompileFlags ? [ ], + # These come at the end of the command, useful to pass flags to the jit run + dartJitFlags ? [ ], + + # Attrset of entry point files to build and install. + # Where key is the final binary path and value is the source file path + # e.g. { "bin/foo" = "bin/main.dart"; } + # Set to null to read executables from pubspec.yaml + dartEntryPoints ? null, + # Used when wrapping aot, jit, kernel, and js builds. + # Set to null to disable wrapping. + dartRuntimeCommand ? + if dartOutputType == "aot-snapshot" then + "${dart}/bin/dartaotruntime" + else if (dartOutputType == "jit-snapshot" || dartOutputType == "kernel") then + "${dart}/bin/dart" + else if dartOutputType == "js" then + "${nodejs}/bin/node" + else + null, + + runtimeDependencies ? [ ], + extraWrapProgramArgs ? "", + + autoPubspecLock ? null, + pubspecLock ? + if autoPubspecLock == null then + throw "The pubspecLock argument is required. If import-from-derivation is allowed (it isn't in Nixpkgs), you can set autoPubspecLock to the path to a pubspec.lock instead." + else + assert lib.assertMsg (builtins.pathExists autoPubspecLock) + "The pubspec.lock file could not be found!"; + lib.importJSON ( + runCommand "${lib.getName args}-pubspec-lock-json" { + nativeBuildInputs = [ yq ]; + } ''yq . '${autoPubspecLock}' > "$out"'' + ), + ... + }: + let + generators = callPackage ./generators.nix { inherit dart; } { buildDrvArgs = args; }; + + pubspecLockFile = builtins.toJSON pubspecLock; + pubspecLockData = pub2nix.readPubspecLock { + inherit + src + packageRoot + pubspecLock + gitHashes + customSourceBuilders + ; + sdkSourceBuilders = { + # https://github.com/dart-lang/pub/blob/e1fbda73d1ac597474b82882ee0bf6ecea5df108/lib/src/sdk/dart.dart#L80 + "dart" = + name: + runCommand "dart-sdk-${name}" { passthru.packageRoot = "."; } '' + for path in '${dart}/pkg/${name}'; do + if [ -d "$path" ]; then + ln -s "$path" "$out" + break + fi + done + + if[ ! -e "$out" ]; then + echo 1>&2 'The Dart SDK does not contain the requested package: ${name}!' + exit 1 + fi + ''; + } + // sdkSourceBuilders; + }; + packageConfig = generators.linkPackageConfig { + inherit pubspecLock; + packageConfig = pub2nix.generatePackageConfig { + pname = if args.pname != null then "${args.pname}-${args.version}" else null; + + dependencies = + # Ideally, we'd only include the main dependencies and their transitive + # dependencies. + # + # The pubspec.lock file does not contain information about where + # transitive dependencies come from, though, and it would be weird to + # include the transitive dependencies of dev and override dependencies + # without including the dev and override dependencies themselves. + builtins.concatLists (builtins.attrValues pubspecLockData.dependencies); + + inherit (pubspecLockData) dependencySources; + }; + extraSetupCommands = extraPackageConfigSetup; + }; + + inherit (dartHooks.override { inherit dart; }) + dartConfigHook + dartBuildHook + dartInstallHook + dartFixupHook + ; + + in + assert + !(builtins.isString dartOutputType && dartOutputType != "") + -> throw "dartOutputType must be a non-empty string"; + + (builtins.removeAttrs args [ "gitHashes" "sdkSourceBuilders" "pubspecLock" @@ -198,10 +212,5 @@ let meta = (args.meta or { }) // { platforms = args.meta.platforms or dart.meta.platforms; }; - } - ); -in -assert - !(builtins.isString dartOutputType && dartOutputType != "") - -> throw "dartOutputType must be a non-empty string"; -baseDerivation + }; +} diff --git a/pkgs/development/compilers/flutter/build-support/build-flutter-application.nix b/pkgs/development/compilers/flutter/build-support/build-flutter-application.nix index 4eb8f310f265..a2adc097947e 100644 --- a/pkgs/development/compilers/flutter/build-support/build-flutter-application.nix +++ b/pkgs/development/compilers/flutter/build-support/build-flutter-application.nix @@ -14,33 +14,63 @@ # absolutely no mac support for now -{ - pubGetScript ? null, - flutterBuildFlags ? [ ], - targetFlutterPlatform ? "linux", - extraWrapProgramArgs ? "", - flutterMode ? null, - ... -}@args: - -let - hasEngine = flutter ? engine && flutter.engine != null && flutter.engine.meta.available; - flutterMode = args.flutterMode or (if hasEngine then flutter.engine.runtimeMode else "release"); - - flutterFlags = lib.optional hasEngine "--local-engine host_${flutterMode}${ - lib.optionalString (!flutter.engine.isOptimized) "_unopt" - }"; - - flutterBuildFlags = [ - "--${flutterMode}" - ] - ++ (args.flutterBuildFlags or [ ]) - ++ flutterFlags; - - builderArgs = +lib.extendMkDerivation { + constructDrv = + argsFn: let + evalArgs = lib.fix argsFn; + targetFlutterPlatform = evalArgs.targetFlutterPlatform or "linux"; + + minimalFlutter = flutter.override { + supportedTargetFlutterPlatforms = [ + "universal" + targetFlutterPlatform + ]; + }; + + buildAppWith = flutter: buildDartApplication.override { dart = flutter; }; + in + buildAppWith minimalFlutter ( + finalAttrs: + let + args = argsFn finalAttrs; + in + args + // { + passthru = (args.passthru or { }) // { + multiShell = buildAppWith flutter args; + }; + } + ); + + extendDrvArgs = + finalAttrs: + args@{ + pubGetScript ? null, + flutterBuildFlags ? [ ], + targetFlutterPlatform ? "linux", + extraWrapProgramArgs ? "", + flutterMode ? null, + ... + }: + let + hasEngine = flutter ? engine && flutter.engine != null && flutter.engine.meta.available; + flutterMode' = args.flutterMode or (if hasEngine then flutter.engine.runtimeMode else "release"); + + flutterFlags = lib.optional hasEngine "--local-engine host_${flutterMode'}${ + lib.optionalString (!flutter.engine.isOptimized) "_unopt" + }"; + + flutterBuildFlags' = [ + "--${flutterMode'}" + ] + ++ (args.flutterBuildFlags or [ ]) + ++ flutterFlags; + universal = args // { - inherit flutterMode flutterFlags flutterBuildFlags; + flutterMode = flutterMode'; + flutterFlags = flutterFlags; + flutterBuildFlags = flutterBuildFlags'; sdkSetupScript = '' # Pub needs SSL certificates. Dart normally looks in a hardcoded path. @@ -128,8 +158,6 @@ let }; in { - inherit universal; - linux = universal // { outputs = universal.outputs or [ ] ++ [ "debug" ]; @@ -225,21 +253,4 @@ let }; } .${targetFlutterPlatform} or (throw "Unsupported Flutter host platform: ${targetFlutterPlatform}"); - - minimalFlutter = flutter.override { - supportedTargetFlutterPlatforms = [ - "universal" - targetFlutterPlatform - ]; - }; - - buildAppWith = flutter: buildDartApplication.override { dart = flutter; }; -in -buildAppWith minimalFlutter ( - builderArgs - // { - passthru = builderArgs.passthru or { } // { - multiShell = buildAppWith flutter builderArgs; - }; - } -) +} From 139edf9d6a070ecad976372c12b7906550de8b5f Mon Sep 17 00:00:00 2001 From: kyehn Date: Sat, 28 Feb 2026 09:29:57 +0800 Subject: [PATCH 2/2] fladder: use finalAttrs --- pkgs/by-name/fl/fladder/package.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/by-name/fl/fladder/package.nix b/pkgs/by-name/fl/fladder/package.nix index cb2e34b40598..e987af6a1c47 100644 --- a/pkgs/by-name/fl/fladder/package.nix +++ b/pkgs/by-name/fl/fladder/package.nix @@ -22,14 +22,14 @@ let media_kit_hash = "sha256-oJQ9sRQI4HpAIzoS995yfnzvx5ZzIubVANzbmxTt6LE="; in -flutter.buildFlutterApplication rec { +flutter.buildFlutterApplication (finalAttrs: { pname = "fladder"; version = "0.10.1"; src = fetchFromGitHub { owner = "DonutWare"; repo = "Fladder"; - tag = "v${version}"; + tag = "v${finalAttrs.version}"; hash = "sha256-lmtEgBxCmEYcckhSAXhMPDzNQBluTyW0yjkt6Rr9byA="; }; @@ -107,4 +107,4 @@ flutter.buildFlutterApplication rec { ]; mainProgram = "Fladder"; }; -} +})