aboutsummaryrefslogtreecommitdiff
path: root/nixpkgs/nixos/doc/manual/development/option-declarations.xml
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/nixos/doc/manual/development/option-declarations.xml')
-rw-r--r--nixpkgs/nixos/doc/manual/development/option-declarations.xml199
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>