Skip to content

Commit

Permalink
modules/nixpkgs: Make customizable & support multiple evaluations
Browse files Browse the repository at this point in the history
  • Loading branch information
bb010g committed Apr 19, 2023
1 parent c1b1f4f commit 704ac53
Show file tree
Hide file tree
Showing 2 changed files with 176 additions and 14 deletions.
181 changes: 173 additions & 8 deletions modules/nixpkgs.nix
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#
# Nixpkgs module. The only exception to the rule.
#
# Provides a `pkgs` argument in `perSystem`.
# Provides customizable `nixpkgs` and `pkgs` arguments in `perSystem`.
#
# Arguably, this shouldn't be in flake-parts, but in nixpkgs.
# Nixpkgs could define its own module that does this, which would be
Expand All @@ -11,16 +11,181 @@
# will be accepted into flake-parts, because it's against the
# spirit of Flakes.
#
{ config, flake-parts-lib, inputs, lib, options, ... }:
let
inherit (lib)
last
literalExpression
mapAttrs
mdDoc
mkOption
mkOptionDefault
mkOverride
types
;
inherit (flake-parts-lib)
mkPerSystemOption
mkSubmoduleOptions
submoduleWithModules
;
extendSubModules = type: modules:
type.substSubModules (type.getSubModules ++ modules);
getOptionSubOptions = locSuffix: opt:
let
loc = opt.loc ++ locSuffix;
type = extendSubModules opt.type [{ _module.args.name = last loc; }];
in
type.getSubOptions loc;
rootConfig = config;
rootOptions = options;
in
{
options = {
nixpkgs = {
evals = mkOption {
default = { default = { }; };
description = ''
Configuration for Nixpkgs evaluations of {option}`perSystem.nixpkgs.evals`.
'';
type = types.lazyAttrsOf (submoduleWithModules { } ({ config, name, options, ... }: {
_file = ./nixpkgs.nix;
options = {
input = mkOption {
description = mdDoc ''
Nixpkgs function for evaluation.
'';
default = inputs.nixpkgs or (throw
"flake-parts: The flake does not have a `nixpkgs` input. Please add it, or set `${options.input}` yourself."
);
defaultText = literalExpression ''inputs.nixpkgs'';
type = types.coercedTo types.path import (types.functionTo types.unspecified);
};
settings = mkOption {
default = { };
description = mdDoc ''
Settings argument for the Nixpkgs evaluations of {option}`perSystem.nixpkgs.evals.<name>`.
'';
type = rootOptions.nixpkgs.settings.type;
};
};
config = {
settings.config = rootConfig.nixpkgs.settings;
};
}));
};
settings = mkOption {
default = { };
description = mdDoc ''
Default settings argument for each Nixpkgs evaluations of {option}`nixpkgs.evals`.
'';
type = submoduleWithModules { } ({ config, name, options, ... }: {
_file = ./nixpkgs.nix;
freeformType = types.lazyAttrsOf types.raw;
options = {
config = mkOption {
default = { };
description = mdDoc ''
Config for this Nixpkgs evaluation.
'';
type = submoduleWithModules { } {
_file = ./nixpkgs.nix;
freeformType = types.lazyAttrsOf types.raw;
};
};
crossOverlays = mkOption {
default = [ ];
description = mdDoc ''
List of Nixpkgs overlays to apply to target packages only for this Nixpkgs evaluation.
'';
type = types.listOf (types.uniq (types.functionTo (types.functionTo (types.lazyAttrsOf types.unspecified))));
};
overlays = mkOption {
default = [ ];
description = mdDoc ''
List of Nixpkgs overlays for this Nixpkgs evaluation.
'';
type = types.listOf (types.uniq (types.functionTo (types.functionTo (types.lazyAttrsOf types.unspecified))));
};
};
});
};
};
perSystem = mkPerSystemOption ({ config, system, ... }: {
_file = ./nixpkgs.nix;
options = {
nixpkgs = {
evals = mkOption {
default = { };
description = ''
Configuration for Nixpkgs evaluations.
'';
type = types.lazyAttrsOf (submoduleWithModules { } [
({ config, name, options, ... }: {
_file = ./nixpkgs.nix;
options = {
output = mkOption {
default = rootConfig.nixpkgs.evals.${name}.input config.settings;
defaultText = literalExpression
''config.nixpkgs.evals.''${name}.input config.perSystem.nixpkgs.''${name}.settings'';
description = mdDoc ''
Evaluated Nixpkgs.
'';
type = types.raw;
};
settings = mkOption {
default = { };
description = mdDoc ''
Settings argument for the Nixpkgs evaluations of {option}`perSystem.nixpkgs.evals.<name>`.
'';
type = (getOptionSubOptions [ name ] rootOptions.nixpkgs.evals).settings.type;
};
};
})
# Separate module, for type merging
({ config, name, options, ... }: {
_file = ./nixpkgs.nix;
options = {
settings = mkSubmoduleOptions {
crossSystem = mkOption {
default = config.settings.localSystem;
defaultText = literalExpression ''config.perSystem.nixpkgs.evals.''${name}.settings.localSystem'';
description = mdDoc ''
The system that packages will ultimately be run on for this Nixpkgs evaluation.
'';
type = types.either types.str types.attrs;
};
localSystem = mkOption {
default = system;
defaultText = literalExpression ''system'';
description = mdDoc ''
The system that packages will be built on for this Nixpkgs evaluation.
See the Nixpkgs manual for the subtle division of labor between `localSystem` &
`crossSystem` and the three `*Platform`s.
'';
type = types.either types.str types.attrs;
};
};
};
})
]);
};
};
};
config = {
nixpkgs = {
evals = mapAttrs (name: genericConfig: { }) rootConfig.nixpkgs.evals;
};
};
});
};
config = {
perSystem = { inputs', lib, options, ... }: {
perSystem = { config, nixpkgs, options, ... }: {
_file = ./nixpkgs.nix;
config = {
_module.args.pkgs = lib.mkOptionDefault (
builtins.seq
inputs'.nixpkgs or (throw
"flake-parts: The flake does not have a `nixpkgs` input. Please add it, or set `${options._module.args}.pkgs` yourself."
)
inputs'.nixpkgs.legacyPackages
_module.args.nixpkgs = mkOptionDefault (mapAttrs (name: nixpkgs: nixpkgs.output) config.nixpkgs.evals);
_module.args.pkgs = mkOptionDefault (
nixpkgs.default or (throw "flake-parts: The `perSystem` argument `nixpkgs` does not have a default attribute. Please configure `${options._module.args}.nixpkgs.default`, or set `${options._module.args}.nixpkgs` or `${options._module.args}.pkgs` yourself.")
);
};
};
Expand Down
9 changes: 3 additions & 6 deletions template/unfree/flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,12 @@

inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";

outputs = inputs@{ flake-parts, nixpkgs, ... }:
outputs = inputs@{ flake-parts, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
systems = [ "x86_64-linux" "aarch64-darwin" ];
perSystem = { pkgs, system, ... }: {
# This sets `pkgs` to a nixpkgs with allowUnfree option set.
_module.args.pkgs = import nixpkgs {
inherit system;
config.allowUnfree = true;
};
# This sets `pkgs` to a Nixpkgs with the `allowUnfree` option set.
nixpkgs.config.allowUnfree = true;

packages.default = pkgs.hello-unfree;
};
Expand Down

0 comments on commit 704ac53

Please sign in to comment.