You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
199 lines
6.5 KiB
199 lines
6.5 KiB
<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"> |
|
<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: |
|
<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> |
|
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. |
|
</para> |
|
|
|
<para> |
|
The function <varname>mkOption</varname> accepts the following arguments. |
|
<variablelist> |
|
<varlistentry> |
|
<term> |
|
<varname>type</varname> |
|
</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> |
|
<varname>default</varname> |
|
</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> |
|
<varname>example</varname> |
|
</term> |
|
<listitem> |
|
<para> |
|
An example value that will be shown in the NixOS manual. |
|
</para> |
|
</listitem> |
|
</varlistentry> |
|
<varlistentry> |
|
<term> |
|
<varname>description</varname> |
|
</term> |
|
<listitem> |
|
<para> |
|
A textual description of the option, in DocBook format, that will be |
|
included in the NixOS manual. |
|
</para> |
|
</listitem> |
|
</varlistentry> |
|
</variablelist> |
|
</para> |
|
|
|
<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 (slim, sddm, gdm ...). |
|
</para> |
|
|
|
<para> |
|
There are two approach to this module structure: |
|
<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> |
|
|
|
<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 |
|
(<xref linkend='ex-option-declaration-eot-service' |
|
/>), and to extend |
|
it in each backend module |
|
(<xref |
|
linkend='ex-option-declaration-eot-backend-slim' />, |
|
<xref |
|
linkend='ex-option-declaration-eot-backend-sddm' />). |
|
</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> |
|
|
|
<example xml:id='ex-option-declaration-eot-service'> |
|
<title>Extensible type placeholder in the service module</title> |
|
<screen> |
|
services.xserver.displayManager.enable = mkOption { |
|
description = "Display manager to use"; |
|
type = with types; nullOr (enum [ ]); |
|
};</screen> |
|
</example> |
|
|
|
<example xml:id='ex-option-declaration-eot-backend-slim'> |
|
<title>Extending <literal>services.xserver.displayManager.enable</literal> in the <literal>slim</literal> module</title> |
|
<screen> |
|
services.xserver.displayManager.enable = mkOption { |
|
type = with types; nullOr (enum [ "slim" ]); |
|
};</screen> |
|
</example> |
|
|
|
<example xml:id='ex-option-declaration-eot-backend-sddm'> |
|
<title>Extending <literal>services.xserver.displayManager.enable</literal> in the <literal>sddm</literal> module</title> |
|
<screen> |
|
services.xserver.displayManager.enable = mkOption { |
|
type = with types; nullOr (enum [ "sddm" ]); |
|
};</screen> |
|
</example> |
|
|
|
<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>
|
|
|