<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> </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; in that case, if the option value is never used, 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, kdm, 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 approachs 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-kdm' />).</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-kdm'><title>Extending <literal>services.foo.backend</literal> in the <literal>kdm</literal> module</title> <screen> services.xserver.displayManager.enable = mkOption { type = with types; nullOr (enum [ "kdm" ]); };</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>