nichts/nyx/docs/notes/2023-06-07-extended-nixpkgs.md

104 lines
3.5 KiB
Markdown
Raw Normal View History

2024-04-09 23:11:33 +02:00
# 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).