103 lines
3.5 KiB
Markdown
103 lines
3.5 KiB
Markdown
# Notes for 7th of June, 2023
|
||
|
||
Those are my notes on extending nixpkgs with your own functions and
|
||
abstractions. There may be other ways of doing it, but this is the one I find
|
||
to be most ergonomic.
|
||
|
||
## What is `nixpkgs.lib`
|
||
|
||
In the context of the Nix package manager and NixOS, `nixpkgs.lib` refers to
|
||
a module within the Nixpkgs repository. The `nixpkgs.lib` module provides a
|
||
set of utility functions and definitions that are commonly used across the
|
||
Nixpkgs repository. It contains various helper functions and abstractions that
|
||
make it easier to write Nix expressions and define packages. We often use those
|
||
functions to simplify our configurations and the nix package build processes.
|
||
|
||
## Why would you need to extend `nixpkgs.lib`
|
||
|
||
While the library functions provided by nixpkgs is quite extensive and usually
|
||
suits my needs, I sometimes feel the need to define my own function or wrap an
|
||
existing function to complete a task. Normally we can handle the process of a
|
||
function inside a simple `let in` and be well off, but there may be times you
|
||
need to re-use the existing function across your configuration file.
|
||
|
||
In such times, you might want to either write your own lib and inherit it at
|
||
the source of your `flake.nix` to then inherit them across your configuration.
|
||
|
||
Today's notes document the process of doing exactly that.
|
||
|
||
## Extending `nixpkgs.lib`
|
||
|
||
I find the easiest way of extending nixpkgs.lib to be using an overlay.
|
||
|
||
```nix
|
||
# lib/default.nix
|
||
{
|
||
nixpkgs,
|
||
lib,
|
||
inputs,
|
||
...
|
||
}: nixpkgs.lib.extend (
|
||
final: prev: {
|
||
# your functions go here
|
||
}
|
||
)
|
||
```
|
||
|
||
The above structure takes the existing `lib` from `nixpkgs`, and appends your
|
||
own configurations to it. You may then import this library in your `flake.nix`
|
||
to pass it to other imports and definitions.
|
||
|
||
```nix
|
||
# flake.nix
|
||
flake = let
|
||
# extended nixpkgs lib, contains my custom functions
|
||
lib = import ./lib {inherit nixpkgs lib inputs;};
|
||
in {
|
||
# entry-point for nixos configurations
|
||
nixosConfigurations = import ./hosts {inherit nixpkgs self lib;};
|
||
};
|
||
```
|
||
|
||
In this example (see my `flake.nix` for the actual implementation) I import my
|
||
extended lib from `lib/default.nix`, where I defined the overlay. I then pass
|
||
the extended lib to my `nixosConfiguratiıns`, which is an entry-point for all
|
||
of my NixOS configurations. As such, I am able to re-use my own utility
|
||
functions across my system as I see fit.
|
||
|
||
The problem with this approach is that it may be confusing for other people
|
||
reviewing your configuration. With this approach, `lib.customFunction` looks
|
||
identical to any lib function, which may lead to people thinking the function
|
||
exists in nixpkgs itself while it is only provided by your configuration. The
|
||
solution for that is simple though, instead of extending `nixpkgs.lib`, you may
|
||
define your own lib that does not inherit from `nixpkgs.lib` and only contains
|
||
your functions. The process would be similar, and you would not need to define
|
||
an overlay.
|
||
|
||
```nix
|
||
# flake.nix
|
||
flake = let
|
||
# extended nixpkgs lib, contains my custom functions
|
||
lib' = import ./lib {inherit nixpkgs lib inputs;};
|
||
in {
|
||
# entry-point for nixos configurations
|
||
nixosConfigurations = import ./hosts {inherit nixpkgs self lib';};
|
||
};
|
||
```
|
||
|
||
where your `lib/default.nix` looks like
|
||
|
||
```nix
|
||
# lib/default.nix
|
||
{
|
||
nixpkgs,
|
||
lib,
|
||
inputs,
|
||
...
|
||
}: {
|
||
# your functions here
|
||
}
|
||
```
|
||
|
||
You can find a real life example of the alternative approach in
|
||
my [neovim-flake's lib](https://github.com/NotAShelf/neovim-flake/blob/main/lib/stdlib-extended.nix).
|