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.