{ lib }:
let
inherit (lib)
all
any
attrByPath
attrNames
catAttrs
concatLists
concatMap
concatStringsSep
elem
filter
findFirst
foldl'
getAttrFromPath
head
id
imap1
isAttrs
isBool
isFunction
isList
isString
length
mapAttrs
mapAttrsToList
mapAttrsRecursiveCond
min
optional
optionalAttrs
optionalString
recursiveUpdate
reverseList sort
setAttrByPath
toList
types
warnIf
zipAttrsWith
;
inherit (lib.options)
isOption
mkOption
showDefs
showFiles
showOption
unknownModule
literalExpression
;
showDeclPrefix = loc: decl: prefix:
" - option(s) with prefix `${showOption (loc ++ [prefix])}' in module `${decl._file}'";
showRawDecls = loc: decls:
concatStringsSep "\n"
(sort (a: b: a < b)
(concatMap
(decl: map
(showDeclPrefix loc decl)
(attrNames decl.options)
)
decls
));
in
rec {
/*
Evaluate a set of modules. The result is a set with the attributes:
‘options’: The nested set of all option declarations,
‘config’: The nested set of all option values.
‘type’: A module system type representing the module set as a submodule,
to be extended by configuration from the containing module set.
This is also available as the module argument ‘moduleType’.
‘extendModules’: A function similar to ‘evalModules’ but building on top
of the module set. Its arguments, ‘modules’ and ‘specialArgs’ are
added to the existing values.
Using ‘extendModules’ a few times has no performance impact as long
as you only reference the final ‘options’ and ‘config’.
If you do reference multiple ‘config’ (or ‘options’) from before and
after ‘extendModules’, performance is the same as with multiple
‘evalModules’ invocations, because the new modules' ability to
override existing configuration fundamentally requires a new
fixpoint to be constructed.
This is also available as a module argument.
‘_module’: A portion of the configuration tree which is elided from
‘config’. It contains some values that are mostly internal to the
module system implementation.
!!! Please think twice before adding to this argument list! The more
that is specified here instead of in the modules themselves the harder
it is to transparently move a set of modules to be a submodule of another
config (as the proper arguments need to be replicated at each call to
evalModules) and the less declarative the module set is. */
evalModules = evalModulesArgs@
{ modules
, prefix ? []
, # This should only be used for special arguments that need to be evaluated
# when resolving module structure (like in imports). For everything else,
# there's _module.args. If specialArgs.modulesPath is defined it will be
# used as the base path for disabledModules.
specialArgs ? {}
, # This would be remove in the future, Prefer _module.args option instead.
args ? {}
, # This would be remove in the future, Prefer _module.check option instead.
check ? true
}:
let
withWarnings = x:
lib.warnIf (evalModulesArgs?args) "The args argument to evalModules is deprecated. Please set config._module.args instead."
lib.warnIf (evalModulesArgs?check) "The check argument to evalModules is deprecated. Please set config._module.check instead."
x;
legacyModules =
optional (evalModulesArgs?args) {
config = {
_module.args = args;
};
}
++ optional (evalModulesArgs?check) {
config = {
_module.check = mkDefault check;
};
};
regularModules = modules ++ legacyModules;
# This internal module declare internal options under the `_module'
# attribute. These options are fragile, as they are used by the
# module system to change the interpretation of modules.
#
# When extended with extendModules or moduleType, a fresh instance of
# this module is used, to avoid conflicts and allow chaining of
# extendModules.
internalModule = rec {
_file = "lib/modules.nix";
key = _file;
options = {
_module.args = mkOption {
# Because things like `mkIf` are entirely useless for
# `_module.args` (because there's no way modules can check which
# arguments were passed), we'll use `lazyAttrsOf` which drops
# support for that, in turn it's lazy in its values. This means e.g.
# a `_module.args.pkgs = import (fetchTarball { ... }) {}` won't
# start a download when `pkgs` wasn't evaluated.
type = types.lazyAttrsOf types.raw;
# Only render documentation once at the root of the option tree,
# not for all individual submodules.
# Allow merging option decls to make this internal regardless.
${if prefix == []
then null # unset => visible
else "internal"} = true;
# TODO: Change the type of this option to a submodule with a
# freeformType, so that individual arguments can be documented
# separately
description = ''
Additional arguments passed to each module in addition to ones
like <literal>lib</literal>, <literal>config</literal>,
and <literal>pkgs</literal>, <literal>modulesPath</literal>.
</para>
<para>
This option is also available to all submodules. Submodules do not
inherit args from their parent module, nor do they provide args to
their parent module or sibling submodules. The sole exception to
this is the argument <literal>name</literal> which is provided by
parent modules to a submodule and contains the attribute name
the submodule is bound to, or a unique generated name if it is
not bound to an attribute.
</para>
<para>
Some arguments are already passed by default, of which the
following <emphasis>cannot</emphasis> be changed with this option:
<itemizedlist>
<listitem>
<para>
<varname>lib</varname>: The nixpkgs library.
</para>
</listitem>
<listitem>
<para>
<varname>config</varname>: The results of all options after merging the values from all modules together.
</para>
</listitem>
<listitem>
<para>
<