Wyrażenia Nix
Wyrażenie Nix jest jak każdy ekspresji języka programowania: wszystko, co ma wartość wartości lub funkcji. Wartość w tym przypadku może być również listą lub zestawem. Ponieważ moduł Nix (plik z rozszerzeniem .nix
) może zawierać dowolne wyrażenie Nix, można oczekiwać, że plik konfiguracyjny NixOS ( /etc/nixos/configuration.nix
) będzie zawierał pojedyncze wyrażenie Nix jako jego zawartość.
Plik konfiguracyjny NixOS zawiera wyrażenie Nix w postaci:
{config, pkgs, ...}: { /* various configuration options */ }
Jeśli przyjrzysz się uważnie, zobaczysz, że jest to funkcja , ponieważ funkcje są zgodne z formą pattern: form
. Możesz także zobaczyć, że jest to funkcja, która akceptuje zestaw i zwraca zestaw. Na przykład, jeśli masz funkcję f = {x, y}: {a = x + y;}
, możesz ją wywołać jako f {x=1; y=2;}
i odzyskać zestaw {a=3;}
.
Oznacza to, że kiedy wywołujesz nixos-rebuild switch
, coś wywołuje funkcję w pliku konfiguracyjnym NixOS z zestawem, który musi zawierać atrybuty config
i pkgs
.
import
Zgodnie z przykładem ./hardware-configuration.nix
prostego sposobu na wyodrębnienie listy pakietów do oddzielnego modułu packages.nix
jest po prostu zgrywanie environment.systemPackages
opcji i umieszczenie jej ./packages.nix
w imports
opcji. Twój /etc/nixos/configuration.nix
wyglądałby jak:
{ config, ... }:
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
# Include the package list.
./packages.nix
];
# SOME STUFF
# SOME STUFF
}
Twój /etc/nixos/packages.nix
wyglądałby jak:
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [ emacs gitFull ];
}
Jak to działa? Po uruchomieniu nixos-rebuild switch
proces, który ocenia wyrażenia Nix i decyduje się zainstalować pakiety i tak dalej wywołania configuration.nix
z zestawem atrybutów, z których niektóre to config
i pkgs
.
Stwierdzi atrybut imports
wewnątrz zwróconego zestawu, tak ocenia każde wyrażenie Nix w modułach, które imports
zawiera z tymi samymi argumentami ( config
, pkgs
itp).
Musisz mieć pkgs
jako argument (lub, technicznie rzecz biorąc, atrybut zestawu, który sam jest argumentem) funkcji w packages.nix
, ponieważ z perspektywy języka Nix proces może lub nie może wywoływać funkcję z zestawem, który zawiera pkgs
. Jeśli tak się nie stanie, do jakiego atrybutu odnosiłbyś się podczas uruchamiania with pkgs
?
Musisz również mieć wielokropek, ponieważ funkcja może być wywoływana z innymi atrybutami, nie tylko pkgs
.
Dlaczego nie ma pkgs
w configuration.nix
? Możesz go mieć, ale jeśli nie odwołujesz się do niego nigdzie w pliku, możesz go bezpiecznie pominąć, ponieważ elipsa i tak je uwzględni.
Aktualizowanie atrybutu przez wywołanie funkcji zewnętrznej
Innym sposobem jest po prostu utworzenie funkcji, która zwraca zestaw z jakimś atrybutem i wartością tego atrybutu, który byś w nim wstawił environment.systemPackages
. To jest twój 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
}
Twój packages.nix
:
pkgs: with pkgs; [ emacs gitFull ]
import ./packages.nix pkgs
oznacza: załaduj i zwróć wyrażenie Nix, ./packages.nix
a ponieważ jest to funkcja, wywołaj ją z argumentem pkgs
. with pkgs; [ emacs gitFull ]
jest wyrażeniem z , przenosi zakres wyrażenia przed średnikiem do wyrażenia po średniku. Bez tego byłoby [ pkgs.emacs pkgs.gitFull ]
.
imports
jest tylko listą, więc możesz warunkowo dołączyć do niej elementy, np.imports = [ ./foo.nix ./bar.nix ] ++ (if baz then [ ./quux.nix ] else []);