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