Глава 8. Продвинутые практики pkg-plist | FreeBSD Documentation Portal
Description: Продвинутые практики pkg-plist
Keywords: pkg-plist,practices,configuration

# Глава 8. Продвинутые практики pkg-plist

Этот перевод может быть устаревшим. Для того, чтобы помочь с переводом, пожалуйста, обратитесь к Сервер переводов FreeBSD.

## 8.1. Изменение содержимого pkg-plist в зависимости от make-переменных

Некоторые порты, в частности, порты `p5-`, должны менять содержимое своих файлов pkg-plist в зависимости от того, с какими параметрами они были отконфигурированы (или в зависимости от версии языка `perl` в случае портов `p5-`). Чтобы облегчить этот процесс, любые вхождения ключевых слов `%%OSREL%%`, `%%PERL_VER%%` и `%%PERL_VERSION%%` в файле pkg-plist будут заменяться соответствующими значениями. Значением `%%OSREL%%` является номер версии операционной системы (например, `4.9`). `%%PERL_VERSION%%` и `%%PERL_VER%%` обозначают полный номер версии `perl` (например, `5.8.9`). Некоторые другие `%%VARS%%`, имеющие отношение к файлам документации порта, описаны в соответствующем разделе.

Если вам нужно сделать другие подстановки, вы можете указать в переменной `PLIST_SUB` список пар `VAR=VALUE`, и все вхождения `%%VAR%%` в файле pkg-plist будут заменяться на значение VALUE.

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

    OCTAVE_VERSION=	${PORTREVISION}
    PLIST_SUB=	OCTAVE_VERSION=${OCTAVE_VERSION}

в файле Makefile и использовать `%%OCTAVE_VERSION%%` везде, где нужно указать номер версии в файле pkg-plist. Таким образом, при обновлении порта вам не нужно будет менять десятки (а в некоторых случаях и сотни) строк в файле pkg-plist.

Если файлы устанавливаются по условию в зависимости от опций, установленных в порте, обычный способ обработки — это добавление префикса `%%OPT%%` для строк в pkg-plist, которые нужны при включении опции, или `%%NO_OPT%%`, когда опция отключена, а также добавление `OPTIONS_SUB=yes` в Makefile. Подробнее см. `OPTIONS_SUB`.

Например, если есть файлы, которые устанавливаются только при включении опции `X11`, и в Makefile указано:

    OPTIONS_DEFINE=	X11
    OPTIONS_SUB=	yes

В pkg-plist укажите `%%X11%%` перед строками, которые устанавливаются только при включении опции, например:

    %%X11%%bin/foo-gui

Эта подстановка будет сделана между выполнением целей `pre-install` и `do-install`, посредством чтения файла PLIST и записью в файл TMPPLIST (по умолчанию это файл WRKDIR/.PLIST.mktmp). Так что если ваш порт строит PLIST на лету, делайте это во время или до выполнения цели `pre-install`. Кроме того, если вашему порту требуется отредактировать получающийся файл, делайте это в цели `post-install` изменением файла TMPPLIST.

Ещё один способ изменения списка упаковки порта основан на установке переменных `PLIST_FILES` и `PLIST_DIRS`. Значение каждой переменной рассматривается как список путей для записи в TMPPLIST вместе с содержимым PLIST. Хотя имена, перечисленные в `PLIST_FILES` и `PLIST_DIRS`, подлежат замене `%%VAR%%`, как описано выше, лучше использовать `${VAR}` напрямую. За исключением этого, имена из `PLIST_FILES` появятся в итоговом списке упаковки без изменений, тогда как к именам из `PLIST_DIRS` будет добавлен префикс `@dir`. Чтобы вступить в силу, `PLIST_FILES` и `PLIST_DIRS` должны быть установлены до записи TMPPLIST, то есть в `pre-install` или ранее.

Время от времени использования `OPTIONS_SUB` недостаточно. В таких случаях добавление специфичного `TAG` в `PLIST_SUB` внутри Makefile со специальным значением `@comment` заставляет инструменты пакетирования игнорировать строку. Например, если некоторые файлы устанавливаются только при включённой опции `X11` и архитектуре `i386`:

    .include <bsd.port.pre.mk>

    .if ${PORT_OPTIONS:MX11} && ${ARCH} == "i386"
    PLIST_SUB+=	X11I386=""
    .else
    PLIST_SUB+=	X11I386="@comment "
    .endif

## 8.2. Пустые каталоги

### 8.2.1. Очистка пустых каталогов

При удалении порт должен удалить пустые каталоги, которые он создал. Большинство этих каталогов автоматически удаляются с помощью pkg(8), но для каталогов, созданных вне ${PREFIX}, или пустых каталогов требуется дополнительная работа. Обычно это делается добавлением строк `@dir` для таких каталогов. Подкаталоги должны быть удалены до удаления родительских каталогов.

    [...]
    @dir /var/games/oneko/saved-games
    @dir /var/games/oneko

### 8.2.2. Создание пустых каталогов

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

    post-install:
    	${MKDIR} ${STAGEDIR}${PREFIX}/some/directory

Добавьте каталог в pkg-plist так же, как и любой другой. Например:

    @dir some/directory

## 8.3. Файлы конфигурации

Если порт устанавливает файлы конфигурации в PREFIX/etc (или в другое место), не указывайте их в pkg-plist. Это приведёт к тому, что `pkg delete` удалит файлы, которые были тщательно отредактированы пользователем, а повторная установка перезапишет их.

Вместо этого устанавливайте образцы файлов с расширением filename.sample. Макрос `@sample` автоматизирует этот процесс; подробности его работы см. в разделе Расширение списка пакетов с помощью ключевых слов. Для каждого образца файла добавьте строку в pkg-plist:

    @sample etc/orbit.conf.sample

Если существует очень веская причина не устанавливать рабочий файл конфигурации по умолчанию, укажите только имя примера файла в pkg-plist, без части `@sample` с последующим пробелом, и добавьте сообщение, указывающее, что пользователь должен скопировать и отредактировать файл перед тем, как программа заработает.

| Когда порт устанавливает свою конфигурацию в подкаталоге ${PREFIX}/etc, используйте `ETCDIR`, который по умолчанию равен `${PREFIX}/etc/${PORTNAME}`. Это значение может быть переопределено в Makefile порта, если для порта принято использовать другой каталог. Макрос `%%ETCDIR%%` будет использоваться вместо этого в pkg-plist.

| Примеры конфигурационных файлов всегда должны иметь суффикс .sample. Если по каким-то историческим причинам использование стандартного суффикса невозможно, или если примеры файлов взяты из другого каталога, используйте эту конструкцию:
    @sample etc/orbit.conf-dist etc/orbit.conf
или
    @sample %%EXAMPLESDIR%%/orbit.conf etc/orbit.conf
Формат: `@sample файл-образец фактический-конфигурационный-файл`.

## 8.4. Динамический или статический список упаковки

Статический список упаковки — это список упаковки, который доступен в Коллекции Портов или как файл pkg-plist (с подстановкой переменных или без неё), или как встроенный в Makefile через `PLIST_FILES` и `PLIST_DIRS`. Даже если содержимое было автоматически сгенерировано инструментом или целью в Makefile до включения в Коллекцию портов коммиттером (например, с использованием `make makeplist`), такой список всё равно считается статическим, поскольку его можно посмотреть без необходимости загрузки или компиляции distfile.

Динамический список упаковки — это список упаковки, который генерируется во время компиляции порта на основе установленных файлов и каталогов. Невозможно изучить его до загрузки и компиляции исходного кода портированного приложения или после выполнения команды `make clean`.

Хотя использование динамических списков упаковки не запрещено, сопровождающие должны использовать статические списки упаковки везде, где это возможно, поскольку это позволяет пользователям выполнять grep(1) по доступным портам для обнаружения, например, какой порт устанавливает определённый файл. Динамические списки должны быть использованы в основном для сложных портов, для которых изменения в списке упаковки кардинальным образом основаны на возможностях порта, настраиваемых параметрами, (и, таким образом, делая сопровождение статических списков упаковки невозможным), или портов, которые изменяют список упаковки на основе версии используемого им программного обеспечения (например, порты, которые порождают документы при помощи Javadoc).

## 8.5. Автоматическое создание списка упаковки

Сначала убедитесь, что порт почти готов, и отсутствует только файл pkg-plist. Запуск команды `make makeplist` покажет пример для файла pkg-plist. Вывод `makeplist` необходимо дважды перепроверять на корректность, так как он пытается автоматически угадать некоторые вещи и может ошибаться.

Файлы конфигурации пользователя должны устанавливаться как filename.sample, как описано в разделе Файлы конфигурации. info/dir не должен быть указан, а соответствующие строки install-info должны быть добавлены, как указано в разделе info-файлы. Любые библиотеки, устанавливаемые портом, должны быть перечислены, как указано в разделе общие библиотеки.

### 8.5.1. Расширение `PLIST_SUB` с помощью регулярных выражений

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

Для решения этой проблемы для каждого `PLACEHOLDER=значение` можно задать `PLACEHOLDER_regex=регулярное_выражение`, где `регулярное_выражение` более точно соответствует значению.

Пример 1. Использование PLIST_SUB с регулярными выражениями

Порты Perl могут устанавливать архитектурно-зависимые файлы в специальное дерево. В FreeBSD для упрощения портирования это дерево называется `mach`. Например, порт, который устанавливает файл, чей путь содержит `mach`, может иметь эту часть строки пути заменённой неправильными значениями. Рассмотрим этот Makefile:

    PORTNAME=	Machine-Build
    DISTVERSION=	1
    CATEGORIES=	devel perl5
    MASTER_SITES=	CPAN
    PKGNAMEPREFIX=	p5-

    MAINTAINER=	perl@FreeBSD.org
    COMMENT=	Building machine
    WWW=		https://search.cpan.org/dist/Machine-Build

    USES=		perl5
    USE_PERL5=	configure

    PLIST_SUB=	PERL_ARCH=mach

Файлы, установленные портом:

    /usr/local/bin/machine-build
    /usr/local/lib/perl5/site_perl/man/man1/machine-build.1.gz
    /usr/local/lib/perl5/site_perl/man/man3/Machine::Build.3.gz
    /usr/local/lib/perl5/site_perl/Machine/Build.pm
    /usr/local/lib/perl5/site_perl/mach/5.20/Machine/Build/Build.so

Запуск `make makeplist` ошибочно создает:

    bin/%%PERL_ARCH%%ine-build
    %%PERL5_MAN1%%/%%PERL_ARCH%%ine-build.1.gz
    %%PERL5_MAN3%%/Machine::Build.3.gz
    %%SITE_PERL%%/Machine/Build.pm
    %%SITE_PERL%%/%%PERL_ARCH%%/%%PERL_VER%%/Machine/Build/Build.so

Измените строку `PLIST_SUB` в Makefile на:

    PLIST_SUB=	PERL_ARCH=mach \
    		PERL_ARCH_regex=\bmach\b

Теперь `make makeplist` правильно генерирует:

    bin/machine-build
    %%PERL5_MAN1%%/machine-build.1.gz
    %%PERL5_MAN3%%/Machine::Build.3.gz
    %%SITE_PERL%%/Machine/Build.pm
    %%SITE_PERL%%/%%PERL_ARCH%%/%%PERL_VER%%/Machine/Build/Build.so

## 8.6. Расширение списка пакетов, используя ключевые слова

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

    @sample(games,games,640) etc/config.sample

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

    @sample(,games,660) etc/config.sample

| Если ключевое слово используется в необязательной записи, оно должно быть добавлено после помощника:
    %%FOO%%@sample etc/orbit.conf.sample
Это происходит потому, что вспомогательные функции plist для опций используются для закомментирования строки, поэтому они должны быть указаны первыми. Дополнительную информацию см. в `OPTIONS_SUB`.

### 8.6.1. `@desktop-file-utils`

Будет выполнять `update-desktop-database -q` после установки и удаления. Никогда не используйте напрямую, добавьте `USES=desktop-file-utils` в Makefile.

### 8.6.2. `@fc` каталог

Добавить запись `@dir` для каталога, переданного в качестве аргумента, и выполнить `fc-cache -fs` для этого каталога после установки и удаления.

### 8.6.3. `@fontsdir` каталог

Добавить запись `@dir` для каталога, переданного в качестве аргумента, и запустить `mkfontscale` и `mkfontdir` в этом каталоге после установки и удаления. Кроме того, при удалении удаляются кэш-файлы fonts.scale и fonts.dir, если они пусты.

### 8.6.4. `@info` файл

Добавляет файл, переданный в качестве аргумента, в plist и обновляет индекс документа info при установке и удалении. Кроме того, удаляет индекс, если он пуст, при удалении. Это никогда не следует использовать вручную, а только через `INFO`. Подробнее см. в Файлы Info.

### 8.6.5. `@kld` каталог

Выполняет `kldxref` для каталога при установке и удалении. Дополнительно при удалении каталог будет удалён, если он пуст.

### 8.6.6. `@rmtry` файл

Удаляет файл при удалении и не выдает ошибку, если файл отсутствует.

### 8.6.7. `@sample` файл [файл]

Это используется для обработки установки файлов конфигурации, используя примеры файлов, поставляемых с пакетом. "Реальный" файл (не пример) — это либо второе имя файла, если оно присутствует, либо первое имя файла без расширения .sample.

Это делает три вещи. Во-первых, добавляет первый переданный файл в качестве аргумента, образец файла, в plist. Затем, при установке, если фактический файл не найден, копирует образец файла в фактический файл. И наконец, при удалении, удаляет фактический файл, если он не был изменён. Дополнительную информацию см. в Файлы конфигурации.

### 8.6.8. `@shared-mime-info` каталог

Выполняет `update-mime-database` для указанного каталога при установке и удалении.

### 8.6.9. `@shell` файл

Добавить файл, переданный в качестве аргумента, в plist.

При установке добавить полный путь к file в /etc/shells, убедившись, что он не добавлен повторно. При удалении удалите его из /etc/shells.

### 8.6.10. `@terminfo`

Не использовать самостоятельно. Если порт устанавливает файлы *.terminfo, добавьте `USES=terminfo` в его Makefile.

При установке и удалении, если присутствует `tic`, обновить ${PREFIX}/shared/misc/terminfo.db из файлов *.terminfo в ${PREFIX}/shared/misc.

### 8.6.11. Основные ключевые слова

Есть несколько ключевых слов, которые жёстко закодированы и документированы в pkg-create(8). Для полноты изложения они также документированы здесь.

#### 8.6.11.1. `@` [файл]

Ключевое слово `empty` является заполнителем, используемым, когда необходимо изменить владельца, группу или права доступа к файлу. Например, чтобы установить группу файла в `games` и добавить бит setgid, добавьте:

    @(,games,2755) sbin/daemon

#### 8.6.11.2. `@preexec` команда, `@postexec` команда, `@preunexec` команда, `@postunexec` команда

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

`@preexec` команда

  Выполнить команду как часть скриптов pre-install.

`@postexec` команда

  Выполнить команду как часть скриптов post-install.

`@preunexec` команда

  Выполнить команду как часть скриптов pre-deinstall.

`@postunexec` команда

  Выполнить команду как часть скриптов post-deinstall.

Если в команде содержится любая из этих последовательностей, они раскрываются непосредственно. Для следующих примеров предположим, что `@cwd` установлен в /usr/local, а последним извлечённым файлом был bin/emacs.

`%F`

  Раскрывается до последнего извлеченного имени файла (как указано). В примере bin/emacs.

`%D`

  Раскрыть до текущего префикса каталога, установленного с помощью `@cwd`. В этом примере /usr/local.

`%B`

  Раскрыть до базового имени полного имени файла, то есть префикс текущего каталога плюс последняя спецификация файла, за вычетом имени файла в конце спецификации. В данном примере это будет /usr/local/bin.

`%f`

  Раскрывается до части имени файла в полном квалифицированном имени, или противоположный случай для `%B`. В примере, emacs.

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

#### 8.6.11.3. `@mode` режим

Установить разрешения по умолчанию для всех последующих извлекаемых файлов в режим. Формат такой же, как используется в chmod(1). Использование без аргумента вернёт разрешения по умолчанию (режим файла при упаковке).

| Это должен быть числовой режим, например `644`, `4755` или `600`. Нельзя использовать относительный режим, например `u+s`.

#### 8.6.11.4. `@owner` пользователь

Установить владельца по умолчанию для всех последующих файлов в пользователь. Использование без аргумента вернёт владельца по умолчанию (`root`).

#### 8.6.11.5. `@group` группа

Установить группу-владельца по умолчанию для всех последующих файлов в группу. Использование без аргумента вернёт группу-владельца по умолчанию (`wheel`).

#### 8.6.11.6. `@comment` строка

Эта строка игнорируется при упаковке.

#### 8.6.11.7. `@dir` каталог

Объявить имя каталога. По умолчанию каталоги, созданные в `PREFIX` при установке пакета, автоматически удаляются. Используйте эту опцию, если необходимо создать пустой каталог в `PREFIX` или если каталогу требуется нестандартный владелец, группа или права. Каталоги за пределами `PREFIX` необходимо регистрировать. Например, /var/db/${PORTNAME} требует записи `@dir`, тогда как ${PREFIX}/shared/${PORTNAME} — нет, если он содержит файлы или использует стандартные владельца, группу и права.

#### 8.6.11.8. `@exec` команда, `@unexec` команда (Устарело)

Выполнить команду как часть процесса установки или удаления. Рекомендуется использовать `@preexec` команда вместо этого.

#### 8.6.11.9. `@dirrm` каталог (Устарело)

Объявить имя каталога для удаления при деинсталляции. По умолчанию каталоги, созданные в `PREFIX` при установке пакета, удаляются при его деинсталляции.

#### 8.6.11.10. `@dirrmtry` каталог (Устарело)

Объявить имя каталога для удаления, аналогично `@dirrm`, но не выводить предупреждение, если каталог не может быть удален.

### 8.6.12. Создание новых ключевых слов

Файлы списка пакетов могут быть расширены ключевыми словами, которые определены в каталоге ${PORTSDIR}/Keywords. Настройки каждого ключевого слова хранятся в файле UCL с именем keyword.ucl. Файл должен содержать как минимум один из следующих разделов:

- `attributes`

- `action`

- `pre-install`

- `post-install`

- `pre-deinstall`

- `post-deinstall`

- `pre-upgrade`

- `post-upgrade`

#### 8.6.12.1. `attributes`

Изменяет владельца, группу или режим доступа, используемые ключевым словом. Содержит ассоциативный массив, в котором возможными ключами являются `owner`, `group` и `mode`. Значениями являются, соответственно, имя пользователя, имя группы и режим доступа к файлу. Например:

    attributes: { owner: "games", group: "games", mode: 0555 }

#### 8.6.12.2. `action`

Определяет, что происходит с параметром ключевого слова. Содержит массив, где возможные значения:

`setprefix`

  Установите префикс для следующих записей в plist.

`dir`

  Зарегистрировать каталог для создания при установке и удаления при деинсталляции.

`dirrm`

  Зарегистрировать каталог для удаления при деинсталляции. Устарело.

`dirrmtry`

  Зарегистрировать каталог для попытки удаления при деинсталляции. Устарело.

`file`

  Зарегистрировать файл.

`setmode`

  Установить режим для следующих записей plist.

`setowner`

  Установить владельца для следующих записей plist.

`setgroup`

  Установить группу для следующих записей в plist.

`comment`

  Не выполняет никаких действий, эквивалентно отсутствию раздела `action`.

`ignore_next`

  Игнорировать следующую запись в plist.

#### 8.6.12.3. `arguments`

Если установлено значение `true`, добавляется обработка аргументов, разделяя всю строку, `%@`, на нумерованные аргументы, `%1`, `%2`, и так далее. Например, для такой строки:

    @foo some.content other.content

`%1` и `%2` будут содержать:

    some.content
    other.content

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

    actions: [file(1)]

#### 8.6.12.4. `pre-install`, `post-install`, `pre-deinstall`, `post-deinstall`, `pre-upgrade`, `post-upgrade`

Эти ключевые слова содержат sh(1) скрипт, который выполняется до или после установки, удаления или обновления пакета. В дополнение к обычным заполнителям `@exec %foo`, описанным в `@preexec` команда, существует новый заполнитель `%@`, который представляет аргумент ключевого слова.

#### 8.6.12.5. Примеры пользовательских ключевых слов

Пример 2. Пример ключевого слова `@dirrmtryecho`

Это ключевое слово выполняет две функции: добавляет строку `@dirrmtry directory` в список упаковки и сообщает о том, что каталог удаляется при деинсталляции пакета.

    actions: [dirrmtry]
    post-deinstall: <<EOD
      echo "Directory %D/%@ removed."
    EOD

Пример 3. Реальный пример, как реализован `@sample`

Этот ключевое слово выполняет три действия. Оно добавляет первый filename, переданный в качестве аргумента `@sample`, в список упаковки, добавляет в скрипт `post-install` инструкции для копирования образца в фактический файл конфигурации, если он ещё не существует, и добавляет в инструкции `post-deinstall` удаление файла конфигурации, если он не был изменён.

    actions: [file(1)]
    arguments: true
    post-install: <<EOD
      case "%1" in
      /*) sample_file="%1" ;;
      *) sample_file="%D/%1" ;;
      esac
      target_file="${sample_file%.sample}"
      set -- %@
      if [ $# -eq 2 ]; then
          target_file=${2}
      fi
      case "${target_file}" in
      /*) target_file="${target_file}" ;;
      *) target_file="%D/${target_file}" ;;
      esac
      if ! [ -f "${target_file}" ]; then
        /bin/cp -p "${sample_file}" "${target_file}" && \
          /bin/chmod u+w "${target_file}"
      fi
    EOD
    pre-deinstall: <<EOD
      case "%1" in
      /*) sample_file="%1" ;;
      *) sample_file="%D/%1" ;;
      esac
      target_file="${sample_file%.sample}"
      set -- %@
      if [ $# -eq 2 ]; then
          set -- %@
          target_file=${2}
      fi
      case "${target_file}" in
      /*) target_file="${target_file}" ;;
      *) target_file="%D/${target_file}" ;;
      esac
      if cmp -s "${target_file}" "${sample_file}"; then
        rm -f "${target_file}"
      else
        echo "You may need to manually remove ${target_file} if it is no longer needed."
      fi
    EOD

Изменено: 15 марта 2026 г. by Vladlen Popolitov

Назад
Главная
Далее