diff options
Diffstat (limited to 'nixos/doc/manual/from_md/development/option-declarations.section.xml')
-rw-r--r-- | nixos/doc/manual/from_md/development/option-declarations.section.xml | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/nixos/doc/manual/from_md/development/option-declarations.section.xml b/nixos/doc/manual/from_md/development/option-declarations.section.xml new file mode 100644 index 00000000000..0ac5e0eeca2 --- /dev/null +++ b/nixos/doc/manual/from_md/development/option-declarations.section.xml @@ -0,0 +1,327 @@ +<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" 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: + </para> + <programlisting language="bash"> +options = { + name = mkOption { + type = type specification; + default = default value; + example = example value; + description = "Description for use in the NixOS manual."; + }; +}; +</programlisting> + <para> + The attribute names within the <literal>name</literal> 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 + <literal>services.nix-serve.bindAddress</literal> references the + <literal>nix-serve</literal> Nixpkgs package. + </para> + <para> + The function <literal>mkOption</literal> accepts the following + arguments. + </para> + <variablelist> + <varlistentry> + <term> + <literal>type</literal> + </term> + <listitem> + <para> + The type of the option (see + <xref linkend="sec-option-types" />). This argument is + mandatory for nixpkgs modules. Setting this is highly + recommended for the sake of documentation and type checking. + In case it is not set, a fallback type with unspecified + behavior is used. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>default</literal> + </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> + <literal>defaultText</literal> + </term> + <listitem> + <para> + A textual representation of the default value to be rendered + verbatim in the manual. Useful if the default value is a + complex expression or depends on other values or packages. Use + <literal>lib.literalExpression</literal> for a Nix expression, + <literal>lib.literalDocBook</literal> for a plain English + description in DocBook format. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>example</literal> + </term> + <listitem> + <para> + An example value that will be shown in the NixOS manual. You + can use <literal>lib.literalExpression</literal> and + <literal>lib.literalDocBook</literal> in the same way as in + <literal>defaultText</literal>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <literal>description</literal> + </term> + <listitem> + <para> + A textual description of the option, in DocBook format, that + will be included in the NixOS manual. + </para> + </listitem> + </varlistentry> + </variablelist> + <section xml:id="sec-option-declarations-util"> + <title>Utility functions for common option patterns</title> + <section xml:id="sec-option-declarations-util-mkEnableOption"> + <title><literal>mkEnableOption</literal></title> + <para> + Creates an Option attribute set for a boolean value option i.e + an option to be toggled on or off. + </para> + <para> + This function takes a single string argument, the name of the + thing to be toggled. + </para> + <para> + The option’s description is <quote>Whether to enable + <name>.</quote>. + </para> + <para> + For example: + </para> + <anchor xml:id="ex-options-declarations-util-mkEnableOption-magic" /> + <programlisting language="bash"> +lib.mkEnableOption "magic" +# is like +lib.mkOption { + type = lib.types.bool; + default = false; + example = true; + description = "Whether to enable magic."; +} +</programlisting> + <section xml:id="sec-option-declarations-util-mkPackageOption"> + <title><literal>mkPackageOption</literal></title> + <para> + Usage: + </para> + <programlisting language="bash"> +mkPackageOption pkgs "name" { default = [ "path" "in" "pkgs" ]; example = "literal example"; } +</programlisting> + <para> + Creates an Option attribute set for an option that specifies + the package a module should use for some purpose. + </para> + <para> + <emphasis role="strong">Note</emphasis>: You shouldn’t + necessarily make package options for all of your modules. You + can always overwrite a specific package throughout nixpkgs by + using + <link xlink:href="https://nixos.org/manual/nixpkgs/stable/#chap-overlays">nixpkgs + overlays</link>. + </para> + <para> + The default package is specified as a list of strings + representing its attribute path in nixpkgs. Because of this, + you need to pass nixpkgs itself as the first argument. + </para> + <para> + The second argument is the name of the option, used in the + description <quote>The <name> package to use.</quote>. + You can also pass an example value, either a literal string or + a package’s attribute path. + </para> + <para> + You can omit the default path if the name of the option is + also attribute path in nixpkgs. + </para> + <anchor xml:id="ex-options-declarations-util-mkPackageOption" /> + <para> + Examples: + </para> + <anchor xml:id="ex-options-declarations-util-mkPackageOption-hello" /> + <programlisting language="bash"> +lib.mkPackageOption pkgs "hello" { } +# is like +lib.mkOption { + type = lib.types.package; + default = pkgs.hello; + defaultText = lib.literalExpression "pkgs.hello"; + description = "The hello package to use."; +} +</programlisting> + <anchor xml:id="ex-options-declarations-util-mkPackageOption-ghc" /> + <programlisting language="bash"> +lib.mkPackageOption pkgs "GHC" { + default = [ "ghc" ]; + example = "pkgs.haskell.package.ghc921.ghc.withPackages (hkgs: [ hkgs.primes ])"; +} +# is like +lib.mkOption { + type = lib.types.package; + default = pkgs.ghc; + defaultText = lib.literalExpression "pkgs.ghc"; + example = lib.literalExpression "pkgs.haskell.package.ghc921.ghc.withPackages (hkgs: [ hkgs.primes ])"; + description = "The GHC package to use."; +} +</programlisting> + <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 (sddm, gdm ...). + </para> + <para> + There are two approaches we could take with this module + structure: + </para> + <itemizedlist> + <listitem> + <para> + Configuring the display managers independently by adding + an enable option to every display manager module + backend. (NixOS) + </para> + </listitem> + <listitem> + <para> + Configuring the display managers in the central module + by adding an option to select which display manager + backend to use. + </para> + </listitem> + </itemizedlist> + <para> + Both approaches have problems. + </para> + <para> + Making backends independent can quickly become hard to + manage. For display managers, there can only be one enabled + at a time, but the type system cannot enforce this + restriction as there is no relation between each backend’s + <literal>enable</literal> option. As a result, this + restriction has to be done explicitly by adding assertions + in each display manager backend module. + </para> + <para> + On the other hand, managing the display manager backends in + the central module will require changing 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 + (<link linkend="ex-option-declaration-eot-service">Example: + Extensible type placeholder in the service module</link>), + and to extend it in each backend module + (<link linkend="ex-option-declaration-eot-backend-gdm">Example: + Extending + <literal>services.xserver.displayManager.enable</literal> in + the <literal>gdm</literal> module</link>, + <link linkend="ex-option-declaration-eot-backend-sddm">Example: + Extending + <literal>services.xserver.displayManager.enable</literal> in + the <literal>sddm</literal> module</link>). + </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 enforces that there + can only be a single display manager enabled. + </para> + <anchor xml:id="ex-option-declaration-eot-service" /> + <para> + <emphasis role="strong">Example: Extensible type placeholder + in the service module</emphasis> + </para> + <programlisting language="bash"> +services.xserver.displayManager.enable = mkOption { + description = "Display manager to use"; + type = with types; nullOr (enum [ ]); +}; +</programlisting> + <anchor xml:id="ex-option-declaration-eot-backend-gdm" /> + <para> + <emphasis role="strong">Example: Extending + <literal>services.xserver.displayManager.enable</literal> in + the <literal>gdm</literal> module</emphasis> + </para> + <programlisting language="bash"> +services.xserver.displayManager.enable = mkOption { + type = with types; nullOr (enum [ "gdm" ]); +}; +</programlisting> + <anchor xml:id="ex-option-declaration-eot-backend-sddm" /> + <para> + <emphasis role="strong">Example: Extending + <literal>services.xserver.displayManager.enable</literal> in + the <literal>sddm</literal> module</emphasis> + </para> + <programlisting language="bash"> +services.xserver.displayManager.enable = mkOption { + type = with types; nullOr (enum [ "sddm" ]); +}; +</programlisting> + <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> + </section> + </section> +</section> |