diff options
Diffstat (limited to 'nixpkgs/nixos/doc/manual/development/option-declarations.xml')
-rw-r--r-- | nixpkgs/nixos/doc/manual/development/option-declarations.xml | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/nixpkgs/nixos/doc/manual/development/option-declarations.xml b/nixpkgs/nixos/doc/manual/development/option-declarations.xml new file mode 100644 index 00000000000..eee81bf6426 --- /dev/null +++ b/nixpkgs/nixos/doc/manual/development/option-declarations.xml @@ -0,0 +1,199 @@ +<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> |