Добро пожаловать на шестнадцатую пилюлю Nix.
В предыдущей пятнадцатой пилюле мы выяснили, как Nix обрабатывает выражения в угловых скобках. Теперь мы знаем, где находится <nixpkgs>.

Теперь мы готовы к погружению в репозиторий nixpkgs сквозь всё многообразие инструментов и паттернов проектирования. Хочу обратить ваше внимание на то, что у nixpkgs есть собственное руководство. Как мы говорили выше, Nix не накладывает ограничений на то, каким должен быть репозиторий, так что nixpkgs — всего лишь один из возможных вариантов. Разные руководства подчёркивают тот факт, что связь между Nix и nixpkgs не такая сильная, как вы, возможно, думали.

Выражение default.nix

Вместо того, чтобы с головой погрузиться в изучение пакетов, давайте для начала разберёмся со структурой nixpkgs в целом.

Разрабатывая собственный репозиторий, мы создали для него файл default.nix, куда поместили выражения для нескольких пакетов.

Точно также и у nixpkgs есть собственный default.nix, который загружается, когда кто-то ссылается на <nixpkgs>. Он проверяет, что версия Nix не меньше, чем 1.7 (на момент написания оригинального поста — прим. переводчика), а затем импортирует pkgs/top-level/all-packages.nix. Начиная с этого момента, этот набор пакетов мы будем называть pkgs.

Настоящий файл, который объединяет все пакеты — это all-packages.nix. Обратите внимание, что пакеты хранятся в подкаталоге pkgs/, в то время, как сама NixOS — в подкаталоге nixos/.

Содержимое all-packages.nix весьма интересно. Это функция, которая принимает пару интересных параметров:

  • system: значение по-умолчанию — текущая система

  • config: значение по-умолчанию null

  • прочее...

Параметр system, если верить комментарию в выражении — это система, для которой собираются пакеты. Он, например, позволяет собирать пакеты i686 на машине amd64.

Параметр config — это просто набор атрибутов. Пакеты могут использовать эти атрибуты, чтобы менять конфигурацию дериваций.

Параметр system

Вы часто встретите этот параметр в различных выражениях .nix, например, в выражениях выпусков (releases). Причина в том, что pkgs принимает параметр system, так что, импортируя pkgs, вы можете передать в него нужное значение.

myrelease.nix:

{ system ? builtins.currentSystem }:

let pkgs = import <nixpkgs> { inherit system; };
...

Для чего это может понадобиться? Например, для того, чтобы без серьёзных ухищрений выбрать набор пакетов конкретной системы:

nix-build -A psmisc --argstr system i686-linux

Этот вызов соберёт деривацию psmisc для i686-linux вместо x86_67-linux. Концепция очень похожа на мультиархивы Debian.

Настройка кросс-компиляции есть и в nixpkgs, но мы не будем погружаться в изучение этого вопроса, поскольку я в нём пока не разбирался (речь про автора оригинального цикла — Люка Бруно; впрочем, переводчик тоже в вопросе не разбирался — прим. переводчика).

Параметр config

Я уверен, вы читали в wiki или других руководствах про ~/.config/nixpkgs/config.nix (ранее — ~/.nixpkgs/config.nix), и я уверен, вы задавались вопросом, почему этот путь «вшит» в Nix.
На самом деле, он вшит не в Nix, а в nixpkgs.

Выражение all-packages.nix принимает параметр config. Если там содержится null, функция ищет переменную окружения NIXPKGS_CONFIG. Если переменная не найдена, nixpkgs обращается к $HOME/.config/nixpkgs/config.nix.

При обнаружении config.nix, он будет импортирован как выражение Nix, которое и станет значением config (конечно, в том случае, если параметр не был явно передан при импорте <nixpkgs>).

Значение config доступно после импорта репозитория:

$ nix repl
nix-repl> pkgs = import <nixpkgs> {}
nix-repl> pkgs.config
{ }
nix-repl> pkgs = import <nixpkgs> { config = { foo = "bar"; }; }
nix-repl> pkgs.config
{ foo = "bar"; }

Что указывать в config — вопрос удобства и соглашений.

Например, config.allowUnfree — атрибут, запрещающий сборку пакетов, чья лицензия по умолчанию не является свободной. Настройка config.pulseaudio подсказывает, собирать ли пакеты с поддержкой PulseAudio, если это возможно и если деривация это умеет.

О функциях .nix

Файл .nix содержит выражение Nix, которое может быть функцией. Напомню, что nix-build обрабатывает только те выражения, результатом которых является деривация. Так что вполне естественно возвращать деривацию напрямую из файла .nix. Кроме того, вполне естественно передавать в файл .nix параметры, помогающие настроить эту деривацию.

Для таких случае Nix использует трюк:

  • Если выражение является деривацией, собрать её.

  • Если выражение является функцией, вызвать её и собрать деривацию, которую она вернула.

Например, с помощью nix-build можно собрать такой файл:

{ pkgs ? import <nixpkgs> {} }:

pkgs.psmisc

Nix может вызвать функцию, поскольку у параметра pkgs есть значение по умолчанию. Вы можете передать другое значение pkgs, используя опцию --arg.

Останется ли схема рабочей, если у вас будет функция, которая возвращает функцию, которая возвращает деривацию? Нет, Nix вызывает найденную функцию только один раз.

Заключение

Мы разобрались с тем, что из себя представляет репозиторий <nixpkgs>. Это функция, которая принимает несколько параметров и возвращает набор всех пакетов. Из-за ленивых вычислений, собраны будут только те деривации, к которым вы обратитесь.

Вы можете использовать этот репозиторий, чтобы собирать собственные пакеты, как мы сделали в предыдущей пилюле, создавая наш собственный репозиторий.

В последнее время я немного занят выпуском NixOS 14.11 и другими вещами, а также думаю о переходе с Blogger на другую блог-платформу, больше ориентированную на программистов.
Поэтому прошу прощения, что пишу редко и мало (снова речь идёт об авторе оригинального цикла Люка Бруно — прим. переводчика).

В следующей пилюле

...мы поговорим о переопределении пакетов в репозитории nixpkgs. Что, если бы вам захотелось изменить несколько параметров вашей библиотеки? Смогут ли пакеты, настроив параметры, подключить новую библиотеку вместо старой? Одна из возможностей, как мы узнали в этой главе — использование параметра config. Однако у этого подхода есть ограничения. А другой способ — это переопределение дериваций.

Комментарии (0)