Option priorities¶
Module options have a priority, represented as an integer, which determines the precedence for setting the option to a particular value. When merging values, the priority with the lowest numeric value will be used.
When evaluating modules, the default
attribute in mkOption
uses mkOptionDefault
internally to assign a priority of 1500.
There are functions that can be used to set an option definitions priority.
mkDefault
, generally used with option definitions (i.e. config
), has a priority of 1000.
mkForce
, generally used when you really really want a value to be used, has a priority of 10.
Additionally, option definitions without a priority use defaultOverridePriority
, which has a priority of 100.
You can use mkOverride
to create your own option priority.
It takes two arguments: an integer as the priority followed by the option value you want to set.
Like so:
config.some-option = mkOverride 42 false;
Let us take a look at using these priorities and see how they work.
In our options.nix
file, we have a declaration and definition for the option name
.
We are using mkDefault
, which recall has a priority of 1000, to set the value.
{lib, ...}: {
options = {
name = lib.mkOption {
type = lib.types.str;
};
};
config = {
name = lib.mkDefault "Boaty McBoatface";
};
}
Setup an eval.nix
to evaluate our modules and return the config
attribute.
{pkgs}:
(
pkgs.lib.evalModules {
modules = [
./options.nix
];
}
)
.config
Create a run.sh
run script to evaluate the eval.nix
file.
nix eval -f eval.nix \
--apply 'x: x {pkgs = import <nixpkgs> {};}' \
--json | nix run nixpkgs#jq -- -r
And if we run the script (./run.sh
), we have our configuration.
{
"name": "Boaty McBoatface"
}
This is not terribly surprising as we only had a single definition for our option.
There was only a single value that name
could possibly be.
So what happens if we introduce another definition for name
.
In override.nix
we do exactly that.
Here we are setting the value for name
directly in config
, which recall will have a priority of 100.
We expect that this should take precedence over our original definition.
{lib, ...}: {
config = {
name = "A Boat Overridden";
};
}
We have a new eval-override.nix
to evaluate our modules including the new override.nix
.
{pkgs}:
(
pkgs.lib.evalModules {
modules = [
./options.nix
./override.nix
];
}
)
.config
A run-override.sh
run script to evaluate the eval-override.nix
file.
nix eval -f eval-override.nix \
--apply 'x: x {pkgs = import <nixpkgs> {};}' \
--json | nix run nixpkgs#jq -- -r
And if we run the script (./run-override.sh
), we have our configuration.
{
"name": "A Boat Overridden"
}
Great!
Exactly as we expected.
The lower priority value set in override.nix
took precedence.
Let us do it again.
In force.nix
, we introduce another definition for name
, but we use mkForce
.
Recall that mkForce
has a priority value of 10.
If we merge this with our other two definitions, we expect that it should take precedence.
{lib, ...}: {
config = {
name = lib.mkForce "A Forced Boat";
};
}
We have a new eval-force.nix
to evaluate our modules including the new force.nix
.
{pkgs}:
(
pkgs.lib.evalModules {
modules = [
./options.nix
./override.nix
./force.nix
];
}
)
.config
A run-force.sh
run script to evaluate the eval-force.nix
file.
nix eval -f eval-force.nix \
--apply 'x: x {pkgs = import <nixpkgs> {};}' \
--json | nix run nixpkgs#jq -- -r
And if we run the script (./run-force.sh
), we have our configuration.
{
"name": "A Forced Boat"
}
Great! Again exactly as expected.