forked from mirrors/nixpkgs
204 lines
7.3 KiB
XML
204 lines
7.3 KiB
XML
|
<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-option-declarations">
|
|||
|
<title>Option Declarations</title>
|
|||
|
<para>
|
|||
|
An option declaration specifies the name, type and description of a
|
|||
|
NixOS configuration option. It is invalid to define an option that
|
|||
|
hasn’t been declared in any module. An option declaration generally
|
|||
|
looks like this:
|
|||
|
</para>
|
|||
|
<programlisting language="bash">
|
|||
|
options = {
|
|||
|
name = mkOption {
|
|||
|
type = type specification;
|
|||
|
default = default value;
|
|||
|
example = example value;
|
|||
|
description = "Description for use in the NixOS manual.";
|
|||
|
};
|
|||
|
};
|
|||
|
</programlisting>
|
|||
|
<para>
|
|||
|
The attribute names within the <literal>name</literal> attribute
|
|||
|
path must be camel cased in general but should, as an exception,
|
|||
|
match the
|
|||
|
<link xlink:href="https://nixos.org/nixpkgs/manual/#sec-package-naming">
|
|||
|
package attribute name</link> when referencing a Nixpkgs package.
|
|||
|
For example, the option
|
|||
|
<literal>services.nix-serve.bindAddress</literal> references the
|
|||
|
<literal>nix-serve</literal> Nixpkgs package.
|
|||
|
</para>
|
|||
|
<para>
|
|||
|
The function <literal>mkOption</literal> accepts the following
|
|||
|
arguments.
|
|||
|
</para>
|
|||
|
<variablelist>
|
|||
|
<varlistentry>
|
|||
|
<term>
|
|||
|
<literal>type</literal>
|
|||
|
</term>
|
|||
|
<listitem>
|
|||
|
<para>
|
|||
|
The type of the option (see
|
|||
|
<xref linkend="sec-option-types" />). It may be omitted, but
|
|||
|
that’s not advisable since it may lead to errors that are hard
|
|||
|
to diagnose.
|
|||
|
</para>
|
|||
|
</listitem>
|
|||
|
</varlistentry>
|
|||
|
<varlistentry>
|
|||
|
<term>
|
|||
|
<literal>default</literal>
|
|||
|
</term>
|
|||
|
<listitem>
|
|||
|
<para>
|
|||
|
The default value used if no value is defined by any module. A
|
|||
|
default is not required; but if a default is not given, then
|
|||
|
users of the module will have to define the value of the
|
|||
|
option, otherwise an error will be thrown.
|
|||
|
</para>
|
|||
|
</listitem>
|
|||
|
</varlistentry>
|
|||
|
<varlistentry>
|
|||
|
<term>
|
|||
|
<literal>example</literal>
|
|||
|
</term>
|
|||
|
<listitem>
|
|||
|
<para>
|
|||
|
An example value that will be shown in the NixOS manual.
|
|||
|
</para>
|
|||
|
</listitem>
|
|||
|
</varlistentry>
|
|||
|
<varlistentry>
|
|||
|
<term>
|
|||
|
<literal>description</literal>
|
|||
|
</term>
|
|||
|
<listitem>
|
|||
|
<para>
|
|||
|
A textual description of the option, in DocBook format, that
|
|||
|
will be included in the NixOS manual.
|
|||
|
</para>
|
|||
|
</listitem>
|
|||
|
</varlistentry>
|
|||
|
</variablelist>
|
|||
|
<section xml:id="sec-option-declarations-eot">
|
|||
|
<title>Extensible Option Types</title>
|
|||
|
<para>
|
|||
|
Extensible option types is a feature that allow to extend certain
|
|||
|
types declaration through multiple module files. This feature only
|
|||
|
work with a restricted set of types, namely
|
|||
|
<literal>enum</literal> and <literal>submodules</literal> and any
|
|||
|
composed forms of them.
|
|||
|
</para>
|
|||
|
<para>
|
|||
|
Extensible option types can be used for <literal>enum</literal>
|
|||
|
options that affects multiple modules, or as an alternative to
|
|||
|
related <literal>enable</literal> options.
|
|||
|
</para>
|
|||
|
<para>
|
|||
|
As an example, we will take the case of display managers. There is
|
|||
|
a central display manager module for generic display manager
|
|||
|
options and a module file per display manager backend (sddm, gdm
|
|||
|
...).
|
|||
|
</para>
|
|||
|
<para>
|
|||
|
There are two approach to this module structure:
|
|||
|
</para>
|
|||
|
<itemizedlist>
|
|||
|
<listitem>
|
|||
|
<para>
|
|||
|
Managing the display managers independently by adding an
|
|||
|
enable option to every display manager module backend. (NixOS)
|
|||
|
</para>
|
|||
|
</listitem>
|
|||
|
<listitem>
|
|||
|
<para>
|
|||
|
Managing the display managers in the central module by adding
|
|||
|
an option to select which display manager backend to use.
|
|||
|
</para>
|
|||
|
</listitem>
|
|||
|
</itemizedlist>
|
|||
|
<para>
|
|||
|
Both approaches have problems.
|
|||
|
</para>
|
|||
|
<para>
|
|||
|
Making backends independent can quickly become hard to manage. For
|
|||
|
display managers, there can be only one enabled at a time, but the
|
|||
|
type system can not enforce this restriction as there is no
|
|||
|
relation between each backend <literal>enable</literal> option. As
|
|||
|
a result, this restriction has to be done explicitely by adding
|
|||
|
assertions in each display manager backend module.
|
|||
|
</para>
|
|||
|
<para>
|
|||
|
On the other hand, managing the display managers backends in the
|
|||
|
central module will require to change the central module option
|
|||
|
every time a new backend is added or removed.
|
|||
|
</para>
|
|||
|
<para>
|
|||
|
By using extensible option types, it is possible to create a
|
|||
|
placeholder option in the central module
|
|||
|
(<link linkend="ex-option-declaration-eot-service">Example:
|
|||
|
Extensible type placeholder in the service module</link>), and to
|
|||
|
extend it in each backend module
|
|||
|
(<link linkend="ex-option-declaration-eot-backend-gdm">Example:
|
|||
|
Extending
|
|||
|
<literal>services.xserver.displayManager.enable</literal> in the
|
|||
|
<literal>gdm</literal> module</link>,
|
|||
|
<link linkend="ex-option-declaration-eot-backend-sddm">Example:
|
|||
|
Extending
|
|||
|
<literal>services.xserver.displayManager.enable</literal> in the
|
|||
|
<literal>sddm</literal> module</link>).
|
|||
|
</para>
|
|||
|
<para>
|
|||
|
As a result, <literal>displayManager.enable</literal> option
|
|||
|
values can be added without changing the main service module file
|
|||
|
and the type system automatically enforce that there can only be a
|
|||
|
single display manager enabled.
|
|||
|
</para>
|
|||
|
<anchor xml:id="ex-option-declaration-eot-service" />
|
|||
|
<para>
|
|||
|
<emphasis role="strong">Example: Extensible type placeholder in
|
|||
|
the service module</emphasis>
|
|||
|
</para>
|
|||
|
<programlisting language="bash">
|
|||
|
services.xserver.displayManager.enable = mkOption {
|
|||
|
description = "Display manager to use";
|
|||
|
type = with types; nullOr (enum [ ]);
|
|||
|
};
|
|||
|
</programlisting>
|
|||
|
<anchor xml:id="ex-option-declaration-eot-backend-gdm" />
|
|||
|
<para>
|
|||
|
<emphasis role="strong">Example: Extending
|
|||
|
<literal>services.xserver.displayManager.enable</literal> in the
|
|||
|
<literal>gdm</literal> module</emphasis>
|
|||
|
</para>
|
|||
|
<programlisting language="bash">
|
|||
|
services.xserver.displayManager.enable = mkOption {
|
|||
|
type = with types; nullOr (enum [ "gdm" ]);
|
|||
|
};
|
|||
|
</programlisting>
|
|||
|
<anchor xml:id="ex-option-declaration-eot-backend-sddm" />
|
|||
|
<para>
|
|||
|
<emphasis role="strong">Example: Extending
|
|||
|
<literal>services.xserver.displayManager.enable</literal> in the
|
|||
|
<literal>sddm</literal> module</emphasis>
|
|||
|
</para>
|
|||
|
<programlisting language="bash">
|
|||
|
services.xserver.displayManager.enable = mkOption {
|
|||
|
type = with types; nullOr (enum [ "sddm" ]);
|
|||
|
};
|
|||
|
</programlisting>
|
|||
|
<para>
|
|||
|
The placeholder declaration is a standard
|
|||
|
<literal>mkOption</literal> declaration, but it is important that
|
|||
|
extensible option declarations only use the
|
|||
|
<literal>type</literal> argument.
|
|||
|
</para>
|
|||
|
<para>
|
|||
|
Extensible option types work with any of the composed variants of
|
|||
|
<literal>enum</literal> such as
|
|||
|
<literal>with types; nullOr (enum [ "foo" "bar" ])</literal>
|
|||
|
or
|
|||
|
<literal>with types; listOf (enum [ "foo" "bar" ])</literal>.
|
|||
|
</para>
|
|||
|
</section>
|
|||
|
</section>
|