diff --git a/ChangeLog.md b/ChangeLog.md index 6103b3b..2a046d4 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,4 +1,24 @@ +# 2026-01-05 + + - Deprecated `mkSubmoduleOptions`. Declare options directly instead, e.g. + `options.flake.foo = mkOption { ... }`. This works since Nixpkgs 22.05. + + - Deprecated `mkDeferredModuleType` and `mkDeferredModuleOption`. Use + `mkPerSystemType` and `mkPerSystemOption` respectively for `perSystem` + type-merging. For other uses, use Nixpkgs' `types.deferredModuleWith`. + + Note: flake-parts' implementation returns a list on merge, whereas Nixpkgs' + returns a single module. Add `apply = m: [ m ];` to your option if you need + the list behavior. + +# 2024-05-16 + + - **Breaking**: Minimum supported Nixpkgs lib version is now 23.05 (was 22.05), + due to the use of the `class` argument in `evalModules`. + + - Add `class` to `evalModules` calls for imports "type checking". + # 2023-05-30 - Fix a strictness issue in `perInput`, affecting `inputs'`, `self'`. diff --git a/lib.nix b/lib.nix index 76a96e3..c8ea2ba 100644 --- a/lib.nix +++ b/lib.nix @@ -32,8 +32,22 @@ let then maybeFlake._type == "flake" else maybeFlake ? inputs && maybeFlake ? outputs && maybeFlake ? sourceInfo; - # Polyfill https://github.com/NixOS/nixpkgs/pull/163617 - deferredModuleWith = lib.deferredModuleWith or ( + /** + Deprecated for any use except type-merging into `perSystem`. + Use `lib.types.deferredModuleWith` instead, and add `apply = m: [ m ];` if needed. + + The deferredModule type was pioneered in flake-parts for the `perSystem` option. + The Nixpkgs version has an improved merge function that returns a single module, + whereas this version returns a list. The flake-parts version was not updated to + match this improvement in Nixpkgs. + + # History + + This predates `lib.types.deferredModuleWith`, added in Nixpkgs 22.11 + (https://github.com/NixOS/nixpkgs/pull/163617). + Documented as deprecated in flake-parts in January 2026. + */ + deferredModuleWith = attrs@{ staticModules ? [ ] }: mkOptionType { name = "deferredModule"; description = "module"; @@ -54,8 +68,14 @@ let staticModules = lhs.staticModules ++ rhs.staticModules; }; }; - } - ); + }; + + # Internal: preserves legacy list-merge behavior for perSystem type-merging. + mkLegacyDeferredModuleType = + module: + deferredModuleWith { + staticModules = [ module ]; + }; errorExample = '' For example: @@ -141,8 +161,26 @@ let in eval.config.flake; - # For extending options in an already declared submodule. - # Workaround for https://github.com/NixOS/nixpkgs/issues/146882 + /** + Deprecated. Declare options directly, e.g. `options.foo.bar = mkOption { ... }`, + provided that `foo` is already declared as a submodule option. + + In flake-parts, `flake` is declared as a submodule option by the core modules, + so `options.flake.` declarations work directly. + + This function wraps option declarations in a submodule, allowing them to + be merged into an existing submodule option. For example, if `foo` is + already declared as a submodule option, using + `options.foo = mkSubmoduleOptions { bar = mkOption {...}; }` would add + `bar` to the `foo` submodule. + + # History + + This was a workaround for https://github.com/NixOS/nixpkgs/issues/146882, + fixed in Nixpkgs 22.05 by https://github.com/NixOS/nixpkgs/pull/156533. + With the fix, declaring `options.foo.bar` directly works when `foo` is + already a submodule option. Documented as deprecated in flake-parts in January 2026. + */ mkSubmoduleOptions = options: mkOption { @@ -151,18 +189,32 @@ let }; }; - mkDeferredModuleType = - module: - deferredModuleWith { - staticModules = [ module ]; - }; - mkPerSystemType = mkDeferredModuleType; + /** + Deprecated. Use mkPerSystemType/mkPerSystemOption for `perSystem` type-merging, or + use Nixpkgs `types.deferredModule` directly, noting the lack of list wrapping; + see `deferredModuleWith` docs. + */ + mkDeferredModuleType = mkLegacyDeferredModuleType; + /** + Given a module, construct an option type suitable for type-merging into `perSystem`'s type. + */ + mkPerSystemType = mkLegacyDeferredModuleType; + + /** + Deprecated. Use mkPerSystemOption for `perSystem` type-merging, or + use `mkOption` and Nixpkgs `types.deferredModule` directly, noting the + lack of list wrapping; see `deferredModuleWith` docs. + */ mkDeferredModuleOption = module: mkOption { type = flake-parts-lib.mkPerSystemType module; }; + + /** + Given a module, construct an option declaration suitable for merging into the core `perSystem` module. + */ mkPerSystemOption = mkDeferredModuleOption; # Polyfill https://github.com/NixOS/nixpkgs/pull/344216 @@ -177,18 +229,16 @@ let _file = file; options = { - flake = flake-parts-lib.mkSubmoduleOptions { - ${name} = mkOption { - type = attrsWith { - elemType = option.type; - lazy = true; - placeholder = "system"; - }; - default = { }; - description = '' - See {option}`perSystem.${name}` for description and examples. - ''; + flake.${name} = mkOption { + type = attrsWith { + elemType = option.type; + lazy = true; + placeholder = "system"; }; + default = { }; + description = '' + See {option}`perSystem.${name}` for description and examples. + ''; }; perSystem = flake-parts-lib.mkPerSystemOption { @@ -252,7 +302,7 @@ let # A best effort, lenient estimate. Please use a recent nixpkgs lib if you # override it at all. - minVersion = "22.05"; + minVersion = "23.05pre-git"; in diff --git a/modules/apps.nix b/modules/apps.nix index 2f30a77..3030d32 100644 --- a/modules/apps.nix +++ b/modules/apps.nix @@ -8,12 +8,7 @@ let mkTransposedPerSystemModule ; - getExe = lib.getExe or ( - x: - "${lib.getBin x}/bin/${x.meta.mainProgram or (throw ''Package ${x.name or ""} does not have meta.mainProgram set, so I don't know how to find the main executable. You can set meta.mainProgram, or pass the full path to executable, e.g. program = "''${pkg}/bin/foo"'')}" - ); - - programType = lib.types.coercedTo derivationType getExe lib.types.str; + programType = lib.types.coercedTo derivationType lib.getExe lib.types.str; derivationType = lib.types.package // { check = lib.isDerivation; @@ -56,7 +51,7 @@ mkTransposedPerSystemModule { description = '' Programs runnable with nix run ``. ''; - example = lib.literalExpression or lib.literalExample '' + example = lib.literalExpression '' { default.program = "''${config.packages.hello}/bin/hello"; } diff --git a/modules/formatter.nix b/modules/formatter.nix index 838b7cf..e2959ed 100644 --- a/modules/formatter.nix +++ b/modules/formatter.nix @@ -8,20 +8,17 @@ let types ; inherit (flake-parts-lib) - mkSubmoduleOptions mkPerSystemOption ; in { options = { - flake = mkSubmoduleOptions { - formatter = mkOption { - type = types.lazyAttrsOf types.package; - default = { }; - description = '' - An attribute set of per system a package used by [`nix fmt`](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-fmt.html). - ''; - }; + flake.formatter = mkOption { + type = types.lazyAttrsOf types.package; + default = { }; + description = '' + An attribute set of per system a package used by [`nix fmt`](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-fmt.html). + ''; }; perSystem = mkPerSystemOption { diff --git a/modules/nixosConfigurations.nix b/modules/nixosConfigurations.nix index 7dc973b..597132d 100644 --- a/modules/nixosConfigurations.nix +++ b/modules/nixosConfigurations.nix @@ -1,41 +1,36 @@ -{ lib, flake-parts-lib, ... }: +{ lib, ... }: let inherit (lib) mkOption types literalExpression ; - inherit (flake-parts-lib) - mkSubmoduleOptions - ; in { options = { - flake = mkSubmoduleOptions { - nixosConfigurations = mkOption { - type = types.lazyAttrsOf types.raw; - default = { }; - description = '' - Instantiated NixOS configurations. Used by `nixos-rebuild`. + flake.nixosConfigurations = mkOption { + type = types.lazyAttrsOf types.raw; + default = { }; + description = '' + Instantiated NixOS configurations. Used by `nixos-rebuild`. - `nixosConfigurations` is for specific machines. If you want to expose - reusable configurations, add them to [`nixosModules`](#opt-flake.nixosModules) - in the form of modules (no `lib.nixosSystem`), so that you can reference - them in this or another flake's `nixosConfigurations`. - ''; - example = literalExpression '' - { - my-machine = inputs.nixpkgs.lib.nixosSystem { - # system is not needed with freshly generated hardware-configuration.nix - # system = "x86_64-linux"; # or set nixpkgs.hostPlatform in a module. - modules = [ - ./my-machine/nixos-configuration.nix - config.nixosModules.my-module - ]; - }; - } - ''; - }; + `nixosConfigurations` is for specific machines. If you want to expose + reusable configurations, add them to [`nixosModules`](#opt-flake.nixosModules) + in the form of modules (no `lib.nixosSystem`), so that you can reference + them in this or another flake's `nixosConfigurations`. + ''; + example = literalExpression '' + { + my-machine = inputs.nixpkgs.lib.nixosSystem { + # system is not needed with freshly generated hardware-configuration.nix + # system = "x86_64-linux"; # or set nixpkgs.hostPlatform in a module. + modules = [ + ./my-machine/nixos-configuration.nix + config.nixosModules.my-module + ]; + }; + } + ''; }; }; } diff --git a/modules/nixosModules.nix b/modules/nixosModules.nix index 737648d..86ee9cc 100644 --- a/modules/nixosModules.nix +++ b/modules/nixosModules.nix @@ -1,31 +1,26 @@ -{ self, lib, flake-parts-lib, moduleLocation, ... }: +{ self, lib, moduleLocation, ... }: let inherit (lib) mapAttrs mkOption types ; - inherit (flake-parts-lib) - mkSubmoduleOptions - ; in { options = { - flake = mkSubmoduleOptions { - nixosModules = mkOption { - type = types.lazyAttrsOf types.deferredModule; - default = { }; - apply = mapAttrs (k: v: { - _class = "nixos"; - _file = "${toString moduleLocation}#nixosModules.${k}"; - imports = [ v ]; - }); - description = '' - NixOS modules. + flake.nixosModules = mkOption { + type = types.lazyAttrsOf types.deferredModule; + default = { }; + apply = mapAttrs (k: v: { + _class = "nixos"; + _file = "${toString moduleLocation}#nixosModules.${k}"; + imports = [ v ]; + }); + description = '' + NixOS modules. - You may use this for reusable pieces of configuration, service modules, etc. - ''; - }; + You may use this for reusable pieces of configuration, service modules, etc. + ''; }; }; } diff --git a/modules/overlays.nix b/modules/overlays.nix index a09e8f6..172336c 100644 --- a/modules/overlays.nix +++ b/modules/overlays.nix @@ -1,37 +1,32 @@ -{ lib, flake-parts-lib, ... }: +{ lib, ... }: let inherit (lib) mkOption types ; - inherit (flake-parts-lib) - mkSubmoduleOptions - ; in { options = { - flake = mkSubmoduleOptions { - overlays = mkOption { - # uniq -> ordered: https://github.com/NixOS/nixpkgs/issues/147052 - # also update description when done - type = types.lazyAttrsOf (types.uniq (types.functionTo (types.functionTo (types.lazyAttrsOf types.unspecified)))); - # This eta expansion exists for the sole purpose of making nix flake check happy. - apply = lib.mapAttrs (_k: f: final: prev: f final prev); - default = { }; - example = lib.literalExpression or lib.literalExample '' - { - default = final: prev: {}; - } - ''; - description = '' - An attribute set of [overlays](https://nixos.org/manual/nixpkgs/stable/#chap-overlays). + flake.overlays = mkOption { + # uniq -> ordered: https://github.com/NixOS/nixpkgs/issues/147052 + # also update description when done + type = types.lazyAttrsOf (types.uniq (types.functionTo (types.functionTo (types.lazyAttrsOf types.unspecified)))); + # This eta expansion exists for the sole purpose of making nix flake check happy. + apply = lib.mapAttrs (_k: f: final: prev: f final prev); + default = { }; + example = lib.literalExpression '' + { + default = final: prev: {}; + } + ''; + description = '' + An attribute set of [overlays](https://nixos.org/manual/nixpkgs/stable/#chap-overlays). - Note that the overlays themselves are not mergeable. While overlays - can be composed, the order of composition is significant, but the - module system does not guarantee sufficiently deterministic - definition ordering, across versions and when changing `imports`. - ''; - }; + Note that the overlays themselves are not mergeable. While overlays + can be composed, the order of composition is significant, but the + module system does not guarantee sufficiently deterministic + definition ordering, across versions and when changing `imports`. + ''; }; }; }