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