Expressões Nix
Uma expressão Nix é como qualquer expressão da linguagem de programação: qualquer coisa que seja avaliada como um valor ou função. Um valor nesse caso também pode ser uma lista ou um conjunto. Como um módulo Nix (arquivo com extensão .nix
) pode conter qualquer expressão Nix, você esperaria que o arquivo de configuração NixOS ( /etc/nixos/configuration.nix
) contivesse uma única expressão Nix como conteúdo do arquivo.
O arquivo de configuração do NixOS contém uma expressão do Nix no formato:
{config, pkgs, ...}: { /* various configuration options */ }
Se você olhar atentamente, poderá ver que é uma função , porque as funções seguem o formulário pattern: form
. Você também pode ver que é uma função que aceita um conjunto e retorna um conjunto. Por exemplo, se você tiver uma função f = {x, y}: {a = x + y;}
, poderá chamá-la como f {x=1; y=2;}
e recuperar um conjunto {a=3;}
.
Então, isso significa que, quando você chama nixos-rebuild switch
, algo chama a função dentro do arquivo de configuração do NixOS com o conjunto que deve conter atributos config
e pkgs
.
importações
Seguindo o exemplo de ./hardware-configuration.nix
, a maneira simples de extrair a lista de pacotes em um módulo separado packages.nix
é apenas extrair a environment.systemPackages
opção e colocá-la ./packages.nix
na imports
opção. Você /etc/nixos/configuration.nix
ficaria assim:
{ config, ... }:
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
# Include the package list.
./packages.nix
];
# SOME STUFF
# SOME STUFF
}
Você /etc/nixos/packages.nix
ficaria assim:
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [ emacs gitFull ];
}
Como isso funciona? Quando você executa nixos-rebuild switch
, o processo que avalia expressões Nix e decide instalar pacotes e assim por diante chama configuration.nix
com um conjunto de atributos, alguns dos quais são config
e pkgs
.
Ele encontra atributo imports
dentro do conjunto devolvido, de modo que avalia cada expressão Nix nos módulos que imports
contém com os mesmos argumentos ( config
, pkgs
, etc.).
Você deve ter pkgs
como argumento (ou, tecnicamente falando, um atributo de um conjunto, que por si só é um argumento) de uma função packages.nix
, porque, da perspectiva da linguagem Nix, o processo pode ou não chamar a função com o conjunto que contém pkgs
. Caso contrário, a qual atributo você se referiria ao executar with pkgs
?
Você também deve ter reticências, porque a função pode ser chamada com outros atributos, não apenas pkgs
.
Por que não existe pkgs
em configuration.nix
? Você pode obtê-lo, mas se não o consultar em nenhum lugar do arquivo, poderá omiti-lo com segurança, pois as reticências os incluiriam de qualquer maneira.
Atualizando um atributo chamando uma função externa
Outra maneira é apenas criar uma função que retorne um conjunto com algum atributo e o valor desse atributo que você colocaria dentro environment.systemPackages
. Este é o seu 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
}
O seu packages.nix
:
pkgs: with pkgs; [ emacs gitFull ]
import ./packages.nix pkgs
significa: carregar e retornar a expressão Nix ./packages.nix
e, como é uma função, chame-a com um argumento pkgs
. with pkgs; [ emacs gitFull ]
é uma expressão com , ele traz o escopo da expressão antes do ponto e vírgula para a expressão após ponto e vírgula. Sem isso, seria [ pkgs.emacs pkgs.gitFull ]
.
imports
é apenas uma lista, assim você pode acrescentar elementos para que condicionalmente, por exemploimports = [ ./foo.nix ./bar.nix ] ++ (if baz then [ ./quux.nix ] else []);