at 16.09-beta 3.3 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-definitions"> 6 7<title>Option Definitions</title> 8 9<para>Option definitions are generally straight-forward bindings of values to option names, like 10 11<programlisting> 12config = { 13 services.httpd.enable = true; 14}; 15</programlisting> 16 17However, sometimes you need to wrap an option definition or set of 18option definitions in a <emphasis>property</emphasis> to achieve 19certain effects:</para> 20 21<simplesect><title>Delaying Conditionals</title> 22 23<para>If a set of option definitions is conditional on the value of 24another option, you may need to use <varname>mkIf</varname>. 25Consider, for instance: 26 27<programlisting> 28config = if config.services.httpd.enable then { 29 environment.systemPackages = [ <replaceable>...</replaceable> ]; 30 <replaceable>...</replaceable> 31} else {}; 32</programlisting> 33 34This definition will cause Nix to fail with an “infinite recursion” 35error. Why? Because the value of 36<option>config.services.httpd.enable</option> depends on the value 37being constructed here. After all, you could also write the clearly 38circular and contradictory: 39<programlisting> 40config = if config.services.httpd.enable then { 41 services.httpd.enable = false; 42} else { 43 services.httpd.enable = true; 44}; 45</programlisting> 46 47The solution is to write: 48 49<programlisting> 50config = mkIf config.services.httpd.enable { 51 environment.systemPackages = [ <replaceable>...</replaceable> ]; 52 <replaceable>...</replaceable> 53}; 54</programlisting> 55 56The special function <varname>mkIf</varname> causes the evaluation of 57the conditional to be “pushed down” into the individual definitions, 58as if you had written: 59 60<programlisting> 61config = { 62 environment.systemPackages = if config.services.httpd.enable then [ <replaceable>...</replaceable> ] else []; 63 <replaceable>...</replaceable> 64}; 65</programlisting> 66 67</para> 68 69</simplesect> 70 71<simplesect><title>Setting Priorities</title> 72 73<para>A module can override the definitions of an option in other 74modules by setting a <emphasis>priority</emphasis>. All option 75definitions that do not have the lowest priority value are discarded. 76By default, option definitions have priority 1000. You can specify an 77explicit priority by using <varname>mkOverride</varname>, e.g. 78 79<programlisting> 80services.openssh.enable = mkOverride 10 false; 81</programlisting> 82 83This definition causes all other definitions with priorities above 10 84to be discarded. The function <varname>mkForce</varname> is 85equal to <varname>mkOverride 50</varname>.</para> 86 87</simplesect> 88 89<simplesect><title>Merging Configurations</title> 90 91<para>In conjunction with <literal>mkIf</literal>, it is sometimes 92useful for a module to return multiple sets of option definitions, to 93be merged together as if they were declared in separate modules. This 94can be done using <varname>mkMerge</varname>: 95 96<programlisting> 97config = mkMerge 98 [ # Unconditional stuff. 99 { environment.systemPackages = [ <replaceable>...</replaceable> ]; 100 } 101 # Conditional stuff. 102 (mkIf config.services.bla.enable { 103 environment.systemPackages = [ <replaceable>...</replaceable> ]; 104 }) 105 ]; 106</programlisting> 107 108</para> 109 110</simplesect> 111 112</section>