1# Option Definitions {#sec-option-definitions} 2 3Option definitions are generally straight-forward bindings of values to 4option names, like 5 6```nix 7{ 8 config = { 9 services.httpd.enable = true; 10 }; 11} 12``` 13 14However, sometimes you need to wrap an option definition or set of 15option definitions in a *property* to achieve certain effects: 16 17## Delaying Conditionals {#sec-option-definitions-delaying-conditionals} 18 19If a set of option definitions is conditional on the value of another 20option, you may need to use `mkIf`. Consider, for instance: 21 22```nix 23{ 24 config = 25 if config.services.httpd.enable then 26 { 27 environment.systemPackages = [ 28 # ... 29 ]; 30 # ... 31 } 32 else 33 { }; 34} 35``` 36 37This definition will cause Nix to fail with an "infinite recursion" 38error. Why? Because the value of `config.services.httpd.enable` depends 39on the value being constructed here. After all, you could also write the 40clearly circular and contradictory: 41 42```nix 43{ 44 config = 45 if config.services.httpd.enable then 46 { 47 services.httpd.enable = false; 48 } 49 else 50 { 51 services.httpd.enable = true; 52 }; 53} 54``` 55 56The solution is to write: 57 58```nix 59{ 60 config = mkIf config.services.httpd.enable { 61 environment.systemPackages = [ 62 # ... 63 ]; 64 # ... 65 }; 66} 67``` 68 69The special function `mkIf` causes the evaluation of the conditional to 70be "pushed down" into the individual definitions, as if you had written: 71 72```nix 73{ 74 config = { 75 environment.systemPackages = 76 if config.services.httpd.enable then 77 [ 78 # ... 79 ] 80 else 81 [ ]; 82 # ... 83 }; 84} 85``` 86 87## Setting Priorities {#sec-option-definitions-setting-priorities} 88 89A module can override the definitions of an option in other modules by 90setting an *override priority*. All option definitions that do not have the lowest 91priority value are discarded. By default, option definitions have 92priority 100 and option defaults have priority 1500. 93You can specify an explicit priority by using `mkOverride`, e.g. 94 95```nix 96{ services.openssh.enable = mkOverride 10 false; } 97``` 98 99This definition causes all other definitions with priorities above 10 to 100be discarded. The function `mkForce` is equal to `mkOverride 50`, and 101`mkDefault` is equal to `mkOverride 1000`. 102 103## Ordering Definitions {#sec-option-definitions-ordering} 104 105It is also possible to influence the order in which the definitions for an option are 106merged by setting an *order priority* with `mkOrder`. The default order priority is 1000. 107The functions `mkBefore` and `mkAfter` are equal to `mkOrder 500` and `mkOrder 1500`, respectively. 108As an example, 109 110```nix 111{ hardware.firmware = mkBefore [ myFirmware ]; } 112``` 113 114This definition ensures that `myFirmware` comes before other unordered 115definitions in the final list value of `hardware.firmware`. 116 117Note that this is different from [override priorities](#sec-option-definitions-setting-priorities): 118setting an order does not affect whether the definition is included or not. 119 120## Merging Configurations {#sec-option-definitions-merging} 121 122In conjunction with `mkIf`, it is sometimes useful for a module to 123return multiple sets of option definitions, to be merged together as if 124they were declared in separate modules. This can be done using 125`mkMerge`: 126 127```nix 128{ 129 config = mkMerge [ 130 # Unconditional stuff. 131 { 132 environment.systemPackages = [ 133 # ... 134 ]; 135 } 136 # Conditional stuff. 137 (mkIf config.services.bla.enable { 138 environment.systemPackages = [ 139 # ... 140 ]; 141 }) 142 ]; 143} 144``` 145 146## Free-floating definitions {#sec-option-definitions-definitions} 147 148:::{.note} 149The module system internally transforms module syntax into definitions. This always happens internally. 150::: 151 152It is possible to create first class definitions which are not transformed _again_ into definitions by the module system. 153 154Usually the file location of a definition is implicit and equal to the file it came from. 155However, when manipulating definitions, it may be useful for them to be completely self-contained (or "free-floating"). 156 157A free-floating definition is created with `mkDefinition { file = ...; value = ...; }`. 158 159Preserving the file location creates better error messages, for example when copying definitions from one option to another. 160 161Other properties like `mkOverride` `mkMerge` `mkAfter` can be used in the `value` attribute but not on the entire definition. 162 163This is what would work 164 165```nix 166mkDefinition { 167 value = mkForce 42; 168 file = "somefile.nix"; 169} 170``` 171 172While this would NOT work. 173 174```nix 175mkForce (mkDefinition { 176 value = 42; 177 file = "somefile.nix"; 178}) 179``` 180 181The following shows an example configuration that yields an error with the custom position information: 182 183```nix 184{ 185 _file = "file.nix"; 186 options.foo = mkOption { default = 13; }; 187 config.foo = lib.mkDefinition { 188 file = "custom place"; 189 # mkOptionDefault creates a conflict with the option foo's `default = 1` on purpose 190 # So we see the error message below contains the conflicting values and different positions 191 value = lib.mkOptionDefault 42; 192 }; 193} 194``` 195 196evaluating the module yields the following error: 197 198``` 199error: Cannot merge definitions of `foo'. Definition values: 200- In `file.nix': 13 201- In `custom place': 42 202``` 203 204To set the file location for all definitions in a module, you may add the `_file` module syntax attribute, which has a similar effect to using `mkDefinition` on all definitions in the module, without the hassle.