Выражение Nix похоже на любое выражение языка программирования: все, что оценивается в значение или функцию. Значение в данном случае может быть списком или множеством. Поскольку модуль Nix (файл с расширением .nix
) может содержать любое выражение Nix, можно ожидать, что файл конфигурации NixOS (/etc/nixos/configuration.nix
) будет содержать одно выражение Nix в качестве содержимого файла.
Конфигурационный файл NixOS содержит выражение Nix вида:
{config, pkgs, ...}: { /* various configuration options */ }
Если присмотреться, можно увидеть, что это функция, поскольку функции имеют вид pattern: form
. Вы также можете увидеть, что это функция, которая принимает множество и возвращает множество. Например, если у вас есть функция f = {x, y}: {a = x + y;}
, то вы можете вызвать ее как f {x=1; y=2;}
и получить обратно множество {a=3;}
.
Это означает, что когда вы вызываете nixos-rebuild switch
, что-то вызывает функцию внутри конфигурационного файла NixOS с набором, который должен содержать атрибуты config
и pkgs
.
Следуя примеру ./hardware-configuration.nix
, простой способ извлечь список пакетов в отдельный модуль packages.nix
- это просто вырвать опцию environment.systemPackages
и поместить ./packages.nix
в опцию imports
. Ваш /etc/nixos/configuration.nix
будет выглядеть так:
{ config, ... }:
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
# Include the package list.
./packages.nix
];
# SOME STUFF
# SOME STUFF
}
Ваш /etc/nixos/packages.nix
будет выглядеть так:
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [ emacs gitFull ];
}
Как это работает? Когда вы запускаете nixos-rebuild switch
, процесс, который оценивает выражения Nix и решает установить пакеты и так далее, вызывает configuration.nix
с набором атрибутов, некоторые из которых config
и pkgs
.
Он находит атрибут imports
внутри возвращаемого набора, поэтому он оценивает каждое выражение Nix в модулях, которые imports
содержит с теми же аргументами (config
, pkgs
и т.д.).
Вы должны иметь pkgs
в качестве аргумента (или, технически говоря, атрибута множества, которое само является аргументом) функции в packages.nix
, потому что, с точки зрения языка Nix, процесс может вызвать или не вызвать функцию с множеством, содержащим pkgs
. Если нет, то к какому атрибуту вы будете обращаться при выполнении с pkgs
?
Вы также должны поставить многоточие, потому что функция может быть вызвана с другими атрибутами, а не только с pkgs
.
Почему нет pkgs
в configuration.nix
? Вы можете иметь его, но если вы не ссылаетесь на него нигде в файле, вы можете смело опустить его, так как многоточие будет включать их в любом случае.
Другой способ - просто сделать функцию, которая возвращает набор с некоторым атрибутом, а значение этого атрибута вы поместите внутрь environment.systemPackages
. Это ваш 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
}
Ваш packages.nix
:
pkgs: with pkgs; [ emacs gitFull ]
import ./packages.nix pkgs
означает: загрузить и вернуть выражение Nix в ./packages.nix
и, поскольку это функция, вызвать ее с аргументом pkgs
. with pkgs; [ emacs gitFull ]
- это with-expression, он переносит область видимости выражения до точки с запятой на выражение после точки с запятой. Без него это было бы [ pkgs.emacs pkgs.gitFull ]
.
find
действие -exec
можно использовать для этого:
find. \! -exec yourscript {} \; -print
напечатает имена всех файлов, для которых не удалось yourscript
.
-exec
можно использовать для превращения соответствующих внешних команд в тесты find
.
Вы можете ограничить тестируемые файлы, добавив find
тесты перед -exec
; например, чтобы ограничить кандидатов обычными файлами, добавьте-type f
:
find. -type f \! -exec yourscript {} \; -print