Руководство по GNU Guix

Next: , Up: (dir)   [Contents][Index]

GNU Guix

В этом документе описывается GNU Guix версии 2a6d964 — менеджер пакетов, написанный для системы GNU.

This manual is also available in Simplified Chinese (see GNU Guix参考手册), French (see Manuel de référence de GNU Guix), German (see Referenzhandbuch zu GNU Guix), Spanish (see Manual de referencia de GNU Guix), Brazilian Portuguese (see Manual de referência do GNU Guix), and Russian (see Руководство GNU Guix). If you would like to translate it in your native language, consider joining Weblate (see Перевод Guix на другие языки).

Table of Contents


Next: , Previous: , Up: GNU Guix   [Contents][Index]

1 Введение

GNU Guix1 — это утилита для управления пакетами и дистрибутив системы GNU. Guix позволяет непривилегированным пользователям устанавливать, обновлять и удалять программные пакеты, откатываться до предыдущих наборов пакетов, собирать пакеты из исходников и обеспечивает создание и поддержку программного окружения в целом.

Вы можете установить GNU Guix поверх существующей системы GNU/Linux, где он дополнит имеющиеся инструменты, не внося помехи (see Установка), или вы можете использовать его как отдельный дистрибутив операционной системы, Guix System2 See Дистрибутив GNU.


1.1 Управление программным обеспечением Guix Way

Guix предоставляет интерфейс командной строки для управления пакетами (see Управление пакетами), инструменты, которые помогают в разработке программного обеспечения (see Разработка), более сложные утилиты командной строки (see Утилиты), а также программный интерфейс Scheme (see Программный интерфейс). Его демон сборки отвечает за сборку пакетов по запросам пользователей (see Настройка демона) и за скачивание компилированных бинарников из авторизованных ресурсов (see Подстановки).

Guix включает определения пакетов для множества проектов GNU и не-GNU, каждый из которых уважает свободу пользователя в работе за компьютером. Он расширяемый: пользователи могут писать свои собственные определения пакетов (see Описание пакетов) и делать их доступными как независимые пакетные модули (see Пакетные модули). Он также настраиваемый: пользователи могут получать специальные определения пакетов из существующих, в том числе через командную строку (see Параметры преобразования пакета).

Под капотом Guix работает как функциональный пакетный менеджер — принцип, впервые введённый Nix (see Благодарности). В Guix процесс сборки и установки пакета рассматривается как функция в математическом смысле. Эта функция принимает входные данные, как например, скрипты сборки, компилятор, её результат зависит только от входных данных, и он не может зависеть от программ или скриптов, которые не подаются на вход явным образом. Функция сборки всегда производит один результат, когда получает один и тот же набор входных данных. Она не может как-либо изменять окружение запущенной системы; например, она не может создавать, изменять или удалять файлы за пределами её директорий сборки и установки. Это достигается так: процесс сборки запускается в изолированном окружении (или контейнере), в котором видны только входные данные, заданные явно.

Результат работы функций сборки пакетов кешируется в файловой системе в специальной директории, называемой склад (see Хранилище).Каждый пакет устанавливается в собственную директорию склада, по умолчанию — под /gnu/store. Имя директории содержит хеш всех входных данных, используемых для сборки этого пакета, так что изменение входных данных порождает различные имена директорий.

Этот подход является принципиальным, на нём основаны ключевые особенностей Guix: поддержка транзакционного обновления пакета и откаты, установка для отдельного пользователя, сборка мусора от пакетов (see Особенности).


1.2 Дистрибутив GNU

Guix поставляется с дистрибутивом системы GNU, полностью состоящим из свободного программного обеспечения 3. Дистрибутив можно установить отдельно (see Установка системы), но также можно установить Guix в качестве пакетного менеджера поверх установленной системы GNU/Linux (see Установка). Когда нам нужно провести различие между ними, мы называем самодостаточный дистрибутив Guix System.

Дистрибутив предоставляет основные пакеты GNU, такие как GNU libc, GCC и Binutils, а также многие приложения GNU и не-GNU. Полный список доступных пакетов можно просмотреть по онлайн или запустив guix package (see Вызов guix package):

guix package --list-available

Наша цель — предоставить состоящий на 100% из свободного программного обеспечения рабочий дистрибуив Linux или другие варианты GNU. Мы ориентируемся на продвижении и полноценной интеграции компонентов GNU и поддержке программ и утилит, которые помогают пользователям реализовать их свободы.

Пакеты в данные момент доступны для следующих платформ:

x86_64-linux

архитектура Intel/AMD x86_64 с ядром Linux-Libre.

i686-linux

архитектура Intel 32-bit (IA32) с ядром Linux-Libre.

armhf-linux

архитектура ARMv7-A с hard float, Thumb-2 и NEON, использующая двоичный интерфейс приложений EABI hard-float (ABI), с ядром Linux-Libre.

aarch64-linux

процессоры little-endian 64-bit ARMv8-A с ядром Linux-Libre.

i586-gnu

GNU/Hurd на 32 битной архитектуре Intel (IA32).

Эта конфигурация является экспериментальной и находится в разработке. Самый простой способ попробовать - настроить экземпляр hurd-vm-service-type на вашем GNU/Linux компьютере (see hurd-vm-service-type). See Содействие, о том, как помочь!

mips64el-linux (unsupported)

64-разрядные little-endian процессоры MIPS порядком байтов, в частности серии Loongson, n32 ABI и ядро Linux-Libre. Эта конфигурация больше не поддерживается полностью; в частности, фермы сборки проекта больше не предоставляют замены этой архитектуре.

powerpc-linux (unsupported)

32-битные big-endian процессоры PowerPC, в частности PowerPC G4 с поддержкой AltiVec, и ядро Linux-Libre. Эта конфигурация не поддерживается полностью, и работа по обеспечению работоспособности этой архитектуры не ведется.

aarch64-linux

little-endian 64-bit Power ISA processors, Linux-Libre kernel. This includes POWER9 systems such as the RYF Talos II mainboard. This platform is available as a "technology preview": although it is supported, substitutes are not yet available from the build farm (see Подстановки), and some packages may fail to build (see Отслеживание ошибок и изменений). That said, the Guix community is actively working on improving this support, and now is a great time to try it and get involved!

riscv64-linux

64-битные little-endian процессоры RISC-V, в частности RV64GC, и ядро Linux-Libre. Эта платформа доступна как "предварительный просмотр технологий": хотя она поддерживается, заменители пока недоступны из фермы сборки (see Подстановки), и некоторые пакеты могут не собраться (see Отслеживание ошибок и изменений). Тем не менее, сообщество Guix активно работает над улучшением этой поддержки, и сейчас самое время попробовать ее и принять участие!

Пользуясь Guix System, вы объявляете все аспекты конфигурации системы, а Guix заботится об инстанцировании конфигурации в транзакционном, воспроизводимом и безэталонном режимах (see Настройка системы). Система Guix использует ядро Linux-libre, систему инициализации Shepherd (see Introduction in The GNU Shepherd Manual), хорошо известные утилиты и тулчейны GNU, а также графическое окружение или системные службы по вашему выбору.

Система Guix доступна на всех перечисленных платформах, кроме mips64el-linux, powerpc-linux, powerpc64le-linux и riscv64-linux.

Информация о портировании на другие архитектуры и ядра доступна в see Портирование на новую платформу.

Дистрибутив созаётся совместными усилиями, приглашаем вас! См. See Содействие, чтобы узнать о том, как вы можете помочь.


2 Установка

You can install the package management tool Guix on top of an existing GNU/Linux or GNU/Hurd system4, referred to as a foreign distro. If, instead, you want to install the complete, standalone GNU system distribution, Guix System, see Установка системы. This section is concerned only with the installation of Guix on a foreign distro.

Важно: This section only applies to systems without Guix. Following it for existing Guix installations will overwrite important system files.

При установке на чужой дистрибутив GNU Guix дополняет доступные утилиты без внесения помех. Его данные живут только в двух директориях — обычно /gnu/store и /var/guix; другие файлы вашей системы, как /etc, остаются нетронутыми.

Установленный Guix можно обновлять командой guix pull (see Вызов guix pull).


2.1 Бинарная установка

This section describes how to install Guix from a self-contained tarball providing binaries for Guix and for all its dependencies. This is often quicker than installing from source, described later (see Сборка из Git).

Важно: This section only applies to systems without Guix. Following it for existing Guix installations will overwrite important system files.

Some GNU/Linux distributions, such as Debian, Ubuntu, and openSUSE provide Guix through their own package managers. The version of Guix may be older than 2a6d964 but you can update it afterwards by running ‘guix pull’.

We advise system administrators who install Guix, both from the installation script or via the native package manager of their foreign distribution, to also regularly read and follow security notices, as shown by guix pull.

For Debian or derivatives such as Ubuntu or Trisquel, call:

sudo apt install guix

Подобным же образом на openSUSE:

sudo zypper install guix

If you are running Parabola, after enabling the pcr (Parabola Community Repo) repository, you can install Guix with:

sudo pacman -S guix

The Guix project also provides a shell script, guix-install.sh, which automates the binary installation process without use of a foreign distro package manager5. Use of guix-install.sh requires Bash, GnuPG, GNU tar, wget, and Xz.

The script guides you through the following:

  • Downloading and extracting the binary tarball
  • Setting up the build daemon
  • Making the ‘guix’ command available to non-root users
  • Configuring substitute servers

As root, run:

# cd /tmp
# wget https://git.savannah.gnu.org/cgit/guix.git/plain/etc/guix-install.sh
# chmod +x guix-install.sh
# ./guix-install.sh

The script to install Guix is also packaged in Parabola (in the pcr repository). You can install and run it with:

sudo pacman -S guix-installer
sudo guix-install.sh

Примечание: By default, guix-install.sh will configure Guix to download pre-built package binaries, called substitutes (see Подстановки), from the project’s build farms. If you choose not to permit this, Guix will build everything from source, making each installation and upgrade very expensive. See Касательно проверенных бинарников for a discussion of why you may want to build packages from source.

To use substitutes from bordeaux.guix.gnu.org, ci.guix.gnu.org or a mirror, you must authorize them. For example,

# guix archive --authorize < \
     ~root/.config/guix/current/share/guix/bordeaux.guix.gnu.org.pub
# guix archive --authorize < \
     ~root/.config/guix/current/share/guix/ci.guix.gnu.org.pub

When you’re done installing Guix, see Установка приложения for extra configuration you might need, and Начало работы for your first steps!

Примечание: Архив для бинарной установки может быть воспроизведён (повторён) и проверен простым запуском следующей команды в дереве исходников Guix:

make guix-binary.system.tar.xz

..., что в свою очередь, выполнит:

guix pack -s system --localstatedir \
  --profile-name=current-guix guix

See Вызов guix pack для подробной информации об этом полезном инструменте.

Should you eventually want to uninstall Guix, run the same script with the --uninstall flag:

./guix-install.sh --uninstall

With --uninstall, the script irreversibly deletes all the Guix files, configuration, and services.


2.2 Настройка демона

During installation, the build daemon that must be running to use Guix has already been set up and you can run guix commands in your terminal program, see Начало работы:

guix build hello

If this runs through without error, feel free to skip this section. You should continue with the following section, Установка приложения.

However, now would be a good time to replace outdated daemon versions, tweak it, perform builds on other machines (see Использование функционала разгрузки), or start it manually in special environments like “chroots” (see Chrooting into an existing system) or WSL (not needed for WSL images created with Guix, see wsl2-image-type). If you want to know more or optimize your system, this section is worth reading.

Такие операции, как сборка пакета или запуск сборщика мусора, выполняются запуском специальных процесса — демона сборки — по запросам клиентов. Только демон имеет доступ к складу и его базе данных. Так что операции управления складом выполняются с помощью демона. Например, инструменты командной строки, как guix package и guix build, обычно взаимодействуют с демоном через удалённый вызов процедур (RPC) и сообщают, что необходимо сделать.

The following sections explain how to prepare the build daemon’s environment. See Подстановки for how to allow the daemon to download pre-built binaries.


2.2.1 Установка окружения сборки

В случае стандартной многопользовательской установки Guix и его демон (программа guix-daemon) установливаются системным администратором; /gnu/store принадлежит root, и guix-daemon запущен от root. Непривилегированные пользователи могут пользоваться инструментами Guix, чтобы собирать пакеты или получить доступ к складу с какой-либо целью, и демон выполнит это по их запросу, убедившись, что склад находится в должном состоянии, и разрешив сборку пакетов и разделение их между пользователями.

Когда guix-daemon запущен от root, возможно, из соображений безопасности вы не примете того, что процессы сборки пакетов тоже выполняются от root. Чтобы избежать этого, необходимо создать специальных пользователей для сборки. Ими будет пользоваться процесс сборки, запускаемый демоном. Эти пользователи сборки не должны иметь оболочки и домашней директории — они просто будут использоваться, когда демон сбрасывает привилегии root в процессе сборки. Наличие нескольких таких пользователей позволит демону запускать отдельные процессы сборки под отдельными UID, что гарантирует, что они не будут помехой друг другу — важная особенность, учитывая, что сборка рассматривается как чистая функция (see Введение).

В системе GNU/Linux набор пользователей для сборки может быть создан так (используя синтаксис команды Bash shadow):

# groupadd --system guixbuild
# for i in `seq -w 1 10`;
  do
    useradd -g guixbuild -G guixbuild           \
            -d /var/empty -s `which nologin`    \
            -c "Guix build user $i" --system    \
            guixbuilder$i;
  done

Число пользователей для сборки определяет, сколько задач сборки может быть запущено параллельно. Это задаётся опцией --max-jobs (see --max-jobs). Чтобы использовать guix system vm и подобные, вам потребуется добавить пользователей для сборки в группу kvm, так чтобы они имели доступ к /dev/kvm, используя -G guixbuild,kvm вместо -G guixbuild (see Invoking guix system).

The guix-daemon program may then be run as root with the following command6:

# guix-daemon --build-users-group=guixbuild

Так демон стартует процессы сборки в chroot под одним из пользователей группы guixbuilder. В GNU/Linux по умолчанию окружение chroot содержит только следующее:

  • минимальный состав директории /dev, созданной максимально независимо от исходной /dev7;
  • директория /proc; она показывает только процессы контейнера, так как используется отдельное пространство имён процессов PID;
  • /etc/passwd с записью о текущем пользователе и пользователе nobody;
  • /etc/group с записью о группе пользователя;
  • /etc/hosts с записью, которая адресует localhost на 127.0.0.1;
  • директория /tmp, доступная для записи.

The chroot does not contain a /home directory, and the HOME environment variable is set to the non-existent /homeless-shelter. This helps to highlight inappropriate uses of HOME in the build scripts of packages.

All this usually enough to ensure details of the environment do not influence build processes. In some exceptional cases where more control is needed—typically over the date, kernel, or CPU—you can resort to a virtual build machine (see virtual build machines).

Можно указать директорию, в которую демон сохраняет деревья сборки через переменную окружения TMPDIR. Однако дерево сборки внутри chroot всегда называется /tmp/guix-build-name.drv-0, где name - это имя деривации, то есть, например, coreutils-8.24. Так значение TMPDIR не проникает внутрь окружения сборки, что предотвращает расхождения и случаях, когда процессы сборки имеют иные имена их деревьев сборки.

Демон также уважаем переменную окружения http_proxy, когда выполняет скачивание по HTTP как для дериваций с фиксированным результатом (see Деривации), так и для подстановок (see Подстановки).

Если вы устанавливаете Guix как непривилегированный пользователь, всё ещё возможно запустить guix-daemon с указанием --disable-chroot. Однако процессы сборки не будут изолированы один от другого, а также от остальной системы. Так процессы сборки смогут внести помехи в работу друг друга, смогут получить доступ к программам, библиотекам и другим файлам, доступным в системе, что конечно, делает затруднительным рассмотрение сборки как чистой функции.


2.2.2 Использование функционала разгрузки

При желании демон сборки может offload производные сборки на других машинах, на которых запущен Guix, используя offload build hook8. Когда данная функция включена, список указанных пользователем машин для сборки считывается из /etc/guix/machines.scm; каждый раз, когда запрашивается сборка, например через guix build, демон пытается выгрузить ее на одну из машин, удовлетворяющих ограничениям производной сборки, в частности, ее системным типам—например, x86_64-linux. На одной машине можеь быть несколько типов систем, либо потому, что архитектура изначально поддерживает ее, либо через эмуляцию (see Transparent Emulation with QEMU). Отсутствующие необходимые условия для сборки копируются по SSH на целевой компьютер, который затем продолжает сборку; в случает успеха выходные данные копируются на исходную машину. Средство разгрузки поставляется с базовым планировщиком, который пытается выбрать лучшую машину. Лучшая машина выбирается среди доступных машин на основании такиз критериев как:

  1. Наличие слота для сборки. Машина для сборки может иметь столько слотов для сборки (соединений), сколько указано в значении parallel-builds определения объекта build-machine.
  2. Ее относительная скорость, указанная через значение speed определения объекта build-machine.
  3. Ее нагрузка. Нормализованная нагрузка на машину должна быть ниже порогового значения, которое можно настроить с помощью поля overload-threshold объекта build-machine.
  4. Доступность дискового пространства. Должно быть доступно более 100 МБ.

Файл /etc/guix/machines.scm обычно выглядит так:

(list (build-machine
           (name "eightysix.example.org")
           (systems (list "x86_64-linux" "i686-linux"))
           (host-key "ssh-ed25519 AAAAC3Nza…")
           (user "bob")
           (speed 2.))     ;incredibly fast!

      (build-machine
        (name "armeight.example.org")
        (systems (list "aarch64-linux"))
        (host-key "ssh-rsa AAAAB3Nza…")
        (user "alice")

        ;; Remember 'guix offload' is spawned by
        ;; 'guix-daemon' as root.
        (private-key "/root/.ssh/identity-for-guix")))

В примере выше мы обозначили список, состоящий из двух машин: одна — для архитектуры x86_64, а другая — для архитектуры mips64el.

По факту, этот файл, что не удивительно, является файлом Scheme, и он имеет значение, когда запускается хук разгрузки. Он возвращает объекты класса build-machine. Приведённый пример показывает фиксированный список машин для сборки, но можно представить, скажем, используя DNS-SD, он может возвращать список потенциальных машин, обнаруженных в локальной сети (see Guile-Avahi in Using Avahi in Guile Scheme Programs). Тип данных build-machine описан ниже.

Тип данных: build-machine

Этот тип данных представляет машины для сборки, на которые демон может разгружать сборки. Важные поля:

name

Имя хоста удалённой машины.

systems

Тип системы удалённой машины, то есть x86_64-linux.

user

The user account on the remote machine to use when connecting over SSH. Note that the SSH key pair must not be passphrase-protected, to allow non-interactive logins.

host-key

Это публичный ключ хоста в формает OpenSSH. Он используется при аутентификации машины, когда мы подсоединяемс к ней. Это длинная строка, которая выглядит примерно так:

ssh-ed25519 AAAAC3NzaC…mde+UhL hint@example.org

Если на машине запущен демон OpenSSH sshd, ключ хоста может быть найден в файле под директорией /etc/ssh, например, /etc/ssh/ssh_host_ed25519_key.pub.

Если на машине запущен демон SSH GNU lsh, lshd, тогда ключ хоста расположен в /etc/lsh/host-key.pub или подобном файле. Его можно конвертировать в формат OpenSSH, используя lsh-export-key (see Converting keys in LSH Manual):

$ lsh-export-key --openssh < /etc/lsh/host-key.pub
ssh-rsa AAAAB3NzaC1yc2EAAAAEOp8FoQAAAQEAs1eB46LV…

Список необязательных полей:

port (default: 22)

Номер порта сервера SSH на машине.

private-key (default: ~root/.ssh/id_rsa)

Файл приватного ключа в формате OpenSSH, используемого в соединении с машиной. Этот ключ не должен быть защищён парольной фразой.

Отметим, что значение по умолчанию — приватный ключ аккаунта root. Убедитесь, что он существует, если вы используете настройки по умолчанию.

compression (default: "zlib@openssh.com,zlib")
compression-level (default: 3)

Методы компрессии уровня SSH и уровень компрессии.

Отметим, что разгрузка зависит от компрессии SSH, что уменьшает использование траффика при передаче файлов на и с машин для сборки.

daemon-socket (default: "/var/guix/daemon-socket/socket")

Имя файла сокета Unix-домена, который слушает guix-daemon на удалённой машине.

overload-threshold (default: 0.8)

Порог нагрузки, выше которого потенциальная offload машина не учитывается offload планировщиком. Это значение примерно соответствует общему использованию процессора машиной сборки в диапазоне от 0,0 (0%) до 1,0 (100%). Это также можно отключить, установив overload-threshold в #f.

parallel-builds (default: 1)

Число сборок, которые могут быть запущены на машине.

speed (default: 1.0)

Показатель скорости. Планировщик разгрузки предпримет попытку выбрать машину с наибольшим показателем скорости.

features (default: '())

Набор строк, описывающий специфические функции, которые поддерживаются на машине. Например, "kvm" для машин, которые имеют модули Linux KVM и соответствующую поддерку аппаратного обеспечения. Деривации могут запрашивать функции по имени, и тогда они будут запранированы на соответствующих машинах для сборки.

Примечание: On Guix System, instead of managing /etc/guix/machines.scm independently, you can choose to specify build machines directly in the operating-system declaration, in the build-machines field of guix-configuration. See build-machines field of guix-configuration.

Команда guix должна быть в путях для поиска на машинах лоя сборки. Можно проверить это, выполнив:

ssh build-machine guix repl --version

Есть ещё одна вещь, которую нужно выполнить после размещения machines.scm. Выше описано, что при разгрузке файлы передаются вперёд и назад между складами на машинах. Для этого необходимо сгенерировать ключ-пару на кадой машине, чтобы позволить демону экспортировать подписанные архивы файлов из склада (see Вызов guix archive):

# guix archive --generate-key

Примечание: This key pair is not related to the SSH key pair that was previously mentioned in the description of the build-machine data type.

Каждая машина для сорки должна авторизовать ключ машины-инициатора, чтобы принимать элементы из склада, которые присылает инициатор:

# guix archive --authorize < master-public-key.txt

Точно так же машина-инициатор должна авторизовать ключ каждой машины для сборки.

Всё движение с ключами, описанное здесь, создаёт надёжную двустороннюю свзь между инициатором и машинами для сборки. А именно, когда машина-инициатор принимает файлы из машины для сборки (или наборот), её демон может удостоверить их подлинность и невмешательство других, а также то, что они подписаны авторизованным ключом.

Чтобы проверить работоспособность настроек, запустите следующую команду на инициирующем узле:

# guix offload test

Это выполнит попытку соединиться с каждой из машин для сборки, обозначенных в /etc/guix/machines.scm, проверит наличие модулей Guile и Guix на каждой машине, а также сделает попытку экспортировать и импортировать, а затем выведет отчёт об этом процессе.

Если нужно тестировать другой файл с описанием машин, просто приведите его в командной строке:

# guix offload test machines-qualif.scm

И последнее, можно тестировать набор машин, чьи имена соответствуют регулярному выражению, например:

# guix offload test machines.scm '\.gnu\.org$'

Чтобы отобразить текущую загрузку всех машин для сборки, запустите команду на инициирущем узле:

# guix offload status

2.2.3 Поддержка SELinux

Guix включает файл политик SELinnux etc/guix-daemon.cil, который может устанавливаться в систему, в которой включен SELinux, тогда файлы Guix будут помечены и настроены для соответствующего поведения демона. Так как система Guix не предоставляет политику SELinux, политика демона не может использоваться в системе Guix.

2.2.3.1 Установка политики SELinux

Примечание: The guix-install.sh binary installation script offers to perform the steps below for you (see Бинарная установка).

Чтобы установить политику, запустите следующую команду от root:

semodule -i /var/guix/profiles/per-user/root/current-guix/share/selinux/guix-daemon.cil

Then, as root, relabel the file system, possibly after making it writable:

mount -o remount,rw /gnu/store
restorecon -R /gnu /var/guix

At this point you can start or restart guix-daemon; on a distribution that uses systemd as its service manager, you can do that with:

systemctl restart guix-daemon

Когда политика установлена, изменена метка файловой системы и демон перезапущен, она должна работать в контексте guix_daemon_t. Можно проверить это следующей командой:

ps -Zax | grep guix-daemon

Наблюдайте файлы логов SELinux во время работы команды guix build hello, чтобы удостовериться, что SELinux позволяет выполнение необходимых операций.

2.2.3.2 Ограничения

Эта политика не совершенна. Тут есть ряд ограничений или причуд, который нужно учитывать при разворачивании политики SELinux для демона Guix.

  1. guix_daemon_socket_t на самом деле не используется. Никакие операции с сокетом не выполняются. Ничего плохого в том, чтобы иметь эту неиспользуемую метку, но желательно определить правила сокета для этой метки.
  2. guix gc cannot access arbitrary links to profiles. By design, the file label of the destination of a symlink is independent of the file label of the link itself. Although all profiles under $localstatedir are labelled, the links to these profiles inherit the label of the directory they are in. For links in the user’s home directory this will be user_home_t. But for links from the root user’s home directory, or /tmp, or the HTTP server’s working directory, etc, this won’t work. guix gc would be prevented from reading and following these links.
  3. Функция демона прослушивать соединения TCP может более не работать. Это может потребовать дополнительных правил, потому что SELinux относится к сетевым сокетам иначе, чем к файлам.
  4. В настоящее время всем файлам с именами, соответствующими регулярному выражению /gnu/store/.+-(guix-.+|profile)/bin/guix-daemon, присвоена метка guix_daemon_exec_t; это означает, что любому файлу с таким именем в любом профиле разрешён запуск в домене guix_daemon_t. Это не идеально. Атакующий может собрать пакет, который содержит исполняемый файл и убеить пользователя установить и запустить его, и таким образом он получит доступ к домену guix_daemon_t. В этой связи SELinux мог бы не давать ему доступ к файлам, которые разрешены для процессов в этом домене.

    Вам нужно будет изменить метку (label) каталога хранилища после всех обновлений до guix-daemon, например, после запуска guix pull. Предполагая, что хранилище в /gnu, вы можете это сделать с restorecon -vR /gnu, или другими способами, предусмотренными вашей операционной системой.

    Мы можем создать политику с большими ограничениями во время установки, так чтобы только точное имя исполняемого файла установленного в данный момент guix-daemon было помечено меткой guix_daemon_exec_t вместо того, чтобы использовать регулярное выражение, выбирающее большой ряд файлов. Проблемой в данном случае будет то, что root потребуется устанавливать или обновлять политику во время любой установки в случае, если обновлён исполняемый файл guix-daemon.


2.3 Вызов guix-daemon

Программа guix-daemon реализует весь функционал доступа к складу. Это включает запуск процессов сборки, запуск сборщика мусора, проверка доступности результата сборки и т.д. Он должен быть запущен от root так:

# guix-daemon --build-users-group=guixbuild

This daemon can also be started following the systemd “socket activation” protocol (see make-systemd-constructor in The GNU Shepherd Manual).

Для подробностей о том, как настроить его, смотрите see Настройка демона.

По умолчанию guix-daemon запускает процессы сборки под различными UID, от пользователей из группы, обозначенной в --build-users-group. В дополнение каждый процесс сборки запускается в окружении chroot, которое содержит только набор элементов склада, от которых зависит процесс сборки, как это обозначено в деривации (see derivation), а также набор специфичных системных директорий. По умолчанию последнее включает /dev и /dev/pts. Более того, под GNU/Linux окружение сборки — это контейнер: в дополнение к тому, что он имеет собственное дерево файловой системы, он также имеет отдельное пространство имён монтирования, своё собственное пространство имён процессов PID, пространство сетевых имён и т.д. Это позволяет получить воспроизводимые сборки (see Особенности).

Когда демон выполняет сборку по запросу пользователя, он создаёт директорию под /tmp или под директорией, заданной его переменной окружения TMPDIR. Эта директория разделяется с контейнером на время сборки, хотя внутри контейнера дерево сборки всегда называется /tmp/guix-build-name.drv-0.

Директория сборки автоматически удаляется по завершении, если конечно, сборка не завершилась с ошибкой, и клиент не обозначил --keep-failed (see --keep-failed).

Демон слушает соединения и порождает один под-процесс для каждой сессии, запускаемой клиентом (одну из подкоманд guix). Команда guix processes позволяет мониторить активность вашей системы, предоставляя обзор каждой активной сессии и клиентов. Смотрите See Вызов guix processes для подробной информации.

Поддерживаются следующие опции командной строки:

--build-users-group=group

Использовать пользователей из группы group для запуска процессов сборки (see build users).

--no-substitutes

Не использовать подстановки для сборок. Это означает — собирать элементы локально вместо того, чтобы скачивать собранные бинарники (see Подстановки).

Когда демон работает с --no-substitutes, клиенты всё ещё могут явно включить подстановку с помощью удалённого вызова процедур set-build-options (see Хранилище).

--substitute-urls=urls

Использовать адреса urls, разделённые пробелом по умолчанию, как список источников подстановок. Когда эта опция пропущена, используется ‘https://bordeaux.guix.gnu.org https://ci.guix.gnu.org’.

Это означает, что подстановки могут скачиваться из адресов urls, если конечно они подписаны доверенной подписью (see Подстановки).

See Получение заменителей с других серверов, для получения дополнительной информации о том, как настроить демон для получения заменителей с других серверов.

--no-offload

Не использовать подстановки для сборок. Это означает — собирать элементы локально вместо того, чтобы скачивать собранные бинарники (see Подстановки).

--cache-failures

Кешировать ошибки сборки. По умолчанию кешируются только успешные сборки.

При установке этой опции можно использовать guix gc --list-failures, чтобы просматривать элементы склада, помеченные как ошибочные; guix gc --clear-failures удаляет элементы склада из кеша ошибок. See Вызов guix gc.

--cores=n
-c n

Использовать n ядер процессора для сборки каждой деривации; 0 означает использовать все доступные.

Значение по умолчанию - 0, но оно может быть изменено клиентами, в частности, опцией --cores команды guix build (see Запуск guix build).

В результате устанавливается переменная окружения NIX_BUILD_CORES для процесса сборки, который затем может использовать её для применения внутреннего параллелизма, например, для запуска make -j$NIX_BUILD_CORES.

--max-jobs=n
-M n

Разрешить максимум n параллельных задач сборки. Значение по умолчанию - 1. Установка в 0 означает, чтоб сборки не будут выполняться локально, вместо этого, демон будет разгружать сборки (see Использование функционала разгрузки) или просто отчитается об ошибке.

--max-silent-time=seconds

Когда процесс сборки или подстановки молчит более seconds секунд, завершить его и отчитаться об ошибке сборки.

The default value is 3600 (one hour).

Значение, заданное здесь, может быть переопределено клиентами (see --max-silent-time).

--timeout=seconds

Точно так же, когда процесс сборки или подстановки длится более seconds, завершить его и отчитаться об ошибке сборки.

The default value is 24 hours.

Значение, заданное здесь, может быть переопределено клиентами (see --timeout).

--rounds=N

Собирать каждую деривацию n раз подряд и вызывать ошибку, если результаты последовательных сборок не идентичны бит-к-биту. Отметим, что эта настройка может быть переопределена клиентами в команде, например, guix build (see Запуск guix build).

При использовании вместе с --keep-failed различные результаты сохраняются на складе под /gnu/store/…-check. Это делает возможным просмотр различий между двумя результатами.

--debug

Выводить отладочную информацию.

Это полезно для отладки проблем запуска демона, но затем это может быть переопределено клиентами, например, опцией --verbosity команды guix build (see Запуск guix build).

--chroot-directory=dir

Добавить директорию dir в chroot сборки.

Это может изменить результаты процессов сборки, например, если они используют необязательные (опциональные) зависимости, найденные в dir, если они доступны, но только так, а не иначе. Поэтому не рекомендуется делать так. Вместо этого, убедитесь, что каждая деривация объявляет все необходимые входные данные.

--disable-chroot

Отключить chroot для сборки.

Использование этой опции не рекомендуется, так как опять же это позволит процессам сборки получить доступ к не объявленным зависимостям. Это важно, даже если guix-daemon запущен под аккаунтом непривилегированного пользователя.

--log-compression=type

Архивировать логи сборки методом type. Это один из: gzip, bzip2 или none.

Unless --lose-logs is used, all the build logs are kept in the localstatedir. To save space, the daemon automatically compresses them with gzip by default.

--discover[=yes|no]

Следует ли обнаруживать сервера с заменителями в локальной сети с помощью mDNS and DNS-SD.

Эта функция все еще экспериментальная. Однако есть несколько соображений.

  1. Это может быть быстрее/дешевле, чем загрузка (fetching) с удаленных серверов;
  2. Никаких угроз безопасности, будут использоваться только подлинные заменители (see Аутентификация подстановок);
  3. Объявление злоумышленника guix publish в вашей локальной сети не могут предоставить вам вредоносные двоичные файлы, но они могут узнать, какое программное обеспечение вы устанавливаете;
  4. Серверы могут предоставить заменители через HTTP в незашифрованном виде, поэтому любой в локальной сети может видеть, какое программное обеспечение вы устанавливаете.

Также можно включить или отключить обнаружение сервера с заменителями во время выполнения, запустив:

herd discover guix-daemon on
herd discover guix-daemon off
--disable-deduplication

Отключить автоматическую "дедупликацию" файлов на складе.

По умолчанию файлы, добавленные на склад, автоматически "дедуплицируются": если вновь добавленный файл идентичен другому, найденному на складе, демон делает новый файл жесткой ссылкой на другой файл. Это существенно сокращает использование места на диске за счёт небольшого увеличения запросов ввода/вывода в конце процесса сборки. Эта опция отключает такую оптимизацию.

--gc-keep-outputs[=yes|no]

Сообщить, должен ли сборщик мусора (GC) сохранять выходные данные живой деривации.

При установке в "yes" (да), сборщик мусора (GC) будет сохранять результаты любой живой деривации, доступной на складе, — файлы .drv. Значение по умолчанию - "no" (нет) - означает, что результаты дериваций хранятся только, если они доступны из корней сборщика мусора (GC roots). Смотрите See Вызов guix gc для информации о корнях сборщика мусора.

--gc-keep-derivations[=yes|no]

Сообщить, должен ли сборщик мусора (GC) сохранять деривации, соответствующие живым результатам.

При указании "yes" (да), что является значением по умолчанию, сборщик мусора сохраняет деривации, то есть файлы .drv, до тех пор, пока любой из их выходов остаётся живым. Это позволяет пользователям отслеживать исходники элементов на складе. Установка в "no" (нет) немного экономит место на диске.

Таким образом, установка --gc-keep-derivations в "yes" (да) даётт возможность пройти от результатов до дериваций, а установка --gc-keep-outputs в "yes" (да), делает возможным пройти от дериваций до результатов. Если оба установлены в "yes", тогда это сохранит всё используемое для сборки (исходники, компилятор, библиотеки и другие инструменты сборки) живых объектов на складе, без учёта, доступны эти инструменты сборки из корней сборщика мусора или нет. Это удобно для разработчиков, так как это сокращает пересборки или скачивания.

--impersonate-linux-2.6

На системах, основанных на Linux, выдавать себя за Linux 2.6. Это означает, что системный вызов ядра uname будет выдавать 2.6 номером релиза.

Это полезно для сборки программ, которые (обычно по ошибке) зависят от версии ядра.

--lose-logs

Не сохранять логи сборки. По умолчанию они сохраняются под localstatedir/guix/log.

--system=system

Считать system текущим типом системы. По умолчанию это пара архитектура/ядро, обнаруженная во время конфигурации, например, x86_64-linux.

--listen=endpoint

Слушать соединения с endpoint. endpoint интерпретируется как имя файла сокета Unix-домена, если начинается с / (знак слеша). В противном случае endpoint интерпретируется как имя хоста или им хоста и порт для прослушивания. Вот несколько примеров:

--listen=/gnu/var/daemon

Слушать соединения с сокетом Unix-домена /gnu/var/daemon, который создаётся при необходимости.

--listen=localhost

Слушать соединения TCP сетевого интерфейса, относящиеся к localhost, на порту 44146.

--listen=128.0.0.42:1234

Слушать соединения TCP сетевого интерфейса, относящиеся к 128.0.0.42, на порту 1234.

Эта опция может повторяться много раз, в таком случае guix-daemon принимает соединения на всех обозначенных точках. Пользователи могут через клиентские команды сообщать, через какие точки соединяться, для этого нужно устанавливать переменную окружения GUIX_DAEMON_SOCKET (see GUIX_DAEMON_SOCKET).

Примечание: Протокол демона неаутентичный и нешифрованный. Использование --listen=host подходит локальным сетям, как например, кластерам, где только доверенные узлы могут соединяться с демоном сборки. В других случаях, когда необходим удалённый доступ к демону рекомендуется использовать сокеты Unix-домена вместе с SSH.

Когда --listen пропущена, guix-daemon слушает соединения с сокетом Unix-домена, расположенным в localstatedir/guix/daemon-socket/socket.


2.4 Установка приложения

При использовании дистрибутива GNU/Linux, отличного от системы, называемого также чужой дистрибутив, необходимо несколько дополнительных шагов, чтобы всё работало. Вот некоторые из них.

2.4.1 Региональные настройки

Пакеты, установленные с помощью Guix, не будут использовать данные локали хост-системы. Вместо этого вы должны вначале установить один из пакетов локали, доступных в Guix, а затем определить переменную окружения GUIX_LOCPATH:

$ guix install glibc-locales
$ export GUIX_LOCPATH=$HOME/.guix-profile/lib/locale

Note that the glibc-locales package contains data for all the locales supported by the GNU libc and weighs in at around 930 MiB9. If you only need a few locales, you can define your custom locales package via the make-glibc-utf8-locales procedure from the (gnu packages base) module. The following example defines a package containing the various Canadian UTF-8 locales known to the GNU libc, that weighs around 14 MiB:

(use-modules (gnu packages base))

(define my-glibc-locales
  (make-glibc-utf8-locales
   glibc
   #:locales (list "en_CA" "fr_CA" "ik_CA" "iu_CA" "shs_CA")
   #:name "glibc-canadian-utf8-locales"))

Переменная GUIX_LOCPATH играет ту же роль, что и LOCPATH (see LOCPATH in The GNU C Library Reference Manual). Но есть два существенных различия:

  1. GUIX_LOCPATH учитывается только libc в Guix, но не учитывается libc, предоставляемым чужим дистрибутивом. Так что использование GUIX_LOCPATH позволяет вам убедиться, что программы чужого дистрибутива не будут производить загрузку несовместимых данных локали.
  2. libc добавляет суффиксы /X.Y к каждому компоненту GUIX_LOCPATH, где X.Y - это версия libc, например, 2.22. Это значит, что если ваш профиль Guix будет содержать смесь программ, связанных с дугой версией libc, каждая версия libc будет пытаться загружать только данные локали в правильном формате.

Это важно, потому что использование данных локали другой версией libc может быть неприемлемо.

2.4.2 Переключатель службы имен

При использовании Guix на чужом дистрибутиве мы настойчиво рекомендуем, чтобы система запускала демон кеша имён сервисов библиотеки GNU C, nscd, который должен слушать сокет /var/run/nscd/socket. Если это не сделано, приложения, установленные Guix, могут некорректно адресовать имена хостов или аккаунты пользователей и даже падать. Ниже объясняется почему.

Библиотека GNU C реализует выбор имён сервисов (NSS), который представляет собой расширяемый механизм для резолвинга имён в целом: резолвинг имён хостов, аккаунтов пользователей и другое (see Name Service Switch in The GNU C Library Reference Manual).

Будучи расширяемым, NSS поддерживает плагины, которые предоставляют реализации разрешения новых имён: плагин nss-mdns резолвит имена хостов .local, плагин nis адресует пользовательские аккаунты, используя сервис сетевой информации (NIS) и т.д. Эти дополнительные сервисы адресации настраиваются для всей системы в /etc/nsswitch.conf, и все запущенные в системе программы учитывают эти настройки (see NSS Configuration File in The GNU C Reference Manual).

Когда выполняется разрешение имён, например, вызовом функции C getaddrinfo, приложения вначале делают попытку соединиться с nscd; в случае успеха nscd выполняет разрешение имён по их запросу. Если nscd не запущен, тогда они выполняют разрешение имён самостоятельно, загружая сервисы разрешения имён в их собственные адресные пространства и запуская их. Эти сервисы разрешения имён — файлы libnss_*.so — запускаются dlopen, но они могут поставляться системной библиотекой C, а не библиотекой C, с которой залинковано приложение (библиотека C из Guix).

Вот где кроется проблема — если ваше приложение залинковано с библиотекой C Guix (скажем, glibc 2.24) и пытается загрузить плагины NSS из другой библиотеки C (скажем, libnss_mdns.so для glibc 2.22), это вероятно вызовет падение или резолвинг имени завершится с ошибкой.

Запуск nscd в системе, помимо преимуществ, также исключает эту проблему несовместимости программ, потому что файлы libnss_*.so загружены в процессе nscd, а не в самом приложении.

2.4.3 Шрифты X11

The majority of graphical applications use Fontconfig to locate and load fonts and perform X11-client-side rendering. The fontconfig package in Guix looks for fonts in $HOME/.guix-profile by default. Thus, to allow graphical applications installed with Guix to display fonts, you have to install fonts with Guix as well. Essential font packages include font-ghostscript, font-dejavu, and font-gnu-freefont.

После того, как вы установили или удалили шрифты, или когда вы заметили приложение, которое не находит шрифты, вам может потребоваться установить Fontconfig и принудительно обновить кэш шрифтов, выполнив:

guix install fontconfig
fc-cache -rv

Для отображения в графических приложениях текста на китайском, японском, корейском нужно установить font-adobe-source-han-sans или font-wqy-zenhei. Первый имеет множественный выход, один для языковой семьи (see Пакеты со множественным выходом). Например, следующая команда устанавливает шрифты для китайских языков:

guix install font-adobe-source-han-sans:cn

Старые программы, например, xterm, не используют Fontconfig, а вместо этого вызывают рендеринг шрифтов на стороне сервера. Таким программам необходимо указывать полное имя шрифта, используя XLFD (X Logical Font Description), примерно так:

-*-dejavu sans-medium-r-normal-*-*-100-*-*-*-*-*-1

Чтобы иметь возможность использовать такие полные имена для шрифтов TrueType, установленных в вашем профиле Guix, вам нужно расширить пути шрифтов X-сервера:

xset +fp $(dirname $(readlink -f ~/.guix-profile/share/fonts/truetype/fonts.dir))

После этого можно запустить xlsfonts (из пакета xlsfonts), чтобы убедиться, что ваши шрифты TrueType находятся там.

2.4.4 Сертификаты X.509

Пакет nss-certs предоставялет сертификаты X.509, которые позволяют программам аутентифицировать веб-серверы и работать через HTTPS.

При использовании Guix на чужом дистрибутиве можно установить этот пакет и определить соответствующие переменные окружения, чтобы пакеты знали, где искать сертификаты. Смотрите See Сертификаты X.509 для подробной информации.

2.4.5 Пакеты Emacs

Когда вы устанавливаете пакеты Emacs с Guix, файлы пакетов помещаются в каталог share/emacs/site-lisp/ того профиля, в котором они установлены. Библиотеки Elisp доступны для Emacs через переменную среды EMACSLOADPATH, которая устанавливается при установке самого Emacs.

Additionally, autoload definitions are automatically evaluated at the initialization of Emacs, by the Guix-specific guix-emacs-autoload-packages procedure. This procedure can be interactively invoked to have newly installed Emacs packages discovered, without having to restart Emacs. If, for some reason, you want to avoid auto-loading the Emacs packages installed with Guix, you can do so by running Emacs with the --no-site-file option (see Init File in The GNU Emacs Manual).

Примечание: Most Emacs variants are now capable of doing native compilation. The approach taken by Guix Emacs however differs greatly from the approach taken upstream.

Upstream Emacs compiles packages just-in-time and typically places shared object files in a special folder within your user-emacs-directory. These shared objects within said folder are organized in a flat hierarchy, and their file names contain two hashes to verify the original file name and contents of the source code.

Guix Emacs on the other hand prefers to compile packages ahead-of-time. Shared objects retain much of the original file name and no hashes are added to verify the original file name or the contents of the file. Crucially, this allows Guix Emacs and packages built against it to be grafted (see grafts), but at the same time, Guix Emacs lacks the hash-based verification of source code baked into upstream Emacs. As this naming schema is trivial to exploit, we disable just-in-time compilation.

Further note, that emacs-minimal—the default Emacs for building packages—has been configured without native compilation. To natively compile your emacs packages ahead of time, use a transformation like --with-input=emacs-minimal=emacs.


2.5 Обновление Guix

Чтобы обновить Guix, запустите:

guix pull

See Вызов guix pull для дополнительной информации.

В ином дистрибутиве вы можете обновить демон сборки, запустив:

sudo -i guix pull

затем (при условии, что ваш дистрибутив использует инструмент управления сервисами systemd):

systemctl restart guix-daemon.service

В системе Guix обновление демона достигается путем перенастройки системы (see guix system reconfigure).


3 Установка системы

Этот раздел объясняет, как установить систему Guix на компьютер. Guix, как пакетный менеджер, можно также установить на уже установленную систему GNU/Linux (see Установка).


3.1 Ограничения

Мы полагаем, система Guix будет широко применяться для офисных и серверных решений. Гарантия надёжности основана на транзакционных обновлениях, откатах и воспроизводимости. Это наше прочное основание.

More and more system services are provided (see Сервисы).

Nevertheless, before you proceed with the installation, be aware that some services you rely on may still be missing from version 2a6d964.

Мы настойчиво призываем вас присылать отчёты о проблемах (или историиуспеха!). Присоединяйтесь к нам, если вы хотите улучшить Guix. Смотрите See Содействие, чтобы узнать больше.


3.2 По поводу железа

GNU Guix особенно заботится об уважении свободы пользователя при работе за компьютером. Она построена на ядре Linux-libre, что означает, что поддерживается только аппаратное обеспечение, которое имеет свободные драйверы и прошивки. Сегодня широкий список наличествующей аппаратуры поддерживается GNU/Linux-libre — от клавиатур и графических карт до сканеров и контроллеров Ethernet. К сожалению, всё ещё остаётся ряд производителей железа, которые запрещают пользователям управлять их устройствами, и такое аппаратное обеспечение не поддерживается системой Guix.

Основной областью, в которой отсутствуют свободные драйверы и прошивки, являются устройства Wi-Fi. Работают устройства Wi-Fi, которые используют платы Atheros (AR9271 и AR7010) и взаимодействуют с драйвером Linux-libre ath9k, также использующие платы Broadcom/AirForce (BCM43xx with Wireless-Core Revision 5), которые работают с драйвером Linux-libre b43-open. Свободная прошивка существует для обоих и доступна в системе Guix из коробки как часть %base-firmware (see firmware).

Программа установки предупредит вас заранее, если обнаружит устройства, которые, как известно, не работают из-за отсутствия свободной прошивки или свободных драйверов.

Фонд свободного программного обспечения FSF ведёт Уважение вашей свободы (RYF) — программу сертификации аппаратного обеспечения, которое уважает вашу свободу и вашу безопасность и утверждает, что вы имеете контроль над вашими устройствами. Мы побуждаем вас проверить список устройств, сертифицированных RYF.

Другой полезный ресурс — сайт H-Node. Он содержит каталог устройств с информацией об их поддержке в GNU/Linux.


3.3 Установочная флеш и DVD

Установочный образ ISO-9660 может быть записан на USB-флеш или DVD, скачать его можно по адресу: ‘https://ftp.gnu.org/gnu/guix/guix-system-install-2a6d964.x86_64-linux.iso’, где вы можете заменить x86_64-linux на один из:

x86_64-linux

для системы GNU/Linux на 64-битных Intel/AMD-совместимых процессорах;

i686-linux

для системы GNU/Linux на 32-битных Intel-совместимых процессорах.

Обязательно скачайте связанный файл подписи .sig и проверьте аутентичность образа так:

$ wget https://ftp.gnu.org/gnu/guix/guix-system-install-2a6d964.x86_64-linux.iso.sig
$ gpg --verify guix-system-install-2a6d964.x86_64-linux.iso.sig

Если это завершается ошибкой, значит у вас нет необходимого публичного ключа, тогда запустите команду для импорта ключа:

$ wget https://sv.gnu.org/people/viewgpg.php?user_id=15145 \
      -qO - | gpg --import -

и запустите команду gpg --verify.

Обратите внимание, что предупреждение по типу «Этот ключ не сертифицирован с доверенной подписью!» является нормальным.

Этот образ содержит инструменты, необходимые для установки. Он должен копироваться как есть на большую USB-флеш или DVD.

Запись на USB-флеш

Вставьте в компьютер USB-флеш объёмом 1 Гб или более и определите его имя. Учитывая имя (обычно соответствующее /dev/sdX) скопируйте образ на него:

dd if=guix-system-install-2a6d964.x86_64-linux.iso of=/dev/sdX status=progress
sync

Доступ к /dev/sdX обычно требует привилегий root.

Запись на DVD

Вставьте чистый DVD в компьютер и определите имя устройства. Обычно DVD определяется как /dev/srX, скопируйте образ так:

growisofs -dvd-compat -Z /dev/srX=guix-system-install-2a6d964.x86_64-linux.iso

Доступ к /dev/srX обычно требует привилегий root.

Загрузка

Когда это сделано, вы должны перезагрузить систему и загрузиться с USB-флеш или DVD. Последнее обычно требует доступа к меню BIOS или UEFI, где можно выбрать загрузку с USB-флеш.

Sadly, on some machines, the installation medium cannot be properly booted and you only see a black screen after booting even after you waited for ten minutes. This may indicate that your machine cannot run Guix System; perhaps you instead want to install Guix on a foreign distro (see Бинарная установка). But don’t give up just yet; a possible workaround is pressing the e key in the GRUB boot menu and appending nomodeset to the Linux bootline. Sometimes the black screen issue can also be resolved by connecting a different display.

Смотрите See Установка Guix на виртуальную машину (VM), если вы хотите установить систему Guix на виртуальную машину (VM).


3.4 Подготовка к установке

Когда вы загрузитесь, вы можете использовать графическую установку, которая намного проще для начала (see Графическая установка в GUI). Или если вы уже знакомы с GNU/Linux или вы хотите больший контроль, чем это предоставляет графическая установка, вы можете выбрать ручной процесс установки (see Ручная установка).

Графическа установка доступна в TTY1. Вы можете запустить оболочку root в TTY 3-6, нажимая ctrl-alt-f3, ctrl-alt-f4 и т.д. TTY2 отображает эту документацию, открыть его можно клавишами ctrl-alt-f2. Листать документацию можно командами просмотрщика Info (see Stand-alone GNU Info). Установка системы запускает демона мыши GPM, который позволяет вам выделять текст лековй кнопкой мыши и вставлять средней кнопкой.

Примечание: Установка требует доступа к Интернету, чтобы скачивать любые отсутствующие зависимости в вашей конфигурации системы. Смотрите раздел "Сеть" ниже.


3.5 Графическая установка в GUI

Графический установщик представляет собой текстовый интерфейс. Он взаимодействует через диалоговые блоки, проходя шаги установки системы GNU Guix.

Первый диалоговый блок позволяет вам установить систему в таком виде, как во время установки. Вы можете выбрать язык, раскладку клавиатуры, задать настройки сети для установки. На картинке ниже — диалог настройки сети.

networking setup with the graphical
installer

Следующие шаги позволят вам разметить диск, как это показано на картинке ниже. Также можно выбрать шифрование вайловой системы (или без шифрования), ввести имя хоста и пароль root, создать дополнительную учётную запись и другие действия.

partitioning with the graphical
installer

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

resuming the installation process

Когда настройки выполнены, установщик сгенерирует конфигурацию операционной системы и отобразит её (see Использование системы конфигурации). На этом этапе нажатие “OK” запустит установку. После успешнго завершения нужно перезагрузиться и использовать новую систему. Смотрите See После установки системы, чтобы узнать ещё больше!


3.6 Ручная установка

Этот раздел описывает, как можно вручную установить систему GNU Guix на вашу машину. Это потребует знаний GNU/Linux, оболочки и инструментов администрирования. Если вы считаете, это не для вас, используйте вариант графической установки (see Графическая установка в GUI).

Система установки предоставляет root-оболочки в TTY от 3 до 6; нажмите ctrl-alt-f3, ctrl-alt-f4 и так далее, чтобы попасть в них. Они включают много распространенных инструментов, необходимых для установки системы, но они также является полноценной системой Guix. Это означает, что вы можете установить дополнительные пакеты, если вам это понадобится, используя guix package (see Вызов guix package).


3.6.1 Раскладка клавиатуры, Сеть, Разметка диска

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

3.6.1.1 Раскладка клавиатуры

Установочный образ использует раскладку клавиатуры US qwerty. Если нужно поменять её, можно пользоваться командой loadkeys. Например, следующая команда выбирает раскладку клавиатуры Dvorak:

loadkeys dvorak

Смотрите файлы в /run/current-system/profile/share/keymaps, чтобы найти список доступных раскладок. Запустите man loadkeys, чтобы узнать больше.

3.6.1.2 Сеть

Запустите следующую команду, чтобы узнать имена сетевых интерфейсов:

ifconfig -a

… или используйте специальную команду GNU/Linux ip:

ip address

Проводные интерфейсы называются на букву ‘e’; например, интерфейс, соответствующий первому контроллеру Ethernet на материнской плате, называется ‘eno1’. Беспроводные интерфейсы имеют имена, начинающиеся с ‘w’, как ‘w1p2s0’.

Проводное соединение

Чтобы настроить проводную сеть, запустите следующую команду, заменив interface именем проводного интерфейса, который вы хотите использовать.

ifconfig interface up

… или используйте специальную команду GNU/Linux ip:

ifconfig interface up
Беспроводное соединение

Чтобы настроить беспроводную сеть, можно создать конфигурционный файл для wpa_supplicant (расположение файла неважно). Можно пользоваться любым доступным текстовым редактором, например, nano:

nano wpa_supplicant.conf

Следующий пример настроек подойдёт для большинства беспроводных сетей. Нужно предоставить фактический SSID и парольную фразу для сети, к которой вы подключаетесь:

network={
  ssid="my-ssid"
  key_mgmt=WPA-PSK
  psk="the network's secret passphrase"
}

Запустите сервис беспроводной сети в фоновом режиме следующей командой (замените interface именем сетевого интерфейса, который вы используете):

wpa_supplicant -c wpa_supplicant.conf -i interface -B

Запустите man wpa_supplicant, чтобы узнать больше.

Теперь нужно получить IP-адрес. В случае сети, где IP-адреса автоматически распределяются с помощью DHCP, можно запустить:

dhclient -v interface

Попробуйте пинговать сервер, чтобы узнать, работает ли сеть:

ping -c 3 gnu.org

Настройка доступа к сети необходима почти всегда, потому что ораз может не иметь программное обеспечение и инструменты, которые могут понадобиться.

Если вам нужено настроить доступ HTTP и HTTPS прокси, выполните следующую команду:

herd set-http-proxy guix-daemon URL

где URL адрес прокси, например http://example.org:8118.

Если желаете, вы можете продолжить установку удалённо, запустив SSH-сервер:

herd start ssh-daemon

Не забудьте задать пароль командой passwd или настроить публичный ключ OpenSSH для аутентификации, чтобы иметь возможность подключиться.

3.6.1.3 Разметка диска

Если это ещё не сделано, тогда нужно разделить диск, а затем отформатировать целевой(-ые) раздел(ы).

Установочный образ содержит несколько инструментов для разметки, включая Parted (see Overview in GNU Parted User Manual), fdisk и cfdisk. Запустите и настройте ваш диск, используя план разметки, который нужен:

cfdisk

Если ваш диск использует формат GUID Partition Table (GPT), и вы планируете использовать GRUB, работающий с BIOS (что по умолчанию), убедитесь, что раздел BIOS Boot Partition доступен (see BIOS installation in GNU GRUB manual).

Если вместо этого вы хотите использовать GRUB, работающий с EFI, тогда необходима разметка система EFI FAT32 (ESP). Такая разметка может, например, монтироваться в /boot/efi и должна иметь флаг esp. То есть в случае parted:

parted /dev/sda set 1 esp on

Примечание: Не уверенны, что выбрать: GRUB, взаимодействующий с EFI или BIOS? Если существует директория /sys/firmware/efi в установочом образе, тогда вам следует использовать установку EFI и grub-efi-bootloader. В противном случае нужно использовать GRUB, работающий с BIOS, называемый grub-bootloader. Смотрите See Настройка загрузчика для большей информации о загрузчиках.

Когда разметка целевого диска выполнена, нужно создать файловую систему на соответствующем(-их) разделе(-ах)10. В случае ESP, если у вас раздел /dev/sda1, выполните:

mkfs.fat -F32 /dev/sda1

Для корневой файловой системы наиболее широко используется формат ext4. Другие файловые системы, такие как Btrfs, поддерживают сжатие, которое, как известно, прекрасно дополняет дедупликацию файлов, которую демон выполняет независимо от файловой системы (see deduplication).

Желательно добавить метки файловых систем, чтобы вы могли ссылаться на них по именам в объявлениях file-system (see Файловые системы). Обычно это можно сделать опцией -L в mkfs.ext4, например. Допустим, раздел root располагается в /dev/sda2, можно добавить метку my-root следующим образом:

mkfs.ext4 -L my-root /dev/sda2

Если вы планируете зашифровать раздел root, то вы можете использовать для этого утилиты Cryptsetup/LUKS (см. man cryptsetup для получения дополнительной информации).

Assuming you want to store the root partition on /dev/sda2, the command sequence to format it as a LUKS partition would be along these lines:

cryptsetup luksFormat /dev/sda2
cryptsetup open /dev/sda2 my-partition
mkfs.ext4 -L my-root /dev/mapper/my-partition

Когда это сделано, монтируйте целевую файловую систему под /mnt следующей командой (опять же полагая, что метка раздела root — my-root):

mount LABEL=my-root /mnt

Также монтируйте любые другие файловые системы внутрь целевой файловой системы. Если например, выбрана точка монтирования EFI /boot/efi, монтируйте её в /mnt/boot/efi, так, чтобы она обнаруживалась после запуска guix system init.

Наконец, если вы планируете использовать один или более разделов подкачки (see Swap Space), обязательно инициализируйте их с помощью mkswap. Предположим, что у вас есть один раздел подкачки на /dev/sda3, вы должны выполнить:

mkswap /dev/sda3
swapon /dev/sda3

Возможно, вместо этого вы используете swap-файл. Например, предположим, вы хотите использовать в новой системе swap-файл в /swapfile, тогда нужно выполнить11:

# This is 10 GiB of swap space.  Adjust "count" to change the size.
dd if=/dev/zero of=/mnt/swapfile bs=1MiB count=10240
# For security, make the file readable and writable only by root.
chmod 600 /mnt/swapfile
mkswap /mnt/swapfile
swapon /mnt/swapfile

Заметим, что если вы шифруете раздел root и создаёте swap-файл в его файловой системе, как это описано выше, шифрование также будет защищать swap-файл, как и любой другой файл в этой файловой системе.


3.6.2 В продолжении установки

Когда целевые разделы готовы и раздел root монтирован под /mnt, всё готово для старта. Сначала запустите:

herd start cow-store /mnt

Это сделает /gnu/store копируемым при записи (copy-on-write), что заставит систему записывать пакеты, добавляемые в систему на этапе установки, на целевой диск под /mnt, а не держать их в памяти. Это важно, потому что по команде guix system init (смотрите ниже) будут скачиваться или собираться пакеты в /gnu/store, которая изначально находится в файловой системе, загрузженной в память.

Далее нужно редактировать файл объявления операционной системы, которым будет пользоваться установщик. Для этого при установке системы можно использовать три текстовых редактора. Мы ркомендуем GNU nano (see GNU nano Manual) — он поддерживает подсветку синтаксиса и работу со скобками. Другие редакторы: GNU Zile (клон Emacs), nvi (клон исходного редактора BSD vi). Мы настойчиво рекомендуем сохранять файл конфигураций в целевой файловой системе root, например, как /mnt/etc/config.scm. Иначе есть возможность потерять конфигурационный файл, когда вы загрузитесь в новую установенную систему.

Смотрите See Использование системы конфигурации для подробностей о конфигурационном файле. Конфигурационный файл для примера доступен под /etc/configuration установочного образа. Например, чтобы получить систему с графическим сервером (т.е. десктопную систему), можно это сделать примерно так:

# mkdir /mnt/etc
# cp /etc/configuration/desktop.scm /mnt/etc/config.scm
# nano /mnt/etc/config.scm

Нужно уделить внимание содержимому конфигурационного файла, в частности:

  • Убедитесь, что bootloader-configuration указывает на тот раздел, в который вы хотите установить GRUB. Он должен содержать grub-bootloader, если вы используете legacy-GRUB, или grub-efi-bootloader для новых систем UEFI. Для систем legacy поле target содержит имя устройства, например, /dev/sda; для систем UEFI он указывает имя раздела EFI, например, /boot/efi. Так что обязательно проверьте, чтобы нужный путь был монтирован, и запись file-system содержала нужную конфигурацию.
  • Убедитесь, чтобы в полях device были указаны метки ваших файловых систем внутри конфигурации file-system, если конечно, конфигурация file-system использует процедуру file-system-label в поле device.
  • При наличии шифрованных разделов RAID, обязательно добавьте поле mapped-devices, чтобы описать их (see Размеченные устройства).

Когда вы подготовили конфигурационный файл, нужно инициализировать новую систему (помните, что целевой раздел root монтирован под /mnt):

guix system init /mnt/etc/config.scm /mnt

Это копирует все нужные файлы и устанавливает GRUB в /dev/sdX, если конечно, вы не задали опцию --no-bootloader. Подробнее - see Invoking guix system. Эта команда может вызывать скачивание или сборку отсутствующих пакетов, что может занять время.

Когда эта команда завершена, надеемся, успешно, можно запустить reboot и загрузиться в новую систему. Пароль root в новой системе изначально пустой; пароли других пользователей должны быть заданы командой passwd от root, если конечно, ваша конфиурация не содержит указания (see user account passwords). Смотрите See После установки системы, чтобы узнать, что дальше!


3.7 После установки системы

Success, you’ve now booted into Guix System! You can upgrade the system whenever you want by running:

guix pull
sudo guix system reconfigure /etc/config.scm

This builds a new system generation with the latest packages and services.

Now, see Начало работы, and join us on #guix on the Libera.Chat IRC network or on guix-devel@gnu.org to share your experience!


3.8 Установка Guix на виртуальную машину (VM)

Если вы хотите установить систему Guix на виртуальную машину (VM) или на виртуальный приватный сервер (VPS) вместо вашей любимой машины, этот раздел для вас.

Чтобы загрузить Guix в QEMU VM и установить образ, выполните шаги:

  1. Во-первых, найдите и распакуйте установочный образ системы Guix, как описано ранее (see Установочная флеш и DVD).
  2. Создайте образ диска, который будет содержать установленную систему. Чтобы создать образ диска qcow2, используйте команду qemu-img:
    qemu-img create -f qcow2 guixsd.img 50G
    

    Результирующий файл будет намного меньше 50Гб (обычно менее 1Мб), но он будет увеличиваться с заполнение виртуального устройства.

  3. Загрузите установочный образ USB в VM:
    qemu-system-x86_64 -m 1024 -smp 1 -enable-kvm \
      -nic user,model=virtio-net-pci -boot menu=on,order=d \
      -drive file=guix-system.img \
      -drive media=cdrom,readonly=on,file=guix-system-install-2a6d964.system.iso
    

    -enable-kvm опционален, но значительно улучшает производительность, see Running Guix in a Virtual Machine.

  4. Теперь вы в корне VM, проделайте процесс установки See Подготовка к установке и последующие инструкции.

Когда установка завершена, можно загрузиться в систему, которая расположена в образе guixsd.img. Смотрите See Running Guix in a Virtual Machine, чтобы узнать, как это сделать.


3.9 Сборка установочного образа

Установочный образ, описанный выше, собран командой guix system, а именно:

guix system disk-image -t iso9660 gnu/system/install.scm

Нужно просмотреть gnu/system/install.scm в дереве исходников, а также Invoking guix system, чтобы получить больше информации об установочном образе.

3.10 Сбрка и установка образа для плат ARM

Многие платы ARM требуют специфический вариант загрузчика U-Boot.

Если вы собираете образ диска, а загрузчик не доступен (на другом устройстве загрузке и т.п.), советуем собрать образ, который включает загрузчик, то есть так:

guix system disk-image --system=armhf-linux -e '((@ (gnu system install) os-with-u-boot) (@ (gnu system install) installation-os) "A20-OLinuXino-Lime2")'

A20-OLinuXino-Lime2 — это имя материнской платы. Если вы обозначите недействительную плату, будет выведен список возможных плат.


4 Начало работы

Предположительно, вы попали в этот раздел, потому что либо вы установили Guix поверх другого дистрибутива (see Установка), либо вы установили отдельную операционную систему Guix (see Установка системы). Пора вам начать использовать Guix, и этот раздел призван помочь вам в этом.

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

guix search text editor

Эта команда показывает количество подходящих пакетов, каждый раз показывая имя пакета, версию, описание и дополнительную информацию. Как только вы определились с тем, какой пакет хотите использовать, скажем, Emacs (ха!), вы можете установить его следующей командой (запустите эту команду как обычный пользователь, root привилегии не нужны!):

guix install emacs

Вы установили свой первый пакет, поздравляю! В процессе вы, вероятно, заметили, что Guix загружает заранее собранные двоичные файлы; или, если вы явно решили не использовать предварительно созданные двоичные файлы, то, вероятно, Guix все еще собирает программное обеспечение (see Подстановки, для дополнительной информации).

Пока вы используете Guix System, guix install команда должна выводить данную подсказку:

hint: Consider setting the necessary environment variables by running:

     GUIX_PROFILE=\"$HOME/.guix-profile\"
     . \"$GUIX_PROFILE/etc/profile\"

Или смотрите `guix package --search-paths -p "$HOME/.guix-profile"'.

Indeed, you must now tell your shell where emacs and other programs installed with Guix are to be found. Pasting the two lines above will do just that: it will add $HOME/.guix-profile/bin—which is where the installed package is—to the PATH environment variable. You can paste these two lines in your shell so they take effect right away, but more importantly you should add them to ~/.bash_profile (or equivalent file if you do not use Bash) so that environment variables are set next time you spawn a shell. You only need to do this once and other search paths environment variables will be taken care of similarly—e.g., if you eventually install python and Python libraries, GUIX_PYTHONPATH will be defined.

Вы можете продолжать установку пакетов по своему желанию. Чтобы вывести список установленных пакетов, запустите:

guix package --list-installed

Для удаления пакета вы можете выполнить команду guix remove. Отличительная черта - возможность откатить любую операцию, которую вы сделали (установка, удаление, обновление):

guix package --roll-back

Каждая операция фактически является транзакцией, которая создает новое поколение. Эти поколения и разницу между ними можно отобразить, запустив:

guix package --list-generations

Теперь вы знаете основы управления пакетами!

Больше информации: See Управление пакетами, для получения дополнительной информации об управлении пакетами. Вам может понравиться декларативное управление пакетами с помощью guix package --manifest, управление отдельными профилями с помощью --profile, удаление старых поколений, сбор мусора и другие полезные функции, которые помогут пригодится по мере того, как вы ближе познакомитесь с Guix. Если вы разработчик, see Разработка для получения дополнительных инструментов. И если вам интересно, see Особенности, чтобы заглянуть под капот.

You can also manage the configuration of your entire home environment—your user “dot files”, services, and packages—using Guix Home. See Home Configuration, to learn more about it!

После того, как вы установили набор пакетов, вам нужно будет периодически обновлять их до последней и самой лучшей версии. Для этого вы сначала загрузите последнюю версию Guix и его коллекцию пакетов:

guix pull

Конечным результатом является новая команда guix в ~/.config/guix/current/bin. Если вы не используете Guix System, при первом запуске guix pull обязательно следуйте подсказке, которую выводит команда, и, подобно тому, что мы видели выше, вставьте эти две строки в свой терминал и .bash_profile:

GUIX_PROFILE="$HOME/.config/guix/current/etc/profile"
. "$GUIX_PROFILE/etc/profile"

Вы также должны указать своей оболочке, чтобы она указывала на новую команду guix:

hash guix

На данный момент вы используете новый Guix. Вы можете обновить все ранее установленные пакеты:

guix upgrade

Когда вы запустите эту команду, вы увидите, что загружены двоичные файлы (или, возможно, собраны некоторые пакеты), и в конечном итоге вы получите обновленные пакеты. Если один из этих обновленных пакетов вам не понравится, помните, что вы всегда можете выполнить откат!

Вы можете отобразить точную версию Guix, которую сейчас используете, запустив:

guix describe

Отображаемая информация - это все, что нужно для воспроизведения того же самого Guix, будь то в другой момент времени или на другой машине.

Больше информации: See Вызов guix pull, для дополнительной информации. See Каналы, как указать дополнительные каналы для получения пакетов, как реплицировать Guix и т. д. Также команда time-machine может оказаться полезной (see Запуск guix time-machine).

Если вы установили Guix System, первое, что вам нужно сделать, это обновить вашу систему. После того, как вы запустите команду guix pull, чтобы получить последнюю версию Guix, вы можете обновить систему следующим образом:

sudo guix system reconfigure /etc/config.scm

Upon completion, the system runs the latest versions of its software packages. Just like for packages, you can always roll back to a previous generation of the whole system. See Начало работы, to learn how to manage your system.

Теперь вы знаете достаточно, чтобы начать!

Ресурсы: Остальная часть этого руководства представляет собой справочник по всему, что связано с Guix. Вот несколько дополнительных ресурсов, которые могут вам пригодиться:

  • See The GNU Guix Cookbook, статьи с готовыми решениями для различных ситуаций в стиле “how-to”.
  • GNU Guix Reference Card шпаргалка с большинством команд и опций, которые вам когда-либо понадобятся.
  • Веб-сайт содержит обучающие видеоролики по таким темам, как повседневное использование Guix, как получить помощь и как стать участником сообщества.
  • See Документация, чтобы узнать, как получить доступ к документации на вашем компьютере.

Мы надеемся, что вам понравится Guix так же, как и сообществу нравится его создавать!


5 Управление пакетами

Целью GNU Guix является предоставление пользователям возможности легко устанавливать, обновлять и удалять пакеты программного обеспечения, без необходимости изучения процедур их сборки и без необходимости разрешения зависимостей. Также Guix имеет следующие обязательные особенности.

Этот раздел описывает основные особенности Guix и предоставляемые им инструменты управления пакетами. Кроме интерфейса командной строки, который описан ниже (see guix package), можно также использовать интерфейс Emacs-Guix (see The Emacs-Guix Reference Manual), если установить пакет emacs-guix (выполните команду M-x guix-help, чтобы начать работу с ним):

guix install emacs-guix

5.1 Особенности

Здесь мы предполагаем, что вы уже сделали свои первые шаги с Guix (see Начало работы) и хотели бы получить обзор того, что происходит под капотом.

При использовании Guix каждый пакет после установки размещается в package store, в собственной директории, например, /gnu/store/xxx-package-1.2, где xxx - это строка base32.

Вместо того, чтобы ссылаться на эти директории, пользователям нужно обращаться к их профилям, профиль указывает на пакеты, которые они хотят использовать. Эти профили хранятся в домашней директории каждого пользователя в $HOME/.guix-profile.

Например, alice устанавливает GCC 4.7.2. В результате /home/alice/.guix-profile/bin/gcc указывает на /gnu/store/…-gcc-4.7.2/bin/gcc. Допустим, на той же машине bob установил GCC 4.8.0. Профиль пользователя bob просто указывает на /gnu/store/…-gcc-4.8.0/bin/gcc. То есть обе версии GCC присутствуют в одной системе без помех.

Команда guix package — главный инструмент для управления пакетами (see Вызов guix package). Она работает с профилями пользователей, которые имеют права обычных пользователей.

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

In addition, any package transaction may be rolled back. So, if, for example, an upgrade installs a new version of a package that turns out to have a serious bug, users may roll back to the previous instance of their profile, which was known to work well. Similarly, the global system configuration on Guix is subject to transactional upgrades and roll-back (see Начало работы).

Все пакеты на складе могут быть собраны как мусор. Guix может определить, какие пакеты всё ещё используются профилями пользователей, и удалить те, которые однозначно больше не используются (see Вызов guix gc). Также пользователи могут явно удалить старые поколения (generations) их профилей, поэтому пакеты, на которые ссылались старые профили, могут быть удалены.

Guix реализует чисто функциональный подход к управлению пакетами, как описано во введении (see Введение). В /gnu/store имя директории каждого пакета содержит хеш всех входных данных, которые использовались при сборке пакета: компилятор, библиотеки, скрипты сборки и т.д. Это прямое соответствие позволяет пользователям убедиться, что данная установка пакета соответствует текущему состоянию дистрибутива. Также это помогает улучшить воспроизводимость сборки: благодаря изолированному окружению сборки, которая используется при установке пакета, результат сборки содержит точно такие же файлы на разных машинах (see container).

Эта концепция позволяет Guix поддерживать прозрачное внедрение бинарников/исходников. Когда доступен элемент /gnu/store, собранный заранее на внешнем источнике, то есть готова подстановка, Guix просто скачивает и распаковывает его. В противном случае он собирает пакет из исходников на локальной машине (see Подстановки). Так как результаты сборки обычно воспроизводимы бит-к-биту, пользователи не должны доверять серверам, которые поставляют подстановки — они могут целенаправленно запросить локальную сборку и не пользоваться серверами подстановки (see Вызов guix challenge).

Control over the build environment is a feature that is also useful for developers. The guix shell command allows developers of a package to quickly set up the right development environment for their package, without having to manually install the dependencies of the package into their profile (see Вызов guix shell).

Guix и его определения пакетов подчняются контролю версиями, и guix pull позволяет "путешествовать во времени" по истории Guix (see Вызов guix pull). Это позволяет повторять инстанцию Guix на разных машинах или по прошествию времени, что в свою очередь позволяет вам повторять полностью программное окружение из достпуных трекеров источников программного обеспечения.


5.2 Вызов guix package

Команда guix package — инструмент, который позволяет пользователям устанавливать, обновлять и удалять пакеты, а также откатываться до предыдущих конфигураций (see Особенности). Его синтаксис:

guix package options

В первую очередь, options (опции) задают операции, которые нужно выполнить в транзакции. По завершении создаётся новый профиль, а предыдущие поколения (generations) профиля остаются доступными, если пользователь решит откатиться.

Например, чтобы удалить lua и устанвоить guile и guile-cairo в одной транзакции, напечатайте:

guix package -r lua -i guile guile-cairo

Для вашего удобства мы также предоставляем следующие синонимы:

  • guix search - синоним guix package -s,
  • guix install - синоним guix package -i,
  • guix remove - синоним guix package -r,
  • guix upgrade — это синоним guix package -u,
  • и guix show псевдоним (alias) для guix package --show=.

Эти синонимы не такие мощные, как guix package, и предоставляют меньше опций, так что в некоторых случаях вам скорее нужно пользоваться непосредственно guix package.

guix package также поддерживает декларативный подход, с помощью которого пользователь зааёт точный набор пакетов, которые должны быть доступны, и передаёт его в опции --manifest (see --manifest).

Для каждого пользователя автоматически создаётся символическая ссылка на профиль по умолчанию, она располагается в файле $HOME/.guix-profile. Эта ссылка всегда указывает на текущее поколение пользовательского профиля по умолчанию. Так пользователи могут добавить $HOME/.guix-profile/bin в свою переменную окружения PATH и прочее. Если вы не используете систему Guix, предполагается добавление следующих строк в ваш ~/.bash_profile (see Bash Startup Files in The GNU Bash Reference Manual), чтобы порождаемые оболочки получили все необходимые определения переменных окружения:

GUIX_PROFILE="$HOME/.guix-profile" ; \
source "$GUIX_PROFILE/etc/profile"

В случае многопользовательской установки, профили пользователей сохраняются в месте, которое зарегстрировано как garbage-collector root, которое указывет на $HOME/.guix-profile (see Вызов guix gc). Эта директория обычно ссылается на localstatedir/guix/profiles/per-user/user, где localstatedir — значение, переданное скрипту configure опцией --localstatedir, а user — имя пользователя. Директория per-user создаёся, когда запускается guix-daemon, а поддиректория user создаётся guix package.

Опции options могут быть следующими:

--install=package
-i package

Установить заданный пакет.

Each package may specify a simple package name, such as guile, optionally followed by an at-sign and version number, such as guile@3.0.7 or simply guile@3.0. In the latter case, the newest version prefixed by 3.0 is selected.

If no version number is specified, the newest available version will be selected. In addition, such a package specification may contain a colon, followed by the name of one of the outputs of the package, as in gcc:doc or binutils@2.22:lib (see Пакеты со множественным выходом).

Packages with a corresponding name (and optionally version) are searched for among the GNU distribution modules (see Пакетные модули).

Alternatively, a package can directly specify a store file name such as /gnu/store/...-guile-3.0.7, as produced by, e.g., guix build.

Иногда пакеты имеют распространённые входные данные (propagated inputs) — это зависимости, которые устанавливаются автоматически вместе с требуемыми пакетами (см. see propagated-inputs in package objects для подробной информации о распространяемых входных днных в определениях пакетов).

Примером является библиотека GNU MPC: его файлы заголовков C ссылаются на файлы библиотеки GNU MPFR, которые в свою очередь, ссылаются на библиотеку GMP. Так при установке MPC, также в профиль будут устанволены библиотеки MPFR и GMP; удаление MPC также удалит MPFR и GMP, если конечно, они не были явно установлены пользователем.

Кроме того, пакеты иногда зависят от переменных окружения — от их путей поиска (смотрите разъяснение --search-paths ниже). Любая отсутствующая или, возможно, некорректная переменная окружения вызывает сообщение отчета.

--install-from-expression=exp
-e exp

Устанавить пакет, соответствующий exp.

exp must be a Scheme expression that evaluates to a <package> object. This option is notably useful to disambiguate between same-named variants of a package, with expressions such as (@ (gnu packages commencement) guile-final).

Отметим, что эта опция устанавливает первое содержимое пакета, чего может быть недостаточно, если нужен специфичный выход пакета со множественным выходом.

--install-from-file=file
-f file

Устанавить пакет, который определён в файле.

Например, file может содержать определение (see Описание пакетов):

(use-modules (guix)
             (guix build-system gnu)
             (guix licenses))

(package
  (name "hello")
  (version "2.10")
  (source (origin
            (method url-fetch)
            (uri (string-append "mirror://gnu/hello/hello-" version
                                ".tar.gz"))
            (sha256
             (base32
              "0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i"))))
  (build-system gnu-build-system)
  (synopsis "Hello, GNU world: An example GNU package")
  (description "Guess what GNU Hello prints!")
  (home-page "http://www.gnu.org/software/hello/")
  (license gpl3+))

Developers may find it useful to include such a guix.scm file in the root of their project source tree that can be used to test development snapshots and create reproducible development environments (see Вызов guix shell).

file может также содержать JSON-представление одного или нескольких определений пакетов. Запуск guix package -f на файле hello.json со следующим содержимым, установит пакет greeter после сборки myhello:

(use-modules (guix)
             (gnu packages gdb)
             (gnu packages autotools)
             (gnu packages texinfo))

;; Augment the package definition of GDB with the build tools
;; needed when developing GDB (and which are not needed when
;; simply installing it.)
(package
  (inherit gdb)
  (native-inputs (modify-inputs (package-native-inputs gdb)
                   (prepend autoconf-2.69 automake texinfo))))
--remove=package
-r package

Удалить обозначенный пакет.

Касаемо --install, каждый пакет package может задавать номер версии и имя содержимого в добавлении к имени пакета. Например, -r glibc:debug удалит содержимое debug из glibc.

--upgrade[=regexp …]
-u [regexp …]

Обновить все устанволенные пакеты. Если задано одно или более значений regexp, обновление затронет только пакеты, которые соответствуют regexp. Также смотрите опцию --do-not-upgrade ниже.

Отметим, что это обновляет пакеты, которые установлены в системе, до последних версий, имеющихся в дистрибутиве. Чтобы обновить дистрибутив, нужно регулярно запускать guix pull (see Вызов guix pull).

При обновлении автоматически применяются преобразования пакета, которые были первоначально применены при создании профиля (see Параметры преобразования пакета). Например, предположим, что вы сначала установили Emacs из ветки разработки с помощью:

guix install emacs-next --with-branch=emacs-next=master

В следующий раз, когда вы запустите guix upgrade, Guix снова посмотрит на ветку разработки Emacs и соберет новый emacs-next.

Обратите внимание, что параметры преобразования, такие как --with-branch и --with-source, зависят от внешнего состояния; вам решать, чтобы они работали должным образом. Вы также можете отменить преобразования, которые применяются к пакету, запустив:

guix install package
--do-not-upgrade[=regexp …]

При совместном использовании с опцией --upgrade не обновляет ни один пакет, чьё имя соответствует regexp. Например, обновить все пакеты в текущем профиле , кроме тех, которые содержат подстроку "emacs":

$ guix package --upgrade . --do-not-upgrade emacs
--manifest=file
-m file

Создаёт новую версию профиля из объекта манифеста, возвращаемого кодом Scheme в file. Этот параметр можно указывать несколько раз. В результате манифесты будут объединены в один.

Это позволяет вам описать содержимое профиля вместо того, чтобы собирать его последовательностью команд --install и других. Преимущество в том, что file может подчиняться контролю версиями, копироваться на другие машины, чтобы повторить такой же профиль и т.д.

file должен возвращать объект manifest, который, грубо говоря, является списком пакетов:

(use-package-modules guile emacs)

(packages->manifest
 (list emacs
       guile-2.0
       ;; Use a specific package output.
       (list guile-2.0 "debug")))

See Writing Manifests, for information on how to write a manifest. See --export-manifest, to learn how to obtain a manifest file from an existing profile.

--roll-back

Откатиться до предыдущего поколения профиля, то есть отменить последнюю транзакцию.

При сочетании с опциеями как --install, откат выполняется до всех прочих действий.

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

После выполнения отката, установка, удаление или обновление пакетов по факту заменяет прежние будущие поколения. То есть история поколений в профиле всегда линейная.

--switch-generation=pattern
-S pattern

Переключиться на определённое поколение, опрделённое pattern.

pattern может быть либо номером поколения или числом с префиксом "+" или "-". Последнее означает сменить вперёд/назад на обозначенное число поколений. Например, если вы хотите вернуться к последнему поколению после --roll-back, используйте --switch-generation=+1.

Разница между --roll-back и --switch-generation=-1 заключается в том, что --switch-generation не создаёт нулевое поколение, так что если заданное поколение не существует, текущее поколение не будет изменено.

--search-paths[=kind]

Вывести отчёт об определениях переменных окружения в синтаксисе Bash. Это может понадобиться для использования набора установленных пакетов. Эти переменные окружения используются некоторыми установленными пакетами для поиска файлов.

For example, GCC needs the CPATH and LIBRARY_PATH environment variables to be defined so it can look for headers and libraries in the user’s profile (see Environment Variables in Using the GNU Compiler Collection (GCC)). If GCC and, say, the C library are installed in the profile, then --search-paths will suggest setting these variables to profile/include and profile/lib, respectively (see Search Paths, for info on search path specifications associated with packages.)

Обычный способ определить эти переменные окружения в оболочке:

$ eval $(guix package --search-paths)

Вид kind может быть либо точный адрес exact, либо префикс prefix, либо суффикс suffix, то есть возвращаемые переменные окружения могут быть либо точными, либо префиксами и суффиксами текущего значения этих переменных. При пропуске вид kind по умолчанию выбирается точный exact.

Эта опция также может использоваться для вычисления комбинированных путей поиска нескольких профилей. Рассмотрим пример:

$ guix package -p foo -i guile
$ guix package -p bar -i guile-json
$ guix package -p foo -p bar --search-paths

Последняя команда выше составляет отчёт о переменной GUILE_LOAD_PATH, даже если по отдельности ни foo, ни bar не предшествуют рекомендациям.

--profile=profile
-p profile

Использовать profile вместо пользовательского профиля по умолчанию.

profile должен быть именем файла, который будет создан по завершении. Конкретно profile будет простой символической ссылкой (“символическая ссылка”), указывающей на текущий профиль, в котором установлены пакеты:

$ guix install hello -p ~/code/my-profile
…
$ ~/code/my-profile/bin/hello
Hello, world!

Чтобы избавиться от профиля, нужно удалить символическую ссылку и привязанные к ней элементы, которые указывают на конкретные поколения:

$ rm ~/code/my-profile ~/code/my-profile-*-link
--list-profiles

Перечислить все профили пользователя:

$ guix package --list-profiles
/home/charlie/.guix-profile
/home/charlie/code/my-profile
/home/charlie/code/devel-profile
/home/charlie/tmp/test

При запуске от имени root будут перечислены все профили всех пользователей.

--allow-collisions

Разрешить соперничающие пакеты в новом профиле. Используйте на свой собственный страх и риск!

По умолчанию guix package делает отчёт о противоречиях collisions в профиле. Противоречия происходят, когда дви или более разных версии или варианта данного пакета присутсвуют в профиле.

--bootstrap

Использовать бутстрап Guile для сборки профиля. Эта опция полезна только разработчикам дистрибутива.

В дополнение к этим действиям guix package поддерживает следующие опции при обращении к текущему состоянию профиля или для проверки доступности пакетов:

--search=regexp
-s regexp

Вывести список пакетов, чьи имена или описания содержат выражение regexp с учётом регистра, упорядоченные по соответствию. Печать всех метаданных соответствующих пакетов в формате recutils (see GNU recutils databases in GNU recutils manual).

Это позволяет извлекать заданые поля, используя команду recsel, например:

$ guix package -s malloc | recsel -p name,version,relevance
name: jemalloc
version: 4.5.0
relevance: 6

name: glibc
version: 2.25
relevance: 1

name: libgc
version: 7.6.0
relevance: 1

Также для отображения имён всех доступных пакетов под лицензией GNU LGPL версии 3:

$ guix package -s "" | recsel -p name -e 'license ~ "LGPL 3"'
name: elfutils

name: gmp
…

Также можно уточнить поиск, используя несколько флагов -s в команде guix package или несколько аргументов в guix search. Например, следующая команда возвращает список настольных игр (используя синоним guix search на этот раз):

$ guix search '\<board\>' game | recsel -p name
name: gnubg
…

При пропуске -s game мы получим пакеты программного обеспечения, которые работают с печатными платами (boards); удалив угловые скобки рядом с board, получим пакеты, которые также работают с клавиатурами (keyboards).

А теперь более запутанный пример. Следующая команда ищет библиотеки криптографии, фильтрует библиотеки Haskel, Perl, Python и Ruby и печатает имена и краткие описания найденных пакетов:

$ guix search crypto library | \
    recsel -e '! (name ~ "^(ghc|perl|python|ruby)")' -p name,synopsis

См. See Selection Expressions in GNU recutils manual для подробной информации о регуларяных выражениях selection expressions для recsel -e.

--show=package

Показать детали пакета package из списка доступных пакетов в формате recutils (see GNU recutils databases in GNU recutils manual).

$ guix package --show=guile | recsel -p name,version
name: guile
version: 3.0.5

name: guile
version: 3.0.2

name: guile
version: 2.2.7
…

Можно также указать полное имя пакета, чтобы только получить детали его определённой версии (в этот раз, используя guix show псевдоним):

$ guix show guile@3.0.5 | recsel -p name,version
name: guile
version: 3.0.5
--list-installed[=regexp]
-I [regexp]

Вывести текущий список установленных пакетов в заданном профиле, отобразив самый последний установленный пакет последним. Если задано regexp, будут выведены только пакеты, чьи имена содержат regexp.

Для каждого установленного пакета выводит следующие элементы, разделенные табуляцией (tab): имя пакета, строка версии, частью какого пакета является установленный пакет (например, out вывода по умолчанию включает include его заголовки т.д.), а также путь этого пакета на складе.

--list-available[=regexp]
-A [regexp]

Вывести список пакетов, доступных на текущий момент в дистрибутиве данной системы (see Дистрибутив GNU). Если задано regexp, выводит только установленные пакеты, чьё имя содержит regexp.

Для каждого пакета выводит следующие элементы, разделённые табуляцией: его имя, строка версии, часть пакета (see Пакеты со множественным выходом), а также расположение его определения в исходниках.

--list-generations[=pattern]
-l [pattern]

Вывести список поколений (generations) с датами их создания; для каждого поколения отобразить установленные пакеты, самый последний установленный пакет отобразать последним. Отметим, что нулевое поколение никогда не показывается.

Для каждого установленного пакета отображает следующие элементы, разделённые табуляцией: имя пакета, строка версии, частью какого пакета является установленный пакет (see Пакеты со множественным выходом), а также расположение пакета на складе.

Если используется pattern, команда выводит только соответствующие поколения. Правильные паттерны содержат:

  • Числа и числа, разделённые запятыми. Оба паттерна обозначают номера поколений. Например, --list-generations=1 возвращает первое.

    Опция --list-generations=1,8,2 выводит три поколения в заданном пордке. Пробелы и запятые на конце запрещены.

  • Ranges. --list-generations=2..9 выводит заданные поколения и все между ними. Отметим, что начало диапазона должно быть меньше его конца.

    Также можно пропустить конечную точку. Например, --list-generations=2.. возвращает все поколения, начиная со второго.

  • Сроки. Также можно задать последние N дней, недель или месяцев, указав число и первую букву срока (d,w,m). Например, --list-generations=20d отобразит список поколений старше 20 дней.
--delete-generations[=pattern]
-d [pattern]

Если pattern пропущен, удалит все поголения, кроме текущего.

Эта команда принимает такие же паттерны, как --list-generations. Если pattern задан, удалит соответствующие поколения. Если паттерн pattern задаёт срок, выбираются поколения старше срока. Например, --delete-generations=1m удалит поколения, которые старше одного месяца.

Если текущее поколение попадает под условия паттерна, оно не будет удалено. А также нулевое поокление никогда не удаляется.

Отметим, что удаление поколений делает невозможным откат к ним. Следовательно эта команда должна использоваться внимательно.

--export-manifest

Напишите в стандартный вывод манифест, подходящий для --manifest, соответствующий выбранному профилю (-ам).

Эта опция предназначена для того, чтобы помочь вам перейти из “императивного” режима работы—запустив guix install, guix upgrade и т.д.—в декларативный режим, который предлагает --manifest.

Имейте в виду, что полученный манифест приблизительно соответствует тому, что на самом деле содержится в вашем профиле; например, в зависимости от того, как был создан ваш профиль, он может относиться к пакетам или версиям пакетов, которые не совсем то, что вы указали.

Имейте в виду, что манифест является чисто символическим: он содержит только имена пакетов и, возможно, версии, и их значение со временем меняется. Если вы хотите “привязать” каналы к ревизиям, которые использовались для создания профиля (ов), см. --export-channels ниже.

%default-channels

Вывести на стандартный вывод список каналов, используемых выбранным профилем (-ями), в формате, подходящем для guix pull --channels или guix time-machine --channels (see Каналы).

Вместе с --export-manifest этот параметр предоставляет информацию, позволяющую копировать текущий профиль (see Копирование Guix).

Однако обратите внимание, что выходные данные этой команды приблизительно используются для создания этого профиля. В частности, один профиль мог быть построен из нескольких различных версий одного и того же канала. В этом случае --export-manifest выбирает последнюю версию и записывает список других ревизий в комментарий. Если вам действительно нужно выбрать пакеты из разных ревизий канала, вы можете использовать подчиненные элементы в своем манифесте для этого (see Младшие версии).

Если вы хотите перейти от “императивной” модели к полностью декларативной модели, состоящей из файла манифеста и файла каналов, закрепляющего точную желаемые версии каналов, то --export-manifest хорошая отправная точка.

Наконец, так как guix package может запускать процессы сборки, она поддерживает все привычные опции сборки (see Стандартные параметры сборки). Она также поддерживает опции трансформации пакетов, как --with-source (see Параметры преобразования пакета). Однако, отметим, что трансформации пакетов теряются после обновлений; чтобы сохранить трансформации при обновлениях, нужно определить собственный вариант пакета в модуле Guile и добавить его в GUIX_PACKAGE_PATH (see Описание пакетов).


5.3 Подстановки

Guix поддерживает прозрачное развертывание исходников/бинарников, это означает, что он может либо собирать что-то локально, либо загружать предварительно собранные элементы с сервера, либо и то, и другое. Мы называем эти готовые элементы подстановками (substitutes) — они заменяют результаты локальной сборки. Во многих случаях загрузка подстановки намного быстрее, чем сборка пакетов локально.

В качестве подстановок может выступать какой угодно результат сборки деривации (see Деривации). Конечно, обычно это собранные пакеты, но также архивы исходников, например, представляя собой результаты сборок дериваций, могут быть доступны в качестве подстановок.


5.3.1 Official Substitute Servers

bordeaux.guix.gnu.org и ci.guix.gnu.org - это интерфейсы для официальных сборочных ферм, которые постоянно собирают пакеты из Guix для некоторых архитектур и делают их доступными в качестве подстановок. Это источники подстановок по умолчанию; их можно переопределить, передав опцию --substitute-urls либо в guix-daemon (see guix-daemon --substitute-urls), либо в клиентские инструменты, такие как guix package (see client --substitute-urls option).

URL подстановок могут быть либо HTTP, либо HTTPS. Рекомендуется HTTPS, так как такая связь шифруется; и наоборот, использование HTTP делает связь видимой для подслушивающих, и они могут использовать собранную информацию, чтобы определить, например, что ваша система не имеет патчей, покрывающих уязвимости безопасности.

Подстановки из официальных сборочных ферм доступны по умолчанию при использовании Guix System (see Дистрибутив GNU). Однако они отключены по умолчанию при использовании Guix на стороннем дистрибутиве, если вы явно не включили их с помощью одного из рекомендуемых шагов установки (see Установка). В следующих параграфах описано, как включить или отключить подстановки для официальной сборочной фермы; эта же процедура может быть использована для включения подстановок с любого другого сервера подстановок.


5.3.2 Авторизация сервера подстановок

Чтобы разрешить Guix скачать подстановки с bordeaux.guix.gnu.org, ci.guix.gnu.org или зеркала, вы должны добавить соответствующий открытый ключ в список контроля доступа (ACL) импорта архивов с помощью команды guix archive (see Вызов guix archive). Это подразумевает, что вы доверяете серверу подстановок в том, что он не взломан и предоставляет подлинные подстановки.

Примечание: If you are using Guix System, you can skip this section: Guix System authorizes substitutes from bordeaux.guix.gnu.org and ci.guix.gnu.org by default.

Открытые ключи для каждого из поддерживаемых проектом серверов подстановок устанавливаются вместе с Guix в prefix/share/guix/, где prefix - префикс установки Guix. Если вы установили Guix из исходного кода, убедитесь, что проверили GPG-подпись файла guix-2a6d964.tar.gz, который содержит этот файл открытых ключей. Затем вы можете запустить что-то вроде этого:

# guix archive --authorize < prefix/share/guix/bordeaux.guix.gnu.org.pub
# guix archive --authorize < prefix/share/guix/ci.guix.gnu.org.pub

Когда это сделано, вывод команды guix build должен измениться с примерно такого:

$ guix build emacs --dry-run
The following derivations would be built:
   /gnu/store/yr7bnx8xwcayd6j95r2clmkdl1qh688w-emacs-24.3.drv
   /gnu/store/x8qsh1hlhgjx6cwsjyvybnfv2i37z23w-dbus-1.6.4.tar.gz.drv
   /gnu/store/1ixwp12fl950d15h2cj11c73733jay0z-alsa-lib-1.0.27.1.tar.bz2.drv
   /gnu/store/nlma1pw0p603fpfiqy7kn4zm105r5dmw-util-linux-2.21.drv
…

на примерно следующий:

$ guix build emacs --dry-run
112.3 MB would be downloaded:
   /gnu/store/pk3n22lbq6ydamyymqkkz7i69wiwjiwi-emacs-24.3
   /gnu/store/2ygn4ncnhrpr61rssa6z0d9x22si0va3-libjpeg-8d
   /gnu/store/71yz6lgx4dazma9dwn2mcjxaah9w77jq-cairo-1.12.16
   /gnu/store/7zdhgp0n1518lvfn8mb96sxqfmvqrl7v-libxrender-0.9.7
…

Текст изменился с “The following derivations would be built" на “112.3 MB would be downloaded". Это указывает на то, что подстановки с настроенных серверов подстановок пригодны для использования и будут загружены для будущих сборок, когда это станет возможно.

Механизм подстановок может быть отключен глобально путём запуска guix-daemon с --no-substitutes (see Вызов guix-daemon). Также он может отключиться временно путём указания опции --no-substitutes в guix package, guix build и других инструментах командной строки.


5.3.3 Получение заменителей с других серверов

Guix может искать и получать заменители с нескольких серверов. Это полезно, когда вы используете пакеты из дополнительных каналов, для которых официальный сервер не имеет заменителей, но их предоставляет другой сервер. Еще одна ситуация, когда это полезно, если вы предпочитаете выполнять загрузку с замещающего сервера вашей организации, прибегая к официальному серверу только в качестве запасного варианта или полностью отклоняя его.

Вы можете дать Guix список URL-адресов серверов с заменителями, и он проверит их в указанном порядке. Вам также необходимо явно авторизовать открытые ключи серверов с заменителями, чтобы Guix принял заменители, которые они подписывают.

В системе Guix это достигается путем изменения конфигурации службы guix. Поскольку служба guix является частью списков служб по умолчанию, %base-services и %desktop-services, вы можете использовать modify-services для изменения ее конфигурации и добавьте нужные URL-адреса и заменить ключи (see modify-services).

В качестве примера предположим, что вы хотите получить заменители из guix.example.org и авторизовать ключ этого сервера в дополнение к bordeaux.guix.gnu.org и ci.guix.gnu.org. Полученная конфигурация операционной системы будет выглядеть примерно так:

(operating-system
  ;; …
  (services
    ;; Assume we're starting from '%desktop-services'.  Replace it
    ;; with the list of services you're actually using.
    (modify-services %desktop-services
      (guix-service-type config =>
                        (guix-configuration
                          (inherit config)
                          (substitute-urls
                            (append (list "https://guix.example.org")
                                    %default-substitute-urls))
                          (authorized-keys
                            (append (list (local-file "./key.pub"))
                                    %default-authorized-guix-keys)))))))

Предполагается, что файл key.pub содержит ключ подписи guix.example.org. После внесения этого изменения в файл конфигурации вашей операционной системы (например, /etc/config.scm) вы можете перенастроить и перезапустить службу guix-daemon или перезагрузиться, чтобы изменения вступили в силу:

$ sudo guix system reconfigure /etc/config.scm
$ sudo herd restart guix-daemon

Если вы используете Guix в качестве пакетного менеджера на другом дистрибутиве, вместо вышеописанного вы должны предпринять следующие шаги, чтобы получить заменители с дополнительных серверов:

  1. Отредактируйте файл конфигурации службы для guix-daemon; когда исользуете systemd, это обычно /etc/systemd/system/guix-daemon.service. Добавьте параметр --substitute-urls команды guix-daemon при вызове в командной строке и перечислите интересующие URL-адреса (see guix-daemon --substitute-urls):
    … --substitute-urls='https://guix.example.org https://bordeaux.guix.gnu.org https://ci.guix.gnu.org'
    
  2. Перезапустите демон. Пример для systemd:
    systemctl daemon-reload
    systemctl restart guix-daemon.service
    
  3. Авторизуйте ключ нового сервера (see Вызов guix archive):
    # guix archive --authorize < master-public-key.txt
    

    Опять же, это предполагает key.pub, содержащий открытый ключ, который guix.example.org использует для подписи замененителей.

Now you’re all set! Substitutes will be preferably taken from https://guix.example.org, using bordeaux.guix.gnu.org then ci.guix.gnu.org as fallback options. Of course you can list as many substitute servers as you like, with the caveat that substitute lookup can be slowed down if too many servers need to be contacted.

Troubleshooting: To diagnose problems, you can run guix weather. For example, running:

guix weather coreutils

not only tells you which of the currently-configured servers has substitutes for the coreutils package, it also reports whether one of these servers is unauthorized. See Вызов guix weather, for more information.

Обратите внимание, что бывают также ситуации, когда можно добавить URL-адрес замещающего сервера без авторизации его ключа. See Аутентификация подстановок, чтобы понять этот тонкий момент.


5.3.4 Аутентификация подстановок

Guix определяет и вызывает ошибку, если происходит попытка использовать поддельную подстановку. А также он игнорирует подстановки, которые не подписаны, или те, которые не подписаны ни одним ключом из списка ACL.

Но всё же есть одно исключение: если не авторизованный сервер предоставляет подстановки, которые являются идентичными бит-к-биту с теми, которые предоставляет авторизованный сервер, тогда неавторизованный сервер становится приемлемым для скачивания. Например, положим, мы выбрали два сервера подстановок такой опцией:

--substitute-urls="https://a.example.org https://b.example.org"

Если ACL содержит только ключ для b.example.org, и если вдруг a.example.org предоставляет идентичные подстановки, тогда Guix будет скачивать подстановки из a.example.org, потому что он идёт первым в списке и может рассматриваться как зеркало b.example.org. На практике независимые машины сборки обычно производят одинаковые бинарники благодаря воспроизводимым сборкам (смотрите ниже).

При использовании HTTPS, сертификат X.509 сервера не проверяется (другими словами, сервер не проходит аутентификацию), супротив тому, что HTTPS-клиенты, как веб-браузеры, обычно делают это. Это потому, что Guix аутентифицирует саму информацию подстановки, как это описано выше, что собственно и представляет для нас интерес (в то время, как сертификаты X.509 относятся к аутентификации связок между доменными именами и публичными ключами).


5.3.5 Настройки proxy

Подстановки скачиваются через HTTP или HTTPS. Можно установить переменную окружения http_proxy в окружении guix-daemon, чтобы она учитывалась при скачивании. Отметим, что значение http_proxy в окружении, в котором запускаются guix build, guix package и другие клиентские команды совершенно не даёт эффекта.


5.3.6 Ошибки при подстановке

Даже когда подстановка для деривации доступна, иногда попытка подстановки завершается неудачно. Это может происходить по разным причинам: сервер подстановок может быть отключен, подстановка могла быть недавно удалена, связь может прерываться и т.д.

Когда подстановки включены, и подстановка для деривации доступна, но попытка подстановки завершается с ошибкой, Guix будет пытаться собрать деривацию локально в зависимости от того, задана или нет опция --fallback (see common build option --fallback). То есть, если --fallback пропущена, тогда локальная сборка не будет выполняться, а деривация будет рассматриваться как неудачная. Однако, если --fallback задана, тогда Guix попытается собрать деривацию локально, и успех или неудача деривации будет зависеть от успешной или неудачной процедуры локальной сборки. Отметим, что когда подстановки отключены или нет доступных подстановок для деривации, локальная сборка всегда будет исполняться, вне зависимости от установки опции --fallback.

Чтобы узнать,. сколько подстановок доступны в данный момент, можно попробовать запустить команду guix weather (see Вызов guix weather). Эта команда предоставляет статистику подстановок, предоставляемых сервером.


5.3.7 Касательно проверенных бинарников

Today, each individual’s control over their own computing is at the mercy of institutions, corporations, and groups with enough power and determination to subvert the computing infrastructure and exploit its weaknesses. While using substitutes can be convenient, we encourage users to also build on their own, or even run their own build farm, such that the project run substitute servers are less of an interesting target. One way to help is by publishing the software you build using guix publish so that others have one more choice of server to download substitutes from (see Вызов guix publish).

Guix определяет цель максимизировать воспроизводимость сборок (see Особенности). В большинстве случаев независимые сборки заданного пакета или деривации должны давать результаты, идентичные до бита. То есть, благодаря ряду независимых сборок пакета мы можем улучшить чистоту наших систем. Команда guix challenge должна помочь пользователям оценить серверы подстановок, а разработчикам - помочь выявить недетерминистические сборки пакетов (see Вызов guix challenge). Подобным образом опция --check команды guix build даёт возможность пользователям проверить, яляются ли установленные ранее подстановки подлинными, выполнив их локальную сборку (see guix build --check).

Мы хотим, чтобы Guix в будущем поддерживал публикации и запросы бинарников от/для пользователей в формате равноправного обмена (peer-to-peer). Если вы желаете обсудить этот проект, присоединяйтесь к нам guix-devel@gnu.org.


5.4 Пакеты со множественным выходом

Часто пакеты, определённые в Guix, имеют один выход, это значит, что исходный пакет даёт только одну директорию на складе. При запуске guix package -i glibc это устанавливает результат по умолчанию; результат по умолчанию называется выходом, но его имя может пропускаться, как показано в этой команде. В этом частном случае результат по умолчанию для glibc содержит все файлы заголовков C, разделяемые библиотеки, статические библиотеки, документацию Info и другие поставляемые файлы.

Часто более приемлемым будет разделить различные типы файлов, поставляемых одним исходным пакетом, на отдельные выходы (результаты). Например, библиотека GLib C, используемая GTK+ и связанными с ним пакетами, устанавливает более 20Мб связанной документации в виде страниц HTML. Чтобы экономить место, пользователи, которым это не нужно, документацию можно выделить в отдельный выход, называемый doc. Чтобы установить основной выход GLib, который содерит всё, кроме документации, можно запустить:

guix install glib

Команда для установки её документации:

guix install glib:doc

While the colon syntax works for command-line specification of package outputs, it will not work when using a package variable in Scheme code. For example, to add the documentation of glib to the globally installed packages of an operating-system (see operating-system Reference), a list of two items, the first one being the package variable and the second one the name of the output to select (a string), must be used instead:

(use-modules (gnu packages glib))
;; glib-with-documentation is the Guile symbol for the glib package
(operating-system
 ...
 (packages
  (append
   (list (list glib-with-documentation "doc"))
         %base-packages)))

Некоторые пакеты устанавливают программы с различными “отпечатками зависимостей”. Например, пакет WordNet устанавливает и инструменты командной строки, и графический интерфейс (GUI). Первое зависит только от библиотеки C, а последнее зависит от Tcl/Tk и библиотек X. В таком случае мы оставляем инструменты командной строки в качестве результата по умолчанию, в то время как GUI поставляется как отдельный выход. Это экономит место для пользователей, которым не нужен GUI. Команда guix size может помочь выявить такие ситуации (see Вызов guix size). guix graph также полезна (see Вызов guix graph).

Есть несколько таких пакетов со множественным выходом в дистрибутиве GNU. Другие традиционные имена выходов включают lib - для библиотек и иногда файлов заголовков, bin - для самих программ, debug - для отладочной информации (see Установка файлов отладки). Выходы пакетов представлены в третьей колонке вывода guix package --list-available (see Вызов guix package).


5.5 Invoking guix locate

There’s so much free software out there that sooner or later, you will need to search for packages. The guix search command that we’ve seen before (see Вызов guix package) lets you search by keywords:

guix search video editor

Sometimes, you instead want to find which package provides a given file, and this is where guix locate comes in. Here is how you can find which package provides the ls command:

$ guix locate ls
coreutils@9.1       /gnu/store/…-coreutils-9.1/bin/ls

Of course the command works for any file, not just commands:

$ guix locate unistr.h
icu4c@71.1          /gnu/store/…/include/unicode/unistr.h
libunistring@1.0    /gnu/store/…/include/unistr.h

You may also specify glob patterns with wildcards. For example, here is how you would search for packages providing .service files:

$ guix locate -g '*.service'
man-db@2.11.1        …/lib/systemd/system/man-db.service
wpa-supplicant@2.10  …/system-services/fi.w1.wpa_supplicant1.service

The guix locate command relies on a database that maps file names to package names. By default, it automatically creates that database if it does not exist yet by traversing packages available locally, which can take a few minutes (depending on the size of your store and the speed of your storage device).

Примечание: For now, guix locate builds its database based on purely local knowledge—meaning that you will not find packages that never reached your store. Eventually it will support downloading a pre-built database so you can potentially find more packages.

By default, guix locate first tries to look for a system-wide database, usually under /var/cache/guix/locate; if it does not exist or is too old, it falls back to the per-user database, by default under ~/.cache/guix/locate. On a multi-user system, administrators may want to periodically update the system-wide database so that all users can benefit from it, for instance by setting up package-database-service-type (see package-database-service-type).

Основной синтаксис:

guix locate [options…] file

... where file is the name of a file to search for (specifically, the “base name” of the file: files whose parent directories are called file are not matched).

The available options are as follows:

--glob
-g

Interpret file… as glob patterns—patterns that may include wildcards, such as ‘*.scm’ to denote all files ending in ‘.scm’.

--stats

Display database statistics.

--update
-u

Update the file database.

By default, the database is automatically updated when it is too old.

--clear

Clear the database and re-populate it.

This option lets you start anew, ensuring old data is removed from the database, which also avoids having an endlessly growing database. By default guix locate automatically does that periodically, though infrequently.

--database=file

Use file as the database, creating it if necessary.

By default, guix locate picks the database under ~/.cache/guix or /var/cache/guix, whichever is the most recent one.

--method=method
-m method

Use method to select the set of packages to index. Possible values are:

manifests

This is the default method: it works by traversing profiles on the machine and recording packages it encounters—packages you or other users of the machine installed, directly or indirectly. It is fast but it can miss other packages available in the store but not referred to by any profile.

store

This is a slower but more exhaustive method: it checks among all the existing packages those that are available in the store and records them.


5.6 Вызов guix gc

Пакеты, которые установлены, но не используются, могут быть очищены как мусор (garbage-collected). Команда guix gc позволяет пользователям непосредственно запустить сборщик мусора и восстановить место в директории /gnu/store. Это единственный способ удалить файлы из /gnu/store — удаление файлов вручную может поломать её безвозвратно!

Сборщик мусора имеет набор известных корней (roots): любой файл в /gnu/store, доступный из корня, рассматривается как живой (live) и не может быть удалён; любой другой файл рассматривается как мёртвый (dead) и может быть удалён. Набор корней сборщика мусора (сокращённо "GC roots") содержит профили пользователей по умолчанию; по умолчанию символические ссылки в /var/guix/gcroots представляют эти корни сборщика мусора. Новые корни могут добавляться, например, командой guix build --root (see Запуск guix build). Команда guix gc --list-roots отображает их.

Перед запуском guix gc --collect-garbage для освобождения места часто бывает полезно удалить старые поколения из пользовательских профилей; так старые пакеты, относящиеся к этим поколениям, будут удалены. Это можно сделать, запустив guix package --delete-generations (see Вызов guix package).

Мы рекомендуем запускать сборщик мусора периодически, или когда вы хотите освободить место на диске. Например, чтобы гарантировать, что по меньшей мере 5 Гб будет доступно на вашем диске, просто запустите:

guix gc -F 5G

Хорошо бы запускать это как неинтерактивную периодическую задачу (see Запланированное исполнения задач, чтобы узнать, как добавить такую задачу). Запуск guix gc без аргументов соберёт столько мусора, сколько возможно, но это часто не удобно: можно обнаружить, что придётся заново собирать или скачивать программы, "убитые" сборщиком мусора, хотя они необходимы для сборки другого софта, например, это касается инструментов компилятора.

Команда guix gc предоставляет три способа взаимодействия: может использоваться для сборки мусора (garbage-collect) любых мёртвых файлов (по умолчанию), для удаления конкретных файлов (опция --delete), для вывода информации сборщика мусора, а также для более изощрённых запросов. Опции сборщика мусора:

--collect-garbage[=min]
-C [min]

Собрать мусор, то есть недоступные файлы в /gnu/store и поддиректориях. Это операция по умолчанию, если не заданы опции.

Если задана min, остановиться, когда min байт собрано. min может быть числом байт или может содержать единицу измерения в суффиксе, как например, MiB для мебибайт и GB гигабайт (see size specifications in GNU Coreutils).

Если min пропущено, собрать весь мусор.

--free-space=free
-F free

Собирать мусор, пока не станет доступно free места в /gnu/store, если возможно; free описывает дисковое пространство, как 500MiB, как это описанов выше.

Когда free или более места стало свободно в /gnu/store, ничего не делать и немедленно выйти.

--delete-generations[=duration]
-d [duration]

Before starting the garbage collection process, delete all the generations older than duration, for all the user profiles and home environment generations; when run as root, this applies to all the profiles of all the users.

Например, следующая команда удаляет все поколения всех ваших профилей, которые старше 2 месцев (кроме текущего поколения), а затем запускается процесс освобождения мместа, пока по меньшей мере 10 GiB не станет доступно:

guix gc -d 2m -F 10G
--delete
-D

Попытаться удалить все файлы и директории склада, приведённые в аргументах. Это завершается с ошибкой, если какие-либо файлы не присутствуют на складе, или если они ещё живы (live).

--list-failures

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

Это ничего не выводит, если демон не был запущен с опцией --cache-failures (see --cache-failures).

--list-roots

Вывести список корней сборщика мусора (GC roots), которыми владеет пользователь; при запуске от root, выводит список всех корней сборщика мусора.

--list-busy

Составляет список элементов хранилица, исользуемых запущенными в данное время процессами. Эти элементы считаются корнями GC: они не могут быть удалены.

--clear-failures

Удалить заданные элементы склада из кеша неудачных сборок.

Опять же эта опция имеет смысл, если демон запущен с --cache-failures. В противном случае это не имеет эффекта.

--list-dead

Вывести список мёртвых файлов и директорий, которые по-прежнему присутствуют на складе, то есть файлы и директории, не доступные более из любого корня.

--list-live

Вывести список живых файлов и директорий склада.

В дополнение можно запросить связи между существующими файлами на складе:

--references
--referrers

Вывести список связанных (обязательно, ссылающихся) файлов на складе с указанными аргументами.

--requisites
-R

Вывести всё необходимое для файлов на складе, указанных в аргументах. Всё необходимое включает сами файлы на складе, их связи и связи их связей рекурсивно. Другими словами, выводимый список — это непосредственный конвейер файлов на складе.

См. See Вызов guix size для информации об инструменте профилирования конвейера для элемента. См. See Вызов guix graph для информации об инструменте визуализации графа связей.

--derivers

Вернуть деривацию(-ии), производящие данные элементы склада (see Деривации).

Например, эта команда:

guix gc --derivers `guix package -I ^emacs$ | cut -f4`

возвращает файл(ы) .drv, которые произвели пакет emacs, установленный в вашем профиле.

Отметим, что может быть не найдено ни одного файла .drv, например, потому что эти файлы были удалены сборщиком мусора. Также может быть более одного файла .drv из-за дериваций с фиксированным выходом.

Наконец, следующие опции позволяют проверить целостность склада и контролировать использование диска.

--verify[=options]

Проверить целостность склада.

По умолчанию убедиться, что все элементы склада, которые в базе данных демона помечены как действующие, на самом деле присутствуют в /gnu/store.

Опции options, если они указаны, должны представлять собой список, разделённый запятыми, содержащий одно или более значений contents и repair.

Если задано --verify=contents, демон вычисляет хеш содержимого каждого элемента склада и сравнивает с его хешем в базе данных. Несовпадения хеша отображаются в отчёте как повреждение данных. Так как она проходит все файлы склада, эта команда может занять много времени, особенно в системах с медленным диском.

Использование --verify=repair или --verify=contents,repair указывает демону предпринять попытку восстановить разрушенные элементы склада, выбирая подстановки для них (see Подстановки). Так как восстановление не атомарное, и поэтому потенциально опасно, оно доступно только системному администратору. Малозатратная альтернатива в случае, если вы знаете точно, какие элементы склада испорчены, — это guix build --repair (see Запуск guix build).

--optimize

Оптимизировать склад с помощью жёстких ссылок на идентичные файлы — это дедупликация.

Демон выполняет дедупликацию после каждой успешной сборки или импорта архива, если конечно оно не было запущено с --disable-deduplication (see --disable-deduplication). Так что эта опция особенно важна, если демон запущено с --disable-deduplication.

--vacuum-database

Guix uses an sqlite database to keep track of the items in (see Хранилище). Over time it is possible that the database may grow to a large size and become fragmented. As a result, one may wish to clear the freed space and join the partially used pages in the database left behind from removed packages or after running the garbage collector. Running sudo guix gc --vacuum-database will lock the database and VACUUM the store, defragmenting the database and purging freed pages, unlocking the database when it finishes.


5.7 Вызов guix pull

Packages are installed or upgraded to the latest version available in the distribution currently available on your local machine. To update that distribution, along with the Guix tools, you must run guix pull: the command downloads the latest Guix source code and package descriptions, and deploys it. Source code is downloaded from a Git repository, by default the official GNU Guix repository, though this can be customized. guix pull ensures that the code it downloads is authentic by verifying that commits are signed by Guix developers.

Specifically, guix pull downloads code from the channels (see Каналы) specified by one of the following, in this order:

  1. опция --channels;
  2. the user’s ~/.config/guix/channels.scm file, unless -q is passed;
  3. the system-wide /etc/guix/channels.scm file, unless -q is passed (on Guix System, this file can be declared in the operating system configuration, see channels field of guix-configuration);
  4. встроенные по умолчанию каналы определены в переменной %default-channels.

После выполнения этой команды guix package будет использовать пакеты и те их версии, которые имеются в только что полученной копии Guix. Эта последняя версия будет источником также всех команд Guix, модулей Scheme. Из этого обновления станет доступен набор команд guix.

Любой пользователь может обновить свою копию Guix, используя guix pull, эффект коснётся только пользователя, который запустил guix pull. Например, если пользователь root запускает guix pull, это не имеет эффекта на версию Guix, которую видит alice sees, и наоборот.

Результат запуска guix pull — это профиль profile, доступный в ~/.config/guix/current, содержащий последний Guix.

Опция --list-generations или -l выводит список последних поколений, поставленных guix pull, вместе с деталями об их происхождении:

$ guix pull -l
Generation 1	Jun 10 2018 00:18:18
  guix 65956ad
    repository URL: https://git.savannah.gnu.org/git/guix.git
    branch: origin/master
    commit: 65956ad3526ba09e1f7a40722c96c6ef7c0936fe

Generation 2	Jun 11 2018 11:02:49
  guix e0cc7f6
    repository URL: https://git.savannah.gnu.org/git/guix.git
    branch: origin/master
    commit: e0cc7f669bec22c37481dd03a7941c7d11a64f1d

Generation 3	Jun 13 2018 23:31:07	(current)
  guix 844cc1c
    repository URL: https://git.savannah.gnu.org/git/guix.git
    branch: origin/master
    commit: 844cc1c8f394f03b404c5bb3aee086922373490c

Смотрите See guix describe, для информации о других способах получить информацию о текущем статусе Guix.

Этот профиль ~/.config/guix/current работает, как любой другой профиль, созданный guix package (see Вызов guix package). Так что можно вывести список поколений, откатиться до предыдущего поколения, то есть до предыдущего Guix, и так далее:

$ guix package -p ~/.config/guix/current --roll-back
switched from generation 3 to 2
$ guix package -p ~/.config/guix/current --delete-generations=1
deleting /var/guix/profiles/per-user/charlie/current-guix-1-link

Вы также можете использовать guix package (see Вызов guix package), чтобы управлять профилем, называя его явно:

$ guix package -p ~/.config/guix/current --roll-back
switched from generation 3 to 2
$ guix package -p ~/.config/guix/current --delete-generations=1
deleting /var/guix/profiles/per-user/charlie/current-guix-1-link

Команда guix pull обычно вызывается без аргументов, но поддерживает следующие опции:

--url=url
--commit=commit
--branch=branch

Download code for the guix channel from the specified url, at the given commit (a valid Git commit ID represented as a hexadecimal string or the name of a tag), or branch.

Эти опции внедрены для удобства, но также можно задать конфигурационный файл ~/.config/guix/channels.scm или использовать опцию --channels (смотрите ниже).

--channels=file
-C file

Считать список каналов из файла file вместо ~/.config/guix/channels.scm. file должен содержать код Scheme, который определяет список объектов "канал". См. See Каналы для подробной информации.

--no-channel-files
-q

Inhibit loading of the user and system channel files, ~/.config/guix/channels.scm and /etc/guix/channels.scm.

--news
-N

Display news written by channel authors for their users for changes made since the previous generation (see Writing Channel News). When --details is passed, additionally display new and upgraded packages.

You can view that information for previous generations with guix pull -l.

--list-generations[=pattern]
-l [pattern]

Вывести список всех поколений ~/.config/guix/current или, если предоставлен паттерн pattern, подмножество поколений, которые соответствуют pattern. Синтаксис pattern — такой же, как у guix package --list-generations (see Вызов guix package).

By default, this prints information about the channels used in each revision as well as the corresponding news entries. If you pass --details, it will also print the list of packages added and upgraded in each generation compared to the previous one.

--details

Instruct --list-generations or --news to display more information about the differences between subsequent generations—see above.

--roll-back

Откатиться до предыдущего поколения профиля, то есть отменить последнюю транзакцию.

--switch-generation=pattern
-S pattern

Переключиться на определённое поколение, опрделённое pattern.

pattern может быть либо номером поколения или числом с префиксом "+" или "-". Последнее означает сменить вперёд/назад на обозначенное число поколений. Например, если вы хотите вернуться к последнему поколению после --roll-back, используйте --switch-generation=+1.

--delete-generations[=pattern]
-d [pattern]

Если pattern пропущен, удалит все поголения, кроме текущего.

Эта команда принимает такие же паттерны, как --list-generations. Если pattern задан, удалит соответствующие поколения. Если паттерн pattern задаёт срок, выбираются поколения старше срока. Например, --delete-generations=1m удалит поколения, которые старше одного месяца.

Если текущее поколение попадает под условия паттерна, оно не будет удалено. А также нулевое поокление никогда не удаляется.

Отметим, что удаление поколений делает невозможным откат к ним. Следовательно эта команда должна использоваться внимательно.

См. See Вызов guix describe, чтобы узнать, как вывести информацию только о текущем поколении.

--profile=profile
-p profile

Использовать профиль profile вместо ~/.config/guix/current.

--dry-run
-n

Показать, какие коммиты будут использоваться, и что будет собрано или скачано в виде подстановок, но не выполнять эту работу.

--allow-downgrades

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

По умолчанию guix pull защищает от так называемых “атак на более раннюю версию”, когда репозиторий Git данного канала будет сброшен до более ранней или несвязанной версии, что может привести к установке более старых, известных уязвимых версий пакетов.

Примечание: Прежде чем использовать --allow-downgrades, убедитесь, что вы понимаете его последствия для безопасности.

--disable-authentication

Разрешить загрузку канала без его аутентификации.

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

Примечание: Прежде чем использовать --disable-authentication, убедитесь, что вы понимаете его последствия для безопасности.

--system=system
-s system

Предпринять попытку собрать систему system, т.е. i686-linux, вместо типа системы хоста сборки.

--bootstrap

Использовать бутстрап Guile для сорки последнего Guix. Эта опция полезна только для разработчиков.

Механизм каналов channel позволяет указать guix pull, из какого репозитория или ветки скачивать, а также какие дополнительные репозитории должны использоваться для развёртки. См. See Каналы для подробной информации.

В добавок guix pull поддерживает все стандартные опции сборки (see Стандартные параметры сборки).


5.8 Запуск guix time-machine

Команда guix time-machine предоставляет доступ к другим версиям Guix, например, для установки более старых версий пакетов или для воспроизведения вычислений в идентичной среде. Версия используемого Guix определяется коммитом или файлом описания канала, созданным guix describe (see Вызов guix describe).

Let’s assume that you want to travel to those days of November 2020 when version 1.2.0 of Guix was released and, once you’re there, run the guile of that time:

guix time-machine --commit=v1.2.0 -- \
  environment -C --ad-hoc guile -- guile

The command above fetches Guix 1.2.0 (and possibly other channels specified by your channels.scm configuration files—see below) and runs its guix environment command to spawn an environment in a container running guile (guix environment has since been subsumed by guix shell; see Вызов guix shell). It’s like driving a DeLorean12! The first guix time-machine invocation can be expensive: it may have to download or even build a large number of packages; the result is cached though and subsequent commands targeting the same commit are almost instantaneous.

As for guix pull, in the absence of any options, time-machine fetches the latest commits of the channels specified in ~/.config/guix/channels.scm, /etc/guix/channels.scm, or the default channels; the -q option lets you ignore these configuration files. The command:

guix time-machine -q -- build hello

will thus build the package hello as defined in the main branch of Guix, without any additional channel, which is in general a newer revision of Guix than you have installed. Time travel works in both directions!

Примечание: The history of Guix is immutable and guix time-machine provides the exact same software as they are in a specific Guix revision. Naturally, no security fixes are provided for old versions of Guix or its channels. A careless use of guix time-machine opens the door to security vulnerabilities. See --allow-downgrades.

guix time-machine raises an error when attempting to travel to commits older than “v0.16.0” (commit ‘4a0b87f0’), dated Dec. 2018. This is one of the oldest commits supporting the channel mechanism that makes “time travel” possible.

Примечание: Although it should technically be possible to travel to such an old commit, the ease to do so will largely depend on the availability of binary substitutes. When traveling to a distant past, some packages may not easily build from source anymore. One such example are old versions of OpenSSL whose tests would fail after a certain date. This particular problem can be worked around by running a virtual build machine with its clock set to the right time (see Virtual Build Machines).

Основной синтаксис:

guix time-machine options… -- command arg

где command и arg… передаются без изменений в команду guix указанной ревизии. options, которые определяют эту ревизию, такие же, как и для guix pull (see Вызов guix pull):

--url=url
--commit=commit
--branch=branch

Use the guix channel from the specified url, at the given commit (a valid Git commit ID represented as a hexadecimal string or the name of a tag), or branch.

--channels=file
-C file

Считать список каналов из файла file вместо ~/.config/guix/channels.scm. file должен содержать код Scheme, который определяет список объектов "канал". См. See Каналы для подробной информации.

--no-channel-files
-q

Inhibit loading of the user and system channel files, ~/.config/guix/channels.scm and /etc/guix/channels.scm.

Thus, guix time-machine -q is equivalent to the following Bash command, using the “process substitution” syntax (see Process Substitution in The GNU Bash Reference Manual):

guix time-machine -C <(echo %default-channels) …

Если указанные пакеты ещё не собраны, guix archive автоматически соберёт их. Процесс сборки может контролироваться обычными опциями сборки (see Стандартные параметры сборки).

If guix time-machine is executed without any command, it prints the file name of the profile that would be used to execute the command. This is sometimes useful if you need to get store file name of the profile—e.g., when you want to guix copy it.


5.9 Младшие версии

Примечание: Функциональность, описанная здесь, — это обзор технологии версии 2a6d964. Интерфейс может меняться.

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

Технически работа с ранними версиями — это в целом отдельный процесс Guix, связанный с главным процессом Guix через REPL (see Вызов guix repl). Модуль (guix inferior) позволяет запускать ранние версии и взаимодействовать с ними. Он также предоставляет высокоуровневый интерфейс для обзора и управления пакетами, которые поставляет ранняя версия — ранние версии пакетов.

При сочетании с каналами (see Каналы) ранние версии предоставляют простой способ взаимодействовать с отдельными ревизиями Guix. Например, предположим, вы хотите установить в ваш профиль текущий пакет guile вместе с тем guile-json, который был определён в предыдущей ревизии Guix (может быть, потому что новый guile-json имеет несовместимый API, и вы хотите запустить ваш код со старым API). Чтобы это сделать, можно написать манифест для использования с guix package --manifest (see Writing Manifests). В этом манифесте вы создадите описание ранней версии той предыдущей ревизии Guix, которая вас интересует, в которой вы ищете пакет guile-json ранней версии:

(use-modules (guix inferior) (guix channels)
             (srfi srfi-1))   ;for 'first'

(define channels
  ;; This is the old revision from which we want to
  ;; extract guile-json.
  (list (channel
         (name 'guix)
         (url "https://git.savannah.gnu.org/git/guix.git")
         (commit
          "65956ad3526ba09e1f7a40722c96c6ef7c0936fe"))))

(define inferior
  ;; An inferior representing the above revision.
  (inferior-for-channels channels))

;; Now create a manifest with the current "guile" package
;; and the old "guile-json" package.
(packages->manifest
 (list (first (lookup-inferior-packages inferior "guile-json"))
       (specification->package "guile")))

Далее запуск guix package --manifest может вызвать сборку канала, который вы обозначили ранее, и в результате это задействует раннюю версию. Последовательные запуски будут быстрее, потому что ревизия Guix будет кеширована.

Модуль (guix inferior) предоставляет следующие процедуры для работы с ранними версиями:

Procedure: inferior-for-channels channels [#:cache-directory] [#:ttl]

Return an inferior for channels, a list of channels. Use the cache at cache-directory, where entries can be reclaimed after ttl seconds. This procedure opens a new connection to the build daemon.

Как побочный эффект, эта процедура может собирать или скачивать подстановки бинарников для channels, что может занять время.

Procedure: open-inferior directory [#:command "bin/guix"]

Open the inferior Guix in directory, running directory/command repl or equivalent. Return #f if the inferior could not be launched.

Процедуры, приведённые ниже, обеспечивают работу и управление ранними версиями пакетов.

Procedure: inferior-packages inferior

Возвращает список пакетов, относящихся к ранней версии inferior.

Procedure: lookup-inferior-packages inferior name [version]

Return the sorted list of inferior packages matching name in inferior, with highest version numbers first. If version is true, return only packages with a version number prefixed by version.

Procedure: inferior-package? obj

Возвращает true, если объект obj — это пакет ранней версии.

Procedure: inferior-package-name package
Procedure: inferior-package-version package
Procedure: inferior-package-synopsis package
Procedure: inferior-package-description package
Procedure: inferior-package-home-page package
Procedure: inferior-package-location package
Procedure: inferior-package-inputs package
Procedure: inferior-package-native-inputs package
Procedure: inferior-package-propagated-inputs package
Procedure: inferior-package-transitive-propagated-inputs package
Procedure: inferior-package-native-search-paths package
Procedure: inferior-package-transitive-native-search-paths package
Procedure: inferior-package-search-paths package

Эти процедуры являются двойниками метода доступа к записям пакетов (see package Ссылка). Большинство из них работают с запросами для ранней версии, из которой происходит package, так что ранняя версия должна оставаться живой, когда вы вызываете эти процедуры.

Пакеты ранних версий могут использоваться прозрачно, как любой другой пакет или объект типа файл в выражении G-expressions (see G-Expressions). Они также прозрачно используются в процедуре packages->manifest, которая обычно используется в манифестах (see the --manifest option of guix package). Так можно вставлять пакет ранней версии в принципе куда угодно, как если вставлять обычный пакет: в манифесты, в поле packages вашего объявления operating-system и т.д.


5.10 Вызов guix describe

Часто может возникать вопрос: "Какую ревизию Guix я использую?" - Или: "Какие каналы я использую?" Это полезна информация во многих ситуациях: если вы хотите повторить окружение на другой машине или в другом пользовательском аккаунте, если вы хотите составить отчёт об ошибке, чтобы определить, какие изменения в канале, который вы используете, вызвали ошибку, или если вы хотите записать состояние вашей системы в целях воспроизводимости. Команда guix describe отвечает на эти вопросы.

В случае запуска после guix pull команда guix describe отображает канал(ы), из которых производилась сборка, включая URL и репозиториев и ID коммитов (see Каналы):

$ guix describe
Generation 10	Sep 03 2018 17:32:44	(current)
  guix e0fa68c
    repository URL: https://git.savannah.gnu.org/git/guix.git
    branch: master
    commit: e0fa68c7718fffd33d81af415279d6ddb518f727

Если вы знакомы с системой контроля версиями Git, эта команда по сути похожа на git describe; выход тот же, что в guix pull --list-generations, но ограничен текущим поколением (see the --list-generations option). Так как ID коммита Git выше ссылается однозначно на снимок Guix, эта информация — всё, что нужно для описания используемой ревизии Guix и повторения её.

Чтобы проще повторить Guix, guix describe также может вызываться для вывода списка каналов вместо читаемого описания выше:

$ guix describe -f channels
(list (channel
        (name 'guix)
        (url "https://git.savannah.gnu.org/git/guix.git")
        (commit
          "e0fa68c7718fffd33d81af415279d6ddb518f727")))
        (introduction
           (make-channel-introduction
             "9edb3f66fd807b096b48283debdcddccfea34bad"
             (openpgp-fingerprint
               "BBB0 2DDF 2CEA F6A8 0D1D  E643 A2A0 6DF2 A33A 54FA")))))

Можно сохранить это в файл и подать на вход guix pull -C на любой другой машине или через время, чтобы инициализировать эту конкретную ревизию Guix (see the -C option). Теперь, когда можно развернуть подобную ревизию Guix, вы можете также полностью повторить программное окружение. Мы скромно полагаем, это чудесно. Надеемся, вам это тоже понравится!

Подробнее об опциях, поддерживаемых guix describe:

--format=format
-f format

Произвести вывод в указанном формате format, одном из:

human

произвести вывод для чтения человеком;

каналы

произвести список спецификаций каналов, который может использоваться в guix pull -C или вставлен в файл ~/.config/guix/channels.scm (see Вызов guix pull);

channels-sans-intro

как channels, но без поля Introduction; используйте его для создания спецификации канала, подходящей для Guix версии 1.1.0 или более ранней. Поле Introduction связано с аутентификацией канала (see Channel Authentication) и не поддерживается этими более ранними версиями;

json

произвести список спецификаций каналов в формате JSON;

recutils

произвести список спецификаций каналов в формате Recutils.

--list-roots

Вывести доступные форматы для --format опции.

--profile=profile
-p profile

Вывести информацию о профиле profile.


5.11 Вызов guix archive

Команда guix archive даёт возможность пользователям экспортировать файлы со склада в простой архив и затем импортировать их на машину с работающим Guix. В частности, это позволяет передавать файлы склада одной машины на склад другой машины.

Примечание: Если вы ищете способ производить архивы в формате, который подходит для инструментов, отличных от Guix, смотрите see Вызов guix pack.

Чтобы экспортировать файлы склада в архив в стандартный вывод, выполните:

guix archive --export options specifications...

Спецификации specifications могут быть либо именами файлов или пакетами, как для команде guix package (see Вызов guix package). Например, следующая команда создаёт архив, содержащий выход gui пакета git и главный выход emacs:

guix archive --export git:gui /gnu/store/...-emacs-24.3 > great.nar

Если указанные пакеты ещё не собраны, guix archive автоматически соберёт их. Процесс сборки может контролироваться обычными опциями сборки (see Стандартные параметры сборки).

Чтобы передать пакет emacs на машину, соединённую по SSH, нужно следующее:

guix archive --export -r emacs | ssh the-machine guix archive --import

Точно также для передачи всего профиля пользователя из одной машины на другую, выполните:

guix archive --export -r $(readlink -f ~/.guix-profile) | \
  ssh the-machine guix archive --import

Однако заметим, что в обоих примерах, передаются весь emacs и профиль вместе с их зависимости (ввиду -r), не учитывая, что доступно на складе целевой машины. Опция --missing помогает определить отсутствующие элементы на целевом складе. Команда guix copy упрощает и оптимизирует весь этот процесс, так что в данном случае она решает проблему (see Вызов guix copy).

Каждый элемент храниища написан в normalized archive или nar формате (описано ниже), и вывод guix archive --export (и ввод guix archive --import) есть nar bundle.

Формат nar по духу сравним с tar, но с отличиями, которые делают его более подходящим для наших целей. Во-первых, вместо записи всех метаданных Unix для каждого файла, в формате nar упоминается только тип файла (обычный, каталог или символическая ссылка); Разрешения Unix и владелец/группа отклонены. Во-вторых, порядок, в котором хранятся записи каталога, всегда следует порядку имен файлов в соответствии с порядком сопоставления C локали. Это делает создание архивов полностью детерминированным.

Формат пакета nar - это, по сути, конкатенация нуля или более nars вместе с метаданными для каждого элемента store, который содержит: имя файла, ссылки, соответствующую derivation и цифровую подпись.

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

Основные опции:

--export

Экспортировать указанные файлы хранилища или пакеты (смотрите ниже). Писать результирующий архив в стандартный вывод.

Зависимости не включаются в выход, если не задана опция --recursive.

-r
--recursive

При сочетании с --export это указывает guix archive включать в архив зависимости обозначенных элементов. Так результирующий архив будет "сам в себе": содержит полный конвейер экспортированных элементов склада.

--import

Читать архив из стандартного ввода и импортировать файлы, поставляемые им, на склад. Отклонить, если архив имеет недействительную цифровую подпись, или если он подписан публичным ключом, который не находится в списке авторизованных ключей (смотрите --authorize ниже).

--missing

Читать список имён файлов склада из стандартного ввода, одна линия - один файл, и писать в стандартный вывод подмножество этих файлов, отсутствующих на складе.

--generate-key[=parameters]

Генерировать новую ключ-пару для демона. Это необходимо получить перед тем, как экспортировать архивы опцией --export. Отметим, что эта операция обычно занимает время, так как необходимо собрать много энтропии для ключ-пары.

Сгенерированная ключ-пара обычно сохраняется под /etc/guix, в файлы signing-key.pub (публичный ключ) и signing-key.sec (прватный ключ, который должен оставаться в секрете). Если параметры parameters пропущены, генерируется ключ ECDSA, используя кривую Ed25519, или для Libgcrypt версии ранее 1.6.0 — это 4096-битный ключ RSA. Альтернативно в параметрах parameters можно указать genkey, соответствующие Libgcrypt (see gcry_pk_genkey in The Libgcrypt Reference Manual).

--authorize

Авторизовать импорт, подписанный публичным ключом, поступивший на стандартный ввод. Публичный ключ должен быть в формате s-expression, то есть в таком же формате, как файл signing-key.pub.

Список авторизованных ключей хранится в файле /etc/guix/acl, доступном для редактирования человеком. Файл содержит s-expression расширенного формата, и он структурирован в виде списка контроля доступа в Simple Public-Key Infrastructure (SPKI).

--extract=directory
-x directory

Читать архив, представляющий один элемент, в качестве поставленного серверами подстановки (see Подстановки) и извлечь его в директорию directory. Это низкоуровневая операция, необходимая только в очень редких случаях, смотрите ниже.

Например, следующая команда распаковывает подстановку Emacs, поставленную bordeaux.guix.gnu.org в /tmp/emacs:

$ wget -O - \
  https://bordeaux.guix.gnu.org/nar/gzip/…-emacs-24.5 \
  | gunzip | guix archive -x /tmp/emacs

Архивы, представляющие один элемент, отличаются от архивов, содержащих множество элементов, производимых guix archive --export. Они содержат один элемент склада, но они не включают подпись. Так что эта операция не использует верификацию, и его выход должен рассматриваться как небезопасный.

Основная цель этой операции — упростить просмотр содержимого архива, происходящего, возможно, из недоверенных серверов подстановок.

--list
-t

Читать архив, представляющий один элемент, в качестве поставленного серверами подстановки (see Подстановки) и распечатайте список файлов, которые он содержит, как в этом примере:

$ wget -O - \
  https://bordeaux.guix.gnu.org/nar/lzip/…-emacs-26.3 \
  | lzip -d | guix archive -t

6 Каналы

Guix and its package collection are updated by running guix pull. By default guix pull downloads and deploys Guix itself from the official GNU Guix repository. This can be customized by providing a file specifying the set of channels to pull from (see Вызов guix pull). A channel specifies the URL and branch of a Git repository to be deployed, and guix pull can be instructed to pull from one or more channels. In other words, channels can be used to customize and to extend Guix, as we will see below. Guix is able to take into account security concerns and deal with authenticated updates.


6.1 Указание дополнительных каналов

Чтобы использовать канал, напишите ~/.config/guix/channels.scm, чтобы обозначить guix pull скачивать оттуда в дополнение к каналу(-ам) Guix по умолчанию:

;; Add my personal packages to those Guix provides.
(cons (channel
        (name 'my-personal-packages)
        (url "https://example.org/personal-packages.git"))
      %default-channels)

Заметим, что сниппет выше (всегда!) код Scheme; мы используем cons для добавления канала в список каналов, то есть в переменную %default-channels (see cons and lists in GNU Guile Reference Manual). Если этот файл написан, guix pull производит сборку не только Guix, но и пакетных модулей из вашего репозитория. В результате в ~/.config/guix/current содержится объединение Guix и ваших собственных пакетных модулей:

$ guix describe
Generation 19	Aug 27 2018 16:20:48
  guix d894ab8
    repository URL: https://git.savannah.gnu.org/git/guix.git
    branch: master
    commit: d894ab8e9bfabcefa6c49d9ba2e834dd5a73a300
  variant-packages dd3df5e
    repository URL: https://example.org/variant-packages.git
    branch: master
    commit: dd3df5e2c8818760a8fc0bd699e55d3b69fef2bb

The output of guix describe above shows that we’re now running Generation 19 and that it includes both Guix and packages from the variant-packages channel (see Вызов guix describe).


6.2 Использование отдельного канала Guix

Канал, названный guix, обозначает, откуда должен скачиваться сам Guix (его инструменты командной строки и коллекция пакетов). Например, предположим вы хотите обновиться из вашей собственной копии репозитория Guix на example.org, а именно из ветки super-hacks, тогда можно написать в ~/.config/guix/channels.scm следующую спецификацию:

;; Tell 'guix pull' to use my own repo.
(list (channel
        (name 'guix)
        (url "https://example.org/my-guix.git")
        (branch "super-hacks")))

From there on, guix pull will fetch code from the super-hacks branch of the repository at example.org. The authentication concern is addressed below (see Аутентификация канала).

Note that you can specify a local directory on the url field above if the channel that you intend to use resides on a local file system. However, in this case guix checks said directory for ownership before any further processing. This means that if the user is not the directory owner, but wants to use it as their default, they will then need to set it as a safe directory in their global git configuration file. Otherwise, guix will refuse to even read it. Supposing your system-wide local directory is at /src/guix.git, you would then create a git configuration file at ~/.gitconfig with the following contents:

[safe]
        directory = /src/guix.git

This also applies to the root user unless when called with sudo by the directory owner.


6.3 Копирование Guix

The guix describe command shows precisely which commits were used to build the instance of Guix we’re using (see Вызов guix describe). We can replicate this instance on another machine or at a different point in time by providing a channel specification “pinned” to these commits that looks like this:

;; Deploy specific commits of my channels of interest.
(list (channel
       (name 'guix)
       (url "https://git.savannah.gnu.org/git/guix.git")
       (commit "d894ab8e9bfabcefa6c49d9ba2e834dd5a73a300"))
      (channel
       (name 'my-personal-packages)
       (url "https://example.org/personal-packages.git")
       (branch "dd3df5e2c8818760a8fc0bd699e55d3b69fef2bb")))

To obtain this pinned channel specification, the easiest way is to run guix describe and to save its output in the channels format in a file, like so:

guix describe -f channels > channels.scm

Полученный файл channels.scm можно передать в команды guix pull (see Вызов guix pull) или guix time-machine (see Запуск guix time-machine) с опцией -C , как в этом примере:

guix time-machine -C channels.scm -- shell python -- python3

Given the channels.scm file, the command above will always fetch the exact same Guix instance, then use that instance to run the exact same Python (see Вызов guix shell). On any machine, at any time, it ends up running the exact same binaries, bit for bit.

Pinned channels address a problem similar to “lock files” as implemented by some deployment tools—they let you pin and reproduce a set of packages. In the case of Guix though, you are effectively pinning the entire package set as defined at the given channel commits; in fact, you are pinning all of Guix, including its core modules and command-line tools. You’re also getting strong guarantees that you are, indeed, obtaining the exact same software.

Это даёт вам супервозможности, позволяя вам отслеживать и управлять происхождением артефактов бинарников с точной детализацией, также повторять программные окружения — это воспроизводимость высокого уровня. Смотрите See Младшие версии, чтобы узнать другие преимущества таких супервозможностей.


6.4 Customizing the System-Wide Guix

If you’re running Guix System or building system images with it, maybe you will want to customize the system-wide guix it provides—specifically, /run/current-system/profile/bin/guix. For example, you might want to provide additional channels or to pin its revision.

This can be done using the guix-for-channels procedure, which returns a package for the given channels, and using it as part of your operating system configuration, as in this example:

(use-modules (gnu packages package-management)
             (guix channels))

(define my-channels
  ;; Channels that should be available to
  ;; /run/current-system/profile/bin/guix.
  (append
   (list (channel
          (name 'guix-science)
          (url "https://github.com/guix-science/guix-science")
          (branch "master")))
   %default-channels))

(operating-system
  ;; …
  (services
    ;; Change the package used by 'guix-service-type'.
    (modify-services %base-services
      (guix-service-type
       config => (guix-configuration
                  (inherit config)
                  (channels my-channels)
                  (guix (guix-for-channels my-channels)))))))

The resulting operating system will have both the guix and the guix-science channels visible by default. The channels field of guix-configuration above further ensures that /etc/guix/channels.scm, which is used by guix pull, specifies the same set of channels (see channels field of guix-configuration).

The (gnu packages package-management) module exports the guix-for-channels procedure, described below.

Procedure: guix-for-channels channels

Return a package corresponding to channels.

The result is a “regular” package, which can be used in guix-configuration as shown above or in any other place that expects a package.


6.5 Аутентификация канала

guix pull и guix time-machine аутентифицируют код, полученный из каналов: они гарантируют, что каждый полученный коммит подписан авторизованным разработчиком. Цель состоит в том, чтобы защитить канал от несанкционированных изменений, которые могут привести к запуску вредоносного кода пользователями.

Как пользователь, вы должны предоставить channel introduction в вашем файле канала, чтобы Guix знал как авторизовать свой первый коммит. Спецификация канала, включая введения, выглядит как-то так:

(channel
  (name 'some-channel)
  (url "https://example.org/some-channel.git")
  (introduction
   (make-channel-introduction
    "6f0d8cc0d88abb59c324b2990bfee2876016bb86"
    (openpgp-fingerprint
     "CABB A931 C0FF EEC6 900D  0CFB 090B 1199 3D9A EBB5"))))

В приведенной выше спецификации указано имя и URL-адрес канала. Вызов make-channel-introduction выше указывает, что аутентификация этого канала начинается с коммита 6f0d8cc…, который подписывается ключом OpenPGP с отпечатком CABB A931….

Для основного канала, называемого guix, вы автоматически получаете эту информацию из вашей установки Guix. Для других каналов, укажите introduction для канала, предоставленное авторами канала, в ваш файл channels.scm. Убедитесь, что вы получили introduction канала из надежного источника, так как это основа вашего доверия.

Если вам любопытены механизмы авторизации, читайте дальше!


6.6 Каналы с заменителями

При запуске guix pull Guix сначала скомпилирует определения каждого доступного пакета. Это тяжелая операция, для которой могут быть доступны заменители (see Подстановки). Следующий фрагмент в channels.scm гарантирует, что guix pull использует последний коммит с доступными заменами для определений пакетов: это делается путем запроса к серверу непрерывной интеграции по адресу https://ci.guix.gnu.org.

(use-package-modules guile emacs)

(list (channel-with-substitutes-available
       %default-guix-channel
       "https://ci.guix.gnu.org"))

Учтите, что это не означает, что все пакеты, которые вы установите после запуска guix pull, будут иметь доступные заменители. Это только гарантирует, что guix pull не будет пытаться скомпилировать определения пакетов. Это особенно полезно при использовании машин с ограниченными ресурсами.


6.7 Создание канала

Let’s say you have a bunch of custom package variants or personal packages that you think would make little sense to contribute to the Guix project, but would like to have these packages transparently available to you at the command line. By creating a channel, you can use and publish such a package collection. This involves the following steps:

  1. A channel lives in a Git repository so the first step, when creating a channel, is to create its repository:
    mkdir my-channel
    cd my-channel
    git init
    
  2. The next step is to create files containing package modules (see Пакетные модули), each of which will contain one or more package definitions (see Описание пакетов). A channel can provide things other than packages, such as build systems or services; we’re using packages as it’s the most common use case.

    For example, Alice might want to provide a module called (alice packages greetings) that will provide her favorite “hello world” implementations. To do that Alice will create a directory corresponding to that module name.

    mkdir -p alice/packages
    $EDITOR alice/packages/greetings.scm
    git add alice/packages/greetings.scm
    

    You can name your package modules however you like; the main constraint to keep in mind is to avoid name clashes with other package collections, which is why our hypothetical Alice wisely chose the (alice packages …) name space.

    Note that you can also place modules in a sub-directory of the repository; see Пакетные модули в поддиректории, for more info on that.

  3. With this first module in place, the next step is to test the packages it provides. This can be done with guix build, which needs to be told to look for modules in the Git checkout. For example, assuming (alice packages greetings) provides a package called hi-from-alice, Alice will run this command from the Git checkout:
    guix build -L. hi-from-alice
    

    ... where -L. adds the current directory to Guile’s load path (see Load Paths in GNU Guile Reference Manual).

  4. It might take Alice a few iterations to obtain satisfying package definitions. Eventually Alice will commit this file:
    git commit
    

    Как автор канала, рассмотрите возможность объединения материалов для аутентификации с вашим каналом, чтобы пользователи могли его аутентифицировать. See Аутентификация канала и Указание авторизаций канала для получения информации о том, как это сделать.

  5. To use Alice’s channel, anyone can now add it to their channel file (see Указание дополнительных каналов) and run guix pull (see Вызов guix pull):
    $EDITOR ~/.config/guix/channels.scm
    guix pull
    

    Guix will now behave as if the root directory of that channel’s Git repository had been permanently added to the Guile load path. In this example, (alice packages greetings) will automatically be found by the guix command.

Voilà!

Внимание: Before you publish your channel, we would like to share a few words of caution:

  • Перед публикацией канала, пожалуйста, рассмотрите возможность поделиться вашими определениями пакетов со сборником Guix (see Содействие). Guix, как проект, открыт свободному программному обеспечению любого назначения, и пакеты в сборнике Guix готовы и доступны для использования всеми пользователями Guix и прошли проверку качества.
  • Package modules and package definitions are Scheme code that uses various programming interfaces (APIs). We, Guix developers, never change APIs gratuitously, but we do not commit to freezing APIs either. When you maintain package definitions outside Guix, we consider that the compatibility burden is on you.
  • Вывод: если вы используете внешний канал, и этот канал ломается, пожалуйста, заявите об этой проблеме авторам каналв, но не в проект Guix.

Вы предупреждены! Обозначив это, мы верим, что внешние каналы — это способ для вас проявлять свою свободу и вместе с тем расширять коллекцию пакетов Guix и делиться улучшениями, что является основными догматами свободного программного обеспечения. Пожалуйста, свяжитесь с нами по e-mail guix-devel@gnu.org, если вы хотите обсудить это.


6.8 Пакетные модули в поддиректории

Как автор канала, вы можете хранить модули канала в подкаталоге. Если ваши модули находятся в подкаталоге guix, вы должны добавить файл метаданных .guix-channel, который содержит:

(channel
  (version 0)
  (directory "guix"))

The modules must be underneath the specified directory, as the directory changes Guile’s load-path. For example, if .guix-channel has (directory "base"), then a module defined as (define-module (gnu packages fun)) must be located at base/gnu/packages/fun.scm.

Doing this allows for only parts of a repository to be used as a channel, as Guix expects valid Guile modules when pulling. For instance, guix deploy machine configuration files are not valid Guile modules, and treating them as such would make guix pull fail.


6.9 Объявление зависимостей канала

Авторы канала могут решить расширить коллекцию пакетов пакетами, которые поставляются другими каналами. Они могут объявить, что их канал зависит от других каналов, в файле метаданных .guix-channel, который нужно разместить в корне репозитория канала.

Файл метаданных должен содержать простое выражение S-expression как это:

(channel
 (version 0)
 (dependencies
  (channel
   (name 'some-collection)
   (url "https://example.org/first-collection.git")

   ;; The 'introduction' bit below is optional: you would
   ;; provide it for dependencies that can be authenticated.
   (introduction
    (channel-introduction
      (version 0)
      (commit "a8883b58dc82e167c96506cf05095f37c2c2c6cd")
      (signer "CABB A931 C0FF EEC6 900D  0CFB 090B 1199 3D9A EBB5"))))
  (channel
   (name 'some-other-collection)
   (url "https://example.org/second-collection.git")
   (branch "testing"))))

В примере выше объявлен канал, который зависит от двух других каналов, из которых оба будут скачаны автоматически. Модули, предоставляемые каналом, будут скомпилированы в окружении, в котором доступны модули всех этих каналов.

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


6.10 Указание авторизаций канала

Как мы видели выше, Guix гарантирует, что исходный код, который он получает из каналов, поступает от авторизованных разработчиков. Как автор канала, вам необходимо указать список авторизованных разработчиков в файле .guix-authorizations в репозитории Git канала. Правило аутентификации простое: каждый коммит должен быть подписан ключом, указанным в файле .guix-authorizations его родительского коммита(ов) 13 файл .guix-authorizations выглядит так:

;; Пример '.guix-authorizations' файла.

(authorizations
 (version 0)               ;current file format version

 (("AD17 A21E F8AE D8F1 CC02  DBD9 F8AE D8F1 765C 61E3"
   (name "alice"))
  ("2A39 3FFF 68F4 EF7A 3D29  12AF 68F4 EF7A 22FB B2D5"
   (name "bob"))
  ("CABB A931 C0FF EEC6 900D  0CFB 090B 1199 3D9A EBB5"
   (name "charlie"))))

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

Это правило аутентификации создает проблему с курицей и яйцом: как мы аутентифицируем первый коммит? В связи с этим: как нам поступать с каналами, история репозитория которых содержит неподписанные коммиты и не имеет .guix-authorizations? И как нам разветвлять существующие каналы?

Channel introductions answer these questions by describing the first commit of a channel that should be authenticated. The first time a channel is fetched with guix pull or guix time-machine, the command looks up the introductory commit and verifies that it is signed by the specified OpenPGP key. From then on, it authenticates commits according to the rule above. Authentication fails if the target commit is neither a descendant nor an ancestor of the introductory commit.

Кроме того, ваш канал должен предоставлять все ключи OpenPGP, которые когда-либо упоминались в .guix-authorizations, хранящиеся как файлы .key, которые могут быть либо двоичными, либо “ASCII-armored”. По умолчанию эти файлы .key ищутся в ветке с именем keyring, но вы можете указать другое имя ветки в .guix-channel следующим образом:

(channel
  (version 0)
  (keyring-reference "my-keyring-branch"))

Подытоживая, как автор канала, вы должны сделать три вещи, чтобы позволить другим пользователям авторизовать ваш код:

  1. Экспортируйте ключи OpenPGP прошлых и нынешних коммиттеров с помощью gpg --export и сохраните их в файлах .key, по умолчанию в ветке с именем keyring (мы рекомендуем сделать это в orphan branch).
  2. Добавьте .guix-authorizations в репозиторий канала. Сделайте это в подписанном коммите (see Доступ к коммитам, чтобы узнать, как подписывать коммиты Git)
  3. Рекламируйте channel introduction, например, на веб-странице вашего канала. Channel introduction, как мы видели выше, - это пара коммит/ключ, то есть коммит, который представляет .guix-authorizations, и отпечаток OpenPGP, использованный для его подписи.

Before pushing to your public Git repository, you can run guix git authenticate to verify that you did sign all the commits you are about to push with an authorized key:

guix git authenticate commit signer

где commit и signer являются вашим channel introduction. See Вызов guix package, подробнее.

Публикация подписанного канала требует дисциплины: любая ошибка, такая как неподписанная фиксация или фиксация, подписанная неавторизованным ключом, не позволит пользователям pull’ить с вашего канала - в этом весь смысл аутентификации! Обратите внимание на merge, в частности: merge коммиты считаются аутентичными, если и только если они подписаны ключом, присутствующим в файле .guix-authorizations обоих веток.


6.11 Основной URL

Авторы каналов могут указать основной URL-адрес репозитория Git своего канала в файле .guix-channel, например:

(channel
  (version 0)
  (url "https://example.org/guix.git"))

Это позволяет guix pull определять, pull’ит ли он код из зеркала канала; в этом случае он предупреждает пользователя о том, что зеркало может быть устаревшим, и отображает основной URL-адрес. Таким образом, пользователей нельзя обмануть, заставив их получить код с устаревшего зеркала, которое не получает обновлений безопасности.

Эта функция имеет смысл только для аутентифицированных репозиториев, таких как официальный канал guix, для которого guix pull гарантирует, что полученный код аутентичен.


6.12 Написание новостей канала

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

Вместо этого каналы могут предоставлять файл новостей; когда пользователи канала запускают guix pull, этот файл новостей автоматически читается, и guix pull --news может отображать объявления, которые соответствуют новым зафиксированным коммитам, если таковые имеются.

Для этого авторы каналов должны сначала объявить имя файла новостей в своем файле .guix-channel:

(channel
  (version 0)
  (news-file "etc/news.txt"))

Сам файл новостей, etc/news.txt в этом примере, должен выглядеть примерно так:

(channel-news
  (version 0)
  (entry (tag "the-bug-fix")
         (title (en "Fixed terrible bug")
                (fr "Oh la la"))
         (body (en "@emph{Good news}!  It's fixed!")
               (eo "Certe ĝi pli bone funkcias nun!")))
  (entry (commit "bdcabe815cd28144a2d2b4bc3c5057b051fa9906")
         (title (en "Added a great package")
                (ca "Què vol dir guix?"))
         (body (en "Don't miss the @code{hello} package!"))))

В то время как файл новостей использует синтаксис Scheme, избегайте называть его расширением .scm, иначе он будет выбран при построении канала и выдаст ошибку, поскольку это недопустимый модуль. Кроме того, вы можете переместить модуль канала в подкаталог и сохранить файл новостей в другом каталоге.

Файл состоит из списка news entries. Каждая запись связана с коммитом или тегом: она описывает изменения, сделанные в этом коммите, возможно, также и в предыдущих коммитах. Пользователи видят записи только при первом получении коммита, на который ссылается запись.

Поле title должно быть однострочным, а body может быть произвольно длинным, и оба могут содержать Texinfo разметку (see Overview in GNU Texinfo). И заголовок, и тело являются списком языковых тегов/кортежей сообщений, что позволяет комманде guix pull отображать новости на языке, соответствующем языку пользователя.

Если вы хотите перевести новости, используя рабочий процесс на основе gettext, вы можете извлечь переводимые строки с помощью xgettext (see xgettext Invocation in GNU Gettext Utilities). Например, если вы сначала пишете новости на английском языке, команда ниже создает PO-файл, содержащий строки для перевода:

xgettext -o news.po -l scheme -ken etc/news.txt

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


7 Разработка

Если вы являетесь разработчиком программного обеспечения, Guix предоставляет инструменты, которые вы можете найти полезными, независимо от языка разработки. Об этом данный раздел.

The guix shell command provides a convenient way to set up one-off software environments, be it for development purposes or to run a command without installing it in your profile. The guix pack command allows you to create application bundles that can be easily distributed to users who do not run Guix.


7.1 Вызов guix shell

The purpose of guix shell is to make it easy to create one-off software environments, without changing one’s profile. It is typically used to create development environments; it is also a convenient way to run applications without “polluting” your profile.

Примечание: The guix shell command was recently introduced to supersede guix environment (see Вызов guix environment). If you are familiar with guix environment, you will notice that it is similar but also—we hope!—more convenient.

Основной синтаксис:

guix shell [options] [package…]

The following example creates an environment containing Python and NumPy, building or downloading any missing package, and runs the python3 command in that environment:

guix shell python python-numpy -- python3

Note that it is necessary to include the main python package in this command even if it is already installed into your environment. This is so that the shell environment knows to set PYTHONPATH and other related variables. The shell environment cannot check the previously installed environment, because then it would be non-deterministic. This is true for most libraries: their corresponding language package should be included in the shell invocation.

Примечание: guix shell can be also be used as a script interpreter, also known as shebang. Here is an example self-contained Python script making use of this feature:

#!/usr/bin/env -S guix shell python python-numpy -- python3
import numpy
print("This is numpy", numpy.version.version)

You may pass any guix shell option, but there’s one caveat: the Linux kernel has a limit of 127 bytes on shebang length.

Development environments can be created as in the example below, which spawns an interactive shell containing all the dependencies and environment variables needed to work on Inkscape:

guix shell --development inkscape

Exiting the shell places the user back in the original environment before guix shell was invoked. The next garbage collection (see Вызов guix gc) may clean up packages that were installed in the environment and that are no longer used outside of it.

As an added convenience, guix shell will try to do what you mean when it is invoked interactively without any other arguments as in:

guix shell

If it finds a manifest.scm in the current working directory or any of its parents, it uses this manifest as though it was given via --manifest. Likewise, if it finds a guix.scm in the same directories, it uses it to build a development profile as though both --development and --file were present. In either case, the file will only be loaded if the directory it resides in is listed in ~/.config/guix/shell-authorized-directories. This provides an easy way to define, share, and enter development environments.

By default, the shell session or command runs in an augmented environment, where the new packages are added to search path environment variables such as PATH. You can, instead, choose to create an isolated environment containing nothing but the packages you asked for. Passing the --pure option clears environment variable definitions found in the parent environment14; passing --container goes one step further by spawning a container isolated from the rest of the system:

guix shell --container emacs gcc-toolchain

The command above spawns an interactive shell in a container where nothing but emacs, gcc-toolchain, and their dependencies is available. The container lacks network access and shares no files other than the current working directory with the surrounding environment. This is useful to prevent access to system-wide resources such as /usr/bin on foreign distros.

This --container option can also prove useful if you wish to run a security-sensitive application, such as a web browser, in an isolated environment. For example, the command below launches Ungoogled-Chromium in an isolated environment, which:

  • shares network access with the host
  • inherits host’s environment variables DISPLAY and XAUTHORITY
  • has access to host’s authentication records from the XAUTHORITY file
  • has no information about host’s current directory
guix shell --container --network --no-cwd ungoogled-chromium \
  --preserve='^XAUTHORITY$' --expose="${XAUTHORITY}" \
  --preserve='^DISPLAY$' -- chromium

guix shell определяет переменную GUIX_ENVIRONMENT в оболочке, которую создаёт; её значением является имя файла профиля этого окружения. Это позволяет пользователям, скажем, определить специфичные значения окружений разработки в .bashrc (see Bash Startup Files in The GNU Bash Reference Manual):

if [ -n "$GUIX_ENVIRONMENT" ]
then
    export PS1="\u@\h \w [dev]\$ "
fi

... или просмотеть профиль:

$ ls "$GUIX_ENVIRONMENT/bin"

Доступные опции резюмированы ниже.

--check

Set up the environment and check whether the shell would clobber environment variables. It’s a good idea to use this option the first time you run guix shell for an interactive session to make sure your setup is correct.

For example, if the shell modifies the PATH environment variable, report it since you would get a different environment than what you asked for.

Such problems usually indicate that the shell startup files are unexpectedly modifying those environment variables. For example, if you are using Bash, make sure that environment variables are set or modified in ~/.bash_profile and not in ~/.bashrc—the former is sourced only by log-in shells. See Bash Startup Files in The GNU Bash Reference Manual, for details on Bash start-up files.

--development
-D

Cause guix shell to include in the environment the dependencies of the following package rather than the package itself. This can be combined with other packages. For instance, the command below starts an interactive shell containing the build-time dependencies of GNU Guile, plus Autoconf, Automake, and Libtool:

guix shell -D guile autoconf automake libtool
--expression=expr
-e expr

Создать окружение для пакета или списка пакетов, которые соответствуют выражению expr.

Например, запуск:

guix shell -D -e '(@ (gnu packages maths) petsc-openmpi)'

запускает оболочку с окружением для этого специфического варианта пакета PETSc.

Запуск:

guix shell -e '(@ (gnu) %base-packages)'

стартует оболочку со всеми доступными базовыми пакетами.

Команды выше используют только выход по умолчанию обозначенных пакетов. Чтобы выбрать другие выходы, можно указать два элемента кортежей:

guix shell -e '(list (@ (gnu packages bash) bash) "include")'

See package->development-manifest, for information on how to write a manifest for the development environment of a package.

--file=file
-f file

Create an environment containing the package or list of packages that the code within file evaluates to.

Например, file может содержать определение (see Описание пакетов):

(use-modules (guix)
             (gnu packages gdb)
             (gnu packages autotools)
             (gnu packages texinfo))

;; Augment the package definition of GDB with the build tools
;; needed when developing GDB (and which are not needed when
;; simply installing it.)
(package
  (inherit gdb)
  (native-inputs (modify-inputs (package-native-inputs gdb)
                   (prepend autoconf-2.69 automake texinfo))))

With the file above, you can enter a development environment for GDB by running:

guix shell -D -f gdb-devel.scm
--manifest=file
-m file

Создать окружение для пакетов, содержащихся в объекте манифеста, возвращаемого кодом Scheme в файле file.

Это то же, что опция с таким же именем в guix package (see --manifest) и использует такие же файлы манифестов.

See Writing Manifests, for information on how to write a manifest. See --export-manifest below on how to obtain a first manifest.

--export-manifest

Write to standard output a manifest suitable for --manifest corresponding to given command-line options.

This is a way to “convert” command-line arguments into a manifest. For example, imagine you are tired of typing long lines and would like to get a manifest equivalent to this command line:

guix shell -D guile git emacs emacs-geiser emacs-geiser-guile

Just add --export-manifest to the command line above:

guix shell --export-manifest \
  -D guile git emacs emacs-geiser emacs-geiser-guile

... and you get a manifest along these lines:

(concatenate-manifests
  (list (specifications->manifest
          (list "git"
                "emacs"
                "emacs-geiser"
                "emacs-geiser-guile"))
        (package->development-manifest
          (specification->package "guile"))))

You can store it into a file, say manifest.scm, and from there pass it to guix shell or indeed pretty much any guix command:

guix shell -m manifest.scm

Voilà, you’ve converted a long command line into a manifest! That conversion process honors package transformation options (see Параметры преобразования пакета) so it should be lossless.

--profile=profile
-p profile

Создает окружение, содержащее пакеты, установленные в profile. Используйте guix package (see Вызов guix package) для создания и управления профилями.

--pure

Сброс существующих переменных окружения при сборке нового окружения, кроме обозначенных в опции --preserve (смотрите ниже). Эффект этой опции — создание окружения, в котором пути поиска содержат только входные данные пакета.

--preserve=regexp
-E regexp

При использовании вместе с --pure, оставить содержимое переменных окружения, соответствующих выражению regexp — другими словами, включить их в "белый список" переменных окружения, которые не должны обнуляться. Эту опцию можно повторять несколько раз.

guix shell --pure --preserve=^SLURM openmpi … \
  -- mpirun …

Этот пример запускает mpirun в контексте, в котором определены только следующие переменные окружения: PATH, переменные окружения, чьи имена начинаются с ‘SLURM’, а также обычные "дорогие" переменные (HOME, USER, и т.д.).

--search-paths

Отобразить определения переменных окружения, которые составляют окружение.

--system=system
-s system

Попытаться собрать систему system, то есть i686-linux.

--container
-C

Запустить command в изолированном контейнере. Текущая рабочая директория за пределами контейнера отображается внутри контейнера. В дополнение, если это не переопределено опцией --user, тогда настраивается фиктивная домашняя директория, которая совпадает с домашней директорией текущего пользователя, а также соответствующий файл /etc/passwd.

Порождаемый процесс снаружи предстаёт как запущенный от текущего пользователя. Внутри контейнера он имеет такие же UID и GID, что и текущий пользователь, если не обозначена --user (смотрите ниже).

--network
-N

Разделять пространство сетевых имён контейнера с хостящей системой. Контейнеры, созданные без этого флага, могут только иметь доступ к петлевому устройству.

--link-profile
-P

Связать профиль окружения контейнера с ~/.guix-profile внутри контейнера. Это эквивалент запуска команды ln -s $GUIX_ENVIRONMENT ~/.guix-profile внутри контейнера. Связывание завершится ошибкой и отменит создание окружения, если директория уже существует, что, конечно, будет происходить, если guix shell вызвана в домашней директории пользователя.

Определённые пакеты сконфигурированы, чтобы смотреть конфигурационные файлы и данные в ~/.guix-profile;15 --link-profile позволяет этим программам вести себя ожидаемо внутри окружения.

--user=user
-u user

Использовать в контейнере имя пользователя user вместо текущего пользователя. Созданная внутри контейнера запись /etc/passwd будет содержать имя user, домашняя директория будет /home/user, но не будут копированы пользовательские данные GECOS. Более того, внутри контейнера UID и GID будут 1000. user не обязательно должен существовать в системе.

В дополнение, любой разделяемый или расширяемый путь (смотрите --share и --expose соответственно), чьи цели находятся в домашней директории пользователя, будут отображены соответственно в /home/USER; это включает автоматическое отображение текущей рабочей директории.

# will expose paths as /home/foo/wd, /home/foo/test, and /home/foo/target
cd $HOME/wd
guix shell --container --user=foo \
     --expose=$HOME/test \
     --expose=/tmp/target=$HOME/target

Это ограничит утечку данных идентификации пользователя через домашние пути и каждое из полей пользователя. Это один единственный компонент расширенного решения приватности/анонимности — ничто не войдёт, ничто не выйдет.

--no-cwd

Для контейнеров стандартным поведением является разделение текущего рабочего каталога с изолированным контейнером и немедленное переключение на этот каталог в контейнере. Если это нежелательно, --no-cwd приведет к автоматическому доступу к текущему рабочему каталогу not, который изменится на домашний каталог пользователя в контейнере. Смотрите также --user.

--expose=source[=target]
--share=source[=target]

Расширить файловую систему контейнера источником source из хостящей системы в качестве файловой системы только для чтения с целью target внутри контейнера. Если цель target не задана, источник source используется как целевая точка монтирования в контейнере.

Пример ниже порождает Guile REPL в контейнере, в котором домашняя директория пользователя доступна только для чтения через директорию /exchange:

guix shell --container --expose=$HOME=/exchange guile -- guile
--symlink=spec
-S spec

For containers, create the symbolic links specified by spec, as documented in pack-symlink-option.

--emulate-fhs
-F

When used with --container, emulate a Filesystem Hierarchy Standard (FHS) configuration within the container, providing /bin, /lib, and other directories and files specified by the FHS.

As Guix deviates from the FHS specification, this option sets up the container to more closely mimic that of other GNU/Linux distributions. This is useful for reproducing other development environments, testing, and using programs which expect the FHS specification to be followed. With this option, the container will include a version of glibc that will read /etc/ld.so.cache within the container for the shared library cache (contrary to glibc in regular Guix usage) and set up the expected FHS directories: /bin, /etc, /lib, and /usr from the container’s profile.

--nesting
-W

When used with --container, provide Guix inside the container and arrange so that it can interact with the build daemon that runs outside the container. This is useful if you want, within your isolated container, to create other containers, as in this sample session:

$ guix shell -CW coreutils
[env]$ guix shell -C guile -- guile -c '(display "hello!\n")'
hello!
[env]$ exit

The session above starts a container with coreutils programs available in PATH. From there, we spawn guix shell to create a nested container that provides nothing but Guile.

Another example is evaluating a guix.scm file that is untrusted, as shown here:

guix shell -CW -- guix build -f guix.scm

The guix build command as executed above can only access the current directory.

Under the hood, the -W option does several things:

  • отобразит сокет демона (по умолчанию /var/guix/daemon-socket/socket) внутри контейнера;
  • map the whole store (by default /gnu/store) inside the container such that store items made available by nested guix invocations are visible;
  • add the currently-used guix command to the profile in the container, such that guix describe returns the same state inside and outside the container;
  • share the cache (by default ~/.cache/guix) with the host, to speed up operations such as guix time-machine and guix shell.
--rebuild-cache

In most cases, guix shell caches the environment so that subsequent uses are instantaneous. Least-recently used cache entries are periodically removed. The cache is also invalidated, when using --file or --manifest, anytime the corresponding file is modified.

The --rebuild-cache forces the cached environment to be refreshed. This is useful when using --file or --manifest and the guix.scm or manifest.scm file has external dependencies, or if its behavior depends, say, on environment variables.

--root=file
-r file

Создать символическую ссылку file на профиль этого окружения и зарегистрировать её как корень сборщика мусора.

Это полезно, если вы хотите защитить своё окружение от сборщика мусора, сделать его "постоянным".

When this option is omitted, guix shell caches profiles so that subsequent uses of the same environment are instantaneous—this is comparable to using --root except that guix shell takes care of periodically removing the least-recently used garbage collector roots.

In some cases, guix shell does not cache profiles—e.g., if transformation options such as --with-latest are used. In those cases, the environment is protected from garbage collection only for the duration of the guix shell session. This means that next time you recreate the same environment, you could have to rebuild or re-download packages.

See Вызов guix gc, for more on GC roots.

guix shell также поддерживает все обычные опции сборки, которые поддерживает команда guix build (see Стандартные параметры сборки), а также опции трансформации пакета (see Параметры преобразования пакета).


7.2 Вызов guix environment

The purpose of guix environment is to assist in creating development environments.

Deprecation warning: The guix environment command is deprecated in favor of guix shell, which performs similar functions but is more convenient to use. See Вызов guix shell.

Being deprecated, guix environment is slated for eventual removal, but the Guix project is committed to keeping it until May 1st, 2023. Please get in touch with us at guix-devel@gnu.org if you would like to discuss it.

Основной синтаксис:

guix environment options package

Следующий пример порождает новую оболочку, установленную для разработки GNU Guile:

guix environment guile

Если необходимые зависимости еще не собраны, guix environment автоматически построит их. Среда новой оболочки - это расширенная версия среды, в которой была запущена guix environment. Она содержит необходимые пути поиска для сборки данного пакета, добавленные к существующим переменным среды. Чтобы создать “чистую” среду, в которой исходные переменные среды не были установлены, используйте параметр --pure 16.

Выход из окружения Guix аналогичен выходу из оболочки и возвращает пользователя в старое окружение до вызова guix environment. Следующая сборка мусора (see Вызов guix gc) очистит пакеты, которые были установлены в окружении и больше не используются за ее пределами.

guix environment определяет переменную GUIX_ENVIRONMENT в оболочке, которую создаёт; её значением является имя файла профиля этого окружения. Это позволяет пользователям, скажем, определить специфичные значения окружений разработки в .bashrc (see Bash Startup Files in The GNU Bash Reference Manual):

if [ -n "$GUIX_ENVIRONMENT" ]
then
    export PS1="\u@\h \w [dev]\$ "
fi

... или просмотеть профиль:

$ ls "$GUIX_ENVIRONMENT/bin"

Дополним, что может быть указано более одного пакета, в таком случае используется объединённые входные данные для указанных пакетов. Например, команда ниже порождает оболочку, в котором доступны все зависимости, как Guile, так и Emacs:

guix environment guile emacs

Иногда интерактивная сессия оболочки не нужна. Можно вызвать произвольную команду при указании токена --, который отделяет команду от остальных аргументов:

guix environment guile -- make -j4

In other situations, it is more convenient to specify the list of packages needed in the environment. For example, the following command runs python from an environment containing Python 3 and NumPy:

guix environment --ad-hoc python-numpy python -- python3

Более того, возможно, вам потребуются зависимости пакета, а также некоторые дополнительные пакеты, которые не являются зависимостями процесса сборки или процесса исполнения (работы), но важны при разработке. Для этого и указан флаш --ad-hoc. Пакеты, обозначенные до --ad-hoc интерпретируются как пакеты, чьи зависимости будут добавлены в окружение. Пакеты, которые обозначены после --ad-hoc, интерпретируются как пакеты, которые будут добавлены в окружение непосредственно. Например, следующая команда создаёт окружение разработки Guix, которая в дополнение включает Git и strace:

guix environment guix --ad-hoc git strace

Иногда возникает необходимость изолировать окружение настолько, насколькоо возможно, для максимальной чистоты и воспроизводимости. В частности, при использовании Guix на дистрибутиве, отличном от системы Guix, желательно предотвращать доступ из окружения разработки к /usr/bin и другим ресурсам системы. Например, следующая команда порождает Guile REPL в "контейнере", в котором монтированы только склад и текущая рабочая директория:

guix environment --ad-hoc --container guile -- guile

Примечание: Опция --container требует Linux-libre 3.19 или новее.

Другой типичный вариант использования контейнеров - запуск приложений, чувствительных к безопасности, таких как веб-браузер. Чтобы запустить Eolie, мы должны предоставить доступ к некоторым файлам и каталогам; мы используем nss-certs и предоставляем /etc /ssl /certs/ для аутентификации HTTPS; наконец, мы сохраняем переменную среды DISPLAY, поскольку контейнерные графические приложения не будут отображаться без нее.

guix environment --preserve='^DISPLAY$' --container --network \
  --expose=/etc/machine-id \
  --expose=/etc/ssl/certs/ \
  --share=$HOME/.local/share/eolie/=$HOME/.local/share/eolie/ \
  --ad-hoc eolie nss-certs dbus --  eolie

Доступные опции резюмированы ниже.

--check

Set up the environment and check whether the shell would clobber environment variables. See --check, for more info.

--root=file
-r file

Создать символическую ссылку file на профиль этого окружения и зарегистрировать её как корень сборщика мусора.

Это полезно, если вы хотите защитить своё окружение от сборщика мусора, сделать его "постоянным".

Если эта опция пропущена, окружеие защищено от сборщика мусора только на время сессии guix environment. Это означает, что в следующий раз, когда вы создадите такое же окружение, вам потребуется пересобирать и скачивать пакеты заново. See Вызов guix gc, for more on GC roots.

--expression=expr
-e expr

Создать окружение для пакета или списка пакетов, которые соответствуют выражению expr.

Например, запуск:

guix environment -e '(@ (gnu packages maths) petsc-openmpi)'

запускает оболочку с окружением для этого специфического варианта пакета PETSc.

Запуск:

guix environment --ad-hoc -e '(@ (gnu) %base-packages)'

стартует оболочку со всеми доступными базовыми пакетами.

Команды выше используют только выход по умолчанию обозначенных пакетов. Чтобы выбрать другие выходы, можно указать два элемента кортежей:

guix environment --ad-hoc -e '(list (@ (gnu packages bash) bash) "include")'
--load=file
-l file

Создать окружение для пакета или списка пакетов, код которых задан в файле file.

Например, file может содержать определение (see Описание пакетов):

(use-modules (guix)
             (gnu packages gdb)
             (gnu packages autotools)
             (gnu packages texinfo))

;; Augment the package definition of GDB with the build tools
;; needed when developing GDB (and which are not needed when
;; simply installing it.)
(package
  (inherit gdb)
  (native-inputs (modify-inputs (package-native-inputs gdb)
                   (prepend autoconf-2.69 automake texinfo))))
--manifest=file
-m file

Создать окружение для пакетов, содержащихся в объекте манифеста, возвращаемого кодом Scheme в файле file.

Это то же, что опция с таким же именем в guix package (see --manifest) и использует такие же файлы манифестов.

See guix shell --export-manifest, for information on how to “convert” command-line options into a manifest.

--ad-hoc

Включить все указанные пакеты в результирующее окружение, если бы целевой (лат. ad hoc) пакет имел бы их как входные данные. Эта опция полезна для быстрого создания окружения без необходимости писать выражение типа пакет, содержащее желаемые входные данные.

Например, команда:

guix environment --ad-hoc guile guile-sdl -- guile

запускает guile в окружении, в котором доступны Guile и Guile-SDL.

Отметим, что этот пример явно запрашивает выходы guile и guile-sdl по умолчанию, но возможно запросить специфичный выход, то есть glib:bin запрашивает выход bin из glib (see Пакеты со множественным выходом).

Эта опция может сочетаться с поведением по умолчанию guix environment. Пакеты, которые появляются до --ad-hoc интерпретируются как пакеты, чьи зависимости будут добавлены в окружение (поведение по умолчанию). Пакеты, которые появляются после этой опции, интерпретируются как пакеты, которые будут добавлены в окружение непосредственно.

--profile=profile
-p profile

Создает окружение, содержащее пакеты, установленные в profile. Используйте guix package (see Вызов guix package) для создания и управления профилями.

--pure

Сброс существующих переменных окружения при сборке нового окружения, кроме обозначенных в опции --preserve (смотрите ниже). Эффект этой опции — создание окружения, в котором пути поиска содержат только входные данные пакета.

--preserve=regexp
-E regexp

При использовании вместе с --pure, оставить содержимое переменных окружения, соответствующих выражению regexp — другими словами, включить их в "белый список" переменных окружения, которые не должны обнуляться. Эту опцию можно повторять несколько раз.

guix environment --pure --preserve=^SLURM --ad-hoc openmpi … \
  -- mpirun …

Этот пример запускает mpirun в контексте, в котором определены только следующие переменные окружения: PATH, переменные окружения, чьи имена начинаются с ‘SLURM’, а также обычные "дорогие" переменные (HOME, USER, и т.д.).

--search-paths

Отобразить определения переменных окружения, которые составляют окружение.

--system=system
-s system

Попытаться собрать систему system, то есть i686-linux.

--container
-C

Запустить command в изолированном контейнере. Текущая рабочая директория за пределами контейнера отображается внутри контейнера. В дополнение, если это не переопределено опцией --user, тогда настраивается фиктивная домашняя директория, которая совпадает с домашней директорией текущего пользователя, а также соответствующий файл /etc/passwd.

Порождаемый процесс снаружи предстаёт как запущенный от текущего пользователя. Внутри контейнера он имеет такие же UID и GID, что и текущий пользователь, если не обозначена --user (смотрите ниже).

--network
-N

Разделять пространство сетевых имён контейнера с хостящей системой. Контейнеры, созданные без этого флага, могут только иметь доступ к петлевому устройству.

--link-profile
-P

Связать профиль окружения контейнера с ~/.guix-profile внутри контейнера. Это эквивалент запуска команды ln -s $GUIX_ENVIRONMENT ~/.guix-profile внутри контейнера. Связывание завершится ошибкой и отменит создание окружения, если директория уже существует, что, конечно, будет происходить, если guix environment вызвана в домашней директории пользователя.

Определённые пакеты сконфигурированы, чтобы смотреть конфигурационные файлы и данные в ~/.guix-profile;17 --link-profile позволяет этим программам вести себя ожидаемо внутри окружения.

--user=user
-u user

Использовать в контейнере имя пользователя user вместо текущего пользователя. Созданная внутри контейнера запись /etc/passwd будет содержать имя user, домашняя директория будет /home/user, но не будут копированы пользовательские данные GECOS. Более того, внутри контейнера UID и GID будут 1000. user не обязательно должен существовать в системе.

В дополнение, любой разделяемый или расширяемый путь (смотрите --share и --expose соответственно), чьи цели находятся в домашней директории пользователя, будут отображены соответственно в /home/USER; это включает автоматическое отображение текущей рабочей директории.

# will expose paths as /home/foo/wd, /home/foo/test, and /home/foo/target
cd $HOME/wd
guix environment --container --user=foo \
     --expose=$HOME/test \
     --expose=/tmp/target=$HOME/target

Это ограничит утечку данных идентификации пользователя через домашние пути и каждое из полей пользователя. Это один единственный компонент расширенного решения приватности/анонимности — ничто не войдёт, ничто не выйдет.

--no-cwd

Для контейнеров стандартным поведением является разделение текущего рабочего каталога с изолированным контейнером и немедленное переключение на этот каталог в контейнере. Если это нежелательно, --no-cwd приведет к автоматическому доступу к текущему рабочему каталогу not, который изменится на домашний каталог пользователя в контейнере. Смотрите также --user.

--expose=source[=target]
--share=source[=target]

Расширить файловую систему контейнера источником source из хостящей системы в качестве файловой системы только для чтения с целью target внутри контейнера. Если цель target не задана, источник source используется как целевая точка монтирования в контейнере.

Пример ниже порождает Guile REPL в контейнере, в котором домашняя директория пользователя доступна только для чтения через директорию /exchange:

guix environment --container --expose=$HOME=/exchange --ad-hoc guile -- guile
--emulate-fhs
-F

For containers, emulate a Filesystem Hierarchy Standard (FHS) configuration within the container, see the official specification. As Guix deviates from the FHS specification, this option sets up the container to more closely mimic that of other GNU/Linux distributions. This is useful for reproducing other development environments, testing, and using programs which expect the FHS specification to be followed. With this option, the container will include a version of glibc which will read /etc/ld.so.cache within the container for the shared library cache (contrary to glibc in regular Guix usage) and set up the expected FHS directories: /bin, /etc, /lib, and /usr from the container’s profile.

guix environment также поддерживает все обычные опции сборки, которые поддерживает команда guix build (see Стандартные параметры сборки), а также опции трансформации пакета (see Параметры преобразования пакета).


7.3 Вызов guix pack

Иногда бывает необходимо передать программу людям, которые (ещё!) не являются счастливыми обладателями Guix. Вы могли бы им рекомендовать заустить guix package -i something, но в данном случае это не подхлдит. Тогда guix pack решает вопрос.

Примечание: Если вы ищете способ обмена бинарниками между машинами, работающими с Guix, see Вызов guix copy, Вызов guix publish и Вызов guix archive.

Команда guix pack создаёт обёрнутый набор или программный набор: она создаёт архив tarball или другой архив, содержащий исполняемые файлы программного обеспечения, которое вас интересует, а также все его зависимости. Результирующий архив может использоваться на любой машине, которая не имеет Guix, а люди могут запустить совершенно такие же бинарники, как у вас в Guix. Набор создаётся со свойством воспроизводимости до бита, так что любой может проверить, что он действительно содержит результаты сборок, которые вы поставляете.

Например, чтобы создать набор, содержащий Guile, Emacs, Geiser и все их зависимости, можно запустить:

$ guix pack guile emacs geiser
…
/gnu/store/…-pack.tar.gz

Результатом будет архив tarball, содержащий директорию /gnu/store со всеми соответствующими пакетами. Результирующий архив содержат профиль с тремя запрошенными пакетами; профиль представляет то же самое, что можно создать командой guix package -i. Это механизм, который используется, собственно, для создания автономного (standalone) бинарного архива Guix (see Бинарная установка).

Пользователи этого пакета должны запускать /gnu/store/…-profile/bin/guile для запуска Guile, что может быть не удобно. Чтобы исправить это, можно создать, например, символическую ссылку /opt/gnu/bin на профиль:

guix pack -S /opt/gnu/bin=bin guile emacs geiser

Так пользователи смогут благополучно напечатать /opt/gnu/bin/guile, и всё хорошо.

Что если получатель вашего пакета не имеет привилегий root на своей машине, и поэтому не может распаковать его в корне файловой системы? В таком случае вам стоит использовать опцию --relocatable (смотрите ниже). Эта опция производит перемещаемые бинарники, в том плане, что они могут размещаться где угодно в иерархии файловой системы: в примере выше пользователи могут распаковать ваш архив в свои домашние директории и напрямую запустить ./opt/gnu/bin/guile.

В качестве альтернативы можно производить пакет в формате образа Docker, используя следующую команду:

guix pack -f docker guile emacs geiser

Результатом будет архив, который можно передать команде docker load, followed by docker run:

docker load < file
docker run -ti guile-guile-readline /bin/guile

where file is the image returned by guix pack, and guile-guile-readline is its “image tag”. See the Docker documentation for more information.

Ещё одна опция производит образ SquashFS следующей командой:

guix pack -f squashfs guile emacs geiser

Результатом будет образ файловой системы SquashFS, который может непосредственно монтироваться как образ, содержащий контейнер файловой системы, с помощью контейнерного окружения Singularity, используя команды типа singularity shell или singularity exec.

Несколько опций командной строки позволяют вам переделывать ваш пакет:

--format=format
-f format

Произвести пакет в указанном формате format.

Возможные форматы:

tarball

Это формат по умолчанию. Он производит архив tarball, содержащий все заданные бинарники и символические ссылки.

docker

This produces a tarball that follows the Docker Image Specification. By default, the “repository name” as it appears in the output of the docker images command is computed from package names passed on the command line or in the manifest file. Alternatively, the “repository name” can also be configured via the --image-tag option. Refer to --help-docker-format for more information on such advanced options.

squashfs

Это создает образ SquashFS, содержащий все указанные двоичные файлы и символические ссылки, а также пустые точки монтирования для виртуальных файловых систем, таких как procfs.

Примечание: Singularity требует, чтобы вы указали /bin /sh в образе. По этой причине guix pack -f squashfs всегда подразумевает -S /bin=bin. Таким образом, вызов guix pack всегда должен начинаться с чего-то вроде:

guix pack -f squashfs guile emacs geiser

Если вы забудете пакет bash (или аналогичный), singularity run и singularity exec выдаст бесполезное сообщение “нет такого файла или каталога”.

deb

This produces a Debian archive (a package with the ‘.deb’ file extension) containing all the specified binaries and symbolic links, that can be installed on top of any dpkg-based GNU(/Linux) distribution. Advanced options can be revealed via the --help-deb-format option. They allow embedding control files for more fine-grained control, such as activating specific triggers or providing a maintainer configure script to run arbitrary setup code upon installation.

guix pack -f deb -C xz -S /usr/bin/hello=bin/hello hello

Примечание: Because archives produced with guix pack contain a collection of store items and because each dpkg package must not have conflicting files, in practice that means you likely won’t be able to install more than one such archive on a given system. You can nonetheless pack as many Guix packages as you want in one such archive.

Внимание: dpkg will assume ownership of any files contained in the pack that it does not know about. It is unwise to install Guix-produced ‘.deb’ files on a system where /gnu/store is shared by other software, such as a Guix installation or other, non-deb packs.

rpm

This produces an RPM archive (a package with the ‘.rpm’ file extension) containing all the specified binaries and symbolic links, that can be installed on top of any RPM-based GNU/Linux distribution. The RPM format embeds checksums for every file it contains, which the rpm command uses to validate the integrity of the archive.

Advanced RPM-related options are revealed via the --help-rpm-format option. These options allow embedding maintainer scripts that can run before or after the installation of the RPM archive, for example.

The RPM format supports relocatable packages via the --prefix option of the rpm command, which can be handy to install an RPM package to a specific prefix.

guix pack -f rpm -R -C xz -S /usr/bin/hello=bin/hello hello
sudo rpm --install --prefix=/opt /gnu/store/...-hello.rpm

Примечание: Contrary to Debian packages, conflicting but identical files in RPM packages can be installed simultaneously, which means multiple guix pack-produced RPM packages can usually be installed side by side without any problem.

Внимание: rpm assumes ownership of any files contained in the pack, which means it will remove /gnu/store upon uninstalling a Guix-generated RPM package, unless the RPM package was installed with the --prefix option of the rpm command. It is unwise to install Guix-produced ‘.rpm’ packages on a system where /gnu/store is shared by other software, such as a Guix installation or other, non-rpm packs.

--relocatable
-R

Создавать relocatable binaries — то есть двоичные файлы, которые можно разместить в любом месте иерархии файловой системы и запускать оттуда.

Когда эта опция передается один раз, конечные двоичные файлы требуют поддержки user namespaces в ядре Linux; при передаче дважды18, Relocatable двоичные файлы возвращаются к другим методам, если пользовательские пространства имен недоступны, и по существу работают где угодно - см. ниже что под этим подразумевается.

Например, если вы создаете пакет, содержащий Bash, с помощью:

guix pack -RR -S /mybin=bin bash

... вы можете скопировать этот пакет на машину, на которой отсутствует Guix, и из своего домашнего каталога как обычный пользователь запустите:

tar xf pack.tar.gz
./mybin/sh

В этой оболочке, если вы наберете ls /gnu/store, вы заметите, что отобразятся /gnu/store и содержатся все зависимости bash, даже если на машине нет /gnu/store! Это, вероятно, самый простой способ установить программное обеспечение, созданное с помощью Guix, на машине, отличной от Guix.

Примечание: По умолчанию relocatable двоичные файлы полагаются на функцию user namespace ядра Linux, которая позволяет непривилегированным пользователям монтировать или изменять root. Старые версии Linux не поддерживали его, а некоторые дистрибутивы GNU/Linux его отключили.

Чтобы создать relocatable двоичные файлы, которые работают даже при отсутствии пользовательских пространств имен, передайте --relocatable или -R дважды. В этом случае двоичные файлы будут пытаться использовать пространство имен пользователей и возвращаться к другому механизму выполнения, если пространства имен пользователей не поддерживаются. Поддерживаются следующие механизмы выполнения:

по умолчанию

Попробовать использовать пространства имен пользователей и вернуться к PRoot, если пространства имен пользователей не поддерживаются (см. ниже).

форматирование кода

Попробовать использовать пространства имен пользователей и вернуться к Fakechroot, если пространства имен пользователей не поддерживаются (см. ниже).

user

Запустить программу через пользовательские пространства имен и прервать, если они не поддерживаются.

chroot

Запустить PRoot. Программа PRoot обеспечивает необходимую поддержку виртуализации файловой системы. Это достигается с помощью системного вызова ptrace в запущенной программе. Преимущество этого подхода заключается в том, что это не требует специальной поддержки ядра, но это требует дополнительных затрат времени выполнения каждый раз, когда выполняется системный вызов.

chroot

Запустить Fakechroot. Fakechroot виртуализирует доступ к файловой системе путем перехвата вызовов функций библиотеки C, таких как open, stat, exec и т.п. В отличие от PRoot, накладных расходов очень мало. Однако это не всегда работает: например, некоторые обращения к файловой системе, сделанные из библиотеки C, не перехватываются, а обращения к файловой системе, сделанные через прямые системные вызовы, также не перехватываются, что приводит к нестабильному поведению.

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

--commit=commit

Используйте command в качестве точки входа конечного пакета, если формат пакета поддерживает это — в настоящее время docker и squashfs (Singularity) поддерживают это. command должна относиться к профилю, содержащемуся в пакете.

Точка входа указывает команду, которую по умолчанию автоматически запускают такие инструменты, как docker run или singularity run. Например, вы можете сделать:

guix pack -f docker guile emacs geiser

Полученный пакет может быть легко импортирован, и запущен через docker run без дополнительных аргументов, пораждая bin/guile:

docker load -i pack.tar.gz
docker run image-id
--entry-point-argument=command
-A command

Use command as an argument to entry point of the resulting pack. This option is only valid in conjunction with --entry-point and can appear multiple times on the command line.

guix pack -f docker --entry-point=bin/guile --entry-point-argument="--help" guile
--max-layers=n

Specifies the maximum number of Docker image layers allowed when building an image.

guix pack -f docker --max-layers=100 guile

This option allows you to limit the number of layers in a Docker image. Docker images are comprised of multiple layers, and each layer adds to the overall size and complexity of the image. By setting a maximum number of layers, you can control the following effects:

  • Disk Usage: Increasing the number of layers can help optimize the disk space required to store multiple images built with a similar package graph.
  • Pulling: When transferring images between different nodes or systems, having more layers can reduce the time required to pull the image.
--expression=expr
-e expr

Процедура, при выполнении которой возвращается пакет.

Это то же, что опция с таким же именем в guix package (see --manifest) и использует такие же файлы манифестов.

--manifest=file
-m file

Использовать пакеты, содержащиеся в объекте манифеста, возвращенном кодом Scheme в file. Эта опция может быть указана несколько раз, и в этом случае манифесты объединяются.

Она служит для того же, что и одноименная опция в guix package (see --manifest) и использует те же файлы манифеста. Она позволяет вам один раз определить набор пакетов и использовать его как для создания профилей, так и для создания архивов для использования на машинах, на которых не установлен Guix. Обратите внимание, что вы можете указать либо файл манифеста либо список пакетов, но не то и другое вместе.

See Writing Manifests, for information on how to write a manifest. See guix shell --export-manifest, for information on how to “convert” command-line options into a manifest.

--system=system
-s system

Предпринять попытку собрать систему system, т.е. i686-linux, вместо типа системы хоста сборки.

--target=triplet

Cross-сборка для triplet, который должен быть допустимым GNU triplet, например \ "aarch64-linux-gnu\" (see GNU configuration triplets in Autoconf).

--compression=tool
-C tool

Архивировать логи сборки методом type. Это один из: gzip, bzip2 или none.

--symlink=spec
-S spec

Добавить в пакет символические ссылки, указанные в spec. Эта опция может быть указана несколько раз.

spec имеет вид source=target, где source - это символическая ссылка, которая будет создана, а target - это цель символьной ссылки.

Например, -S /opt/gnu/bin=bin создает символическую ссылку /opt/gnu/bin, указывающую на подкаталог bin профиля.

--save-provenance

Сохранить информацию о происхождении пакетов, переданных в командной строке. Информация о происхождении включает в себя URL и фиксацию используемых каналов (see Каналы).

Информация о происхождении сохраняется в файле /gnu/store/…-profile/manifest в пакете вместе с обычными метаданными пакета - названием и версией каждого пакета, их propagated inputs и т.п. Это полезная информация для получателя pack, который исходя из нее знает, как (предположительно) был собран pack.

Этот параметр не включен по умолчанию, поскольку, как и временные метки, информация о происхождении не влияет на процесс сборки. Другими словами, существует бесконечное количество URL-адресов каналов и ID коммитов, которые могут привести к одному и тому же pack. Таким образом, запись таких “тихих” метаданных в output потенциально нарушает свойство побитовой воспроизводимости.

--root=file
-r file

Создать символическую ссылку file на профиль этого окружения и зарегистрировать её как корень сборщика мусора.

--localstatedir
--profile-name=name

Включите в конечный пакет “локальный каталог состояния”, /var/guix и, в частности, профиль /var/guix/profiles/per-user/root/name — по умолчанию name - это guix-profile, что соответствует ~root/.guix-profile.

/var/guix содержит базу данных store (see Хранилище), а также корни сборщика мусора (see Вызов guix gc). Предоставление ее в pack означает, что store является “полным” и управляемым Guix; отсутствие в pack означает, что store “мертв”: пакеты нельзя добавить в него или удалить из него после извлечения pack.

Одним из вариантов использования является включающий себя двоичный архив Guix (see Бинарная установка).

--derivation
-d

Выведите имя derivation, которая создает pack.

--bootstrap

Использовать bootstrap бинарники для сборки пакета. Эта опция полезна только разработчикам Guix.

Кроме того, guix pack поддерживает все стандартные параметры сборки (see Стандартные параметры сборки) и все параметры преобразования пакетов (see Параметры преобразования пакета).


7.4 Тулчейн GCC

Guix предлагает индивидуальные пакеты компиляторов, как например, gcc. Но если вам необходим полный набор инструментов (тулчейн) для компиляции и линковки исходного кода, тогда то, что вам действительно нужно, — это пакет gcc-toolchain. Этот пакет предоставляет полный тулчейн GCC для разработки C/C++, включая сам GCC, библиотеку GNU C (заголовки и бинарники, а также отладочные символы в выходе debug), Binutils и набор линковщика.

Цель оболочки — проверять опции -L и -l, направленные линковщику, и соответствующие аргументы -rpath, и вызывать соответствующий линковщик с этим новым набором аргументов. Вы можете указать оболочке отклонять линковку с библиотеками, находящимися не на складе, установив переменную окружения GUIX_LD_WRAPPER_ALLOW_IMPURITIES в значение no.

Пакет gfortran-toolchain предоставляет полный набор инструментов GCC для разработки Fortran. Для других языков используйте ‘guix search gcc toolchain’ (see Invoking guix package).


7.5 Вызов guix package

Команда guix git Authenticate аутентифицирует проверку Git по тому же правилу, что и для каналов (see channel authentication). То есть, начиная с данного коммита, он гарантирует, что все последующие коммиты подписаны ключом OpenPGP, отпечаток которого указан в файле .guix-authorizations его родительского коммита(ов).

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

Основной синтаксис:

guix environment options package

By default, this command authenticates the Git checkout in the current directory; it outputs nothing and exits with exit code zero on success and non-zero on failure. commit above denotes the first commit where authentication takes place, and signer is the OpenPGP fingerprint of public key used to sign commit. Together, they form a channel introduction (see channel introduction). On your first successful run, the introduction is recorded in the .git/config file of your checkout, allowing you to omit them from subsequent invocations:

guix git authenticate [options…]

Should you have branches that require different introductions, you can specify them directly in .git/config. For example, if the branch called personal-fork has a different introduction than other branches, you can extend .git/config along these lines:

[guix "authentication-personal-fork"]
	introduction-commit = cabba936fd807b096b48283debdcddccfea3900d
	introduction-signer = C0FF EECA BBA9 E6A8 0D1D  E643 A2A0 6DF2 A33A 54FA
	keyring = keyring

The first run also attempts to install pre-push and post-merge hooks, such that guix git authenticate is invoked as soon as you run git push, git pull, and related commands; it does not overwrite preexisting hooks though.

The command-line options described below allow you to fine-tune the process.

--extract=directory
-x directory

Открыть репозиторий Git в directory вместо текущего каталога.

--expression=expr
-F free

Загрузить связку ключей OpenPGP из reference, ссылки на branch, например origin/keyring или my-keyring. branch должна содержать открытые ключи OpenPGP в файлах .key либо в двоичной форме, либо в “ASCII-armored” виде. По умолчанию связка ключей загружается из branch с именем keyring.

--end=commit

Authenticate revisions up to commit.

--stats

Отобразить статистику подписания commit’ов по завершению.

--search=regexp

Ранее аутентифицированные коммиты кэшируются в файле под ~/.cache/guix/authentication. Эта опция заставляет хранить кеш в файле key в этом каталоге.

--install-from-file=file

По умолчанию любой коммит, родительский коммит которого не содержит файла .guix-authorizations, считается недостоверным. Напротив, эта опция учитывает авторизацию в file для любого коммита, в котором отсутствует .guix-authorizations. Формат file такой же, как у .guix-authorizations (see .guix-authorizations format).


8 Программный интерфейс

GNU Guix предоставляет несколько Scheme программных интерфейсов (API) для определения, сборки и запроса пакетов. Первый интерфейс позволяет пользователям писать высокоуровневые определения пакетов. Эти определения относятся к знакомым концепциям упаковки, таким как имя и версия пакета, его система сборки и зависимости. Затем эти определения можно превратить в конкретные действия по сборке.

Действия по сборке выполняются демоном Guix от имени пользователей. В стандартной настройке демон имеет доступ на запись в хранилище—каталог /gnu/store—, в то время как пользователи не имеют. Рекомендуемая установка также предусматривает, что демон выполняет сборки в chroot, под определенными пользователями сборки, чтобы минимизировать влияние на остальную систему.

Доступны API нижнего уровня для взаимодействия с демоном и хранилищем. Чтобы дать демону команду выполнить действие сборки, пользователи фактически предоставляют ему derivation. Derivation - это низкоуровневое представление действий сборки, которые должны быть предприняты, и среды, в которой они должны происходить - derivation’ы относятся к определениям пакетов, как сборка для программ на C. Термин “derivation” происходит от того факта, что результаты сборки производные от них.

This chapter describes all these APIs in turn, starting from high-level package definitions. See Структура исходного кода, for a more general overview of the source code.


8.1 Пакетные модули

С точки зрения программирования, определения пакетов дистрибутива GNU предоставляются модулями Guile в пространстве имен (gnu packages …) 19 (see Guile modules in GNU Guile Reference Manual)). Например, модуль (gnu packages emacs) экспортирует переменную с именем emacs, которая привязана к <package> объекту (see Описание пакетов).

Пространство имен модуля (gnu packages …) автоматически сканируется на наличие пакетов с помощью инструментов командной строки. Например, при запуске guix install emacs все модули (gnu packages …) сканируются до тех пор, пока не будет найден тот, который экспортирует объект пакета с именем emacs. Это средство поиска пакетов реализовано в модуле (gnu packages).

Пользователи могут хранить определения пакетов в модулях с разными именами - например, (my-packages emacs) 20. Есть два способа сделать эти определения пакетов видимыми для пользовательских интерфейсов:

  1. Добавить каталог, содержащий модули вашего пакета, в пути поиска с помощью флага -L команды guix package и другие команды (see Стандартные параметры сборки) или указать переменную окружения GUIX_PACKAGE_PATH, описанную ниже.
  2. Определить канал и настроить guix pull так, чтобы он учитывал его. Канал - это, по сути, репозиторий Git, содержащий модули пакетов. See Каналы, чтобы узнать больше о том, как определять и использовать каналы.

GUIX_PACKAGE_PATH работает аналогично другим переменным пути поиска:

Environment Variable: GUIX_PACKAGE_PATH

Это список каталогов, разделенных двоеточиями, для поиска дополнительных модулей пакета. Каталоги, перечисленные в этой переменной, имеют приоритет над собственными модулями дистрибутива.

Дистрибутив полностью bootstrapped и самодостаточный: каждый пакет построен исключительно на основе других пакетов в дистрибутиве. Корнем этого графа зависимостей является небольшой набор bootstrap бинарный файлы, предоставляемых модулем (gnu packages bootstrap). Для получения дополнительной информации о начальной загрузке see Начальная загрузка.


8.2 Описание пакетов

Интерфейс высокого уровня к определениям пакетов реализован в модулях (guix packages) и (guix build-system). Например, определение пакета или рецепта для пакета GNU Hello выглядит так:

(define-module (gnu packages hello)
  #:use-module (guix packages)
  #:use-module (guix download)
  #:use-module (guix build-system gnu)
  #:use-module (guix licenses)
  #:use-module (gnu packages gawk))

(define-public hello
  (package
    (name "hello")
    (version "2.10")
    (source (origin
              (method url-fetch)
              (uri (string-append "mirror://gnu/hello/hello-" version
                                  ".tar.gz"))
              (sha256
               (base32
                "0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i"))))
    (build-system gnu-build-system)
    (arguments '(#:configure-flags '("--enable-silent-rules")))
    (inputs (list gawk))
    (synopsis "Hello, GNU world: An example GNU package")
    (description "Guess what GNU Hello prints!")
    (home-page "https://www.gnu.org/software/hello/")
    (license gpl3+)))

Не будучи Scheme экспертом, вы можете догадаться о значении различных полей. Это выражение связывает переменную hello с объектом <package>, который по сути является record (see Scheme records in GNU Guile Reference Manual). Этот объект пакета можно проверить с помощью процедур из модуля (guix packages); например, (package-name hello) возвращает—сюрприз!—"hello".

Если повезет, вы сможете импортировать часть или все определение интересующего вас пакета из другого репозитория с помощью команды guix import (see Вызов guix import).

В приведенном выше примере hello определен в собственном модуле (gnu packages hello). Технически в этом нет строгой необходимости, но это удобно: все пакеты, определенные в модулях под (gnu packages …), автоматически становятся известны инструментам командной строки (see Пакетные модули).

В приведенном выше определении пакета стоит отметить несколько моментов:

  • Поле source пакета представляет собой объект <origin> (see origin Справка, for the complete reference). Здесь используется метод url-fetch из (guix download), что означает, что источником является файл, который нужно загрузить через FTP или HTTP.

    Префикс mirror://gnu указывает url-fetch использовать одно из зеркал GNU, определенных в (guix download).

    Поле sha256 указывает ожидаемый хэш SHA256 загружаемого файла. Это обязательно и позволяет Guix проверять целостность файла. Форма (base32 …) указывает представление хеша в формате base32. Вы можете получить эту информацию с помощью guix download (see Вызов guix download) guix hash (see Вызов guix hash).

    При необходимости форма origin может также иметь поле patches со списком исправлений, которые необходимо применить, и поле snippet, содержащее Scheme выражение для изменения исходного кода.

  • Поле build-system указывает процедуру сборки пакета (see Системы сборки). Здесь gnu-build-system представляет знакомую систему сборки GNU, в которой пакеты могут быть настроены, собраны и установлены с помощью обычной последовательности команд ./configure && make && make check && make install.

    Когда вы начинаете упаковывать нетривиальное программное обеспечение, вам могут потребоваться инструменты для управления этими этапами сборки, управления файлами и т.д. See Build Utilities, чтобы узнать об этом подробнее.

  • Поле arguments определяет параметры для системы сборки (see Системы сборки). В примере это интерпретируется gnu-build-system как запуск запроса configure с флагом --enable-silent-rules.

    What about these quote (') characters? They are Scheme syntax to introduce a literal list; ' is synonymous with quote. Sometimes you’ll also see ` (a backquote, synonymous with quasiquote) and , (a comma, synonymous with unquote). See quoting in GNU Guile Reference Manual, for details. Here the value of the arguments field is a list of arguments passed to the build system down the road, as with apply (see apply in GNU Guile Reference Manual).

    Последовательность хэш-двоеточие (#:) определяет Scheme ключевое слово (see Keywords in GNU Guile Reference Manual), а #:configure-flags - это ключевое слово, используемое для передачи аргумента ключевого слова системе сборки (see Coding With Keywords in GNU Guile Reference Manual).

  • The inputs field specifies inputs to the build process—i.e., build-time or run-time dependencies of the package. Here, we add an input, a reference to the gawk variable; gawk is itself bound to a <package> object.

    Обратите внимание, что GCC, Coreutils, Bash и другие важные инструменты не нужно указывать здесь в качестве inputs. Вместо этого gnu-build-system позаботится об их наличии (see Системы сборки).

    Однако любые другие зависимости необходимо указать в поле inputs. Любая не указанная здесь зависимость будет просто недоступна для процесса сборки, что может привести к сбою сборки.

See package Ссылка, для полного описания возможных полей.

Больше информации: Intimidated by the Scheme language or curious about it? The Cookbook has a short section to get started that recaps some of the things shown above and explains the fundamentals. See A Scheme Crash Course in GNU Guix Cookbook, for more information.

После того, как определение пакета введено, пакет может быть фактически собран с помощью инструмента командной строки guix build (see Запуск guix build), устраняя любые возникающие ошибки сборки (see Отладка ошибок сборки). Вы можете легко вернуться к определению пакета с помощью команды guix edit (see Вызов guix edit). See Руководство по упаковке для получения дополнительной информации о том, как тестировать определения пакетов, и Вызов guix lint для получения информации о том, как проверить определение на соответствие стилю. Наконец, see Каналы, чтобы узнать, как расширить дистрибутив, добавив собственные определения пакетов в “канал”.

Наконец, обновление определения пакета до новой исходной версии можно частично автоматизировать с помощью команды guix refresh (see Вызов guix refresh).

За кулисами derivation, соответствующая объекту <package>, сначала вычисляется с помощью процедуры package-diveration. Этот вывод хранится в файле .drv в каталоге /gnu/store. Действия сборки, которые он предписывает, затем могут быть реализованы с помощью процедуры build-derivations (see Хранилище).

Procedure: package-derivation store package [system]

Возвращает the <derivation> объект package для system (see Деривации).

package должен быть допустимым объектом <package>, а system должен быть строкой, обозначающей тип системы—например, "x86_64-linux" для системы GNU на базе x86_64 Linux. store должен быть подключен к демону, который работает с хранилищем (see Хранилище).

Точно так же можно вычислить derivation, которая cross собирает пакет для некоторой другой системы:

Procedure: package-cross-derivation store package target [system]

Return the <derivation> object of package cross-built from system to target.

target должен быть допустимым GNU triplet’ом, обозначающим желамое оборудование и операционную систему, например "aarch64-linux-gnu" (see Specifying Target Triplets in Autoconf).

Когда у вас есть определения пакетов, вы можете легко определить варианты этих пакетов. См. See Defining Package Variants, чтобы узнать об этом подробнее.


8.2.1 package Ссылка

В этом разделе перечислены все параметры, доступные в объявлениях package (see Описание пакетов).

Тип данных: package

Это тип данных, представляющий рецепт пакета.

name

Название пакета в виде строки.

версия

The version of the package, as a string. See Номера версий, for guidelines.

source

Объект, указывающий, как должен быть получен исходный код пакета. В большинстве случаев это объект origin, который обозначает файл, полученный из Интернета (see origin Справка). Это также может быть любой другой объект, подобный файлу, например local-file, который представляет собой файл из локальной файловой системы (see local-file).

система сборки

Система сборки, которую следует использовать для сборки пакета (see Системы сборки).

arguments (default: '())

Аргументы, которые должны быть переданы системе сборки (see Системы сборки). Это список, обычно содержащий последовательные пары ключевое слово-значение, как в этом примере:

(package
  (name "example")
  ;; several fields omitted
  (arguments
    (list #:tests? #f                     ;skip tests
          #:make-flags #~'("VERBOSE=1")   ;pass flags to 'make'
          #:configure-flags #~'("--enable-frobbing"))))

The exact set of supported keywords depends on the build system (see Системы сборки), but you will find that almost all of them honor #:configure-flags, #:make-flags, #:tests?, and #:phases. The #:phases keyword in particular lets you modify the set of build phases for your package (see Фазы сборки).

The REPL has dedicated commands to interactively inspect values of some of these arguments, as a convenient debugging aid (see Using Guix Interactively).

Compatibility Note: Until version 1.3.0, the arguments field would typically use quote (') or quasiquote (`) and no G-expressions, like so:

(package
  ;; several fields omitted
  (arguments   ;old-style quoted arguments
   '(#:tests? #f
     #:configure-flags '("--enable-frobbing"))))

To convert from that style to the one shown above, you can run guix style -S arguments package (see Invoking guix style).

inputs (default: '())
native-inputs (default: '())
propagated-inputs (default: '())

These fields list dependencies of the package. Each element of these lists is either a package, origin, or other “file-like object” (see G-Expressions); to specify the output of that file-like object that should be used, pass a two-element list where the second element is the output (see Пакеты со множественным выходом, for more on package outputs). For example, the list below specifies three inputs:

(list libffi libunistring
      `(,glib "bin"))      ;the "bin" output of GLib

In the example above, the "out" output of libffi and libunistring is used.

Compatibility Note: Until version 1.3.0, input lists were a list of tuples, where each tuple has a label for the input (a string) as its first element, a package, origin, or derivation as its second element, and optionally the name of the output thereof that should be used, which defaults to "out". For example, the list below is equivalent to the one above, but using the old input style:

;; Old input style (deprecated).
`(("libffi" ,libffi)
  ("libunistring" ,libunistring)
  ("glib:bin" ,glib "bin"))  ;the "bin" output of GLib

This style is now deprecated; it is still supported but support will be removed in a future version. It should not be used for new package definitions. See Invoking guix style, on how to migrate to the new style.

Различие между native-inputs и inputs необходимо при рассмотрении кросс-компиляции. При кросс-компиляции зависимости, перечисленные в input, создаются для архитектуры target; и наоборот, зависимости, перечисленные в native-inputs, созданы для архитектуры машины, выполняющей сборку.

native-inputs обычно используется для перечисления инструментов, необходимых во время сборки, но не во время выполнения, таких как Autoconf, Automake, pkg-config, Gettext или Bison. guix lint может сообщить о вероятных ошибках в этой области (see Вызов guix lint).

Наконец, propagated-inputs похоже на inputs, но указанные пакеты будут автоматически установлены в профили (see the role of profiles in Guix) вместе с пакетом, которому они принадлежат (see guix package, for information on how guix package deals with propagated inputs).

Например, это необходимо при упаковке библиотеки C/C++, которой для компиляции требуются заголовки другой библиотеки, или когда файл pkg-config ссылается на другое поле через его Requires.

Другой пример использования propagated-inputs - это языки, в которых отсутствует возможность записывать путь поиска во время выполнения, аналогичный RUNPATH файлов ELF; сюда входят Guile, Python, Perl и другие. При упаковке библиотек, написанных на этих языках, убедитесь, что они могут найти код библиотеки, от которого они зависят, во время выполнения, указав зависимости времени выполнения в propagated-inputs, а не в inputs.

outputs (default: '("out"))

Список выходных имен пакета. See Пакеты со множественным выходом, для типичного использования дополнительных выходов.

native-search-paths (default: '())
search-paths (по умолчанию: '())

A list of search-path-specification objects describing search-path environment variables honored by the package. See Search Paths, for more on search path specifications.

As for inputs, the distinction between native-search-paths and search-paths only matters when cross-compiling. In a cross-compilation context, native-search-paths applies exclusively to native inputs whereas search-paths applies only to host inputs.

Packages such as cross-compilers care about target inputs—for instance, our (modified) GCC cross-compiler has CROSS_C_INCLUDE_PATH in search-paths, which allows it to pick .h files for the target system and not those of native inputs. For the majority of packages though, only native-search-paths makes sense.

replacement (по умолчанию: #f)

Это должен быть либо #f, либо объект пакета, который будет использоваться как замена для этого пакета. See grafts, чтобы узнать подробности.

синопсис

Описание пакета в одну строку.

описание

A more elaborate description of the package, as a string in Texinfo syntax.

лицензия

Лицензия пакета; значение из (guix licenses) или список таких значений.

главная страница

URL-адрес домашней страницы пакета в виде строки.

port (default: 22)

Список систем, поддерживаемых пакетом, в виде строк вида architecture-kernel, например "x86_64-linux".

location (по умолчанию: исходное местоположение формы package)

Исходное расположение пакета. Это полезно переопределить при наследовании от другого пакета, и в этом случае это поле не корректируется автоматически.

Macro: this-package

При использовании в lexical scope определения поля пакета этот идентификатор преобразуется в определяемый пакет.

В приведенном ниже примере показано, как добавить пакет в качестве собственного ввода при кросс-компиляции:

(package
  (name "guile")
  ;; ...

  ;; When cross-compiled, Guile, for example, depends on
  ;; a native version of itself.  Add it here.
  (native-inputs (if (%current-target-system)
                     (list this-package)
                     '())))

Ссылка на this-package вне определения пакета является ошибкой.

The following helper procedures are provided to help deal with package inputs.

Procedure: lookup-package-input package name
Procedure: lookup-package-native-input package name
Procedure: lookup-package-propagated-input package name
Procedure: lookup-package-direct-input package name

Look up name among package’s inputs (or native, propagated, or direct inputs). Return it if found, #f otherwise.

name is the name of a package depended on. Here’s how you might use it:

(use-modules (guix packages) (gnu packages base))

(lookup-package-direct-input coreutils "gmp")
 #<package gmp@6.2.1 …>

In this example we obtain the gmp package that is among the direct inputs of coreutils.

Sometimes you will want to obtain the list of inputs needed to develop a package—all the inputs that are visible when the package is compiled. This is what the package-development-inputs procedure returns.

Procedure: package-development-inputs package [system] [#:target #f]

Return the list of inputs required by package for development purposes on system. When target is true, return the inputs needed to cross-compile package from system to target, where target is a triplet such as "aarch64-linux-gnu".

Note that the result includes both explicit inputs and implicit inputs—inputs automatically added by the build system (see Системы сборки). Let us take the hello package to illustrate that:

(use-modules (gnu packages base) (guix packages))

hello
 #<package hello@2.10 gnu/packages/base.scm:79 7f585d4f6790>

(package-direct-inputs hello)
 ()

(package-development-inputs hello)
 (("source" ) ("tar" #<package tar@1.32 …>) )

In this example, package-direct-inputs returns the empty list, because hello has zero explicit dependencies. Conversely, package-development-inputs includes inputs implicitly added by gnu-build-system that are required to build hello: tar, gzip, GCC, libc, Bash, and more. To visualize it, guix graph hello would show you explicit inputs, whereas guix graph -t bag hello would include implicit inputs (see Вызов guix graph).

Поскольку пакеты являются обычными Scheme объектами, которые захватывают полный граф зависимостей и связанные процедуры сборки, часто бывает полезно написать процедуры, которые принимают пакет и возвращают его измененную версию в соответствии с некоторыми параметрами. Ниже приведены несколько примеров.

Procedure: package-with-c-toolchain package toolchain

Вернуть вариант package, в котором используется toolchain вместо стандартного набора инструментов GNU C/C++. toolchain должен быть списком входов (кортежи меток/пакетов), обеспечивающих эквивалентную функциональность, например, пакет gcc-toolchain.

Пример ниже возвращает вариант пакета hello, созданный с помощью GCC 10.x и остальной части GNU утилит (Binutils и библиотеки GNU C) вместо цепочки инструментов по умолчанию:

(let ((toolchain (specification->package "gcc-toolchain@10")))
  (package-with-c-toolchain hello `(("toolchain" ,toolchain))))

Инструменты сборки являются частью неявных входных данных пакетов - обычно они не указываются как часть различных полей “входных данных”, а вместо этого извлекается системой сборки. Следовательно, эта процедура работает путем изменения системы сборки package, так что она использует toolchain вместо значений по умолчанию. Системы сборки, чтобы узнать больше о системах сборки.


8.2.2 origin Справка

Этот раздел документирует origins. Объявление origin определяет данные, которые должны быть “произведены”—обычно загружены—и чей хэш содержимого известен заранее. Origins в основном используются для представления исходного кода пакетов (see Описание пакетов). По этой причине форма origin позволяет вам объявлять исправления для применения к исходному коду, а также фрагменты кода для его изменения.

Тип данных: origin

Это тип данных, представляющий источник исходного кода.

uri

Объект, содержащий URI источника. Тип объекта зависит от method (см. ниже). Например, при использовании метода url-fetch для (guix download) допустимые значения uri: URL, представленный в виде строки, или их список.

метод

Монадическая процедура, обрабатывающая данный URI. Процедура должна принимать по крайней мере три аргумента: значение поля uri, а также алгоритм хеширования и значение хеш-функции, указанные в поле hash. Она должна возвращать элемент store или derivation в store монаде (see Устройство склада); большинство методов возвращают derivation с фиксированным выводом (see Деривации).

Обычно используемые методы включают url-fetch, который извлекает данные из URL-адреса, и git-fetch, который извлекает данные из репозитория Git (см. ниже).

sha256

Байт-вектор, содержащий хэш SHA-256 источника. Это эквивалент предоставлению объекта SHA256 content-hash в поле hash, описанном ниже.

hash

Объект content-hash источника—см. ниже, как использовать content-hash.

Вы можете получить эту информацию, используя guix download (see Вызов guix download) или guix hash (see Вызов guix hash).

file-name (по умолчанию: #f)

Имя файла, под которым должен быть сохранен исходный код. Когда это #f, в большинстве случаев будет использоваться разумное значение по умолчанию. В случае, если источник извлекается из URL-адреса, будет использоваться имя файла из URL-адреса. Для проверок контроля версий рекомендуется явно указывать имя файла, поскольку значение по умолчанию не очень информативно.

patches (по умолчанию: '())

Список имен файлов, источников или объектов подобных файлами (see file-like objects), указывающих на исправления, которые будут применены к источнику.

Данный список исправлений должен быть безвариативным. В частности, он не может зависеть от значения %current-system или %current-target-system.

snippet (по умолчанию: #f)

G-выражение (see G-Expressions) или S-выражение, которое будет выполнено в исходном каталоге. Это удобный способ изменить исходный код, иногда более удобный, чем патч.

patch-flags (по умолчанию: '("-p1"))

Список флагов командной строки, которые следует передать команде patch.

patch-inputs (по умолчанию: #f)"

Входные пакеты или derivation’ы для процесса исправления. Когда это #f, предоставляется обычный набор входных данных, необходимых для исправления, например GNU Patch.

modules (по умолчанию: '())

Список модулей Guile, которые должны быть загружены в процессе установки исправлений и при выполнении кода, в поле snippet.

patch-guile (по умолчанию: #f)

Пакет Guile, который следует использовать в процессе установки исправлений. Когда это #f, используется разумное значение по умолчанию.

Тип данных: content-hash value [algorithm]

Создать объект хэша содержимого для заданного algorithm и с value в качестве его хеш-значения. Если algorithm опущен, предполагается, что это sha256.

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

Следующие зависимости необязательны:

(content-hash "05zxkyz9bv3j9h0xyid1rhvh3klhsmrpkf3bcs6frvlgyr2gwilj")
(content-hash "05zxkyz9bv3j9h0xyid1rhvh3klhsmrpkf3bcs6frvlgyr2gwilj"
              sha256)
(content-hash (base32
               "05zxkyz9bv3j9h0xyid1rhvh3klhsmrpkf3bcs6frvlgyr2gwilj"))
(content-hash (base64 "kkb+RPaP7uyMZmu4eXPVkM4BN8yhRd8BTHLslb6f/Rc=")
              sha256)

Технически content-hash в настоящее время реализован как макрос. Он выполняет проверки работоспособности во время раскрытия макроса, когда это возможно, например, гарантирует, что value имеет правильный размер для algorithm.

Как мы видели выше, то, как именно извлекаются данные, на которые ссылается источник, определяется его полем method. Модуль (guix download) предоставляет наиболее распространенный метод url-fetch, описанный ниже.

Procedure: url-fetch url hash-algo hash [name] [#:executable? #f]

Return a fixed-output derivation that fetches data from url (a string, or a list of strings denoting alternate URLs), which is expected to have hash hash of type hash-algo (a symbol). By default, the file name is the base name of URL; optionally, name can specify a different file name. When executable? is true, make the downloaded file executable.

Когда один из URL-адресов начинается с mirror://, тогда его хост-часть интерпретируется как имя схемы зеркала, взятой из %mirror-file.

В качестве альтернативного варианта, если URL-адрес начинается с file://, вернуть соответствующее имя файла в store.

Аналогичным образом, модуль (guix git-download) определяет метод источника git-download, который извлекает данные из репозитория управления версиями Git, и тип данных git-reference для описания репозиторий и ревизия для загрузки.

Procedure: git-fetch ref hash-algo hash

Вернуть derivation с фиксированным выводом, которая выбирает объект ref, <git-reference>. Ожидается, что на выходе будет рекурсивный хеш hash типа hash-algo (символ). Использовать name в качестве имени файла или общее имя, если #f.

Procedure: git-fetch/lfs ref hash-algo hash

This is a variant of the git-fetch procedure that supports the Git LFS (Large File Storage) extension. This may be useful to pull some binary test data to run the test suite of a package, for example.

Тип данных: build-machine

Управление конфигурацией операционной системы.

url

URL-адрес репозитория Git для клонирования.

commit

This string denotes either the commit to fetch (a hexadecimal string), or the tag to fetch. You can also use a “short” commit ID or a git describe style identifier such as v1.0.1-10-g58d7909c97.

features (default: '())

Это логическое значение (boolean) указывает, нужно ли рекурсивно получать подмодули Git.

Пример ниже обозначает тег v2.10 репозитория GNU Hello:

(git-reference
  (url "https://git.savannah.gnu.org/git/hello.git")
  (commit "v2.10"))

Это эквивалентно приведенной ниже ссылке, которая явно называет коммит:

(git-reference
  (url "https://git.savannah.gnu.org/git/hello.git")
  (commit "dc7dc56a00e48fe6f231a58f6537139fe2908fb9"))

Для репозиториев Mercurial, модуль (guix hg-download) определяет метод hg-fetch и тип данных hg-reference для поддержки системы контроля версий Mercurial.

Procedure: hg-fetch ref hash-algo hash [name]

Return a fixed-output derivation that fetches ref, a <hg-reference> object. The output is expected to have recursive hash hash of type hash-algo (a symbol). Use name as the file name, or a generic name if #f.

Data Type: hg-reference

This data type represents a Mercurial reference for hg-fetch to retrieve.

url

The URL of the Mercurial repository to clone.

changeset

This string denotes changeset to fetch.

For Subversion repositories, the module (guix svn-download) defines the svn-fetch origin method and svn-reference data type for support of the Subversion version control system.

Procedure: svn-fetch ref hash-algo hash [name]

Вернуть derivation с фиксированным выводом, которая выбирает объект ref, <svn-reference>. Ожидается, что на выходе будет рекурсивный хеш hash типа hash-algo (символ). Использовать name в качестве имени файла или общее имя, если #f.

Data Type: svn-reference

This data type represents a Subversion reference for svn-fetch to retrieve.

url

The URL of the Subversion repository to clone.

revision

This string denotes revision to fetch specified as a number.

features (default: '())

This Boolean indicates whether to recursively fetch Subversion “externals”.

user-name (default: #f)

The name of an account that has read-access to the repository, if the repository isn’t public.

password (default: #f)

Password to access the Subversion repository, if required.

For Bazaar repositories, the module (guix bzr-download) defines the bzr-fetch origin method and bzr-reference data type for support of the Bazaar version control system.

Procedure: bzr-fetch ref hash-algo hash [name]

Вернуть derivation с фиксированным выводом, которая выбирает объект ref, <bzr-reference>. Ожидается, что на выходе будет рекурсивный хеш hash типа hash-algo (символ). Использовать name в качестве имени файла или общее имя, если #f.

Data Type: bzr-reference

This data type represents a Bazaar reference for bzr-fetch to retrieve.

url

The URL of the Bazaar repository to clone.

revision

This string denotes revision to fetch specified as a number.

For CVS repositories, the module (guix cvs-download) defines the cvs-fetch origin method and cvs-reference data type for support of the Concurrent Versions System (CVS).

Procedure: cvs-fetch ref hash-algo hash [name]

Вернуть derivation с фиксированным выводом, которая выбирает объект ref, <cvs-reference>. Ожидается, что на выходе будет рекурсивный хеш hash типа hash-algo (символ). Использовать name в качестве имени файла или общее имя, если #f.

Data Type: cvs-reference

This data type represents a CVS reference for cvs-fetch to retrieve.

root-directory

The CVS root directory.

модуль

Module to fetch.

revision

Revision to fetch.

The example below denotes a version of gnu-standards to fetch:

(cvs-reference
  (root-directory ":pserver:anonymous@cvs.savannah.gnu.org:/sources/gnustandards")
  (module "gnustandards")
  (revision "2020-11-25"))

8.3 Defining Package Variants

One of the nice things with Guix is that, given a package definition, you can easily derive variants of that package—for a different upstream version, with different dependencies, different compilation options, and so on. Some of these custom packages can be defined straight from the command line (see Параметры преобразования пакета). This section describes how to define package variants in code. This can be useful in “manifests” (see Writing Manifests) and in your own package collection (see Создание канала), among others!

Как обсуждалось ранее, пакеты—это объекты первого класса на языке Scheme. Модуль (guix packages) предоставляет конструкцию package для определения новых объектов пакета (see package Ссылка). Самый простой способ определить вариант пакета—использовать ключевое слово inherit вместе с package. Это позволяет вам наследовать от определения пакета, переопределяя нужные поля.

Например, учитывая переменную hello, которая содержит определение для текущей версии GNU Hello, вот как вы могли бы определить вариант для версии 2.2 (выпущенной в 2006 году, это винтаж!):

(use-modules (gnu packages guile))  ;for 'guile-json'

(define hello-2.2
  (package
    (inherit hello)
    (version "2.2")
    (source (origin
              (method url-fetch)
              (uri (string-append "mirror://gnu/hello/hello-" version
                                  ".tar.gz"))
              (sha256
               (base32
                "0lappv4slgb5spyqbh6yl5r013zv72yqg2pcl30mginf3wdqd8k9"))))))

The example above corresponds to what the --with-version or --with-source package transformations option do. Essentially hello-2.2 preserves all the fields of hello, except version and source, which it overrides. Note that the original hello variable is still there, in the (gnu packages base) module, unchanged. When you define a custom package like this, you are really adding a new package definition; the original one remains available.

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

(use-modules (gnu packages gdb))   ;for 'gdb'

(define gdb-sans-guile
  (package
    (inherit gdb)
    (inputs (modify-inputs (package-inputs gdb)
              (delete "guile")))))

The modify-inputs form above removes the "guile" package from the inputs field of gdb. The modify-inputs macro is a helper that can prove useful anytime you want to remove, add, or replace package inputs.

Macro: modify-inputs inputs clauses

Modify the given package inputs, as returned by package-inputs & co., according to the given clauses. Each clause must have one of the following forms:

(delete name…)

Delete from the inputs packages with the given names (strings).

(prepend package…)

Add packages to the front of the input list.

(append package…)

Add packages to the end of the input list.

(replace name replacement)

Replace the package called name with replacement.

The example below removes the GMP and ACL inputs of Coreutils and adds libcap to the front of the input list:

(modify-inputs (package-inputs coreutils)
  (delete "gmp" "acl")
  (prepend libcap))

The example below replaces the guile package from the inputs of guile-redis with guile-2.2:

(modify-inputs (package-inputs guile-redis)
  (replace "guile" guile-2.2))

The last type of clause is append, to add inputs at the back of the list.

В некоторых случаях вам может быть полезно написать функции (“процедуры” Scheme), которые возвращают пакет на основе некоторых параметров. Например, рассмотрим библиотеку luasocket для языка программирования Lua. Мы хотим создать пакеты luasocket для основных версий Lua. Один из способов сделать это—определить процедуру, которая принимает пакет Lua и возвращает зависящий от него пакет luasocket:

(define (make-lua-socket name lua)
  ;; Return a luasocket package built with LUA.
  (package
    (name name)
    (version "3.0")
    ;; several fields omitted
    (inputs (list lua))
    (synopsis "Socket library for Lua")))

(define-public lua5.1-socket
  (make-lua-socket "lua5.1-socket" lua-5.1))

(define-public lua5.2-socket
  (make-lua-socket "lua5.2-socket" lua-5.2))

Здесь мы определили пакеты lua5.1-socket и lua5.2-socket, вызвав make-lua-socket с разными аргументами. См. See Procedures in GNU Guile Reference Manual, для получения дополнительной информации о процедурах. Наличие общедоступных определений верхнего уровня для этих двух пакетов означает, что на них можно ссылаться из командной строки (see Пакетные модули).

Это довольно простые варианты пакета. Для удобства модуль (guix transformations) предоставляет высокоуровневый интерфейс, который напрямую сопоставляется с более сложными параметрами преобразования пакетов (see Параметры преобразования пакета):

Procedure: options->transformation opts

Возвращает процедуру, которая при передаче объекта для сборки (пакета, производной и т. д.), применяет преобразования, указанные в opts, и возвращает результирующие объекты. opts должен быть списком пар символ/строка, например:

((with-branch . "guile-gcrypt=master")
(without-tests . "libgcrypt"))

Каждый символ именует преобразование, а соответствующая строка (string) является аргументом этого преобразования.

Например, команда:

guix build guix \
  --with-branch=guile-gcrypt=master \
  --with-debug-info=zlib

Вывод должен быть таким:

(use-package-modules guile emacs)

(define transform
  ;; The package transformation procedure.
  (options->transformation
   '((with-branch . "guile-gcrypt=master")
     (with-debug-info . "zlib"))))

(packages->manifest
(list (transform (specification->package "guix"))))

Процедура options-> transformation удобна, но, возможно, не так гибка, как вам хотелось бы. Как это реализовано? Проницательный читатель, вероятно, заметил, что большинство вариантов преобразования пакетов выходят за рамки поверхностных изменений, показанных в первых примерах этого раздела: они включают перезапись входных данных, в результате чего граф зависимостей пакета переписывается путем замены определенных входных данных другими.

Перезапись графа зависимостей для замены пакетов в графе реализуется процедурой package-input-rewriting в (guix packages).

Procedure: package-input-rewriting replacements [rewrite-name] [#:deep? #t]

Return a procedure that, when passed a package, replaces its direct and indirect dependencies, including implicit inputs when deep? is true, according to replacements. replacements is a list of package pairs; the first element of each pair is the package to replace, and the second one is the replacement.

При необходимости, rewrite-name - это процедура с одним аргументом, которая принимает имя пакета и возвращает его новое имя после перезаписи.

Рассмотрим пример:

(define libressl-instead-of-openssl
  ;; This is a procedure to replace OPENSSL by LIBRESSL,
  ;; recursively.
  (package-input-rewriting `((,openssl . ,libressl))))

(define git-with-libressl
  (libressl-instead-of-openssl git))

Здесь мы сначала определяем процедуру перезаписи, которая заменяет openssl на libressl. Затем мы используем это, чтобы определить вариант пакета git, который использует libressl вместо openssl. Это именно то, что делает параметр командной строки --with-input (see --with-input).

Следующий вариант package-input-rewriting может сопоставлять пакеты, подлежащие замене, по имени, а не по идентификатору.

Procedure: package-input-rewriting/spec replacements [#:deep? #t]

Return a procedure that, given a package, applies the given replacements to all the package graph, including implicit inputs unless deep? is false.

replacements is a list of spec/procedures pair; each spec is a package specification such as "gcc" or "guile@2", and each procedure takes a matching package and returns a replacement for that package. Matching packages that have the hidden? property set are not replaced.

Приведенный выше пример можно переписать так:

(define libressl-instead-of-openssl
  ;; Replace all the packages called "openssl" with LibreSSL.
  (package-input-rewriting/spec `(("openssl" . ,(const libressl)))))

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

Более общая процедура для перезаписи графа зависимостей пакетов - это package-mapping: она поддерживает произвольные изменения узлов в графе.

Procedure: package-mapping proc [cut?] [#:deep? #f]

Вернуть процедуру, которая для данного пакета применяет proc ко всем зависимым пакетам и возвращает полученный пакет. Процедура останавливает рекурсию, когда cut? возвращает истину для данного пакета. Когда deep? истинно, proc также применяется к неявным входным данным.

Tips: Understanding what a variant really looks like can be difficult as one starts combining the tools shown above. There are several ways to inspect a package before attempting to build it that can prove handy:

  • You can inspect the package interactively at the REPL, for instance to view its inputs, the code of its build phases, or its configure flags (see Using Guix Interactively).
  • When rewriting dependencies, guix graph can often help visualize the changes that are made (see Вызов guix graph).

8.4 Writing Manifests

guix commands let you specify package lists on the command line. This is convenient, but as the command line becomes longer and less trivial, it quickly becomes more convenient to have that package list in what we call a manifest. A manifest is some sort of a “bill of materials” that defines a package set. You would typically come up with a code snippet that builds the manifest, store it in a file, say manifest.scm, and then pass that file to the -m (or --manifest) option that many guix commands support. For example, here’s what a manifest for a simple package set might look like:

;; Manifest for three packages.
(specifications->manifest '("gcc-toolchain" "make" "git"))

Once you have that manifest, you can pass it, for example, to guix package to install just those three packages to your profile (see -m option of guix package):

guix package -m manifest.scm

... or you can pass it to guix shell (see -m option of guix shell) to spawn an ephemeral environment:

guix shell -m manifest.scm

... or you can pass it to guix pack in pretty much the same way (see -m option of guix pack). You can store the manifest under version control, share it with others so they can easily get set up, etc.

But how do you write your first manifest? To get started, maybe you’ll want to write a manifest that mirrors what you already have in a profile. Rather than start from a blank page, guix package can generate a manifest for you (see guix package --export-manifest):

# Write to 'manifest.scm' a manifest corresponding to the
# default profile, ~/.guix-profile.
guix package --export-manifest > manifest.scm

Or maybe you’ll want to “translate” command-line arguments into a manifest. In that case, guix shell can help (see guix shell --export-manifest):

# Write a manifest for the packages specified on the command line.
guix shell --export-manifest gcc-toolchain make git > manifest.scm

In both cases, the --export-manifest option tries hard to generate a faithful manifest; in particular, it takes package transformation options into account (see Параметры преобразования пакета).

Примечание: Manifests are symbolic: they refer to packages of the channels currently in use (see Каналы). In the example above, gcc-toolchain might refer to version 11 today, but it might refer to version 13 two years from now.

If you want to “pin” your software environment to specific package versions and variants, you need an additional piece of information: the list of channel revisions in use, as returned by guix describe. See Копирование Guix, for more information.

Once you’ve obtained your first manifest, perhaps you’ll want to customize it. Since your manifest is code, you now have access to all the Guix programming interfaces!

Let’s assume you want a manifest to deploy a custom variant of GDB, the GNU Debugger, that does not depend on Guile, together with another package. Building on the example seen in the previous section (see Defining Package Variants), you can write a manifest along these lines:

(use-modules (guix packages)
             (gnu packages gdb)               ;for 'gdb'
             (gnu packages version-control))  ;for 'git'

;; Define a variant of GDB without a dependency on Guile.
(define gdb-sans-guile
  (package
    (inherit gdb)
    (inputs (modify-inputs (package-inputs gdb)
              (delete "guile")))))

;; Return a manifest containing that one package plus Git.
(packages->manifest (list gdb-sans-guile git))

Note that in this example, the manifest directly refers to the gdb and git variables, which are bound to a package object (see package Ссылка), instead of calling specifications->manifest to look up packages by name as we did before. The use-modules form at the top lets us access the core package interface (see Описание пакетов) and the modules that define gdb and git (see Пакетные модули). Seamlessly, we’re weaving all this together—the possibilities are endless, unleash your creativity!

The data type for manifests as well as supporting procedures are defined in the (guix profiles) module, which is automatically available to code passed to -m. The reference follows.

Data Type: manifest

Data type representing a manifest.

It currently has one field:

entries

This must be a list of manifest-entry records—see below.

Data Type: manifest-entry

Data type representing a manifest entry. A manifest entry contains essential metadata: a name and version string, the object (usually a package) for that entry, the desired output (see Пакеты со множественным выходом), and a number of optional pieces of information detailed below.

Most of the time, you won’t build a manifest entry directly; instead, you will pass a package to package->manifest-entry, described below. In some unusual cases though, you might want to create manifest entries for things that are not packages, as in this example:

;; Manually build a single manifest entry for a non-package object.
(let ((hello (program-file "hello" #~(display "Hi!"))))
  (manifest-entry
    (name "foo")
    (version "42")
    (item
     (computed-file "hello-directory"
                     #~(let ((bin (string-append #$output "/bin")))
                         (mkdir #$output) (mkdir bin)
                          (symlink #$hello
                                   (string-append bin "/hello")))))))

Доступны следующие поля:

name
версия

Name and version string for this entry.

item

A package or other file-like object (see file-like objects).

output (default: "out")

Output of item to use, in case item has multiple outputs (see Пакеты со множественным выходом).

dependencies (default: '())

List of manifest entries this entry depends on. When building a profile, dependencies are added to the profile.

Typically, the propagated inputs of a package (see propagated-inputs) end up having a corresponding manifest entry in among the dependencies of the package’s own manifest entry.

search-paths (по умолчанию: '())

The list of search path specifications honored by this entry (see Search Paths).

properties (default: '())

List of symbol/value pairs. When building a profile, those properties get serialized.

This can be used to piggyback additional metadata—e.g., the transformations applied to a package (see Параметры преобразования пакета).

parent (default: (delay #f))

A promise pointing to the “parent” manifest entry.

This is used as a hint to provide context when reporting an error related to a manifest entry coming from a dependencies field.

Procedure: concatenate-manifests lst

Concatenate the manifests listed in lst and return the resulting manifest.

Procedure: package->manifest-entry package [output] [#:properties]

Return a manifest entry for the output of package package, where output defaults to "out", and with the given properties. By default properties is the empty list or, if one or more package transformations were applied to package, it is an association list representing those transformations, suitable as an argument to options->transformation (see options->transformation).

The code snippet below builds a manifest with an entry for the default output and the send-email output of the git package:

(use-modules (gnu packages version-control))

(manifest (list (package->manifest-entry git)
                (package->manifest-entry git "send-email")))
Procedure: packages->manifest packages

Return a list of manifest entries, one for each item listed in packages. Elements of packages can be either package objects or package/string tuples denoting a specific output of a package.

Using this procedure, the manifest above may be rewritten more concisely:

(use-modules (gnu packages version-control))

(packages->manifest (list git `(,git "send-email")))
Procedure: package->development-manifest package [system] [#:target]

Return a manifest for the development inputs of package for system, optionally when cross-compiling to target. Development inputs include both explicit and implicit inputs of package.

Like the -D option of guix shell (see guix shell -D), the resulting manifest describes the environment in which one can develop package. For example, suppose you’re willing to set up a development environment for Inkscape, with the addition of Git for version control; you can describe that “bill of materials” with the following manifest:

(use-modules (gnu packages inkscape)          ;for 'inkscape'
             (gnu packages version-control))  ;for 'git'

(concatenate-manifests
 (list (package->development-manifest inkscape)
       (packages->manifest (list git))))

In this example, the development manifest that package->development-manifest returns includes the compiler (GCC), the many supporting libraries (Boost, GLib, GTK, etc.), and a couple of additional development tools—these are the dependencies guix show inkscape lists.

Last, the (gnu packages) module provides higher-level facilities to build manifests. In particular, it lets you look up packages by name—see below.

Procedure: specifications->manifest specs

Given specs, a list of specifications such as "emacs@25.2" or "guile:debug", return a manifest. Specs have the format that command-line tools such as guix install and guix package understand (see Вызов guix package).

As an example, it lets you rewrite the Git manifest that we saw earlier like this:

(specifications->manifest '("git" "git:send-email"))

Notice that we do not need to worry about use-modules, importing the right set of modules, and referring to the right variables. Instead, we directly refer to packages in the same way as on the command line, which can often be more convenient.


8.5 Системы сборки

В каждом определении пакета указывается система сборки и аргументы для этой системы сборки (see Описание пакетов). Это поле build-system представляет процедуру сборки пакета, а также неявные зависимости этой процедуры сборки.

Системы сборки - это объекты <build-system>. Интерфейс для их создания и управления ими предоставляется модулем (guix build-system), а фактические системы сборки экспортируются определенными модулями.

Под капотом системы сборки сначала компилируют объекты пакета в bag. bag похож на пакет, но с меньшим количеством украшений—другими словами, bag - это представление пакета нижнего уровня, которое включает в себя все входные данные этого пакета, включая те, которые были неявно добавлены система сборки. Это промежуточное представление затем компилируется в derivation (see Деривации). package-with-c-toolchain - это пример способа изменить неявные входные данные, которые использует система сборки пакета (see package-with-c-toolchain).

Системы сборки принимают необязательный список из arguments. В определениях пакетов они передаются через поле arguments (see Описание пакетов). Обычно это аргументы ключевого слова (see keyword arguments in Guile in GNU Guile Reference Manual). Значение этих аргументов обычно оценивается в build stratum—то есть процессом Guile, запущенным демоном (see Деривации).

Основная система сборки - это gnu-build-system, которая реализует стандартную процедуру сборки для GNU и многих других пакетов. Она предоставляется модулем (guix build-system gnu).

Variable: gnu-build-system

gnu-build-system представляет систему сборки GNU и ее варианты (see configuration and makefile conventions in GNU Coding Standards).

Вкратце, пакеты, использующие его, настраиваются, собираются и устанавливаются с помощью обычной последовательности команд ./ configure && make && make check && make install. На практике часто требуется несколько дополнительных шагов. Все эти шаги разбиты на отдельные фазы. See Фазы сборки, чтобы узнать больше о фазах сборки и способах их настройки.

Кроме того, эта система сборки гарантирует, что доступна “стандартная” среда для пакетов GNU. Сюда входят такие инструменты, как GCC, libc, Coreutils, Bash, Make, Diffutils, grep и sed (полный список см. в модуле (guix build-system gnu)). Мы называем их неявными входами пакета, потому что в определениях пакетов они не упоминаются.

Эта система сборки поддерживает ряд ключевых аргументов, которые можно передать через поле arguments пакета. Вот некоторые из основных параметров:

build phases

Считать список каналов из файла file вместо ~/.config/guix/channels.scm. file должен содержать код Scheme, который определяет список объектов "канал". См. See Каналы для подробной информации.

Конфигурирование системы

Это список флагов (строк), переданных в сценарий (script) configure. См. See Описание пакетов.

#:make-flags

Этот список строк содержит флаги, передаваемые в качестве аргументов для вызовов make на этапах build, check и install.

#:out-of-source?

Это логическое значение, #f по умолчанию, указывает, следует ли запускать сборки в каталоге сборки отдельно от исходников.

Когда это значение истинно, на этапе configure создается отдельный каталог сборки, происходит переход в этот каталог и оттуда запускается сценарий configure. Это полезно для пакетов, которым это необходимо, таких как glibc.

#:tests?

This Boolean, #t by default, indicates whether the check phase should run the package’s test suite.

#:test-target

This string, "check" by default, gives the name of the makefile target used by the check phase.

#:parallel-build?
#:parallel-tests?

These Boolean values specify whether to build, respectively run the test suite, in parallel, with the -j flag of make. When they are true, make is passed -jn, where n is the number specified as the --cores option of guix-daemon or that of the guix client command (see --cores).

#:validate-runpath?

This Boolean, #t by default, determines whether to “validate” the RUNPATH of ELF binaries (.so shared libraries as well as executables) previously installed by the install phase. See the validate-runpath phase, for details.

#:substitutable?

This Boolean, #t by default, tells whether the package outputs should be substitutable—i.e., whether users should be able to obtain substitutes for them instead of building locally (see Подстановки).

--references
--references

When true, these arguments must be a list of dependencies that must not appear among the references of the build results. If, upon build completion, some of these references are retained, the build process fails.

This is useful to ensure that a package does not erroneously keep a reference to some of it build-time inputs, in cases where doing so would, for example, unnecessarily increase its size (see Вызов guix size).

Most other build systems support these keyword arguments.

Другие объекты <build-system> определены для поддержки других соглашений и инструментов, используемых пакетами свободного программного обеспечения. Они наследуют большую часть gnu-build-system и различаются в основном набором входных данных, неявно добавляемых в процесс сборки, и списком выполняемых фаз. Некоторые из этих систем сборки перечислены ниже.

Variable: agda-build-system

This variable is exported by (guix build-system agda). It implements a build procedure for Agda libraries.

It adds agda to the set of inputs. A different Agda can be specified with the #:agda key.

The #:plan key is a list of cons cells (regexp . parameters), where regexp is a regexp that should match the .agda files to build, and parameters is an optional list of parameters that will be passed to agda when type-checking it.

When the library uses Haskell to generate a file containing all imports, the convenience #:gnu-and-haskell? can be set to #t to add ghc and the standard inputs of gnu-build-system to the input list. You will still need to manually add a phase or tweak the 'build phase, as in the definition of agda-stdlib.

Variable: ant-build-system

Эта переменная экспортируется (guix build-system ant). Она реализует процедуру сборки пакетов Java, которые можно собрать с помощью Ant build tool.

Она добавляет к набору входных данных как ant, так и Java Development Kit (JDK), предоставленные пакетом icedtea. Различные пакеты можно указать с помощью параметров #:ant и #:jdk соответственно.

Когда исходный пакет не предоставляет подходящий файл сборки Ant, параметр #:jar-name можно использовать для создания минимального файла сборки Ant build.xml с задачами для создания указанного архива jar. В этом случае параметр #:source-dir можно использовать для указания подкаталога источника, по умолчанию - src.

Параметр #:main-class можно использовать с минимальным файлом сборки ant для указания основного класса результирующего jar-файла. Это делает файл jar исполняемым. Параметр #:test-include можно использовать для указания списка запускаемых тестов junit. По умолчанию это (list "**/*Test.java"). #:test-exclude можно использовать для отключения некоторых тестов. По умолчанию это (list "**/Abstract*.java"), потому что абстрактные классы не могут быть запущены как тесты.

Параметр #:build-target можно использовать для указания задачи Ant, которая должна выполняться на этапе build. По умолчанию будет запущена задача jar.

Variable: android-ndk-build-system

Эта переменная экспортируется (guix build-system android-ndk). Она реализует процедуру сборки пакетов Android NDK (собственный комплект разработки) с использованием процесса сборки, специфичного для Guix.

Система сборки предполагает, что пакеты устанавливают свои файлы общедоступного интерфейса (заголовки) в подкаталог include вывода out, а их библиотеки - в подкаталог lib вывода out.

Также предполагается, что объединение всех зависимостей пакета не имеет конфликтующих файлов.

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

Variable: asdf-build-system/source
Variable: asdf-build-system/sbcl
Variable: asdf-build-system/ecl

Эти переменные, экспортированные (guix build-system asdf), реализуют процедуры сборки для пакетов Common Lisp с использованием “ASDF”. ASDF - это средство определения системы для программ и библиотек Common Lisp.

Система asdf-build-system/source устанавливает пакеты в исходной форме и может быть загружена с использованием любой распространенной реализации Lisp через ASDF. Другие, такие как asdf-build-system/sbcl, устанавливают двоичные системы в формате, понятном конкретной реализации. Эти системы сборки также могут использоваться для создания исполняемых программ или образов lisp, которые содержат набор предварительно загруженных пакетов.

В системе сборки используются соглашения об именах. Для бинарных пакетов перед именем пакета должен стоять префикс реализации lisp, например sbcl- для asdf-build-system/sbcl.

Кроме того, соответствующий исходный пакет должен быть помечен с использованием того же соглашения, что и пакеты Python (see Модули Python), с использованием префикса cl-.

Для создания исполняемых программ и образов можно использовать процедуры сборки build-program и build-image. Их следует вызывать в фазе сборки после фазы create-symlinks, чтобы только что созданную систему можно было использовать в полученном образе. build-program требует, чтобы список выражений Common Lisp был передан в качестве аргумента #:entry-program.

Если система не определена в собственном файле .asd с тем же именем, тогда следует использовать параметр #:asd-file, чтобы указать, в каком файле определена система. Кроме того, если пакет определяет систему для своих тестов в отдельном файле, он будет загружен перед запуском тестов, если он указан параметром #:test-asd-file. Если он не установлен, будут попробованы файлы <system>-tests.asd, <system>-test.asd, tests.asd и test.asd, если они есть.

Если по какой-то причине пакет должен быть назван иначе, чем это предлагается в соглашениях об именах, можно использовать параметр #:asd-system-name для указания имени системы.

Variable: cargo-build-system

Эта переменная экспортируется (guix build-system cargo). Она поддерживает сборку пакетов с использованием Cargo, инструмента сборки языка программирования Rust.

Она добавляет rustc и cargo к набору входных данных. Другой пакет Rust можно указать с помощью параметра #:rust.

Обычные cargo зависимости должны быть добавлены к определению пакета через параметр #:cargo-inputs в виде списка пар имени и спецификации, где спецификацией может быть определение пакета или источника. Обратите внимание, что в спецификации должен быть указан путь к сжатому архиву, который содержит файл Cargo.toml в своем корне, иначе он будет проигнорирован. Точно так же dev-зависимости cargo должны быть добавлены в определение пакета с помощью параметра #:cargo-development-inputs.

На этапе configure эта система сборки собирет любые исходные данные, указанные в параметрах #:cargo-inputs и #:cargo-development-inputs, доступными для cargo. Она также удалит файл Cargo.lock, который будет воссоздан cargo на этапе build. На этапе install устанавливаются двоичные файлы, определенные crate.

Variable: chicken-build-system

This variable is exported by (guix build-system chicken). It builds CHICKEN Scheme modules, also called “eggs” or “extensions”. CHICKEN generates C source code, which then gets compiled by a C compiler, in this case GCC.

Эта система сборки добавляет chicken к входным данным (inputs) пакета, а также к пакетам gnu-build-system.

The build system can’t (yet) deduce the egg’s name automatically, so just like with go-build-system and its #:import-path, you should define #:egg-name in the package’s arguments field.

Например, если вы создаете пакет, содержащий Bash, с помощью:

(arguments '(#:egg-name "srfi-1"))

Egg dependencies must be defined in propagated-inputs, not inputs because CHICKEN doesn’t embed absolute references in compiled eggs. Test dependencies should go to native-inputs, as usual.

Variable: copy-build-system

Эта переменная экспортируется в (guix build-system copy). Она поддерживает сборку простых пакетов, которые не требуют большой компиляции, в основном просто перемещения файлов.

Она добавляет большую часть пакетов gnu-build-system в набор входных данных. По этой причине copy-build-system не требуется весь шаблонный код, часто необходимый для trivial-build-system.

Чтобы еще больше упростить процесс установки файла, предоставляется аргумент #:install-plan, позволяющий упаковщику указывать, какие файлы куда установить. План установки представляет собой список (source target [filters]). filters необязательны.

  • Когда source соответствует файл или каталог без косой черты, установить его в target.
    • Если target имеет косую черту в конце, установить source basename ниже target.
    • В противном случае установите source как target.
  • Когда source - это каталог с косой чертой в конце или когда используются filters, завершающая косая черта target подразумевается с тем же значением, что и выше.
    • Без filter установить содержимое source в target.
    • С filters среди #:include, #:include-regexp, #:exclude, #:exclude-regexp, установить только избранные файлы в зависимости от фильтров. Каждый фильтр определяется списком строк.
      • С помощью #:include установите все файлы, суффикс пути которых соответствует хотя бы одному из элементов в данном списке.
      • С помощью #:include-regex установить все файлы, подкаталоги которых соответствуют хотя бы одному из регулярных выражений в данном списке.
      • Фильтры #:exclude и #:exclude-regexp являются дополнением к своим аналогам включения. Без флагов #:include установить все файлы, кроме тех, которые соответствуют фильтрам исключения. Если указаны и включения, и исключения, то исключения выполняются поверх включений.
    • When a package has multiple outputs, the #:output argument can be used to specify which output label the files should be installed to.

    В любом случае пути, относительные к source, сохраняются в target.

Примеры:

  • ("foo/bar" "share/my-app/"): Установить bar в share/my-app/bar.
  • ("foo/bar" "share/my-app/baz"): Установить bar в share/my-app/baz.
  • ("foo/" "share/my-app"): Установить содержимое foo в share/my-app, например, установить foo/sub/file в share/my-app/sub/file.
  • ("foo/" "share/my-app" #:include ("sub/file")): Установить только foo/sub/file в share/my-app/sub/file.
  • ("foo/sub" "share/my-app" #:include ("file")): Установить foo/sub/file в share/my-app/file.
  • ("foo/doc" "share/my-app/doc" #:output "doc"): Install "foo/doc" to "share/my-app/doc" within the "doc" output.
Variable: vim-build-system

This variable is exported by (guix build-system vim). It is an extension of the copy-build-system, installing Vim and Neovim plugins into locations where these two text editors know to find their plugins, using their packpaths.

Packages which are prefixed with vim- will be installed in Vim’s packpath, while those prefixed with neovim- will be installed in Neovim’s packpath. If there is a doc directory with the plugin then helptags will be generated automatically.

There are a couple of keywords added with the vim-build-system:

  • With plugin-name it is possible to set the name of the plugin. While by default this is set to the name and version of the package, it is often more helpful to set this to name which the upstream author calls their plugin. This is the name used for :packadd from inside Vim.
  • With install-plan it is possible to augment the built-in install-plan of the vim-build-system. This is particularly helpful if you have files which should be installed in other locations. For more information about using the install-plan, see the copy-build-system (see copy-build-system).
  • With #:vim it is possible to add this package to Vim’s packpath, in addition to if it is added automatically because of the vim- prefix in the package’s name.
  • With #:neovim it is possible to add this package to Neovim’s packpath, in addition to if it is added automatically because of the neovim- prefix in the package’s name.
  • With #:mode it is possible to adjust the path which the plugin is installed into. By default the plugin is installed into start and other options are available, including opt. Adding a plugin into opt will mean you will need to run, for example, :packadd foo to load the foo plugin from inside of Vim.
Variable: clojure-build-system

Эта переменная экспортируется (guix build-system clojure). Она реализует простую процедуру сборки пакетов Clojure с использованием простого старого compile в Clojure. Кросс-компиляция пока не поддерживается.

Она добавляет clojure, icedtea и zip к набору входных данных. Различные пакеты можно указать с помощью параметров #:clojure, #:jdk и #:zip соответственно.

Список исходных каталогов, тестовых каталогов и имен jar-файлов можно указать с помощью параметров #:source-dirs, #:test-dirs и #:jar-names соответственно. Каталог компиляции и основной класс можно указать с помощью параметров #:compile-dir и #:main-class соответственно. Остальные параметры описаны ниже.

Эта система сборки является расширением ant-build-system, но со следующими изменениями:

build

На этом этапе вызывается compile в Clojure для компиляции исходных файлов и запускается jar для создания jar-файлов как из исходных файлов, так и из скомпилированных файлов в соответствии со списком включения и списком исключений, указанным в #:aot-include и #:aot-exclude соответственно. Список исключений имеет приоритет над списком включения. Эти списки состоят из символов, представляющих библиотеки Clojure, или специального ключевого слова #:all, представляющего все библиотеки Clojure, находящиеся в исходных каталогах. Параметр #:omit-source? определяет, следует ли включать исходники в jar-файлы.

check

На этом этапе выполняются тесты в соответствии со списком включения и списком исключений, указанными в #:test-include и #:test-exclude соответственно. Их значения аналогичны значениям #:aot-include и #:aot-exclude, за исключением того, что специальное ключевое слово #:all теперь обозначает все библиотеки Clojure, находящиеся в каталогах test. Параметр #:tests? определяет, нужно ли запускать тесты.

установка

На этом этапе устанавливаются все созданные ранее jars.

Помимо вышесказанного, эта система сборки также содержит дополнительную фазу:

install-doc

На этом этапе устанавливаются все файлы верхнего уровня с базовым именем, совпадающим с %doc-regex. Другое регулярное выражение можно указать с помощью параметра #:doc-regex. Все файлы (рекурсивно) в каталогах документации, указанные в #:doc-dirs, также устанавливаются.

Variable: cmake-build-system

Эта переменная экспортируется (guix build-system cmake). Она реализует процедуру сборки пакетов с использованием инструмента сборки CMake.

Она автоматически добавляет пакет cmake в набор входных данных. Какой пакет используется, можно указать с помощью параметра #:cmake.

Параметр #:configure-flags используется как список флагов, переданных команде cmake. Параметр #:build-type абстрактно определяет флаги, передаваемые компилятору; по умолчанию используется "RelWithDebInfo" (сокращение от “release mode с отладочной информацией”), что примерно означает, что код компилируется с помощью -O2 -g, как в случае пакетов на основе Autoconf по умолчанию.

Variable: composer-build-system

This variable is exported by (guix build-system composer). It implements the build procedure for packages using Composer, the PHP package manager.

It automatically adds the php package to the set of inputs. Which package is used can be specified with the #:php parameter.

The #:test-target parameter is used to control which script is run for the tests. By default, the test script is run if it exists. If the script does not exist, the build system will run phpunit from the source directory, assuming there is a phpunit.xml file.

Variable: dune-build-system

Эта переменная экспортируется в (guix build-system dune). Она поддерживает сборку пакетов с использованием Dune, инструмента сборки для языка программирования OCaml. Она реализована как расширение ocaml-build-system, описанную ниже. Таким образом, в эту систему сборки можно передать параметры #:ocaml и #:findlib.

Она автоматически добавляет пакет dune в набор входных данных. Какой пакет используется, можно указать с помощью параметра #:dune.

Фаза configure отсутствует, потому что dune пакеты обычно не нужно настраивать. Параметр #:build-flags используется как список флагов, переданных команде dune во время сборки.

Параметр #:jbuild? можно передать для использования команды jbuild вместо более новой команды dune при сборке пакета. Его значение по умолчанию - #f.

Параметр #:package может быть передан для указания имени пакета, что полезно, когда пакет содержит несколько пакетов, и вы хотите создать только один из них. Это эквивалентно передаче аргумента -p в dune.

Variable: elm-build-system

This variable is exported by (guix build-system elm). It implements a build procedure for Elm packages similar to ‘elm install’.

The build system adds an Elm compiler package to the set of inputs. The default compiler package (currently elm-sans-reactor) can be overridden using the #:elm argument. Additionally, Elm packages needed by the build system itself are added as implicit inputs if they are not already present: to suppress this behavior, use the #:implicit-elm-package-inputs? argument, which is primarily useful for bootstrapping.

The "dependencies" and "test-dependencies" in an Elm package’s elm.json file correspond to propagated-inputs and inputs, respectively.

Elm requires a particular structure for package names: see Пакеты Elm for more details, including utilities provided by (guix build-system elm).

There are currently a few noteworthy limitations to elm-build-system:

  • The build system is focused on packages in the Elm sense of the word: Elm projects which declare { "type": "package" } in their elm.json files. Using elm-build-system to build Elm applications (which declare { "type": "application" }) is possible, but requires ad-hoc modifications to the build phases. For examples, see the definitions of the elm-todomvc example application and the elm package itself (because the front-end for the ‘elm reactor’ command is an Elm application).
  • Elm supports multiple versions of a package coexisting simultaneously under ELM_HOME, but this does not yet work well with elm-build-system. This limitation primarily affects Elm applications, because they specify exact versions for their dependencies, whereas Elm packages specify supported version ranges. As a workaround, the example applications mentioned above use the patch-application-dependencies procedure provided by (guix build elm-build-system) to rewrite their elm.json files to refer to the package versions actually present in the build environment. Alternatively, Guix package transformations (see Defining Package Variants) could be used to rewrite an application’s entire dependency graph.
  • We are not yet able to run tests for Elm projects because neither elm-test-rs nor the Node.js-based elm-test runner has been packaged for Guix yet.
Variable: go-build-system

Эта переменная экспортируется (guix build-system go). Онf реализует процедуру сборки пакетов Go с использованием стандартного механизмов сборки Go.

Ожидается, что пользователь предоставит значение для ключа #:import-path и, в некоторых случаях, #:unpack-path. import path соответствует пути к файловой системе, ожидаемому сценариями сборки пакета и любыми ссылочными пакетами, и обеспечивает уникальный способ ссылки на Go пакет. Обычно он основан на комбинации удаленного URI исходного кода пакета и иерархической структуры файловой системы. В некоторых случаях вам нужно будет распаковать исходный код пакета в другую структуру каталогов, отличную от той, которая указана в пути импорта, и в таких случаях следует использовать #:unpack-path.

Пакеты, которые предоставляют библиотеки Go, должны устанавливать свой исходный код во встроенные выходные данные. Ключ #:install-source?, который по умолчанию равен #t, определяет, установливается ли исходный код. Для пакетов, которые предоставляют только исполняемые файлы, может быть установлено значение #f.

Packages can be cross-built, and if a specific architecture or operating system is desired then the keywords #:goarch and #:goos can be used to force the package to be built for that architecture and operating system. The combinations known to Go can be found in their documentation.

The key #:go can be used to specify the Go compiler package with which to build the package.

Variable: glib-or-gtk-build-system

Эта переменная экспортируется в (guix build-system glib-or-gtk). Она предназначена для использования с пакетами, использующими GLib или GTK+.

Эта система сборки добавляет следующие две фазы к тем, которые определены в gnu-build-system:

glib-or-gtk-wrap

Фаза glib-or-gtk-wrap гарантирует, что программы в bin/ смогут найти GLib “schemas” и модули GTK+. Это достигается путем включения программ в сценарии запуска, которые соответствующим образом устанавливают переменные среды XDG_DATA_DIRS и GTK_PATH.

Можно исключить определенные выходные данные пакета из этого процесса упаковки, указав их имена в параметре #:glib-or-gtk-wrap-excluded-output. Это полезно, когда известно, что выходной файл не содержит двоичных файлов GLib или GTK+, и где wrapping может произвольно добавить зависимость этого вывода от GLib и GTK+.

glib-or-gtk-compile-schemas

Фаза glib-or-gtk-compile-schemas гарантирует, что все GSettings schemas в GLib скомпилированы. Компиляция выполняется программой glib-compile-schemas. Она предоставляется пакетом glib:bin, который автоматически импортируется системой сборки. Пакет glib, предоставляющий glib-compile-schemas, можно указать с помощью параметра #:glib.

Обе фазы выполняются после фазы install.

Variable: guile-build-system

Эта система сборки предназначена для пакетов Guile, которые состоят исключительно из кода Scheme и настолько скудны, что у них даже нет make-файла, не говоря уже о сценарии configure. Она компилирует Scheme код с помощью guild compile (see Compilation in GNU Guile Reference Manual) и устанавливает файлы .scm и .go в нужное место. Она также устанавливает документацию.

Эта система сборки поддерживает кросс-компиляцию с использованием параметра --target в ‘guild compile’.

Пакеты, созданные с помощью guile-build-system, должны содержать пакет Guile в поле native-inputs.

Variable: julia-build-system

Эта переменная экспортируется в (guix build-system julia). Она реализует процедуру сборки, используемую пакетами julia, которая по сути аналогична запуску ‘julia -e 'используя Pkg; Pkg.add(package)'’ в среде, где JULIA_LOAD_PATH содержит пути ко всем входным данным пакета Julia. Тесты запускаются с Pkg.test.

The Julia package name and uuid is read from the file Project.toml. These values can be overridden by passing the argument #:julia-package-name (which must be correctly capitalized) or #:julia-package-uuid.

Julia packages usually manage their binary dependencies via JLLWrappers.jl, a Julia package that creates a module (named after the wrapped library followed by _jll.jl.

To add the binary path _jll.jl packages, you need to patch the files under src/wrappers/, replacing the call to the macro JLLWrappers.@generate_wrapper_header, adding as a second argument containing the store path the binary.

As an example, in the MbedTLS Julia package, we add a build phase (see Фазы сборки) to insert the absolute file name of the wrapped MbedTLS package:

(add-after 'unpack 'override-binary-path
  (lambda* (#:key inputs #:allow-other-keys)
    (for-each (lambda (wrapper)
                (substitute* wrapper
                  (("generate_wrapper_header.*")
                   (string-append
                    "generate_wrapper_header(\"MbedTLS\", \""
                    (assoc-ref inputs "mbedtls") "\")\n"))))
              ;; There's a Julia file for each platform, override them all.
              (find-files "src/wrappers/" "\\.jl$"))))

Some older packages that aren’t using Project.toml yet, will require this file to be created, too. It is internally done if the arguments #:julia-package-name and #:julia-package-uuid are provided.

Variable: maven-build-system

Эта переменная экспортируется в (guix build-system maven). Она реализует процедуру сборки пакетов Maven. Maven - это инструмент для управления зависимостями и жизненным циклом Java. Пользователь Maven указывает зависимости и плагины в файле pom.xml, который читает Maven. Когда Maven не имеет одной из зависимостей или плагинов в своем репозитории, он загружает их и использует для сборки пакета.

Система сборки maven гарантирует, что maven не будет пытаться загрузить какие-либо зависимости, работая в offline режиме. Maven завершится ошибкой, если зависимость отсутствует. Перед запуском Maven pom.xml (и подпроекты) модифицируются, чтобы указать версию зависимостей и плагинов, которые соответствуют версиям, доступным в среде сборки guix. Зависимости и плагины должны быть установлены в поддельном репозитории maven по адресу lib/m2 и перед запуском maven привязаны к соответствующему репозиторию. Maven получает указание использовать этот репозиторий для сборки и устанавливает туда созданные артефакты. Измененные файлы копируются в каталог lib/m2 выходных данных пакета.

Вы можете указать файл pom.xml с аргументом #:pom-file или позволить системе сборки использовать файл pom.xml по умолчанию в источниках.

Если вам нужно указать версию зависимости вручную, вы можете использовать аргумент #:local-packages. Он принимает список ассоциаций, где ключ - это groupId пакета, а его значение - это список ассоциаций, где ключ - это artifactId пакета, а его значение - это версия, которую вы хотите переопределить в pom.xml.

Некоторые пакеты используют зависимости или плагины, которые не используются ни во время выполнения, ни во время сборки в Guix. Вы можете изменить файл pom.xml, чтобы удалить их, используя аргумент #:exclude. Его значение - это список ассоциаций, где ключ - это groupId плагина или зависимости, которые вы хотите удалить, а значение - это список artifactId, которые вы хотите удалить.

Вы можете переопределить пакеты по умолчанию jdk и maven с помощью соответствующего аргумента, #:jdk и #:maven.

Аргумент #:maven-plugins - это список подключаемых модулей maven, используемых во время сборки, в том же формате, что и поля inputs в объявлении пакета. Его значение по умолчанию - (default-maven-plugins), которое также экспортируется.

Variable: minetest-mod-build-system

This variable is exported by (guix build-system minetest). It implements a build procedure for Minetest mods, which consists of copying Lua code, images and other resources to the location Minetest searches for mods. The build system also minimises PNG images and verifies that Minetest can load the mod without errors.

Variable: minify-build-system

Эта переменная экспортируется в (guix build-system minify). Она реализует процедуру минификации для простых пакетов JavaScript.

Он добавляет uglify-js к набору входных данных и использует его для сжатия всех файлов JavaScript в каталоге src. Другой minifier пакет можно указать с помощью параметра #:uglify-js, но ожидается, что этот пакет запишет минимизированный код в стандартный вывод.

Когда не все входные файлы JavaScript находятся в каталоге src, можно использовать параметр #:javascript-files, чтобы указать список имен файлов для передачи в minifier.

Variable: mozilla-build-system

This variable is exported by (guix build-system mozilla). It sets the --target and --host configuration flags to what software developed by Mozilla expects – due to historical reasons, Mozilla software expects --host to be the system that is cross-compiled from and --target to be the system that is cross-compiled to, contrary to the standard Autotools conventions.

Variable: ocaml-build-system

Эта переменная экспортируется в (guix build-system ocaml). Она реализует процедуру сборки пакетов OCaml, которая заключается в выборе правильного набора команд для запуска для каждого пакета. Пакеты OCaml могут ожидать выполнения множества различных команд. Эта система сборки попробует некоторые из них.

Если в пакете есть файл setup.ml на верхнем уровне, он будет запускать ocaml setup.ml -configure, ocaml setup.ml -build и ocaml setup.ml -install. Система сборки предполагает, что этот файл был сгенерирован OASIS, и позаботится об установке префикса и включении тестов, если они не отключены. Вы можете передать флаги конфигурации и сборки с помощью #:configure-flags и #:build-flags. Ключ #:test-flags может быть передан для изменения набора флагов, используемых для включения тестов. Ключ #:use-make? можно использовать для обхода этой системы на этапах сборки и установки.

Когда в пакете есть файл configure, предполагается, что это созданный вручную скрипт настройки, для которого требуется другой формат аргументов, чем в gnu-build-system. Вы можете добавить дополнительные флаги с помощью клавиши #:configure-flags.

Когда в пакете есть файл Makefile (или #:use-make? - это #t), он будет использоваться, и дополнительные флаги могут быть переданы на этапы сборки и установки с #:make-flags ключом.

Наконец, некоторые пакеты не имеют этих файлов и используют стандартное расположение для своей системы сборки. В этом случае система сборки запустит ocaml pkg/pkg.ml или ocaml pkg/build.ml и позаботится о предоставлении пути к необходимому модулю findlib. Дополнительные флаги можно передать с помощью ключа #:build-flags. Об установке позаботится opam-installer. В этом случае пакет opam необходимо добавить в поле native-inputs в определении пакета.

Обратите внимание, что большинство пакетов OCaml предполагают, что они будут установлены в том же каталоге, что и OCaml, что не является тем, что мы хотим в guix. В частности, они устанавливают файлы .so в каталог своего модуля, что обычно нормально, потому что он находится в каталоге компилятора OCaml. Однако в guix эти библиотеки нельзя найти, и мы используем CAML_LD_LIBRARY_PATH. Эта переменная указывает на lib/ocaml/site-lib/stubslibs, и именно здесь должны быть установлены библиотеки .so.

Variable: python-build-system

Эта переменная экспортируется в (guix build-system python). Она реализует более или менее стандартную процедуру сборки, используемую пакетами Python, которая заключается в запуске python setup.py build, а затем python setup.py install --prefix=/gnu/store/….

For packages that install stand-alone Python programs under bin/, it takes care of wrapping these programs so that their GUIX_PYTHONPATH environment variable points to all the Python libraries they depend on.

Какой пакет Python используется для сборки, можно указать с помощью параметра #:python. Это полезный способ принудительно создать пакет для определенной версии интерпретатора Python, что может потребоваться, если пакет совместим только с одной версией интерпретатора.

По умолчанию guix вызывает setup.py под управлением setuptools, как и pip. Некоторые пакеты несовместимы с setuptools (и pip), поэтому вы можете отключить это, установив для параметра #:use-setuptools? значение #f.

If a "python" output is available, the package is installed into it instead of the default "out" output. This is useful for packages that include a Python package as only a part of the software, and thus want to combine the phases of python-build-system with another build system. Python bindings are a common usecase.

Variable: pyproject-build-system

This is a variable exported by guix build-system pyproject. It is based on python-build-system, and adds support for pyproject.toml and PEP 517. It also supports a variety of build backends and test frameworks.

The API is slightly different from python-build-system:

  • #:use-setuptools? and #:test-target is removed.
  • #:build-backend is added. It defaults to #false and will try to guess the appropriate backend based on pyproject.toml.
  • #:test-backend is added. It defaults to #false and will guess an appropriate test backend based on what is available in package inputs.
  • #:test-flags is added. The default is '(). These flags are passed as arguments to the test command. Note that flags for verbose output is always enabled on supported backends.

It is considered “experimental” in that the implementation details are not set in stone yet, however users are encouraged to try it for new Python projects (even those using setup.py). The API is subject to change, but any breaking changes in the Guix channel will be dealt with.

Eventually this build system will be deprecated and merged back into python-build-system, probably some time in 2024.

Variable: perl-build-system

Эта переменная экспортируется в (guix build-system perl). Она реализует стандартную процедуру сборки для пакетов Perl, которая заключается либо в запуске perl Build.PL --prefix=/gnu/store/…, за которым следуют Build и Build install; или при запуске perl Makefile.PL PREFIX=/gnu/store/…, за которым следуют make и make install, в зависимости от того, какой из Build.PL или Makefile.PL присутствует в дистрибутиве пакета. Предпочтение отдается первому, если в дистрибутиве пакета есть и Build.PL, и Makefile.PL. Это предпочтение можно отменить, указав #t для параметра #:make-maker?.

Первоначальный вызов perl Makefile.PL или perl Build.PL передает флаги, указанные в параметре #:make-maker-flags или #:module-build-flags, соответственно.

Какой пакет Perl используется, можно указать с помощью #:perl.

Variable: renpy-build-system

Эта переменная экспортируется в (guix build-system python). Она реализует более или менее стандартную процедуру сборки, используемую пакетами Python, которая заключается в запуске python setup.py build, а затем python setup.py install --prefix=/gnu/store/….

It further creates a wrapper script in bin/ and a desktop entry in share/applications, both of which can be used to launch the game.

Which Ren’py package is used can be specified with #:renpy. Games can also be installed in outputs other than “out” by using #:output.

Variable: qt-build-system

Эта переменная экспортируется в (guix build-system qt). Она предназначена для использования с приложениями, использующими Qt или KDE.

Эта система сборки добавляет следующие две фазы к тем, которые определены в cmake-build-system:

check-setup

Фаза check-setup подготавливает среду к запуску проверок, которые обычно используются тестовыми программами Qt. Пока это устанавливает только некоторые переменные среды: QT_QPA_PLATFORM=offscreen, DBUS_FATAL_WARNINGS=0 и CTEST_OUTPUT_ON_FAILURE=1.

Этот этап добавляется перед этапом check. Это отдельный этап для облегчения настройки.

qt-wrap

Фаза qt-wrap ищет пути к плагинам Qt5, пути QML и некоторый XDG во входных и выходных данных. Если путь найден, все программы в выходных каталогах bin/, sbin/, libexec/ и lib/libexec/ заключены в сценарии, определяющие необходимые environment переменные.

Можно исключить определенные выходные данные пакета из этого процесса упаковки, указав их имена в параметре #:qt-wrap-excluded-output. Это полезно, когда известно, что вывод не содержит никаких двоичных файлов Qt, и когда обертка может произвольно добавить зависимость этого вывода от Qt, KDE и т.п.

Эта фаза добавляется после фазы install.

Variable: r-build-system

Эта переменная экспортируется в (guix build-system r). Она реализует процедуру сборки, используемую пакетами R, которая, по сути, немного больше, чем запуск ‘R CMD INSTALL --library=/gnu/store/…’ в среде, где R_LIBS_SITE содержит пути ко всем входам пакета R. Тесты запускаются после установки с использованием R-функции tools::testInstalledPackage.

Variable: rakudo-build-system

Эта переменная экспортируется (guix build-system rakudo). Которая реализует систем сборки, используемую Rakudo для Perl6 пакетов. Она устанавливает: пакет в /gnu/store/…/NAME-VERSION/share/perl6; двоичные файлы, библиотеки и ресурсы; помещает файлы в bin/. Тесты можно пропустить, передав #f параметру tests?.

Какой пакет rakudo используется, можно указать с помощью rakudo. Какой пакет perl6-tap-harness, используемый для тестов, можно указать с помощью #:verify6 или удалить, передав #f в параметр with-verify6?. Какой пакет perl6-zef, используемый для тестирования и установки, можно указать с помощью #:zef или удалить, передав #f в параметр with-zef?.

Variable: rebar-build-system

This variable is exported by (guix build-system rebar). It implements a build procedure around rebar3, a build system for programs written in the Erlang language.

It adds both rebar3 and the erlang to the set of inputs. Different packages can be specified with the #:rebar and #:erlang parameters, respectively.

This build system is based on gnu-build-system, but with the following phases changed:

unpack

This phase, after unpacking the source like the gnu-build-system does, checks for a file contents.tar.gz at the top-level of the source. If this file exists, it will be unpacked, too. This eases handling of package hosted at https://hex.pm/, the Erlang and Elixir package repository.

bootstrap
configure

There are no bootstrap and configure phase because erlang packages typically don’t need to be configured.

build

This phase runs rebar3 compile with the flags listed in #:rebar-flags.

check

Unless #:tests? #f is passed, this phase runs rebar3 eunit, or some other target specified with #:test-target, with the flags listed in #:rebar-flags,

установка

This installs the files created in the default profile, or some other profile specified with #:install-profile.

Variable: texlive-build-system

Эта переменная экспортируется в (guix build-system texlive). Она используется для сборки пакетов TeX в batch режиме с указанным движком. Система сборки устанавливает переменную TEXINPUTS для поиска всех исходных файлов TeX во входных данных.

By default it tries to run luatex on all .ins files, and if it fails to find any, on all .dtx files. A different engine and format can be specified with, respectively, the #:tex-engine and #:tex-format arguments. Different build targets can be specified with the #:build-targets argument, which expects a list of file names.

It also generates font metrics (i.e., .tfm files) out of Metafont files whenever possible. Likewise, it can also create TeX formats (i.e., .fmt files) listed in the #:create-formats argument, and generate a symbolic link from bin/ directory to any script located in texmf-dist/scripts/, provided its file name is listed in #:link-scripts argument.

The build system adds texlive-bin from (gnu packages tex) to the native inputs. It can be overridden with the #:texlive-bin argument.

The package texlive-latex-bin, from the same module, contains most of the tools for building TeX Live packages; for convenience, it is also added by default to the native inputs. However, this can be troublesome when building a dependency of texlive-latex-bin itself. In this particular situation, the #:texlive-latex-bin? argument should be set to #f.

Variable: ruby-build-system

Эта переменная экспортируется в (guix build-system ruby). Она реализует процедуру сборки RubyGems, используемую пакетами Ruby, которая включает запуск gem build, за которым следует gem install.

Поле source пакета, использующего эту систему сборки, обычно ссылается на gem архив, поскольку это формат, который разработчики Ruby используют при выпуске своего программного обеспечения. Система сборки распаковывает gem архив, потенциально исправляет исходный код, запускает набор тестов, переупаковывает gem и устанавливает его. Кроме того, на каталоги и архивы можно ссылаться, чтобы можно было создавать unreleased gem’ы из Git или традиционного архива с исходным кодом.

Какой пакет Ruby используется, можно указать с помощью параметра #:ruby. Список дополнительных флагов, передаваемых команде gem, можно указать с помощью параметра #:gem-flags.

Variable: waf-build-system

Эта переменная экспортируется в (guix build-system waf). Она реализует процедуру сборки вокруг сценария waf. Общие этапы—configure, build и install—реализуются путем передачи их имен в качестве аргументов сценарию waf.

Скрипт waf выполняется интерпретатором Python. Какой пакет Python используется для запуска сценария, можно указать с помощью параметра #:python.

Variable: zig-build-system

This variable is exported by (guix build-system zig). It implements the build procedures for the Zig build system (zig build command).

Selecting this build system adds zig to the package inputs, in addition to the packages of gnu-build-system.

There is no configure phase because Zig packages typically do not need to be configured. The #:zig-build-flags parameter is a list of flags that are passed to the zig command during the build. The #:zig-test-flags parameter is a list of flags that are passed to the zig test command during the check phase. The default compiler package can be overridden with the #:zig argument.

The optional zig-release-type parameter declares the type of release. Possible values are: safe, fast, or small. The default value is #f, which causes the release flag to be omitted from the zig command. That results in a debug build.

Variable: scons-build-system

Эта переменная экспортируется в (guix build-system scons). Она реализует процедуру сборки, используемую инструментом сборки программного обеспечения SCons. Эта система сборки запускает scons для сборки пакета, scons test для запуска тестов и затем scons install для установки пакета.

Дополнительные флаги, передаваемые в scons, можно указать с помощью параметра #:scons-flags. Цели сборки и установки по умолчанию могут быть переопределены с помощью #:build-target и #:install-target соответственно. Версия Python, используемая для запуска SCons, может быть указана путем выбора соответствующего пакета SCons с параметром #:scons.

Variable: haskell-build-system

Эта переменная экспортируется в (guix build-system haskell). Она реализует процедуру сборки Cabal, используемую пакетами Haskell, которая включает запуск runhaskell Setup.hs configure --prefix=/gnu/store/… и runhaskell Setup.hs build. Вместо установки пакета путем запуска runhaskell Setup.hs install, чтобы избежать попыток регистрации библиотек в каталоге хранилища компилятора только для чтения, система сборки использует runhaskell Setup.hs copy, за которым следует runhaskell Setup.hs register. Кроме того, система сборки генерирует документацию по пакету, запуская runhaskell Setup.hs haddock, если только #:haddock? #f пройден. Дополнительные параметры можно передать с помощью параметра #:haddock-flags. Если файл Setup.hs не найден, система сборки вместо этого ищет Setup.lhs.

Какой компилятор Haskell используется, можно указать с помощью параметра #:haskell, который по умолчанию равен ghc.

Variable: dub-build-system

Эта переменная экспортируется в (guix build-system dub). Она реализует процедуру сборки Dub, используемую пакетами D, которая включает запуск dub build и dub run. Установка осуществляется путем копирования файлов вручную.

Какой компилятор D используется, можно указать с помощью параметра #:ldc, который по умолчанию равен ldc.

Variable: emacs-build-system

Эта переменная экспортируется в (guix build-system emacs). Она реализует процедуру установки, аналогичную системе упаковки самого Emacs (see Packages in The GNU Emacs Manual).

Сначала она создает файл package-autoloads.el, а затем байт-компилирует все файлы Emacs Lisp. В отличие от системы упаковки Emacs, файлы документации Info перемещаются в стандартный каталог документации, а файл dir удаляется. Файлы пакета Elisp устанавливаются непосредственно в share/emacs/site-lisp.

Variable: font-build-system

Эта переменная экспортируется в (guix build-system font). Она реализует процедуру установки для пакетов шрифтов, в которой upstream предоставляет предварительно скомпилированные файлы TrueType, OpenType и т.д. файлы шрифтов, которые необходимо просто скопировать на место. Она копирует файлы шрифтов в стандартные места выходного каталога.

Variable: meson-build-system

Эта переменная экспортируется в (guix build-system meson). Она реализует процедуру сборки для пакетов, которые используют Meson в качестве своей системы сборки.

Она добавляет к набору входов как Meson, так и Ninja, при необходимости их можно изменить с помощью параметров #:meson и #:ninja.

Эта система сборки является расширением gnu-build-system, но со следующими фазами, измененными на некоторые специфичные для Meson:

configure

На этапе выполняется meson с флагами, указанными в #:configure-flags. Флаг --buildtype всегда установлен на debugoptimized, если что-то еще не указано в #:build-type.

build

На этапе выполняется ninja для параллельной сборки пакета по умолчанию, но это можно изменить с помощью #:parallel-build?.

check

The phase runs ‘meson test’ with a base set of options that cannot be overridden. This base set of options can be extended via the #:test-options argument, for example to select or skip a specific test suite.

установка

Фаза выполняется ninja install и не может быть изменен.

Помимо этого, система сборки также добавляет следующие фазы:

fix-runpath

This phase ensures that all binaries can find the libraries they need. It searches for required libraries in subdirectories of the package being built, and adds those to RUNPATH where needed. It also removes references to libraries left over from the build phase by meson, such as test dependencies, that aren’t actually required for the program to run.

glib-or-gtk-wrap

Эта фаза предоставляется glib-or-gtk-build-system и по умолчанию не включена. Ее можно включить с помощью #:glib-or-gtk?.

glib-or-gtk-compile-schemas

Эта фаза предоставляется glib-or-gtk-build-system и по умолчанию не включена. Ее можно включить с помощью #:glib-or-gtk?.

Variable: linux-module-build-system

linux-module-build-system позволяет создавать модули ядра Linux.

Эта система сборки является расширением gnu-build-system, но со следующими изменениями:

configure

На этой фазе среда настраивается таким образом, чтобы Makefile ядра Linux можно было использовать для сборки внешнего модуля ядра.

build

На этой фазе используется Makefile ядра Linux для сборки внешнего модуля ядра.

установка

На этой фазе используется Makefile ядра Linux для установки внешнего модуля ядра.

Возможно и полезно указать ядро Linux, которое будет использоваться для сборки модуля (в форме arguments пакета с использованием linux-module-build-system используйте ключ #:linux, чтобы указать это).

Variable: node-build-system

Эта переменная экспортируется в (guix build-system node). Она реализует процедуру сборки, используемую Node.js, которая реализует аппроксимацию команды npm install, за которой следует команда npm test.

Какой пакет Node.js используется для интерпретации команд npm, можно указать с помощью параметра #:node, который по умолчанию равен node.

Variable: tree-sitter-build-system

This variable is exported by (guix build-system tree-sitter). It implements procedures to compile grammars for the Tree-sitter parsing library. It essentially runs tree-sitter generate to translate grammar.js grammars to JSON and then to C. Which it then compiles to native code.

Tree-sitter packages may support multiple grammars, so this build system supports a #:grammar-directories keyword to specify a list of locations where a grammar.js file may be found.

Grammars sometimes depend on each other, such as C++ depending on C and TypeScript depending on JavaScript. You may use inputs to declare such dependencies.

Наконец, для пакетов, которым не нужно ничего столь же сложного, предоставляется “trivial” система сборки. Она тривиальна в том смысле, что она практически не оказывает поддержки при сборке: она не извлекает никаких неявных входных данных и не имеет понятия о этапах сборки.

Variable: trivial-build-system

Эта переменная экспортируется (guix build-system trivial).

Эта система сборки требует аргумента #:builder. Этот аргумент должен быть Scheme выражением, которое строит выходные данные пакета—как с build-expression->derivation (see build-expression->derivation).

Variable: channel-build-system

This variable is exported by (guix build-system channel).

This build system is meant primarily for internal use. A package using this build system must have a channel specification as its source field (see Каналы); alternatively, its source can be a directory name, in which case an additional #:commit argument must be supplied to specify the commit being built (a hexadecimal string).

Optionally, a #:channels argument specifying additional channels can be provided.

The resulting package is a Guix instance of the given channel(s), similar to how guix time-machine would build it.


8.6 Фазы сборки

Почти все системы сборки пакетов реализуют понятие фазы сборки: последовательность действий, которые система сборки выполняет при сборке пакета, что приводит к установке побочных продуктов в store. Заметным исключением является “bare-bones” trivial-build-system (see Системы сборки).

As discussed in the previous section, those build systems provide a standard list of phases. For gnu-build-system, the main build phases are the following:

set-paths

Define search path environment variables for all the input packages, including PATH (see Search Paths).

unpack

Распаковать архив исходных текстов и измените текущий каталог на извлеченное дерево исходных текстов. Если источник на самом деле является каталогом, скопировать его в дерево сборки и войдите в этот каталог.

patch-source-shebangs

Изменить shebang, встречающиеся в исходных файлах, чтобы они ссылались на правильные имена файлов хранилища. Например, это изменяет #!/bin/sh на #!/gnu/store/…-bash-4.3/bin/sh.

configure

Запустить сценарий configure с несколькими параметрами по умолчанию, такими как --prefix=/gnu/store/…, а также параметрами, указанными в #:configure-flags аргументе.

build

Запустить make со списком флагов, указанным с помощью #:make-flags. Если аргумент #:parallel-build? истинен (по умолчанию), выполнить сборку с make -j.

check

Запустить make check или другой target, указанный с помощью #:test-target, если только #:tests? #f пройден. Если аргумент #:parallel-tests? истинен (по умолчанию), запустить make check -j.

установка

Запустить make install с флагами, перечисленными в #:make-flags.

patch-shebangs

Изменить shebangs на установленные исполняемые файлы.

strip

Удалить символы отладки из файлов ELF (если #:strip-binaries? не является ложным), скопировав их в выходные данные debug, если они доступны (see Установка файлов отладки).

validate-runpath

Validate the RUNPATH of ELF binaries, unless #:validate-runpath? is false (see Системы сборки).

This validation step consists in making sure that all the shared libraries needed by an ELF binary, which are listed as DT_NEEDED entries in its PT_DYNAMIC segment, appear in the DT_RUNPATH entry of that binary. In other words, it ensures that running or using those binaries will not result in a “file not found” error at run time. See -rpath in The GNU Linker, for more information on RUNPATH.

Как обсуждалось в предыдущем разделе, эти системы сборки предоставляют стандартный список фаз. Для gnu-build-system стандартные фазы включают фазу unpack для распаковки архива исходного кода, фазу configure для запуска ./configure, build фаза для запуска make и (среди прочего) фазу install для запуска make install; see Системы сборки, чтобы получить более подробное представление об этих фазах. Точно так же cmake-build-system наследует эти фазы, но его фаза configure запускает cmake вместо ./configure. Другие системы сборки, такие как python-build-system, имеют совершенно другой список стандартных фаз. Весь этот код выполняется на build side: он выполняется, когда вы фактически собираете пакет, в отдельном процессе сборки, порожденном демоном сборки (see Вызов guix-daemon).

Этапы сборки представлены в виде ассоциативных списков или “alists” (see Association Lists in GNU Guile Reference Manual), где каждый ключ является символом имени фазы, а соответствующее значение - процедурой, которая принимает произвольное количество аргументов. По соглашению эти процедуры получают информацию о сборке в виде ключевых параметров, которые они могут использовать или игнорировать.

Например, вот как (guix build gnu-build-system) определяет %standard-phase, переменную, содержащую список фаз сборки 21:

;; The build phases of 'gnu-build-system'.

(define* (unpack #:key source #:allow-other-keys)
  ;; Extract the source tarball.
  (invoke "tar" "xvf" source))

(define* (configure #:key outputs #:allow-other-keys)
  ;; Run the 'configure' script.  Install to output "out".
  (let ((out (assoc-ref outputs "out")))
    (invoke "./configure"
            (string-append "--prefix=" out))))

(define* (build #:allow-other-keys)
  ;; Compile.
  (invoke "make"))

(define* (check #:key (test-target "check") (tests? #true)
                #:allow-other-keys)
  ;; Run the test suite.
  (if tests?
      (invoke "make" test-target)
      (display "test suite not run\n")))

(define* (install #:allow-other-keys)
  ;; Install files to the prefix 'configure' specified.
  (invoke "make" "install"))

(define %standard-phases
  ;; The list of standard phases (quite a few are omitted
  ;; for brevity).  Each element is a symbol/procedure pair.
  (list (cons 'unpack unpack)
        (cons 'configure configure)
        (cons 'build build)
        (cons 'check check)
        (cons 'install install)))

Это показывает, как %standard-phase определяется как список пар символ/процедура (see Pairs in GNU Guile Reference Manual). Первая пара связывает процедуру unpack с символом unpack—именем; вторая пара аналогичным образом определяет фазу configure и так далее. При сборке пакета, который использует gnu-build-system со списком фаз по умолчанию, эти фазы выполняются последовательно. Вы можете увидеть название каждой фазы, запущенной и завершенной, в журнале сборки пакетов, которые вы собираете.

Теперь посмотрим на сами процедуры. Каждая из них определяется с помощью define*: #:key перечисляет параметры ключевого слова, которые принимает процедура, возможно, со значением по умолчанию, а #:allow-other-keys указывает, что другие параметры ключевого слова являются игнорируется (see Optional Arguments in GNU Guile Reference Manual).

Процедура unpack учитывает параметр source, который система сборки использует для передачи имени файла исходного архива (или checkout контроля версий), и игнорирует другие параметры. Фаза configure касается только параметра output, списка имен выходных пакетов, отображающих имена файлов хранилища (see Пакеты со множественным выходом). Она извлекает имя файла для out, вывода по умолчанию, и передает его ./configure в качестве префикса установки, что означает, что make install в конечном итоге скопирует все файлы в этом каталоге (see configuration and makefile conventions in GNU Coding Standards). build и install игнорируют все свои аргументы. check учитывает аргумент test-target, который указывает имя цели Makefile для запуска тестов; она печатает сообщение и пропускает тесты, если tests? ложно.

Список фаз, используемых для конкретного пакета, можно изменить с помощью параметра #:phase системы сборки. Изменение набора фаз сборки сводится к созданию нового списка фаз на основе списка %standard-phase, описанного выше. Это можно сделать с помощью стандартных процедур списков, таких как alist-delete (see SRFI-1 Association Lists in GNU Guile Reference Manual); однако это удобнее делать с помощью modify-phase (see modify-phases).

Вот пример определения пакета, который удаляет фазу configure из %standard-phase и вставляет новую фазу перед фазой build, которая называется set-prefix-in- makefile:

(define-public example
  (package
    (name "example")
    ;; other fields omitted
    (build-system gnu-build-system)
    (arguments
     (list
      #:phases
      #~(modify-phases %standard-phases
          (delete 'configure)
          (add-before 'build 'set-prefix-in-makefile
            (lambda* (#:key inputs #:allow-other-keys)
              ;; Modify the makefile so that its
              ;; 'PREFIX' variable points to #$output and
              ;; 'XMLLINT' points to the correct path.
              (substitute* "Makefile"
                (("PREFIX =.*")
                 (string-append "PREFIX = " #$output "\n"))
                (("XMLLINT =.*")
                 (string-append "XMLLINT = "
                                (search-input-file inputs "/bin/xmllint")
                                "\n"))))))))))

The new phase that is inserted is written as an anonymous procedure, introduced with lambda*; it looks for the xmllint executable under a /bin directory among the package’s inputs (see package Ссылка). It also honors the outputs parameter we have seen before. See Build Utilities, for more about the helpers used by this phase, and for more examples of modify-phases.

Tip: You can inspect the code associated with a package’s #:phases argument interactively, at the REPL (see Using Guix Interactively).

Имейте в виду, что фазы сборки - это код, выполняемый во время фактической сборки пакета. Это объясняет, почему приведенное выше выражение modify-phase целиком (оно идет после ' или апострофа): это staged для последующего выполнения. See G-Expressions для объяснения staging кода и задействованных code strata.


8.7 Build Utilities

Как только вы начнете писать нетривиальные определения пакетов (see Описание пакетов) или другие действия сборки (see G-Expressions), вы, скорее всего, начнете искать помощников для действий, подобных оболочке—создание каталогов, рекурсивное копирование и удаление файлов, управление этапами сборки и т.д. Модуль (guix build utils) предоставляет такие служебные процедуры.

Большинство систем сборки загружают (guix build utils) (see Системы сборки). Таким образом, при написании настраиваемых фаз сборки для определений пакетов вы обычно можете предположить, что эти процедуры входят в область действия.

При написании G-выражений вы можете импортировать (guix build utils) на “стороне сборки”, используя with-import-modules, а затем поместить его в область видимости с помощью формы use-modules (see Using Guile Modules in GNU Guile Reference Manual):

(with-imported-modules '((guix build utils))  ;import it
  (computed-file "empty-tree"
                 #~(begin
                     ;; Put it in scope.
                     (use-modules (guix build utils))

                     ;; Happily use its 'mkdir-p' procedure.
                     (mkdir-p (string-append #$output "/a/b/c")))))

Оставшаяся часть этого раздела является справочником по большинству служебных процедур, предоставляемых (guix build utils).

8.7.1 Работа с именами файлов в store

В этом разделе описаны процедуры, относящиеся к именам файлов в store.

Procedure: %store-directory

Проверить целостность склада.

Procedure: store-file-name? file

Возвращает true, если объект obj — это пакет ранней версии.

Procedure: strip-store-file-name file

Удалиnm /gnu/store и хэш из file, имени файла в store. Результатом обычно является строка "package-version".

Procedure: package-name->name+version name

Учитывая name, имя пакета, такое как "foo-0.9.1b", возвращает два значения: "foo" и "0.9.1b". Если часть версии недоступна, возвращаются name и #f. Считается, что первый дефис, за которым следует цифра, обозначает часть версии.

8.7.2 Файловые системы

Процедуры, приведённые ниже, обеспечивают работу и управление ранними версиями пакетов.

Procedure: directory-exists? dir

Вернуть #t, если dir существует и является каталогом.

Procedure: executable-file? file

Вернуть #t, если file существует и исполняемый файл.

Вернуть #t, если file является символической ссылкой (также известной как “символическая ссылка”).

Procedure: elf-file? file
Procedure: ar-file? file
Procedure: gzip-file? file

Вернуть #t, если file является, соответственно, файлом ELF, архивом ar (например, статической библиотекой .a) или файлом gzip.

Procedure: reset-gzip-timestamp file [#:keep-mtime? #t]

Если file является файлом gzip, сбросить его timestamp (как в случае gzip --no-name) и вернуть истину. В противном случае вернуть #f. Когда keep-mtime? истинна, сохранить время модификации file.

8.7.3 Управление файлами

Следующие процедуры и макросы помогают создавать, изменять и удалять файлы. Они обеспечивают функциональность, сопоставимую с такими обычными утилитами оболочки, как mkdir -p, cp -r, rm -r и sed. Они дополняют обширный, но низкоуровневый интерфейс файловой системы Guile (see POSIX in GNU Guile Reference Manual).

Macro: with-directory-excursion directory body …

Запустить body с directory в качестве текущего каталога процесса.

По сути, этот макрос изменяет текущий каталог на directory перед вычислением body, используя chdir (see Processes in GNU Guile Reference Manual). Она возвращается в исходный каталог, когда остается динамический extent body, будь то через возврат нормальной процедуры или через нелокальный выход, такой как исключение.

Procedure: mkdir-p dir

Создать каталог dir и всех его предков.

Procedure: install-file file directory

Создать каталог, если он не существует, и скопировать туда file под тем же именем.

Procedure: make-file-writable file

Сделать file доступным для записи его владельцу.

Procedure: copy-recursively source destination [#:log (current-output-port)] [#:follow-symlinks? #f]  [#:copy-file

copy-file] [#:keep-mtime? #f] [#:keep-permissions? #t] [#:select? (const #t)] Copy source directory to destination. Follow symlinks if follow-symlinks? is true; otherwise, just preserve them. Call copy-file to copy regular files. Call select?, taking two arguments, file and stat, for each entry in source, where file is the entry’s absolute file name and stat is the result of lstat (or stat if follow-symlinks? is true); exclude entries for which select? does not return true. When keep-mtime? is true, keep the modification time of the files in source on those of destination. When keep-permissions? is true, preserve file permissions. Write verbose output to the log port.

Procedure: delete-file-recursively dir [#:follow-mounts? #f]

Delete dir recursively, like rm -rf, without following symlinks. Don’t follow mount points either, unless follow-mounts? is true. Report but ignore errors.

Macro: substitute* file ((regexp match-var…) body…) … Substitute regexp in

file by the string returned by body. body is evaluated with each match-var bound to the corresponding positional regexp sub-expression. For example:

(substitute* file
  (("hello")
   "good morning\n")
  (("foo([a-z]+)bar(.*)$" all letters end)
   (string-append "baz" letters end)))

Здесь, когда строка file содержит hello, она заменяется на good morning. Каждый раз, когда строка file соответствует второму регулярному выражению, all привязывается к полному совпадению, letters привязано к первому подвыражению, а end привязано к последнему.

Когда одно из match-var - _, никакая переменная не связана с соответствующей подстрокой соответствия.

В качестве альтернативы file может быть списком имен файлов, и в этом случае все они могут быть заменены.

Будьте осторожны с использованием $ для поиска конца строки; само по себе он не будет соответствовать завершению новой строки в строке. Например, для поиска целой строки, заканчивающейся обратной косой чертой, нужен регекс типа "(.*)\\\\\n$".

8.7.4 Файловые системы

В этом разделе описаны процедуры поиска и фильтрации файлов.

Procedure: file-name-predicate regexp

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

Procedure: find-files dir [pred] [#:stat lstat] [#:directories? #f] [#:fail-on-error? #f] Возвращает

лексикографически отсортированный список файлов в dir, для которых pred возвращает истину. pred передается два аргумента: абсолютное имя файла и его буфер статистики; предикат по умолчанию всегда возвращает истину. pred также может быть регулярным выражением, в этом случае оно эквивалентно (file-name-predicate pred). stat используется для получения информации о файле; использование lstat означает, что символические ссылки не соблюдаются. Если directories? истина, то каталоги также будут включены. Если fail-on-error? истина, генерировать исключение при ошибке.

Вот несколько примеров, в которых мы предполагаем, что текущий каталог является корнем дерева исходников Guix:

;; List all the regular files in the current directory.
(find-files ".")
 ("./.dir-locals.el" "./.gitignore" )

;; List all the .scm files under gnu/services.
(find-files "gnu/services" "\\.scm$")
 ("gnu/services/admin.scm" "gnu/services/audio.scm" )

;; List ar files in the current directory.
(find-files "." (lambda (file stat) (ar-file? file)))
 ("./libformat.a" "./libstore.a" )
Procedure: which program

Вернуть полное имя файла для program, как в $PATH, или #f, если program не найдена.

Procedure: search-input-file inputs name
Procedure: search-input-directory inputs name

Return the complete file name for name as found in inputs; search-input-file searches for a regular file and search-input-directory searches for a directory. If name could not be found, an exception is raised.

Here, inputs must be an association list like inputs and native-inputs as available to build phases (see Фазы сборки).

Here is a (simplified) example of how search-input-file is used in a build phase of the wireguard-tools package:

(add-after 'install 'wrap-wg-quick
  (lambda* (#:key inputs outputs #:allow-other-keys)
    (let ((coreutils (string-append (assoc-ref inputs "coreutils")
                                    "/bin")))
      (wrap-program (search-input-file outputs "bin/wg-quick")
        #:sh (search-input-file inputs "bin/bash")
        `("PATH" ":" prefix ,(list coreutils))))))

8.7.5 Program Invocation

You’ll find handy procedures to spawn processes in this module, essentially convenient wrappers around Guile’s system* (see system* in GNU Guile Reference Manual).

Procedure: invoke program args…

Invoke program with the given args. Raise an &invoke-error exception if the exit code is non-zero; otherwise return #t.

The advantage compared to system* is that you do not need to check the return value. This reduces boilerplate in shell-script-like snippets for instance in package build phases.

Procedure: invoke-error? c

Return true if c is an &invoke-error condition.

Procedure: invoke-error-program c
Procedure: invoke-error-arguments c
Procedure: invoke-error-exit-status c
Procedure: invoke-error-term-signal c
Procedure: invoke-error-stop-signal c

Access specific fields of c, an &invoke-error condition.

Procedure: report-invoke-error c [port]

Report to port (by default the current error port) about c, an &invoke-error condition, in a human-friendly way.

Typical usage would look like this:

(use-modules (srfi srfi-34) ;for 'guard'
             (guix build utils))

(guard (c ((invoke-error? c)
           (report-invoke-error c)))
  (invoke "date" "--imaginary-option"))

-| command "date" "--imaginary-option" failed with status 1
Procedure: invoke/quiet program args…

Invoke program with args and capture program’s standard output and standard error. If program succeeds, print nothing and return the unspecified value; otherwise, raise a &message error condition that includes the status code and the output of program.

Here’s an example:

(use-modules (srfi srfi-34) ;for 'guard'
             (srfi srfi-35) ;for 'message-condition?'
             (guix build utils))

(guard (c ((message-condition? c)
           (display (condition-message c))))
  (invoke/quiet "date")  ;all is fine
  (invoke/quiet "date" "--imaginary-option"))

-| 'date --imaginary-option' exited with status 1; output follows:

    date: unrecognized option '--imaginary-option'
    Try 'date --help' for more information.

8.7.6 Фазы сборки

(guix build utils) также содержит инструменты для управления фазами сборки, которые используются системами сборки (see Системы сборки). Фазы сборки представлены в виде ассоциативных списков или “alists” (see Association Lists in GNU Guile Reference Manual), где каждый ключ представляет собой символ, обозначающий фазу, а связанное значение представляет собой процедуру (see Фазы сборки).

Ядро Guile и модуль (srfi srfi-1) предоставляют инструменты для управления списками. Модуль (guix build utils) дополняет их инструментами, написанными с учетом фаз сборки.

Macro: modify-phases phases clause…

Изменить phases последовательно в соответствии с каждым clause, которое может иметь одну из следующих форм:

(delete old-phase-name)
(replace old-phase-name new-phase)
(add-before old-phase-name new-phase-name new-phase)
(add-after old-phase-name new-phase-name new-phase)

Где каждая phase-name выше - это выражение, преобразующееся в символ, а new-phase - выражение, преобразующееся в процедуру.

Пример ниже взят из определения пакета grep. Он добавляет фазу для запуска после фазы install, которая называется fix-egrep-and-fgrep. Эта фаза представляет собой процедуру (lambda* обозначает анонимную процедуру), которая принимает аргумент ключевого слова #:output и игнорирует дополнительные аргументы ключевого слова (see Optional Arguments in GNU Guile Reference Manual, for more on lambda* and optional and keyword arguments.) В фазе используется substitute* для изменения установленных сценариев egrep и fgrep, чтобы они ссылались на grep по абсолютному имени файла:

(modify-phases %standard-phases
  (add-after 'install 'fix-egrep-and-fgrep
    ;; Patch 'egrep' and 'fgrep' to execute 'grep' via its
    ;; absolute file name instead of searching for it in $PATH.
    (lambda* (#:key outputs #:allow-other-keys)
      (let* ((out (assoc-ref outputs "out"))
             (bin (string-append out "/bin")))
        (substitute* (list (string-append bin "/egrep")
                           (string-append bin "/fgrep"))
          (("^exec grep")
           (string-append "exec " bin "/grep")))))))

В приведенном ниже примере фазы изменяются двумя способами: стандартная фаза configure удаляется, предположительно потому, что в пакете нет сценария configure или чего-то подобного, и фаза install по умолчанию заменяется файлом, который вручную копирует устанавливаемые исполняемые файлы:

(modify-phases %standard-phases
  (delete 'configure)      ;no 'configure' script
  (replace 'install
    (lambda* (#:key outputs #:allow-other-keys)
      ;; The package's Makefile doesn't provide an "install"
      ;; rule so do it by ourselves.
      (let ((bin (string-append (assoc-ref outputs "out")
                                "/bin")))
        (install-file "footswitch" bin)
        (install-file "scythe" bin)))))

8.7.7 Wrappers

It is not unusual for a command to require certain environment variables to be set for proper functioning, typically search paths (see Search Paths). Failing to do that, the command might fail to find files or other commands it relies on, or it might pick the “wrong” ones—depending on the environment in which it runs. Examples include:

  • a shell script that assumes all the commands it uses are in PATH;
  • a Guile program that assumes all its modules are in GUILE_LOAD_PATH and GUILE_LOAD_COMPILED_PATH;
  • a Qt application that expects to find certain plugins in QT_PLUGIN_PATH.

For a package writer, the goal is to make sure commands always work the same rather than depend on some external settings. One way to achieve that is to wrap commands in a thin script that sets those environment variables, thereby ensuring that those run-time dependencies are always found. The wrapper would be used to set PATH, GUILE_LOAD_PATH, or QT_PLUGIN_PATH in the examples above.

To ease that task, the (guix build utils) module provides a couple of helpers to wrap commands.

Procedure: wrap-program program [#:sh sh] [#:rest variables]

Make a wrapper for program. variables should look like this:

'(variable delimiter position list-of-directories)

where delimiter is optional. : will be used if delimiter is not given.

For example, this call:

(wrap-program "foo"
              '("PATH" ":" = ("/gnu/.../bar/bin"))
              '("CERT_PATH" suffix ("/gnu/.../baz/certs"
                                    "/qux/certs")))

will copy foo to .foo-real and create the file foo with the following contents:

#!location/of/bin/bash
export PATH="/gnu/.../bar/bin"
export CERT_PATH="$CERT_PATH${CERT_PATH:+:}/gnu/.../baz/certs:/qux/certs"
exec -a $0 location/of/.foo-real "$@"

If program has previously been wrapped by wrap-program, the wrapper is extended with definitions for variables. If it is not, sh will be used as the interpreter.

Procedure: wrap-script program [#:guile guile] [#:rest variables]

Wrap the script program such that variables are set first. The format of variables is the same as in the wrap-program procedure. This procedure differs from wrap-program in that it does not create a separate shell script. Instead, program is modified directly by prepending a Guile script, which is interpreted as a comment in the script’s language.

Special encoding comments as supported by Python are recreated on the second line.

Note that this procedure can only be used once per file as Guile scripts are not supported.


8.8 Search Paths

Many programs and libraries look for input data in a search path, a list of directories: shells like Bash look for executables in the command search path, a C compiler looks for .h files in its header search path, the Python interpreter looks for .py files in its search path, the spell checker has a search path for dictionaries, and so on.

Search paths can usually be defined or overridden via environment variables (see Environment Variables in The GNU C Library Reference Manual). For example, the search paths mentioned above can be changed by defining the PATH, C_INCLUDE_PATH, PYTHONPATH (or GUIX_PYTHONPATH), and DICPATH environment variables—you know, all these something-PATH variables that you need to get right or things “won’t be found”.

You may have noticed from the command line that Guix “knows” which search path environment variables should be defined, and how. When you install packages in your default profile, the file ~/.guix-profile/etc/profile is created, which you can “source” from the shell to set those variables. Likewise, if you ask guix shell to create an environment containing Python and NumPy, a Python library, and if you pass it the --search-paths option, it will tell you about PATH and GUIX_PYTHONPATH (see Вызов guix shell):

$ guix shell python python-numpy --pure --search-paths
export PATH="/gnu/store/…-profile/bin"
export GUIX_PYTHONPATH="/gnu/store/…-profile/lib/python3.9/site-packages"

When you omit --search-paths, it defines these environment variables right away, such that Python can readily find NumPy:

$ guix shell python python-numpy -- python3
Python 3.9.6 (default, Jan  1 1970, 00:00:01)
[GCC 10.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy
>>> numpy.version.version
'1.20.3'

For this to work, the definition of the python package declares the search path it cares about and its associated environment variable, GUIX_PYTHONPATH. It looks like this:

(package
  (name "python")
  (version "3.9.9")
  ;; some fields omitted...
  (native-search-paths
   (list (search-path-specification
          (variable "GUIX_PYTHONPATH")
          (files (list "lib/python/3.9/site-packages"))))))

What this native-search-paths field says is that, when the python package is used, the GUIX_PYTHONPATH environment variable must be defined to include all the lib/python/3.9/site-packages sub-directories encountered in its environment. (The native- bit means that, if we are in a cross-compilation environment, only native inputs may be added to the search path; see search-paths.) In the NumPy example above, the profile where python appears contains exactly one such sub-directory, and GUIX_PYTHONPATH is set to that. When there are several lib/python/3.9/site-packages—this is the case in package build environments—they are all added to GUIX_PYTHONPATH, separated by colons (:).

Примечание: Notice that GUIX_PYTHONPATH is specified as part of the definition of the python package, and not as part of that of python-numpy. This is because this environment variable “belongs” to Python, not NumPy: Python actually reads the value of that variable and honors it.

Corollary: if you create a profile that does not contain python, GUIX_PYTHONPATH will not be defined, even if it contains packages that provide .py files:

$ guix shell python-numpy --search-paths --pure
export PATH="/gnu/store/…-profile/bin"

This makes a lot of sense if we look at this profile in isolation: no software in this profile would read GUIX_PYTHONPATH.

Of course, there are many variations on that theme: some packages honor more than one search path, some use separators other than colon, some accumulate several directories in their search path, and so on. A more complex example is the search path of libxml2: the value of the XML_CATALOG_FILES environment variable is space-separated, it must contain a list of catalog.xml files (not directories), which are to be found in xml sub-directories—nothing less. The search path specification looks like this:

(search-path-specification
 (variable "XML_CATALOG_FILES")
 (separator " ")
 (files '("xml"))
 (file-pattern "^catalog\\.xml$")
 (file-type 'regular))

Worry not, search path specifications are usually not this tricky.

The (guix search-paths) module defines the data type of search path specifications and a number of helper procedures. Below is the reference of search path specifications.

Data Type: search-path-specification

The data type for search path specifications.

variable

The name of the environment variable for this search path (a string).

files

The list of sub-directories (strings) that should be added to the search path.

separator (default: ":")

The string used to separate search path components.

As a special case, a separator value of #f specifies a “single-component search path”—in other words, a search path that cannot contain more than one element. This is useful in some cases, such as the SSL_CERT_DIR variable (honored by OpenSSL, cURL, and a few other packages) or the ASPELL_DICT_DIR variable (honored by the GNU Aspell spell checker), both of which must point to a single directory.

file-type (default: 'directory)

The type of file being matched—'directory or 'regular, though it can be any symbol returned by stat:type (see stat in GNU Guile Reference Manual).

In the XML_CATALOG_FILES example above, we would match regular files; in the Python example, we would match directories.

file-pattern (default: #f)

This must be either #f or a regular expression specifying files to be matched within the sub-directories specified by the files field.

Again, the XML_CATALOG_FILES example shows a situation where this is needed.

Some search paths are not tied by a single package but to many packages. To reduce duplications, some of them are pre-defined in (guix search-paths).

Variable: $SGML_CATALOG_FILES
Variable: $XML_CATALOG_FILES

These two search paths indicate where the TR9401 catalog22 or XML catalog files can be found.

Variable: $SSL_CERT_DIR
Variable: $SSL_CERT_FILE

These two search paths indicate where X.509 certificates can be found (see Сертификаты X.509).

These pre-defined search paths can be used as in the following example:

(package
  (name "curl")
  ;; some fields omitted ...
  (native-search-paths (list $SSL_CERT_DIR $SSL_CERT_FILE)))

How do you turn search path specifications on one hand and a bunch of directories on the other hand in a set of environment variable definitions? That’s the job of evaluate-search-paths.

Procedure: evaluate-search-paths search-paths directories [getenv]

Evaluate search-paths, a list of search-path specifications, for directories, a list of directory names, and return a list of specification/value pairs. Use getenv to determine the current settings and report only settings not already effective.

The (guix profiles) provides a higher-level helper procedure, load-profile, that sets the environment variables of a profile.


8.9 Хранилище

Концептуально store - это место, где хранятся успешно построенные derivation’ы - по умолчанию /gnu/store. Подкаталоги в store называются store items или иногда store paths. У store есть связанная база данных, которая содержит такую информацию, как store paths, на которые ссылается каждый store path, и список валидных store item’ов—результаты успешных сборок. Эта база данных находится в localstatedir/guix/db, где localstatedir - это каталог состояний, указанный через --localstatedir во время configure, обычно /var.

Демон всегда обращается к store от имени своих клиентов (see Вызов guix-daemon). Чтобы управлять store, клиенты подключаются к демону через сокет домена Unix, отправляют ему запросы и читают результат - это вызовы удаленных процедур или RPC.

Примечание: Пользователи должны никогда напрямую изменять файлы в /gnu/store. Это приведет к несоответствиям и нарушит предположения о неизменности функциональной модели Guix (see Введение).

See guix gc --verify, для получения информации о том, как проверить целостность store и попытаться восстановить его после случайных изменений.

Модуль (guix store) предоставляет процедуры для подключения к демону и выполнения RPC. Они описаны ниже. По умолчанию open-connection и, следовательно, все команды guix подключаются к локальному демону или к URI, указанному в переменной среды GUIX_DAEMON_SOCKET.

Environment Variable: GUIX_DAEMON_SOCKET

Если установлено, значение этой переменной должно быть именем файла или URI, обозначающим конечную точку демона. Когда это имя файла, оно обозначает сокет домена Unix, к которому нужно подключиться. Помимо имен файлов, поддерживаются следующие схемы URI:

file
unix

Это для сокетов домена Unix. file:///var/guix/daemon-socket/socket эквивалентен /var/guix/daemon-socket/socket.

guix

Эти URI обозначают соединения через TCP/IP без шифрования и аутентификации удаленного хоста. В URI необходимо указать имя хоста и, возможно, номер порта (по умолчанию используется порт 44146):

guix://master.guix.example.org:1234

Эта настройка подходит для локальных сетей, таких как кластеры, где только доверенные узлы могут подключаться к демону сборки по адресу master.guix.example.org.

Параметр --listen команды guix-daemon можно использовать для указания ему прослушивать TCP-соединения (see --listen).

ssh

Эти URI позволяют подключаться к удаленному демону через SSH. Для этой функции требуется Guile-SSH (see Требования) и рабочий guile binary файл в PATH на конечном компьютере. Он поддерживает открытый ключ и аутентификацию GSSAPI. Типичный URL-адрес может выглядеть так:

ssh://charlie@guix.example.org:22

Что касается guix copy, учитываются обычные файлы конфигурации клиента OpenSSH (see Вызов guix copy).

В будущем могут поддерживаться дополнительные схемы URI.

Примечание: Возможность подключения к демонам удаленной сборки считается экспериментальной с 2a6d964. Пожалуйста, свяжитесь с нами, чтобы поделиться любыми проблемами или предложениями, которые могут у вас возникнуть (see Содействие).

Procedure: open-connection [uri] [#:reserve-space? #t]

Подключится к демону через сокет домена Unix по адресу uri (строка). Когда reserve-space? истинна, указать ему, чтобы он зарезервировал немного дополнительного места в файловой системе, чтобы сборщик мусора мог работать, если диск заполнится. Вернуть объект сервера.

file по умолчанию - %default-socket-path, что является обычным расположением с учетом параметров, переданных в configure.

Procedure: close-connection server

Закрыть соединение с server.

Variable: current-build-output-port

Эта переменная привязана к параметру SRFI-39, который относится к порту, на который должны быть записаны журналы сборки и ошибок, отправляемые демоном.

Процедуры, которые заставляют все RPC принимать объект сервера в качестве своего первого аргумента.

Procedure: valid-path? server path

Возвращать #t, когда path обозначает допустимый элемент хранилища, и #f в противном случае (недопустимый элемент может существовать на диске, но по-прежнему быть недопустимым, например, потому что он является результатом прерывания или неудачной сборки).

Условие &store-protocol-error возникает, если path не имеет префикса в каталоге store (/gnu/store).

Procedure: add-text-to-store server name text [references]

Добавить text в файл name в store и вернуть его store path. references - это список store path’ы, на которые ссылается конечный store path.

Procedure: build-derivations store derivations [mode]

Build derivations, a list of <derivation> objects, .drv file names, or derivation/output pairs, using the specified mode(build-mode normal) by default.

Обратите внимание, что модуль (guix monads) предоставляет как монаду, так и монадические версии вышеупомянутых процедур с целью сделать более удобной работу с кодом, который обращается к store (see Устройство склада).

Этот раздел в настоящее время не завершен.


8.10 Деривации

Действия низкоуровневой сборки и среда, в которой они выполняются, представлены через derivations. Derivation содержит следующую информацию:

  • The outputs of the derivation—derivations создают по крайней мере один файл или каталог в store, но могут создавать и больше.
  • The inputs of the derivation—i.e., its build-time dependencies—which may be other derivations or plain files in the store (patches, build scripts, etc.).
  • Тип системы, на который нацелена derivation - например, x86_64-linux.
  • Имя файла скрипта сборки в store вместе с передаваемыми аргументами.
  • Список переменных среды, которые необходимо определить.

Derivation’ы позволяют клиентам демона передавать действия сборки в store. Они существуют в двух формах: как представление в памяти, как на стороне клиента, так и на стороне демона, и в виде файлов в хранилище, имена которых заканчиваются на .drv - эти файлы называются derivation paths. Derivation paths могут быть переданы в процедуру build-derivations для выполнения действий сборки, которые они предписывают (see Хранилище).

Такие операции, как загрузка файлов и проверка версий, для которых заранее известен ожидаемый хэш содержимого, моделируются как fixed-output derivations. В отличие от обычных дериваций, выходные данные деривации с фиксированным выходом не зависят от его входных данных - например, загрузка исходного кода дает тот же результат независимо от метода загрузки и используемых инструментов.

Outputs of derivations—то есть результаты сборки—имеют множество references, в соответствии с указаниями RPC references или команды guix gc --references (see Вызов guix gc). References - это набор run-time зависимостей результатов сборки. References - это подмножество входных данных derivation; это подмножество автоматически вычисляется демоном сборки путем сканирования всех файлов в выходных данных.

Модуль (guix diverations) предоставляет представление derivation’ов в виде Scheme объектов, а также процедуры для создания derivation’ов и других манипуляций с ними. Самым низкоуровневым примитивом для создания derivation’а является процедура derivation:

Procedure: derivation store name builder args [#:outputs '("out")] [#:hash #f] [#:hash-algo #f]  [#:recursive? #f]

[#:inputs ’()] [#:env-vars ’()]  [#:system (%current-system)] [#:references-graphs #f]  [#:allowed-references #f] [#:disallowed-references #f]  [#:leaked-env-vars #f] [#:local-build? #f]  [#:substitutable? #t] [#:properties ’()] Build a derivation with the given arguments, and return the resulting <derivation> object.

Когда заданы hash и hash-algo, создается fixed-output derivation - то есть результат, который известен заранее, например, загрузка файла. Кроме того, если recursive? истинна, то этот фиксированный вывод может быть исполняемым файлом или каталогом, а hash должен быть хешем архива, содержащего этот вывод.

Когда links-graphs истинна, данная переменная должна быть списком из пар имя файла и путь к store. В этом случае граф ссылок каждого store path экспортируется в среду сборки в соответствующий файл в простом текстовом формате.

Когда allowed-links истинна, данная переменная должна быть списком store item’ов или выходных данных, на которые может ссылаться выход derivation’а. Аналогично, disallowed-links, если она истинна, данная переменная должна быть списком сущностей, на которые не могут ссылаться выходные данные.

Когда leaked-env-vars истинна, данная переменная должна быть списком строк, обозначающих переменные среды, которым разрешено “просачиваться” из среды демона в среду сборки. Это применимо только к fixed-output derivation’ам, т.е. когда hash истинна. Основное использование - разрешить передачу таких переменных, как http_proxy, derivation’ам, которые загружают файлы.

Когда local-build? истинна, объявить, что производная не является хорошим кандидатом для offload и должна быть собрана локально (see Использование функционала разгрузки). Это справедливо для небольших derivation’ов, когда затраты на передачу данных перевешивают выгоды.

Когда substitutable? ложно, объявить, что substitutes derivation’ов не должны использоваться (see Подстановки). Это полезно, например, при создании пакетов, которые фиксируют подробности набора команд центрального процессора.

properties должна быть списком ассоциаций, описывающих “свойства” derivation’а. При выводе они сохраняются как есть, без интерпретации.

Вот пример со shell скриптом в качестве его builder’а, предполагая, что store является открытым соединением с демоном, а bash указывает на исполняемый файл Bash в store:

(use-modules (guix utils)
             (guix store)
             (guix derivations))

(let ((builder   ; add the Bash script to the store
        (add-text-to-store store "my-builder.sh"
                           "echo hello world > $out\n" '())))
  (derivation store "foo"
              bash `("-e" ,builder)
              #:inputs `((,bash) (,builder))
              #:env-vars '(("HOME" . "/homeless"))))
 #<derivation /gnu/store/…-foo.drv => /gnu/store/…-foo>

Как можно догадаться, этот примитив неудобно использовать напрямую. Конечно, лучший подход - писать скрипты сборки на Scheme! Лучше всего для этого написать код сборки как “G-выражение” и передать его в gexp->derivation. Для получения дополнительной информации, see G-Expressions.

Когда-то давно gexp->derivation не существовала, и построение derivation’ов с помощью кода сборки, написанного на Scheme, достигалось с помощью build-expression->derivation, описанной ниже. Эта процедура теперь устарела и заменена более приятным gexp->derivation.

Procedure: build-expression->derivation store name exp [#:system (%current-system)] [#:inputs '()]  [#:outputs '("out")] [#:hash

#f] [#:hash-algo #f]  [#:recursive? #f] [#:env-vars ’()] [#:modules ’()]  [#:references-graphs #f] [#:allowed-references #f]  [#:disallowed-references #f]  [#:local-build? #f] [#:substitutable? #t] [#:guile-for-build #f] Return a derivation that executes Scheme expression exp as a builder for derivation name. inputs must be a list of (name drv-path sub-drv) tuples; when sub-drv is omitted, "out" is assumed. modules is a list of names of Guile modules from the current search path to be copied in the store, compiled, and made available in the load path during the execution of exp—e.g., ((guix build utils) (guix build gnu-build-system)).

exp выполняется в среде, где %output привязан к списку пар output/path, а где %build-inputs привязан к списку пар строка/output-path сделаными из input. Необязательно, env-vars - это список пар строк, определяющих имя и значение переменных среды, видимых builder’у. Builder завершает работу, передавая результат exp в exit; таким образом, когда exp возвращает #f, сборка считается неудачной.

exp собирается с использованием guile-for-build (derivation). Когда guile-for-build опущена или равна #f, вместо этого используется значение fluid’а %guile-for-build.

См. в процедуре derivation значение references-graphs, allowed-references, disallowed-references, local-build? и substitutable?.

Вот пример single-output derivation’а, которая создает каталог, содержащий один файл:

(let ((builder '(let ((out (assoc-ref %outputs "out")))
                  (mkdir out)    ; create /gnu/store/…-goo
                  (call-with-output-file (string-append out "/test")
                    (lambda (p)
                      (display '(hello guix) p))))))
  (build-expression->derivation store "goo" builder))

 #<derivation /gnu/store/…-goo.drv => …>

8.11 Устройство склада

Все процедуры, которые работают с store, описанные в предыдущих разделах, принимают открытое соединение с демоном сборки в качестве первого аргумента. Хотя основная модель является функциональной, они либо имеют побочные эффекты, либо зависят от текущего состояния store.

Первое неудобно: соединение с демоном сборки должно поддерживаться во всех этих функциях, что делает невозможным составление функций, которые не принимают этот параметр, с функциями, которые его принимают. Последнее может быть проблематичным: поскольку операции store имеют побочные эффекты и/или зависят от внешнего состояния, они должны быть правильно упорядочены.

Здесь на помощь приходит модуль (guix monads). Этот модуль предоставляет основу для работы с monads и особенно полезную монаду для наших целей - store monad. Монады - это конструкции, которая позволяют две вещи: связывать “контекст” со значениями (в нашем случае контекст - это store) и строить последовательности вычислений (здесь вычисления включают доступ к store). Значения в монаде—значения, которые несут этот дополнительный контекст—называются монадическими значениями; процедуры, возвращающие такие значения, называются монадическими процедурами.

Рассмотрим эту “нормальную” процедуру:

(define (sh-symlink store)
  ;; Return a derivation that symlinks the 'bash' executable.
  (let* ((drv (package-derivation store bash))
         (out (derivation->output-path drv))
         (sh  (string-append out "/bin/bash")))
    (build-expression->derivation store "sh"
                                  `(symlink ,sh %output))))

Используя (guix monads) и (guix gexp), ее можно переписать как монадическую функцию:

(define (sh-symlink)
  ;; Same, but return a monadic value.
  (mlet %store-monad ((drv (package->derivation bash)))
    (gexp->derivation "sh"
                      #~(symlink (string-append #$drv "/bin/bash")
                                 #$output))))

Во второй версии следует отметить несколько моментов: параметр store теперь является неявным и является “threaded” в вызовах package->derivation и gexp->derivation монадические процедуры, а монадическим значением, возвращаемым package->derivation, является bound с использованием mlet вместо простого let.

Оказывается, вызов package->derivation можно даже опустить, поскольку она будет выполняться неявно, как мы увидим позже (see G-Expressions):

(define (sh-symlink)
  (gexp->derivation "sh"
                    #~(symlink (string-append #$bash "/bin/bash")
                               #$output)))

Вызов монадического sh-symlink ни на что не влияет. Как кто-то однажды сказал: “Вы выходите из монады, как вы выходите из горящего здания: by running”. Итак, чтобы выйти из монады и получить желаемый эффект, нужно использовать run-with-store:

(run-with-store (open-connection) (sh-symlink))
 /gnu/store/...-sh-symlink

Note that the (guix monad-repl) module extends the Guile REPL with new “commands” to make it easier to deal with monadic procedures: run-in-store, and enter-store-monad (see Using Guix Interactively). The former is used to “run” a single monadic value through the store:

scheme@(guile-user)> ,run-in-store (package->derivation hello)
$1 = #<derivation /gnu/store/…-hello-2.9.drv => …>

Последний входит в рекурсивный REPL, где все возвращаемые значения автоматически проходят через хранилище:

scheme@(guile-user)> ,enter-store-monad
store-monad@(guile-user) [1]> (package->derivation hello)
$2 = #<derivation /gnu/store/…-hello-2.9.drv => …>
store-monad@(guile-user) [1]> (text-file "foo" "Hello!")
$3 = "/gnu/store/…-foo"
store-monad@(guile-user) [1]> ,q
scheme@(guile-user)>

Обратите внимание, что немонадические значения не могут быть возвращены в REPL store-monad.

Other meta-commands are available at the REPL, such as ,build to build a file-like object (see Using Guix Interactively).

Основные синтаксические формы для работы с монадами в целом предоставляются модулем (guix monads) и описаны ниже.

Macro: with-monad monad body …

Evaluate any >>= or return forms in body as being in monad.

Macro: return val

Возвращает монадическое значение, инкапсулирующее val.

Macro: >>= mval mproc …

Bind monadic value mval, passing its “contents” to monadic procedures mproc23. There can be one mproc or several of them, as in this example:

(run-with-state
    (with-monad %state-monad
      (>>= (return 1)
           (lambda (x) (return (+ 1 x)))
           (lambda (x) (return (* 2 x)))))
  'some-state)

 4
 some-state
Macro: mlet monad ((var mval) …) body …
Macro: mlet* monad ((var mval) …) body …

Bind the variables var to the monadic values mval in body, which is a sequence of expressions. As with the bind operator, this can be thought of as “unpacking” the raw, non-monadic value “contained” in mval and making var refer to that raw, non-monadic value within the scope of the body. The form (var -> val) binds var to the “normal” value val, as per let. The binding operations occur in sequence from left to right. The last expression of body must be a monadic expression, and its result will become the result of the mlet or mlet* when run in the monad.

mlet* is to mlet what let* is to let (see Local Bindings in GNU Guile Reference Manual).

Macro: mbegin monad mexp …

Bind mexp and the following monadic expressions in sequence, returning the result of the last expression. Every expression in the sequence must be a monadic expression.

This is akin to mlet, except that the return values of the monadic expressions are ignored. In that sense, it is analogous to begin, but applied to monadic expressions.

Macro: mwhen condition mexp0 mexp* …

When condition is true, evaluate the sequence of monadic expressions mexp0..mexp* as in an mbegin. When condition is false, return *unspecified* in the current monad. Every expression in the sequence must be a monadic expression.

Macro: munless condition mexp0 mexp* …

When condition is false, evaluate the sequence of monadic expressions mexp0..mexp* as in an mbegin. When condition is true, return *unspecified* in the current monad. Every expression in the sequence must be a monadic expression.

The (guix monads) module provides the state monad, which allows an additional value—the state—to be threaded through monadic procedure calls.

Variable: %state-monad

The state monad. Procedures in the state monad can access and change the state that is threaded.

Consider the example below. The square procedure returns a value in the state monad. It returns the square of its argument, but also increments the current state value:

(define (square x)
  (mlet %state-monad ((count (current-state)))
    (mbegin %state-monad
      (set-current-state (+ 1 count))
      (return (* x x)))))

(run-with-state (sequence %state-monad (map square (iota 3))) 0)
 (0 1 4)
 3

When “run” through %state-monad, we obtain that additional state value, which is the number of square calls.

Monadic Procedure: current-state

Вернуть текущее состояние в виде монадического значения.

Monadic Procedure: set-current-state value

Set the current state to value and return the previous state as a monadic value.

Monadic Procedure: state-push value

Push value to the current state, which is assumed to be a list, and return the previous state as a monadic value.

Monadic Procedure: state-pop

Pop a value from the current state and return it as a monadic value. The state is assumed to be a list.

Procedure: run-with-state mval [state]

Run monadic value mval starting with state as the initial state. Return two values: the resulting value, and the resulting state.

The main interface to the store monad, provided by the (guix store) module, is as follows.

Variable: %store-monad

The store monad—an alias for %state-monad.

Values in the store monad encapsulate accesses to the store. When its effect is needed, a value of the store monad must be “evaluated” by passing it to the run-with-store procedure (see below).

Procedure: run-with-store store mval [#:guile-for-build] [#:system (%current-system)] Run mval, a monadic

value in the store monad, in store, an open store connection.

Monadic Procedure: text-file name text [references]

Return as a monadic value the absolute file name in the store of the file containing text, a string. references is a list of store items that the resulting text file refers to; it defaults to the empty list.

Monadic Procedure: binary-file name data [references]

Return as a monadic value the absolute file name in the store of the file containing data, a bytevector. references is a list of store items that the resulting binary file refers to; it defaults to the empty list.

Monadic Procedure: interned-file file [name] [#:recursive? #t] [#:select? (const #t)] Return the name of file once

interned in the store. Use name as its store name, or the basename of file if name is omitted.

When recursive? is true, the contents of file are added recursively; if file designates a flat file and recursive? is true, its contents are added, and its permission bits are kept.

When recursive? is true, call (select? file stat) for each directory entry, where file is the entry’s absolute file name and stat is the result of lstat; exclude entries for which select? does not return true.

The example below adds a file to the store, under two different names:

(run-with-store (open-connection)
  (mlet %store-monad ((a (interned-file "README"))
                      (b (interned-file "README" "LEGU-MIN")))
    (return (list a b))))

 ("/gnu/store/rwm…-README" "/gnu/store/44i…-LEGU-MIN")

The (guix packages) module exports the following package-related monadic procedures:

Monadic Procedure: package-file package [file] [#:system (%current-system)] [#:target #f]  [#:output "out"] Return as a

monadic value in the absolute file name of file within the output directory of package. When file is omitted, return the name of the output directory of package. When target is true, use it as a cross-compilation target triplet.

Note that this procedure does not build package. Thus, the result might or might not designate an existing file. We recommend not using this procedure unless you know what you are doing.

Monadic Procedure: package->derivation package [system]
Monadic Procedure: package->cross-derivation package target [system] Monadic version of package-derivation and

package-cross-derivation (see Описание пакетов).


8.12 G-Expressions

So we have “derivations”, which represent a sequence of build actions to be performed to produce an item in the store (see Деривации). These build actions are performed when asking the daemon to actually build the derivations; they are run by the daemon in a container (see Вызов guix-daemon).

It should come as no surprise that we like to write these build actions in Scheme. When we do that, we end up with two strata of Scheme code24: the “host code”—code that defines packages, talks to the daemon, etc.—and the “build code”—code that actually performs build actions, such as making directories, invoking make, and so on (see Фазы сборки).

To describe a derivation and its build actions, one typically needs to embed build code inside host code. It boils down to manipulating build code as data, and the homoiconicity of Scheme—code has a direct representation as data—comes in handy for that. But we need more than the normal quasiquote mechanism in Scheme to construct build expressions.

The (guix gexp) module implements G-expressions, a form of S-expressions adapted to build expressions. G-expressions, or gexps, consist essentially of three syntactic forms: gexp, ungexp, and ungexp-splicing (or simply: #~, #$, and #$@), which are comparable to quasiquote, unquote, and unquote-splicing, respectively (see quasiquote in GNU Guile Reference Manual). However, there are major differences:

  • Gexps are meant to be written to a file and run or manipulated by other processes.
  • When a high-level object such as a package or derivation is unquoted inside a gexp, the result is as if its output file name had been introduced.
  • Gexps carry information about the packages or derivations they refer to, and these dependencies are automatically added as inputs to the build processes that use them.

This mechanism is not limited to package and derivation objects: compilers able to “lower” other high-level objects to derivations or files in the store can be defined, such that these objects can also be inserted into gexps. For example, a useful type of high-level objects that can be inserted in a gexp is “file-like objects”, which make it easy to add files to the store and to refer to them in derivations and such (see local-file and plain-file below).

To illustrate the idea, here is an example of a gexp:

(define build-exp
  #~(begin
      (mkdir #$output)
      (chdir #$output)
      (symlink (string-append #$coreutils "/bin/ls")
               "list-files")))

This gexp can be passed to gexp->derivation; we obtain a derivation that builds a directory containing exactly one symlink to /gnu/store/…-coreutils-8.22/bin/ls:

(gexp->derivation "the-thing" build-exp)

As one would expect, the "/gnu/store/…-coreutils-8.22" string is substituted to the reference to the coreutils package in the actual build code, and coreutils is automatically made an input to the derivation. Likewise, #$output (equivalent to (ungexp output)) is replaced by a string containing the directory name of the output of the derivation.

In a cross-compilation context, it is useful to distinguish between references to the native build of a package—that can run on the host—versus references to cross builds of a package. To that end, the #+ plays the same role as #$, but is a reference to a native package build:

(gexp->derivation "vi"
   #~(begin
       (mkdir #$output)
       (mkdir (string-append #$output "/bin"))
       (system* (string-append #+coreutils "/bin/ln")
                "-s"
                (string-append #$emacs "/bin/emacs")
                (string-append #$output "/bin/vi")))
   #:target "aarch64-linux-gnu")

In the example above, the native build of coreutils is used, so that ln can actually run on the host; but then the cross-compiled build of emacs is referenced.

Another gexp feature is imported modules: sometimes you want to be able to use certain Guile modules from the “host environment” in the gexp, so those modules should be imported in the “build environment”. The with-imported-modules form allows you to express that:

(let ((build (with-imported-modules '((guix build utils))
               #~(begin
                   (use-modules (guix build utils))
                   (mkdir-p (string-append #$output "/bin"))))))
  (gexp->derivation "empty-dir"
                    #~(begin
                        #$build
                        (display "success!\n")
                        #t)))

In this example, the (guix build utils) module is automatically pulled into the isolated build environment of our gexp, such that (use-modules (guix build utils)) works as expected.

Usually you want the closure of the module to be imported—i.e., the module itself and all the modules it depends on—rather than just the module; failing to do that, attempts to use the module will fail because of missing dependent modules. The source-module-closure procedure computes the closure of a module by looking at its source file headers, which comes in handy in this case:

(use-modules (guix modules))   ;for 'source-module-closure'

(with-imported-modules (source-module-closure
                         '((guix build utils)
                           (gnu build image)))
  (gexp->derivation "something-with-vms"
                    #~(begin
                        (use-modules (guix build utils)
                                     (gnu build image))
                        )))

In the same vein, sometimes you want to import not just pure-Scheme modules, but also “extensions” such as Guile bindings to C libraries or other “full-blown” packages. Say you need the guile-json package available on the build side, here’s how you would do it:

(use-modules (gnu packages guile))  ;for 'guile-json'

(with-extensions (list guile-json)
  (gexp->derivation "something-with-json"
                    #~(begin
                        (use-modules (json))
                        )))

The syntactic form to construct gexps is summarized below.

Macro: #~exp
Macro: (gexp exp)

Return a G-expression containing exp. exp may contain one or more of the following forms:

#$obj
(ungexp obj)

Introduce a reference to obj. obj may have one of the supported types, for example a package or a derivation, in which case the ungexp form is replaced by its output file name—e.g., "/gnu/store/…-coreutils-8.22.

If obj is a list, it is traversed and references to supported objects are substituted similarly.

If obj is another gexp, its contents are inserted and its dependencies are added to those of the containing gexp.

If obj is another kind of object, it is inserted as is.

#$obj:output
(ungexp obj output)

This is like the form above, but referring explicitly to the output of obj—this is useful when obj produces multiple outputs (see Пакеты со множественным выходом).

Sometimes a gexp unconditionally refers to the "out" output, but the user of that gexp would still like to insert a reference to another output. The gexp-input procedure aims to address that. See gexp-input.

#+obj
#+obj:output
(ungexp-native obj)
(ungexp-native obj output)

Same as ungexp, but produces a reference to the native build of obj when used in a cross compilation context.

#$output[:output]
(ungexp output [output])

Insert a reference to derivation output output, or to the main output when output is omitted.

This only makes sense for gexps passed to gexp->derivation.

#$@lst
(ungexp-splicing lst)

Like the above, but splices the contents of lst inside the containing list.

#+@lst
(ungexp-native-splicing lst)

Like the above, but refers to native builds of the objects listed in lst.

G-expressions created by gexp or #~ are run-time objects of the gexp? type (see below).

Macro: with-imported-modules modules body…

Mark the gexps defined in body… as requiring modules in their execution environment.

Each item in modules can be the name of a module, such as (guix build utils), or it can be a module name, followed by an arrow, followed by a file-like object:

`((guix build utils)
  (guix gcrypt)
  ((guix config) => ,(scheme-file "config.scm"
                                  #~(define-module ))))

In the example above, the first two modules are taken from the search path, and the last one is created from the given file-like object.

This form has lexical scope: it has an effect on the gexps directly defined in body…, but not on those defined, say, in procedures called from body….

Macro: with-extensions extensions body…

Mark the gexps defined in body… as requiring extensions in their build and execution environment. extensions is typically a list of package objects such as those defined in the (gnu packages guile) module.

Concretely, the packages listed in extensions are added to the load path while compiling imported modules in body…; they are also added to the load path of the gexp returned by body….

Procedure: gexp? obj

Return #t if obj is a G-expression.

G-expressions are meant to be written to disk, either as code building some derivation, or as plain files in the store. The monadic procedures below allow you to do that (see Устройство склада, for more information about monads).

Monadic Procedure: gexp->derivation name exp [#:system (%current-system)] [#:target #f] [#:graft? #t]  [#:hash #f]

[#:hash-algo #f]  [#:recursive? #f] [#:env-vars ’()] [#:modules ’()]  [#:module-path %load-path]  [#:effective-version "2.2"]  [#:references-graphs #f] [#:allowed-references #f]  [#:disallowed-references #f]  [#:leaked-env-vars #f]  [#:script-name (string-append name "-builder")]  [#:deprecation-warnings #f]  [#:local-build? #f] [#:substitutable? #t]  [#:properties ’()] [#:guile-for-build #f] Return a derivation name that runs exp (a gexp) with guile-for-build (a derivation) on system; exp is stored in a file called script-name. When target is true, it is used as the cross-compilation target triplet for packages referred to by exp.

modules is deprecated in favor of with-imported-modules. Its meaning is to make modules available in the evaluation context of exp; modules is a list of names of Guile modules searched in module-path to be copied in the store, compiled, and made available in the load path during the execution of exp—e.g., ((guix build utils) (guix build gnu-build-system)).

effective-version determines the string to use when adding extensions of exp (see with-extensions) to the search path—e.g., "2.2".

graft? determines whether packages referred to by exp should be grafted when applicable.

When references-graphs is true, it must be a list of tuples of one of the following forms:

(file-name obj)
(file-name obj output)
(file-name gexp-input)
(file-name store-item)

The right-hand-side of each element of references-graphs is automatically made an input of the build process of exp. In the build environment, each file-name contains the reference graph of the corresponding item, in a simple text format.

allowed-references must be either #f or a list of output names and packages. In the latter case, the list denotes store items that the result is allowed to refer to. Any reference to another store item will lead to a build error. Similarly for disallowed-references, which can list items that must not be referenced by the outputs.

deprecation-warnings determines whether to show deprecation warnings while compiling modules. It can be #f, #t, or 'detailed.

The other arguments are as for derivation (see Деривации).

The local-file, plain-file, computed-file, program-file, and scheme-file procedures below return file-like objects. That is, when unquoted in a G-expression, these objects lead to a file in the store. Consider this G-expression:

#~(system* #$(file-append glibc "/sbin/nscd") "-f"
           #$(local-file "/tmp/my-nscd.conf"))

The effect here is to “intern” /tmp/my-nscd.conf by copying it to the store. Once expanded, for instance via gexp->derivation, the G-expression refers to that copy under /gnu/store; thus, modifying or removing the file in /tmp does not have any effect on what the G-expression does. plain-file can be used similarly; it differs in that the file content is directly passed as a string.

Procedure: local-file file [name] [#:recursive? #f] [#:select? (const #t)]

Return an object representing local file file to add to the store; this object can be used in a gexp. If file is a literal string denoting a relative file name, it is looked up relative to the source file where it appears; if file is not a literal string, it is looked up relative to the current working directory at run time. file will be added to the store under name–by default the base name of file.

When recursive? is true, the contents of file are added recursively; if file designates a flat file and recursive? is true, its contents are added, and its permission bits are kept.

When recursive? is true, call (select? file stat) for each directory entry, where file is the entry’s absolute file name and stat is the result of lstat; exclude entries for which select? does not return true.

file can be wrapped in the assume-valid-file-name syntactic keyword. When this is done, there will not be a warning when local-file is used with a non-literal path. The path is still looked up relative to the current working directory at run time. Wrapping is done like this:

(define alice-key-file-path "alice.pub")
;; ...
(local-file (assume-valid-file-name alice-key-file-path))

file can be wrapped in the assume-source-relative-file-name syntactic keyword. When this is done, the file name will be looked up relative to the source file where it appears even when it is not a string literal.

This is the declarative counterpart of the interned-file monadic procedure (see interned-file).

Procedure: plain-file name content

Return an object representing a text file called name with the given content (a string or a bytevector) to be added to the store.

This is the declarative counterpart of text-file.

Procedure: computed-file name gexp [#:local-build? #t] [#:options '()]

Return an object representing the store item name, a file or directory computed by gexp. When local-build? is true (the default), the derivation is built locally. options is a list of additional arguments to pass to gexp->derivation.

This is the declarative counterpart of gexp->derivation.

Monadic Procedure: gexp->script name exp [#:guile (default-guile)] [#:module-path %load-path]  [#:system

(%current-system)] [#:target #f] Return an executable script name that runs exp using guile, with exp’s imported modules in its search path. Look up exp’s modules in module-path.

The example below builds a script that simply invokes the ls command:

(use-modules (guix gexp) (gnu packages base))

(gexp->script "list-files"
              #~(execl #$(file-append coreutils "/bin/ls")
                       "ls"))

When “running” it through the store (see run-with-store), we obtain a derivation that produces an executable file /gnu/store/…-list-files along these lines:

#!/gnu/store/…-guile-2.0.11/bin/guile -ds
!#
(execl "/gnu/store/…-coreutils-8.22"/bin/ls" "ls")
Procedure: program-file name exp [#:guile #f] [#:module-path %load-path]

Return an object representing the executable store item name that runs gexp. guile is the Guile package used to execute that script. Imported modules of gexp are looked up in module-path.

This is the declarative counterpart of gexp->script.

Monadic Procedure: gexp->file name exp [#:set-load-path? #t] [#:module-path %load-path]  [#:splice? #f]  [#:guile

(default-guile)] Return a derivation that builds a file name containing exp. When splice? is true, exp is considered to be a list of expressions that will be spliced in the resulting file.

When set-load-path? is true, emit code in the resulting file to set %load-path and %load-compiled-path to honor exp’s imported modules. Look up exp’s modules in module-path.

The resulting file holds references to all the dependencies of exp or a subset thereof.

Procedure: scheme-file name exp [#:splice? #f] [#:guile #f] [#:set-load-path? #t] Return an object representing the Scheme

file name that contains exp. guile is the Guile package used to produce that file.

This is the declarative counterpart of gexp->file.

Monadic Procedure: text-file* name text

Return as a monadic value a derivation that builds a text file containing all of text. text may list, in addition to strings, objects of any type that can be used in a gexp: packages, derivations, local file objects, etc. The resulting store file holds references to all these.

This variant should be preferred over text-file anytime the file to create will reference items from the store. This is typically the case when building a configuration file that embeds store file names, like this:

(define (profile.sh)
  ;; Return the name of a shell script in the store that
  ;; initializes the 'PATH' environment variable.
  (text-file* "profile.sh"
              "export PATH=" coreutils "/bin:"
              grep "/bin:" sed "/bin\n"))

In this example, the resulting /gnu/store/…-profile.sh file will reference coreutils, grep, and sed, thereby preventing them from being garbage-collected during its lifetime.

Procedure: mixed-text-file name text …

Return an object representing store file name containing text. text is a sequence of strings and file-like objects, as in:

(mixed-text-file "profile"
                 "export PATH=" coreutils "/bin:" grep "/bin")

Это декларативный аналог text-file*.

Procedure: file-union name files

Return a <computed-file> that builds a directory containing all of files. Each item in files must be a two-element list where the first element is the file name to use in the new directory, and the second element is a gexp denoting the target file. Here’s an example:

(file-union "etc"
            `(("hosts" ,(plain-file "hosts"
                                    "127.0.0.1 localhost"))
              (\"bashrc\" ,(plain-file "bashrc"
                                     "alias ls='ls --color=auto'"))))

This yields an etc directory containing these two files.

Procedure: directory-union name things

Return a directory that is the union of things, where things is a list of file-like objects denoting directories. For example:

(directory-union "guile+emacs" (list guile emacs))

yields a directory that is the union of the guile and emacs packages.

Procedure: file-append obj suffix …

Return a file-like object that expands to the concatenation of obj and suffix, where obj is a lowerable object and each suffix is a string.

В качестве примера рассмотрим этот gexp:

(gexp->script "run-uname"
              #~(system* #$(file-append coreutils
                                        "/bin/uname")))

Такого же эффекта можно добиться с помощью:

(gexp->script "run-uname"
              #~(system* (string-append #$coreutils
                                        "/bin/uname")))

There is one difference though: in the file-append case, the resulting script contains the absolute file name as a string, whereas in the second case, the resulting script contains a (string-append …) expression to construct the file name at run time.

Macro: let-system system body…
Macro: let-system (system target) body…

Привязать system к текущей целевой системе—например, \"x86_64-linux\"—в body.

In the second case, additionally bind target to the current cross-compilation target—a GNU triplet such as "arm-linux-gnueabihf"—or #f if we are not cross-compiling.

let-system is useful in the occasional case where the object spliced into the gexp depends on the target system, as in this example:

#~(system*
   #+(let-system system
       (cond ((string-prefix? "armhf-" system)
              (file-append qemu "/bin/qemu-system-arm"))
             ((string-prefix? "x86_64-" system)
              (file-append qemu "/bin/qemu-system-x86_64"))
             (else
              (error "dunno!"))))
   "-net" "user" #$image)
Macro: with-parameters ((parameter value) …) exp

This macro is similar to the parameterize form for dynamically-bound parameters (see Parameters in GNU Guile Reference Manual). The key difference is that it takes effect when the file-like object returned by exp is lowered to a derivation or store item.

A typical use of with-parameters is to force the system in effect for a given object:

(with-parameters ((%current-system "i686-linux"))
  coreutils)

The example above returns an object that corresponds to the i686 build of Coreutils, regardless of the current value of %current-system.