Remove mkSubmoduleOptions usages, document as deprecated

The workaround is no longer needed since Nixpkgs 22.05
(https://github.com/NixOS/nixpkgs/pull/156533).
Declaring options directly in a submodule now works, e.g. `options.flake.foo`.

The function is kept for backwards compatibility but documented as deprecated.

The minimum supported Nixpkgs lib version is already 22.05, so this change
does not drop support for any previously supported version.
This commit is contained in:
Robert Hensing 2026-01-05 09:29:29 +01:00
parent a34fae9c08
commit 65b36eb2cb
5 changed files with 91 additions and 93 deletions

42
lib.nix
View file

@ -141,8 +141,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.<name>` 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 {
@ -177,18 +195,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 {

View file

@ -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 {

View file

@ -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
];
};
}
'';
};
};
}

View file

@ -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.
'';
};
};
}

View file

@ -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 or lib.literalExample ''
{
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`.
'';
};
};
}