nixpkgs/nixos/doc/manual/development/option-declarations.xml

158 lines
6.4 KiB
XML
Raw Normal View History

<section xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-option-declarations">
2018-05-02 00:57:09 +01:00
<title>Option Declarations</title>
2018-05-02 00:57:09 +01:00
<para>
2019-09-18 21:13:35 +01:00
An option declaration specifies the name, type and description of a NixOS configuration option. It is invalid to define an option that hasnt been declared in any module. An option declaration generally looks like this:
<programlisting>
options = {
<replaceable>name</replaceable> = mkOption {
type = <replaceable>type specification</replaceable>;
default = <replaceable>default value</replaceable>;
example = <replaceable>example value</replaceable>;
description = "<replaceable>Description for use in the NixOS manual.</replaceable>";
};
};
</programlisting>
2019-09-18 21:13:35 +01:00
The attribute names within the <replaceable>name</replaceable> 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 <varname>services.nix-serve.bindAddress</varname> references the <varname>nix-serve</varname> Nixpkgs package.
2018-05-02 00:57:09 +01:00
</para>
<para>
The function <varname>mkOption</varname> accepts the following arguments.
<variablelist>
<varlistentry>
<term>
<varname>type</varname>
2018-05-02 00:57:09 +01:00
</term>
<listitem>
2018-05-02 00:57:09 +01:00
<para>
2019-09-18 21:13:35 +01:00
The type of the option (see <xref linkend='sec-option-types' />). It may be omitted, but thats not advisable since it may lead to errors that are hard to diagnose.
2018-05-02 00:57:09 +01:00
</para>
</listitem>
2018-05-02 00:57:09 +01:00
</varlistentry>
<varlistentry>
<term>
<varname>default</varname>
2018-05-02 00:57:09 +01:00
</term>
<listitem>
2018-05-02 00:57:09 +01:00
<para>
2019-09-18 21:13:35 +01:00
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.
2018-05-02 00:57:09 +01:00
</para>
</listitem>
2018-05-02 00:57:09 +01:00
</varlistentry>
<varlistentry>
<term>
<varname>example</varname>
2018-05-02 00:57:09 +01:00
</term>
<listitem>
2018-05-02 00:57:09 +01:00
<para>
An example value that will be shown in the NixOS manual.
</para>
</listitem>
2018-05-02 00:57:09 +01:00
</varlistentry>
<varlistentry>
<term>
<varname>description</varname>
2018-05-02 00:57:09 +01:00
</term>
<listitem>
2018-05-02 00:57:09 +01:00
<para>
2019-09-18 21:13:35 +01:00
A textual description of the option, in DocBook format, that will be included in the NixOS manual.
2018-05-02 00:57:09 +01:00
</para>
</listitem>
2018-05-02 00:57:09 +01:00
</varlistentry>
</variablelist>
</para>
<section xml:id="sec-option-declarations-eot">
<title>Extensible Option Types</title>
<para>
2019-09-18 21:13:35 +01:00
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.
2018-05-02 00:57:09 +01:00
</para>
2016-09-07 02:03:32 +01:00
2018-05-02 00:57:09 +01:00
<para>
2019-09-18 21:13:35 +01:00
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.
2016-09-07 02:03:32 +01:00
</para>
2018-05-02 00:57:09 +01:00
<para>
2019-09-18 21:13:35 +01:00
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 (slim, sddm, gdm ...).
2018-05-02 00:57:09 +01:00
</para>
2016-09-07 02:03:32 +01:00
2018-05-02 00:57:09 +01:00
<para>
There are two approach to this module structure:
<itemizedlist>
<listitem>
<para>
2019-09-18 21:13:35 +01:00
Managing the display managers independently by adding an enable option to every display manager module backend. (NixOS)
2018-05-02 00:57:09 +01:00
</para>
2016-09-07 02:03:32 +01:00
</listitem>
2018-05-02 00:57:09 +01:00
<listitem>
<para>
2019-09-18 21:13:35 +01:00
Managing the display managers in the central module by adding an option to select which display manager backend to use.
2018-05-02 00:57:09 +01:00
</para>
2016-09-07 02:03:32 +01:00
</listitem>
2018-05-02 00:57:09 +01:00
</itemizedlist>
2016-09-07 02:03:32 +01:00
</para>
2018-05-02 00:57:09 +01:00
<para>
Both approaches have problems.
</para>
2018-05-02 00:57:09 +01:00
<para>
2019-09-18 21:13:35 +01:00
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.
2018-05-02 00:57:09 +01:00
</para>
2016-09-07 02:03:32 +01:00
2018-05-02 00:57:09 +01:00
<para>
2019-09-18 21:13:35 +01:00
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.
2018-05-02 00:57:09 +01:00
</para>
2016-09-07 02:03:32 +01:00
2018-05-02 00:57:09 +01:00
<para>
2019-09-18 21:13:35 +01:00
By using extensible option types, it is possible to create a placeholder option in the central module (<xref linkend='ex-option-declaration-eot-service'
/>), and to extend it in each backend module (<xref
linkend='ex-option-declaration-eot-backend-slim' />, <xref
2018-05-02 00:57:09 +01:00
linkend='ex-option-declaration-eot-backend-sddm' />).
</para>
2018-05-02 00:57:09 +01:00
<para>
2019-09-18 21:13:35 +01:00
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.
2018-05-02 00:57:09 +01:00
</para>
2016-09-07 02:03:32 +01:00
2018-05-02 00:57:09 +01:00
<example xml:id='ex-option-declaration-eot-service'>
<title>Extensible type placeholder in the service module</title>
2016-09-07 02:03:32 +01:00
<screen>
services.xserver.displayManager.enable = mkOption {
description = "Display manager to use";
type = with types; nullOr (enum [ ]);
2018-05-02 00:57:09 +01:00
};</screen>
</example>
2016-09-07 02:03:32 +01:00
2018-05-02 00:57:09 +01:00
<example xml:id='ex-option-declaration-eot-backend-slim'>
<title>Extending <literal>services.xserver.displayManager.enable</literal> in the <literal>slim</literal> module</title>
2016-09-07 02:03:32 +01:00
<screen>
services.xserver.displayManager.enable = mkOption {
type = with types; nullOr (enum [ "slim" ]);
2018-05-02 00:57:09 +01:00
};</screen>
</example>
2016-09-07 02:03:32 +01:00
2018-05-02 00:57:09 +01:00
<example xml:id='ex-option-declaration-eot-backend-sddm'>
<title>Extending <literal>services.xserver.displayManager.enable</literal> in the <literal>sddm</literal> module</title>
2016-09-07 02:03:32 +01:00
<screen>
services.xserver.displayManager.enable = mkOption {
type = with types; nullOr (enum [ "sddm" ]);
2018-05-02 00:57:09 +01:00
};</screen>
</example>
2016-09-07 02:03:32 +01:00
2018-05-02 00:57:09 +01:00
<para>
2019-09-18 21:13:35 +01:00
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.
2018-05-02 00:57:09 +01:00
</para>
2016-09-07 02:03:32 +01:00
2018-05-02 00:57:09 +01:00
<para>
2019-09-18 21:13:35 +01:00
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>.
2018-05-02 00:57:09 +01:00
</para>
</section>
</section>