Expresiones Nix
Una expresión de Nix es como cualquier expresión de lenguaje de programación: cualquier cosa que se evalúe como un valor o una función. Un valor en este caso también puede ser una lista o un conjunto. Como un módulo Nix (archivo con extensión .nix
) puede contener cualquier expresión Nix, esperaría que el archivo de configuración NixOS ( /etc/nixos/configuration.nix
) contenga una sola expresión Nix como contenido de su archivo.
El archivo de configuración de NixOS contiene una expresión Nix de la forma:
{config, pkgs, ...}: { /* various configuration options */ }
Si observa de cerca, puede ver que es una función , porque las funciones siguen la forma pattern: form
. También puede ver que es una función que acepta un conjunto y devuelve un conjunto. Por ejemplo, si tiene una función f = {x, y}: {a = x + y;}
, puede llamarla como f {x=1; y=2;}
y recuperar un conjunto {a=3;}
.
Eso significa que cuando llamas nixos-rebuild switch
, algo llama a la función dentro del archivo de configuración de NixOS con el conjunto que debe contener atributos config
y pkgs
.
importaciones
Siguiendo el ejemplo de ./hardware-configuration.nix
, la forma simple de extraer la lista de paquetes en un módulo separado packages.nix
es simplemente extraer la environment.systemPackages
opción y ponerla ./packages.nix
en imports
opción. Tu /etc/nixos/configuration.nix
se vería así:
{ config, ... }:
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
# Include the package list.
./packages.nix
];
# SOME STUFF
# SOME STUFF
}
Tu /etc/nixos/packages.nix
se vería así:
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [ emacs gitFull ];
}
¿Cómo funciona? Cuando ejecuta nixos-rebuild switch
, el proceso que evalúa las expresiones Nix y decide instalar paquetes, etc., llama configuration.nix
con un conjunto de atributos, algunos de los cuales son config
y pkgs
.
Se encuentra atributo imports
dentro del conjunto devuelto, por lo que evalúa cada expresión Nix en los módulos que imports
contiene, con los mismos argumentos ( config
, pkgs
, etc).
Debe tener pkgs
como argumento (o, técnicamente hablando, un atributo de un conjunto, que en sí mismo es un argumento) de una función packages.nix
, porque, desde la perspectiva del lenguaje Nix, el proceso podría o no llamar a la función con el conjunto que contiene pkgs
. Si no es así, ¿a qué atributo se referiría al ejecutar with pkgs
?
También debe tener puntos suspensivos, porque la función se puede llamar con otros atributos, no solo pkgs
.
¿Por qué no es pkgs
en configuration.nix
? Puede tenerlo, pero si no se refiere a él en ninguna parte del archivo, puede omitirlo con seguridad, ya que los puntos suspensivos los incluirían de todos modos.
Actualizar un atributo llamando a una función externa
Otra forma es simplemente hacer una función que devuelva un conjunto con algún atributo, y el valor de ese atributo que pondría dentro environment.systemPackages
. Este es tu configuration.nix
:
{ config, pkgs, ... }:
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
];
# SOME STUFF
environment.systemPackages = import ./packages.nix pkgs;
# SOME STUFF
}
Su packages.nix
:
pkgs: with pkgs; [ emacs gitFull ]
import ./packages.nix pkgs
significa: cargar y devolver la expresión Nix en ./packages.nix
y como es una función, llamarla con un argumento pkgs
. with pkgs; [ emacs gitFull ]
es una expresión con , trae el alcance de la expresión antes del punto y coma a la expresión después del punto y coma. Sin eso, lo sería [ pkgs.emacs pkgs.gitFull ]
.
imports
es solo una lista, por lo que puede agregar elementos a eso condicionalmente, por ejemploimports = [ ./foo.nix ./bar.nix ] ++ (if baz then [ ./quux.nix ] else []);