Como dividir /etc/nixos/configuration.nix em módulos separados?

12

Suponha que eu tenha um arquivo muito simples :

{ config, pkgs, ... }:    
{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
    ];
  # SOME STUFF
  environment.systemPackages = with pkgs; [ emacs gitFull ];
  # SOME STUFF
}

Eu sei que o NixOS implementa um sistema de módulos , e um módulo é um .nix file. Todo arquivo .nix deve conter qualquer expressão Nix válida (por exemplo, uma função ou um conjunto) . Isso significa que o arquivo de configuração do NixOS /etc/nixos/configuration.nix é ele mesmo um módulo, contendo uma expressão Nix.

Eu também sei que para tornar a expressão Nix em outro módulo visível para o módulo com o qual estou trabalhando, posso usar um <-href="https://nixes.org/nix/manual/# ssec-builtins "> import function .

Eu quero dividir a declaração de pacotes do sistema (a lista contendo emacs e gitFull ) no arquivo packages.nix . Como faço para dividir o arquivo de configuração do NixOS em módulos separados?

    
por Mirzhan Irkegulov 28.03.2016 / 18:31

1 resposta

19

expressões Nix

Uma expressão Nix é como qualquer expressão de linguagem de programação: qualquer coisa que seja avaliada como um valor ou uma 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 seu conteúdo de arquivo.

O arquivo de configuração do NixOS contém uma expressão Nix do formulário:

{config, pkgs, ...}: { /* various configuration options */ }

Se você olhar de perto, 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;} .

Isso significa que quando você chama nixos-rebuild switch , algo chama a função dentro do arquivo de configuração NixOS com o conjunto que deve conter os 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 opção environment.systemPackages e colocar a opção ./packages.nix into imports . Seu /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
}

Seu /etc/nixos/packages.nix seria semelhante:

{ 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 o atributo imports dentro do conjunto retornado, portanto, ele avalia cada expressão Nix nos módulos que imports contém com os mesmos argumentos ( config , pkgs , etc).

Você deve ter pkgs como um argumento (ou, tecnicamente falando, um atributo de um conjunto, que em si é um argumento) de uma função em packages.nix , porque, da perspectiva da linguagem Nix, o processo pode ou pode não chamar a função com o conjunto que contém pkgs . Se não, a que 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 há pkgs em configuration.nix ? Você pode tê-lo, mas se você não se referir a ele em nenhum lugar do arquivo, você pode omiti-lo com segurança, já que as reticências o incluiriam de qualquer maneira.

Atualizando um atributo chamando uma função externa

Outra maneira é apenas fazer uma função que retorna um conjunto com algum atributo, e o valor desse atributo que você colocaria dentro de environment.systemPackages . Este é 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
}

Seu packages.nix :

pkgs: with pkgs; [ emacs gitFull ]

import ./packages.nix pkgs significa: carregue e retorne a expressão Nix em ./packages.nix e, como é uma função, chame-a com um argumento pkgs . with pkgs; [ emacs gitFull ] é um com expressão , ele traz o escopo da expressão antes do ponto-e-vírgula para a expressão após o ponto-e-vírgula. Sem isso, seria [ pkgs.emacs pkgs.gitFull ] .

    
por 28.03.2016 / 18:31

Tags