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