Creating packages (Русский) - ArchWiki

Jump to content
From ArchWiki
Состояние перевода: На этой странице представлен перевод статьи Creating packages. Дата последней синхронизации: 23 августа 2023. Вы можете помочь синхронизировать перевод, если в английской версии произошли изменения.

Ссылки по теме

- Система сборки Arch
- Стандарты создания пакетов для Arch
- Пользовательский репозиторий Arch
- Creating packages for other distributions
- makepkg (Русский)
- pacman (Русский)
- Patching packages
- PKGBUILD (Русский)
- .SRCINFO (Русский)
- DeveloperWiki:Building in a clean chroot

Эта статья призвана помочь пользователям в создании собственных пакетов с помощью «портоподобной» системы сборки, в том числе для публикации в AUR. В ней рассказывается о создании файла описания сборки пакета — PKGBUILD, используемого утилитой `makepkg` для создания бинарного пакета из исходного кода. Если у вас уже есть `PKGBUILD`, смотрите статью makepkg (Русский). Инструкции относительно существующих правил и способов улучшения качества пакетов описаны в статье Стандарты создания пакетов для Arch.

## Обзор

Пакеты в Arch Linux собираются с помощью утилиты makepkg и информации, хранящейся в файле PKGBUILD. При запуске `makepkg` ищет `PKGBUILD` в текущем каталоге и выполняет записанные в нём инструкции для получения необходимых файлов и/или их компиляции для упаковки в файл пакета (`pkgname.pkg.tar.zst`). Полученный пакет содержит двоичные файлы и инструкции по установке, готовые к установке с помощью pacman.

Пакет Arch — это не более чем tar-архив, или «tarball», сжатый с помощью zstd(1), который содержит следующие созданные утилитой makepkg файлы:

- Бинарные файлы для установки.
- `.PKGINFO`: содержит все метаданные, необходимые pacman для работы с пакетами, зависимостями и т.д.
- `.BUILDINFO`: содержит информацию, необходимую для воспроизводимых сборок. Этот файл присутствует, только если пакет собран с помощью pacman 5.1 или более новой версии. См. BUILDINFO(5).
- `.MTREE`: содержит хэши и временные метки файлов, которые включаются в локальную базу данных, чтобы pacman мог проверить целостность пакета.
- `.INSTALL`: необязательный файл, используемый для выполнения команд после этапа установки/обновления/удаления. (Этот файл присутствует, только если он указан в `PKGBUILD`).
- `.Changelog`: необязательный файл, хранящийся у сопровождающего пакета и документирующий изменения пакета. (Он присутствует не во всех пакетах).

## Подготовка

### Необходимое программное обеспечение

Сперва убедитесь, что необходимые инструменты установлены: мета-пакета base-devel должно быть достаточно; он подтягивает `make` и дополнительные инструменты, необходимые для компиляции из исходного кода.

Ключевым инструментом для сборки пакетов является makepkg (предоставляется пакетом pacman), который делает следующее:

1. Проверяет, установлены ли зависимости пакета.
2. Загружает исходные файлы с указанного сервера(ов).
3. Распаковывает исходные файлы.
4. Компилирует программу и устанавливает её в окружении fakeroot.
5. Удаляет символы из двоичных файлов и библиотек.
6. Генерирует метафайл пакета, который включается в каждый пакет.
7. Сжимает окружение fakeroot в файл пакета.
8. Сохраняет файл пакета в настроенном каталоге назначения, который по умолчанию является текущим рабочим каталогом.

### Загрузка и тестирование установки

Загрузите исходный tarball программы, которую хотите упаковать, распакуйте его и следуйте указаниям автора для установки программы. Запишите все команды и/или шаги, необходимые для компиляции и установки. Вы будете повторять эти же команды в файле `PKGBUILD`.

Большинство авторов программ придерживаются трёхэтапного цикла сборки:

    ./configure
    make
    make install

Это подходящее время, чтобы убедиться, что программа работает правильно.

### Установка в чистый chroot

Рекомендуется следовать DeveloperWiki:Building in a clean chroot, чтобы убедиться, что пакеты и конфигурация вашей системы не приведут к ошибкам в PKGBUILD. Это более надёжный и корректный способ сборки пакетов, позволяющий обнаружить отсутствующие зависимости, о необходимости которых вы не подозревали, поскольку они уже присутствовали в вашей системе.

## Создание PKGBUILD

При запуске `makepkg` ищет в текущем рабочем каталоге файл `PKGBUILD`. Если он найден, то загружает исходный код программы и компилирует его в соответствии с инструкциями, указанными в файле `PKGBUILD`. Инструкции должны быть полностью интерпретируемы оболочкой Bash. После успешного завершения результирующие двоичные файлы и метаданные пакета, то есть версия пакета и зависимости, упаковываются в файл пакета `pkgname.pkg.tar.zst`. Получившийся пакет можно установить, просто используя `makepkg --install`, который вызовет pacman в фоновом режиме, или непосредственно используя `pacman -U pkgname.pkg.tar.zst`.

Чтобы начать сборку нового пакета, сначала создайте новый каталог для пакета и измените текущий каталог на него. Затем необходимо создать файл `PKGBUILD`: можно использовать прототип PKGBUILD, находящийся в `/usr/share/pacman/`, или начать с файла `PKGBUILD` из другого пакета. Последний вариант может оказаться удобным, если уже существует похожий пакет.

### Определение переменных PKGBUILD

Примеры PKGBUILD находятся в `/usr/share/pacman/`. Объяснение возможных переменных `PKGBUILD` можно найти в статье PKGBUILD (Русский).

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

`srcdir`
  Указывает на каталог, в который makepkg помещает файлы, указанные в массиве source.

`pkgdir`
  Указывает на каталог, в который makepkg собирает установленный пакет, который становится корневым каталогом вашего собранного пакета.

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

Примечание: makepkg, а значит, и функции `build()` и `package()`, предназначены для неинтерактивной работы. Интерактивные утилиты или скрипты, вызываемые в этих функциях, могут нарушить работу makepkg, особенно если они вызываются с включенным протоколированием сборки (`--log`). (См. FS#13214.)

### Функции PKGBUILD

При сборке пакета `makepkg` будет вызывать следующие пять функций, если они определены в PKGBUILD. Функция `package()` является обязательной в каждом PKGBUILD и будет вызываться всегда. Если какая-либо из других функций не определена, то `makepkg` просто пропустит вызов этой функции.

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

#### prepare()

С помощью этой функции выполняются команды, используемые для подготовки исходных текстов к сборке, например применение патчей. Эта функция запускается сразу после извлечения пакета, перед pkgver() и функцией сборки. Если извлечение пропущено (`makepkg --noextract`), то `prepare()` не выполняется.

Примечание: (Из PKGBUILD(5)) Функция выполняется в режиме `bash -e`, то есть любая команда, которая завершает работу с ненулевым статусом, приводит к выходу из функции.

Когда неясно, куда поместить ту или иную функцию — в `prepare()` или `build()`, можно воспользоваться эмпирическим правилом: помещать в `prepare()` те шаги, которые должны выполняться ровно один раз после извлечения исходных текстов, а в `build()` — те шаги, которые имеет смысл повторно выполнять после внесения любых ручных правок в извлечённые файлы.

#### pkgver()

`pkgver()` запускается после извлечения исходных текстов, их распаковки и выполнения prepare(). Таким образом, переменную pkgver можно обновить на этапе makepkg.

Это особенно полезно при создании пакетов git/svn/hg/etc., когда процесс сборки может оставаться неизменным, но исходники могут обновляться каждый день, а то и каждый час. Старый способ сделать это заключался в том, чтобы поместить дату в поле pkgver, но тогда даже если если программа не обновлялась, то makepkg все равно пересобирал её из-за изменившегося номера версии. Некоторые полезные команды для этого — `git describe`, `hg identify -ni` и т. д. Пожалуйста, проверяйте их перед отправкой PKGBUILD, так как сбой в функции `pkgver()` может остановить сборку на корню.

Примечание: pkgver не может содержать пробелы или дефисы (`-`). Для исправления этого часто используется sed.

#### build()

Теперь необходимо реализовать функцию `build()` в файле `PKGBUILD`. Эта функция использует обычные команды оболочки в синтаксисе Bash для автоматической компиляции программ и создания каталога `pkg` для их установки. Она позволяет makepkg упаковывать файлы без необходимости рыться в файловой системе.

Первым шагом в функции `build()` является переход в каталог, созданный в результате распаковки архива с исходным кодом. makepkg изменит текущий каталог на `$srcdir` перед выполнением функции `build()`. Поэтому в большинстве случаев, как это предлагается в `/usr/share/pacman/PKGBUILD.proto`, первая команда будет выглядеть следующим образом:

    cd "$pkgname-$pkgver"

Теперь необходимо прописать те же команды, которые использовались при ручной компиляции программы. Функция `build()`, по сути, автоматизирует всё, что вы делали вручную, и компилирует программу в среде сборки fakeroot. Если в упаковываемом программном обеспечении используется скрипт configure, то при сборке пакетов для pacman рекомендуется использовать `--prefix=/usr`. Многие программы устанавливают файлы относительно каталога `/usr/local`, что следует делать только в случае ручной сборки из исходных текстов. Все пакеты Arch Linux должны использовать каталог `/usr`. Как видно из файла `/usr/share/pacman/PKGBUILD.proto`, следующие две строки часто выглядят следующим образом:

    ./configure --prefix=/usr
    make

Примечание: Если вашей программе не требуется сборка — не используйте функцию `build()`. Функция `build()` не является обязательной, а вот `package()` является таковой.

#### check()

Место для вызовов `make check` и аналогичных процедур проверки. Настоятельно рекомендуется иметь `check()`, так как проверка помогает убедиться в том, что программа правильно и хорошо работает с зависимостями.

Пользователи, которым она не нужна (а иногда и сопровождающие, которые не могут исправить пакет для её прохождения), могут отключить её с помощью `BUILDENV+=('!check')` в PKGBUILD/makepkg.conf или вызвать `makepkg` с флагом `--nocheck`.

#### package()

Последним шагом является помещение скомпилированных файлов в каталог, из которого makepkg сможет получить их для создания пакета. По умолчанию это каталог `pkg` — простая среда fakeroot. Каталог `pkg` повторяет иерархию корневой файловой системы путей установки программного обеспечения. Если вам приходится вручную размещать файлы в корне вашей файловой системы, то их следует устанавливать в каталог `pkg` в той же структуре каталогов. Например, если вы хотите установить файл в `/usr/bin`, то вместо этого его следует поместить в `$pkgdir/usr/bin`. Лишь немногие процедуры установки требуют от пользователя копирования десятков файлов вручную. Вместо этого для большинства программ достаточно вызвать команду `make install`. Для корректной установки программы в каталог `pkg` последняя строка должна выглядеть следующим образом:

    make DESTDIR="$pkgdir/" install

Примечание: В некоторых случаях в `Makefile` не используется `DESTDIR`; вместо него может потребоваться использовать `prefix`. Если пакет собран с помощью autoconf / automake, используйте `DESTDIR`; именно это документировано в руководствах. Если `DESTDIR` не работает, попробуйте собрать с помощью `make prefix="$pkgdir/usr/" install`. Если и это не сработает, то придётся подробнее изучить команды установки, выполняемые командой "`make <...> install`".

`makepkg --repackage` запускает только функцию `package()`, то есть создаёт пакет без сборки. Это может сэкономить время, например, если вы изменили только переменную `depends` пакета.

## Тестирование PKGBUILD и пакета

В процессе написания функции `build()` необходимо часто тестировать изменения, чтобы убедиться в отсутствии ошибок. Это можно сделать с помощью команды `makepkg` в каталоге, содержащем файл `PKGBUILD`. При правильно оформленном `PKGBUILD` makepkg создаст пакет; при неработающем или незавершённом `PKGBUILD` она выдаст ошибку.

При успешном завершении работы makepkg поместит в рабочий каталог файл с именем `pkgname-pkgver.pkg.tar.zst`. Этот пакет может быть установлен командой `pacman -U`. Однако то, что файл пакета был собран, не означает, что он полностью работоспособен. Он может содержать только каталог и ни одного файла, если, например, неправильно указан префикс. С помощью функций запроса pacman можно вывести список файлов, содержащихся в пакете, и зависимостей, которые он требует, с помощью `pacman -Qlp [package file]` и `pacman -Qip [package file]` соответственно.

Если пакет выглядит нормально, то все готово! Однако если вы планируете опубликовать файл `PKGBUILD`, то обязательно проверьте и перепроверьте содержимое массива `depends`.

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

### Проверка целостности пакета

После тестирования работоспособности пакета проверьте его на наличие ошибок с помощью namcap:

    $ namcap PKGBUILD
    $ namcap <имя файла пакета>.pkg.tar.zst

Namcap выполнит:

1. Проверку содержимого PKGBUILD на наличие типичных ошибок и иерархию файлов пакета на наличие ненужных или неправильно размещённых файлов
2. Сканирование всех ELF-файлов пакета с помощью `ldd`, автоматически сообщая, какие пакеты с необходимыми разделяемыми библиотеками отсутствуют в `depends`, а какие могут быть опущены как транзитивные зависимости
3. Эвристический поиск отсутствующих и избыточных зависимостей

и многое другое.

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

## Отправка пакетов в AUR

Пожалуйста, прочитайте правила отправки пакетов в AUR, где подробно описан процесс отправки.

## Резюме

1. Загрузите исходный архив программы, для которой создаётся пакет.
2. Попробуйте скомпилировать пакет и установить его в произвольный каталог.
3. Скопируйте прототип `/usr/share/pacman/PKGBUILD.proto` и переименуйте его в `PKGBUILD` во временный рабочий каталог.
4. Отредактируйте `PKGBUILD` в соответствии с потребностями вашего пакета.
5. Запустите `makepkg` и проверьте, правильно ли собран пакет.
6. Если нет - повторите два предыдущих шага.

### Предупреждения

- Прежде чем автоматизировать процесс сборки пакета, необходимо хотя бы раз выполнить его вручную, если только вы не знаете точно, что делаете, заранее, но в этом случае вы бы не читали эту статью. К сожалению, хотя многие авторы программ придерживаются трёхэтапного цикла сборки "`./configure`; `make`; `make install`", он не всегда таков, и ситуация может стать очень неприятной, если придётся применять патчи, чтобы вообще заставить всё работать. Правило: если вы не можете заставить программу скомпилироваться из исходного архива и установить себя в определённый временный подкаталог — не стоит даже пытаться упаковать её. В `makepkg` нет волшебной пыльцы фей, избавляющей от проблем.
- В некоторых случаях пакеты вообще недоступны в виде исходных текстов, и для того, чтобы заставить их работать, приходится использовать что-то вроде `sh installer.run`. Вам придётся провести довольно много исследований (прочитать README, инструкции INSTALL, man-страницы, возможно, ebuild'ы от Gentoo или других программ установки пакетов, возможно, даже MAKEFILE или исходный код), чтобы заставить их работать. В некоторых очень запущенных случаях приходится редактировать исходные файлы, чтобы заставить их работать. Однако `makepkg` должен отработать полностью автономно, без участия пользователя. Поэтому если необходимо отредактировать make-файлы, то, возможно, придётся дополнить `PKGBUILD` патчем и применять его в функции `prepare()`, либо выполнить несколько команд `sed` внутри функции `prepare()`.

## Более подробные руководства

## Автоматизация

### Контрольные суммы

Процесс обновления контрольных сумм для новых выпусков программ может быть автоматизирован с помощью инструмента `updpkgsums`; подробнее об этом см. в разделе makepkg (Русский)#Вычисление новых контрольных сумм.

### Генераторы PKGBUILD

PKGBUILD для некоторых пакетов могут быть созданы автоматически.

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

- Haskell: cblrepo, arch-hs
- Node.js: nodejs-npm2archAUR
- Perl: perl-cpanplus-dist-arch
- Python: pipman-gitAUR, pip2arch-gitAUR, python-pypi2pkgbuildAUR
- Ruby: gem2archAUR, pacgemAUR
- Rust: cargo-pkgbuildAUR

## Смотрите также

- How to correctly create a patch file.
- Arch Linux Classroom IRC Logs of classes about creating PKGBUILDs.
- Fakeroot approach for package installation

Categories:

- About Arch (Русский)
- Package development (Русский)