2022-05-25 14:36:33 +00:00
{ config , lib , flake-parts-lib , self , . . . }:
2021-10-27 09:05:52 +00:00
let
inherit ( lib )
2021-11-22 21:01:38 +00:00
genAttrs
2021-10-27 09:05:52 +00:00
mapAttrs
mkOption
types
;
2022-05-25 14:36:33 +00:00
inherit ( flake-parts-lib )
2022-05-13 08:14:10 +00:00
mkPerSystemType
;
2021-10-27 09:05:52 +00:00
rootConfig = config ;
2022-12-27 11:53:19 +00:00
# Stubs for self and inputs. While it'd be possible to define aliases
# inside perSystem, that is not a general solution, and it would make
# top.config harder to discover, stretching the learning curve rather
# than flattening it.
throwAliasError' = param :
throw ''
` $ { param } ` ( without ` ' ` ) is not a ` perSystem ` module argument , but a
module argument of the top level config .
The following is an example usage of ` $ { param } ` . Note that its binding
is in the ` top ` parameter list , which is declared by the top level module
rather than the ` perSystem ` module .
top @ { config , lib , ${ param } , . . . }: {
perSystem = { config , ${ param } ' , . . . }: {
# in scope here:
# - ${param}
# - ${param}'
# - config (of perSystem)
# - top.config (note the `top@` pattern)
} ;
}
'' ;
throwAliasError = param :
throw ''
` $ { param } ` is not a ` perSystem ` module argument , but a module argument of
the top level config .
The following is an example usage of ` $ { param } ` . Note that its binding
is in the ` top ` parameter list , which is declared by the top level module
rather than the ` perSystem ` module .
top @ { config , lib , ${ param } , . . . }: {
perSystem = { config , . . . }: {
# in scope here:
# - ${param}
# - config (of perSystem)
# - top.config (note the `top@` pattern)
} ;
}
'' ;
2021-10-27 09:05:52 +00:00
in
{
options = {
systems = mkOption {
2022-11-11 06:39:25 +00:00
description = ''
2022-11-11 05:40:37 +00:00
All the system types to enumerate in the flake output subattributes .
In other words , all valid values for ` system ` in e . g . ` packages . <system> . foo ` .
'' ;
2021-10-27 09:05:52 +00:00
type = types . listOf types . str ;
} ;
perInput = mkOption {
2023-01-06 23:12:57 +00:00
description = ''
A function that pre-processes flake inputs .
It is called for users of ` perSystem ` such that ` inputs' . '' ${ name } = c o n f i g . p e r I n p u t s y s t e m i n p u t s . ''$ { n a m e } ` .
This is used for [ ` inputs' ` ] ( ../module-arguments.html #inputs) and [`self'`](../module-arguments.html#self).
The attributes returned by the ` perInput ` function definitions are merged into a single namespace ( per input ) ,
so each module should return an attribute set with usually only one or two predictable attribute names . Otherwise ,
the ` inputs' ` namespace gets polluted .
'' ;
2021-10-27 09:05:52 +00:00
type = types . functionTo ( types . functionTo ( types . lazyAttrsOf types . unspecified ) ) ;
} ;
perSystem = mkOption {
2023-01-06 23:12:57 +00:00
description = ''
A function from system to flake-like attributes omitting the ` <system> ` attribute .
Modules defined here have access to the suboptions and [ some convenient module arguments ] ( ../module-arguments.html ) .
'' ;
2022-05-13 08:14:10 +00:00
type = mkPerSystemType ( { config , system , . . . }: {
_file = ./perSystem.nix ;
config = {
_module . args . inputs' = mapAttrs ( k : rootConfig . perInput system ) self . inputs ;
_module . args . self' = rootConfig . perInput system self ;
2022-12-27 11:53:19 +00:00
# Custom error messages
_module . args . self = throwAliasError' " s e l f " ;
_module . args . inputs = throwAliasError' " i n p u t s " ;
_module . args . getSystem = throwAliasError " g e t S y s t e m " ;
_module . args . withSystem = throwAliasError " w i t h S y s t e m " ;
_module . args . moduleWithSystem = throwAliasError " m o d u l e W i t h S y s t e m " ;
2022-05-13 08:14:10 +00:00
} ;
2021-10-27 09:05:52 +00:00
} ) ;
2022-05-25 16:09:17 +00:00
apply = modules : system :
( lib . evalModules {
inherit modules ;
prefix = [ " p e r S y s t e m " system ] ;
specialArgs = {
inherit system ;
} ;
} ) . config ;
2021-10-27 09:05:52 +00:00
} ;
2021-11-22 21:01:38 +00:00
allSystems = mkOption {
type = types . lazyAttrsOf types . unspecified ;
2022-11-11 06:39:25 +00:00
description = " T h e s y s t e m - s p e c i f i c c o n f i g f o r e a c h o f s y s t e m s . " ;
2021-11-22 21:01:38 +00:00
internal = true ;
} ;
} ;
config = {
allSystems = genAttrs config . systems config . perSystem ;
# TODO: Sub-optimal error message. Get Nix to support a memoization primop, or get Nix Flakes to support systems properly or get Nix Flakes to add a name to flakes.
2022-04-06 16:01:26 +00:00
_module . args . getSystem = system : config . allSystems . ${ system } or ( builtins . trace " u s i n g n o n - m e m o i z e d s y s t e m ${ system } " config . perSystem system ) ;
2023-01-05 00:07:58 +00:00
# The warning is there for a reason. Only use this in situations where the
# performance cost has already been incurred, such as in `flakeModules.easyOverlay`,
# where we run in the context of an overlay, and the performance cost of the
# extra `pkgs` makes the cost of running `perSystem` probably negligible.
2023-01-05 00:15:50 +00:00
_module . args . getSystemIgnoreWarning = system : config . allSystems . ${ system } or ( config . perSystem system ) ;
2021-10-27 09:05:52 +00:00
} ;
}