at 18.03-beta 6.4 kB view raw
1<section xmlns="http://docbook.org/ns/docbook" 2 xmlns:xlink="http://www.w3.org/1999/xlink" 3 xmlns:xi="http://www.w3.org/2001/XInclude" 4 version="5.0" 5 xml:id="sec-option-declarations"> 6 7<title>Option Declarations</title> 8 9<para>An option declaration specifies the name, type and description 10of a NixOS configuration option. It is invalid to define an option 11that hasn’t been declared in any module. An option declaration 12generally looks like this: 13 14<programlisting> 15options = { 16 <replaceable>name</replaceable> = mkOption { 17 type = <replaceable>type specification</replaceable>; 18 default = <replaceable>default value</replaceable>; 19 example = <replaceable>example value</replaceable>; 20 description = "<replaceable>Description for use in the NixOS manual.</replaceable>"; 21 }; 22}; 23</programlisting> 24 25The attribute names within the <replaceable>name</replaceable> 26attribute path must be camel cased in general but should, as an 27exception, match the 28<link 29xlink:href="https://nixos.org/nixpkgs/manual/#sec-package-naming"> 30package attribute name</link> when referencing a Nixpkgs package. For 31example, the option <varname>services.nix-serve.bindAddress</varname> 32references the <varname>nix-serve</varname> Nixpkgs package. 33 34</para> 35 36<para>The function <varname>mkOption</varname> accepts the following arguments. 37 38<variablelist> 39 40 <varlistentry> 41 <term><varname>type</varname></term> 42 <listitem> 43 <para>The type of the option (see <xref linkend='sec-option-types' />). 44 It may be omitted, but that’s not advisable since it may lead to errors 45 that are hard to diagnose.</para> 46 </listitem> 47 </varlistentry> 48 49 <varlistentry> 50 <term><varname>default</varname></term> 51 <listitem> 52 <para>The default value used if no value is defined by any 53 module. A default is not required; but if a default is not given, 54 then users of the module will have to define the value of the 55 option, otherwise an error will be thrown.</para> 56 </listitem> 57 </varlistentry> 58 59 <varlistentry> 60 <term><varname>example</varname></term> 61 <listitem> 62 <para>An example value that will be shown in the NixOS manual.</para> 63 </listitem> 64 </varlistentry> 65 66 <varlistentry> 67 <term><varname>description</varname></term> 68 <listitem> 69 <para>A textual description of the option, in DocBook format, 70 that will be included in the NixOS manual.</para> 71 </listitem> 72 </varlistentry> 73 74</variablelist> 75 76</para> 77 78<section xml:id="sec-option-declarations-eot"><title>Extensible Option 79 Types</title> 80 81 <para>Extensible option types is a feature that allow to extend certain types 82 declaration through multiple module files. 83 This feature only work with a restricted set of types, namely 84 <literal>enum</literal> and <literal>submodules</literal> and any composed 85 forms of them.</para> 86 87 <para>Extensible option types can be used for <literal>enum</literal> options 88 that affects multiple modules, or as an alternative to related 89 <literal>enable</literal> options.</para> 90 91 <para>As an example, we will take the case of display managers. There is a 92 central display manager module for generic display manager options and a 93 module file per display manager backend (slim, sddm, gdm ...). 94 </para> 95 96 <para>There are two approach to this module structure: 97 98 <itemizedlist> 99 <listitem><para>Managing the display managers independently by adding an 100 enable option to every display manager module backend. (NixOS)</para> 101 </listitem> 102 <listitem><para>Managing the display managers in the central module by 103 adding an option to select which display manager backend to use.</para> 104 </listitem> 105 </itemizedlist> 106 </para> 107 108 <para>Both approaches have problems.</para> 109 110 <para>Making backends independent can quickly become hard to manage. For 111 display managers, there can be only one enabled at a time, but the type 112 system can not enforce this restriction as there is no relation between 113 each backend <literal>enable</literal> option. As a result, this restriction 114 has to be done explicitely by adding assertions in each display manager 115 backend module.</para> 116 117 <para>On the other hand, managing the display managers backends in the 118 central module will require to change the central module option every time 119 a new backend is added or removed.</para> 120 121 <para>By using extensible option types, it is possible to create a placeholder 122 option in the central module (<xref linkend='ex-option-declaration-eot-service' 123 />), and to extend it in each backend module (<xref 124 linkend='ex-option-declaration-eot-backend-slim' />, <xref 125 linkend='ex-option-declaration-eot-backend-sddm' />).</para> 126 127 <para>As a result, <literal>displayManager.enable</literal> option values can 128 be added without changing the main service module file and the type system 129 automatically enforce that there can only be a single display manager 130 enabled.</para> 131 132<example xml:id='ex-option-declaration-eot-service'><title>Extensible type 133 placeholder in the service module</title> 134<screen> 135services.xserver.displayManager.enable = mkOption { 136 description = "Display manager to use"; 137 type = with types; nullOr (enum [ ]); 138};</screen></example> 139 140<example xml:id='ex-option-declaration-eot-backend-slim'><title>Extending 141 <literal>services.xserver.displayManager.enable</literal> in the 142 <literal>slim</literal> module</title> 143<screen> 144services.xserver.displayManager.enable = mkOption { 145 type = with types; nullOr (enum [ "slim" ]); 146};</screen></example> 147 148<example xml:id='ex-option-declaration-eot-backend-sddm'><title>Extending 149 <literal>services.xserver.displayManager.enable</literal> in the 150 <literal>sddm</literal> module</title> 151<screen> 152services.xserver.displayManager.enable = mkOption { 153 type = with types; nullOr (enum [ "sddm" ]); 154};</screen></example> 155 156<para>The placeholder declaration is a standard <literal>mkOption</literal> 157 declaration, but it is important that extensible option declarations only use 158 the <literal>type</literal> argument.</para> 159 160<para>Extensible option types work with any of the composed variants of 161 <literal>enum</literal> such as 162 <literal>with types; nullOr (enum [ "foo" "bar" ])</literal> 163 or <literal>with types; listOf (enum [ "foo" "bar" ])</literal>.</para> 164 165</section> 166</section>